Example #1
0
int
main(int argc, char *argv[])
{
	char *testname_re = NULL;
	int lun;
	CU_BasicRunMode mode = CU_BRM_VERBOSE;
	CU_ErrorAction error_action = CUEA_IGNORE;
	int res;
	struct scsi_readcapacity10 *rc10;
	struct scsi_task *inq_task = NULL;
	struct scsi_task *inq_lbp_task = NULL;
	struct scsi_task *inq_bdc_task = NULL;
	struct scsi_task *inq_bl_task = NULL;
	struct scsi_task *rc16_task = NULL;
	struct scsi_task *rsop_task = NULL;
	int full_size;
	int is_usb = 0;
	int xml_mode = 0;
	static struct option long_opts[] = {
		{ "help", no_argument, 0, '?' },
		{ "list", no_argument, 0, 'l' },
		{ "initiator-name", required_argument, 0, 'i' },
		{ "initiator-name-2", required_argument, 0, 'I' },
		{ "test", required_argument, 0, 't' },
		{ "dataloss", no_argument, 0, 'd' },
		{ "allow-sanitize", no_argument, 0, 'S' },
		{ "ignore", no_argument, 0, 'g' },
		{ "fail", no_argument, 0, 'f' },
		{ "abort", no_argument, 0, 'A' },
		{ "silent", no_argument, 0, 's' },
		{ "normal", no_argument, 0, 'n' },
		{ "usb", no_argument, 0, 'u' },
		{ "verbose", no_argument, 0, 'v' },
		{ "xml", no_argument, 0, 'x' },
		{ "Verbose-scsi", no_argument, 0, 'V' },
		{ NULL, 0, 0, 0 }
	};
	int i, c;
	int opt_idx = 0;

	while ((c = getopt_long(argc, argv, "?hli:I:t:sdgfAsSnuvxV", long_opts,
		    &opt_idx)) > 0) {
		switch (c) {
		case 'h':
		case '?':
			print_usage();
			return 0;
		case 'l':
			list_all_tests();
			return 0;
		case 'i':
			initiatorname1 = strdup(optarg);
			break;
		case 'I':
			initiatorname2 = strdup(optarg);
			break;
		case 't':
			testname_re = strdup(optarg);
			break;
		case 'd':
			data_loss++;
			break;
		case 'g':
			error_action = CUEA_IGNORE; /* default */
			break;
		case 'f':
			error_action = CUEA_FAIL;
			break;
		case 'A':
			error_action = CUEA_ABORT;
			break;
		case 's':
			mode = CU_BRM_SILENT;
			break;
		case 'S':
			allow_sanitize = 1;
			break;
		case 'n':
			mode = CU_BRM_NORMAL;
			break;
		case 'u':
			is_usb = 1;
			break;
		case 'v':
			mode = CU_BRM_VERBOSE;	/* default */
			break;
		case 'x':
		        xml_mode = 1;
			break;
		case 'V':
			loglevel = LOG_VERBOSE;
			break;
		default:
			fprintf(stderr,
			    "error: unknown option return: %c (option %s)\n",
			    c, argv[optind]);
			return 1;
		}
	}

	if (optind < argc) {
		tgt_url = strdup(argv[optind++]);
	}
	if (optind < argc) {
		fprintf(stderr, "error: too many arguments\n");
		print_usage();
		return 1;
	}

	/* XXX why is this done? */
	real_iscsi_queue_pdu = dlsym(RTLD_NEXT, "iscsi_queue_pdu");

	if (tgt_url == NULL) {
		fprintf(stderr, "You must specify the URL\n");
		print_usage();
		if (testname_re)
			free(testname_re);
		return 10;
	}

	iscsic = iscsi_context_login(initiatorname1, tgt_url, &lun);
	if (iscsic == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/*
	 * find the size of the LUN
	 * All devices support readcapacity10 but only some support
	 * readcapacity16
	 */
	task = iscsi_readcapacity10_sync(iscsic, lun, 0, 0);
	if (task == NULL) {
		printf("Failed to send READCAPACITY10 command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY10 command: failed with sense. %s\n",
		    iscsi_get_error(iscsic));
		scsi_free_scsi_task(task);
		iscsi_destroy_context(iscsic);
		return -1;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data. %s\n",
		    iscsi_get_error(iscsic));
		scsi_free_scsi_task(task);
		iscsi_destroy_context(iscsic);
		return -1;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba + 1;
	scsi_free_scsi_task(task);

	rc16_task = iscsi_readcapacity16_sync(iscsic, lun);
	if (rc16_task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (rc16_task->status == SCSI_STATUS_GOOD) {
		rc16 = scsi_datain_unmarshall(rc16_task);
		if (rc16 == NULL) {
			printf("failed to unmarshall READCAPACITY16 data. %s\n",
			    iscsi_get_error(iscsic));
			scsi_free_scsi_task(rc16_task);
			iscsi_destroy_context(iscsic);
			return -1;
		}
		block_size = rc16->block_length;
		num_blocks = rc16->returned_lba + 1;
		lbppb = 1 << rc16->lbppbe;
	}

	inq_task = iscsi_inquiry_sync(iscsic, lun, 0, 0, 64);
	if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
		printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
		return -1;
	}
	full_size = scsi_datain_getfullsize(inq_task);
	if (full_size > inq_task->datain.size) {
		scsi_free_scsi_task(inq_task);

		/* we need more data for the full list */
		inq_task = iscsi_inquiry_sync(iscsic, lun, 0, 0, full_size);
		if (inq_task == NULL) {
			printf("Inquiry command failed : %s\n",
			    iscsi_get_error(iscsic));
			return -1;
		}
	}
	inq = scsi_datain_unmarshall(inq_task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(inq_task);
		return -1;
	}

	sbc3_support = 0;
	for (i = 0; i < 8; i++) {
		if (inq->version_descriptor[i] == 0x04C0) {
			sbc3_support = 1;
		}
	}

	/* try reading block limits vpd */
	inq_bl_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 64);
	if (inq_bl_task && inq_bl_task->status != SCSI_STATUS_GOOD) {
		scsi_free_scsi_task(inq_bl_task);
		inq_bl_task = NULL;
	}
	if (inq_bl_task) {
		full_size = scsi_datain_getfullsize(inq_bl_task);
		if (full_size > inq_bl_task->datain.size) {
			scsi_free_scsi_task(inq_bl_task);

			if ((inq_bl_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, full_size)) == NULL) {
				printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
				return -1;
			}
		}

		inq_bl = scsi_datain_unmarshall(inq_bl_task);
		if (inq_bl == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			return -1;
		}
	}

	/* try reading block device characteristics vpd */
	inq_bdc_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS, 255);
	if (inq_bdc_task == NULL) {
		printf("Failed to read Block Device Characteristics page\n");
	}
	if (inq_bdc_task) {
		inq_bdc = scsi_datain_unmarshall(inq_bdc_task);
		if (inq_bdc == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			return -1;
		}
	}

	/* if thin provisioned we also need to read the VPD page for it */
	if (rc16 && rc16->lbpme != 0){
		inq_lbp_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 64);
		if (inq_lbp_task == NULL || inq_lbp_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
			return -1;
		}
		full_size = scsi_datain_getfullsize(inq_lbp_task);
		if (full_size > inq_lbp_task->datain.size) {
			scsi_free_scsi_task(inq_lbp_task);

			/* we need more data for the full list */
			if ((inq_lbp_task = iscsi_inquiry_sync(iscsic, lun, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, full_size)) == NULL) {
				printf("Inquiry command failed : %s\n", iscsi_get_error(iscsic));
				return -1;
			}
		}

		inq_lbp = scsi_datain_unmarshall(inq_lbp_task);
		if (inq_lbp == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			return -1;
		}
	}

	rsop_task = iscsi_report_supported_opcodes_sync(iscsic, lun,
		1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0, 65535);
	if (rsop_task == NULL) {
		printf("Failed to send REPORT_SUPPORTED_OPCODES command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (rsop_task->status == SCSI_STATUS_GOOD) {
		rsop = scsi_datain_unmarshall(rsop_task);
		if (rsop == NULL) {
			printf("failed to unmarshall REPORT_SUPPORTED_OPCODES "
			       "data. %s\n",
			       iscsi_get_error(iscsic));
			scsi_free_scsi_task(rsop_task);
		}
	}

	/* check if the device is write protected or not */
	task = iscsi_modesense6_sync(iscsic, lun, 0, SCSI_MODESENSE_PC_CURRENT,
				     SCSI_MODEPAGE_RETURN_ALL_PAGES,
				     0, 255);
	if (task == NULL) {
		printf("Failed to send MODE_SENSE6 command: %s\n",
		    iscsi_get_error(iscsic));
		iscsi_destroy_context(iscsic);
		return -1;
	}
	if (task->status == SCSI_STATUS_GOOD) {
		struct scsi_mode_sense *ms;

		ms = scsi_datain_unmarshall(task);
		if (ms == NULL) {
			printf("failed to unmarshall mode sense datain blob\n");
			scsi_free_scsi_task(task);
			return -1;
		}
		readonly = !!(ms->device_specific_parameter & 0x80);
	}
	scsi_free_scsi_task(task);

	iscsi_logout_sync(iscsic);
	iscsi_destroy_context(iscsic);

	if (is_usb) {
		printf("USB device. Clamping maximum transfer length to 120k\n");
		maximum_transfer_length = 120 *1024 / block_size;
	}

	if (CU_initialize_registry() != 0) {
		fprintf(stderr, "error: unable to initialize test registry\n");
		return 1;
	}
	if (CU_is_test_running()) {
		fprintf(stderr, "error: test suite(s) already running!?\n");
		exit(1);
	}

	parse_and_add_tests(testname_re);
	if (testname_re)
		free(testname_re);

	CU_basic_set_mode(mode);
	CU_set_error_action(error_action);
	printf("\n");

	/*
	 * this actually runs the tests ...
	 */

	if (xml_mode) {
	  CU_list_tests_to_file();
	  CU_automated_run_tests();
	} else {
	  res = CU_basic_run_tests();
	  printf("Tests completed with return value: %d\n", res);
	}

	CU_cleanup_registry();
	free(discard_const(tgt_url));

	if (inq_task != NULL) {
		scsi_free_scsi_task(inq_task);
	}
	if (inq_bl_task != NULL) {
		scsi_free_scsi_task(inq_bl_task);
	}
	if (inq_lbp_task != NULL) {
		scsi_free_scsi_task(inq_lbp_task);
	}
	if (inq_bdc_task != NULL) {
		scsi_free_scsi_task(inq_bdc_task);
	}
	if (rc16_task != NULL) {
		scsi_free_scsi_task(rc16_task);
	}
	if (rsop_task != NULL) {
		scsi_free_scsi_task(rsop_task);
	}

	return 0;
}
Example #2
0
int
main(int argc, char *argv[])
{
	char *testname_re = NULL;
	CU_BasicRunMode mode = CU_BRM_VERBOSE;
	CU_ErrorAction error_action = CUEA_IGNORE;
	int res;
	struct scsi_readcapacity10 *rc10;
	struct scsi_task *inq_task = NULL;
	struct scsi_task *inq_lbp_task = NULL;
	struct scsi_task *inq_bdc_task = NULL;
	struct scsi_task *inq_bl_task = NULL;
	struct scsi_task *rc16_task = NULL;
	struct scsi_task *rsop_task = NULL;
	int full_size;
	int xml_mode = 0;
	static struct option long_opts[] = {
		{ "help", no_argument, 0, '?' },
		{ "list", no_argument, 0, 'l' },
		{ "initiator-name", required_argument, 0, 'i' },
		{ "initiator-name-2", required_argument, 0, 'I' },
		{ "test", required_argument, 0, 't' },
		{ "dataloss", no_argument, 0, 'd' },
		{ "allow-sanitize", no_argument, 0, 'S' },
		{ "ignore", no_argument, 0, 'g' },
		{ "fail", no_argument, 0, 'f' },
		{ "abort", no_argument, 0, 'A' },
		{ "silent", no_argument, 0, 's' },
		{ "normal", no_argument, 0, 'n' },
		{ "verbose", no_argument, 0, 'v' },
		{ "xml", no_argument, 0, 'x' },
		{ "Verbose-scsi", no_argument, 0, 'V' },
		{ NULL, 0, 0, 0 }
	};
	int i, c;
	int opt_idx = 0;

	while ((c = getopt_long(argc, argv, "?hli:I:t:sdgfAsSnvxV", long_opts,
		    &opt_idx)) > 0) {
		switch (c) {
		case 'h':
		case '?':
			print_usage();
			return 0;
		case 'l':
			list_all_tests();
			return 0;
		case 'i':
			initiatorname1 = strdup(optarg);
			break;
		case 'I':
			initiatorname2 = strdup(optarg);
			break;
		case 't':
			testname_re = strdup(optarg);
			break;
		case 'd':
			data_loss++;
			break;
		case 'g':
			error_action = CUEA_IGNORE; /* default */
			break;
		case 'f':
			error_action = CUEA_FAIL;
			break;
		case 'A':
			error_action = CUEA_ABORT;
			break;
		case 's':
			mode = CU_BRM_SILENT;
			break;
		case 'S':
			allow_sanitize = 1;
			break;
		case 'n':
			mode = CU_BRM_NORMAL;
			break;
		case 'v':
			mode = CU_BRM_VERBOSE;	/* default */
			break;
		case 'x':
		        xml_mode = 1;
			break;
		case 'V':
			loglevel = LOG_VERBOSE;
			break;
		default:
			fprintf(stderr,
			    "error: unknown option return: %c (option %s)\n",
			    c, argv[optind]);
			return 1;
		}
	}

	/* parse all trailing arguments as device paths */
	mp_num_sds = 0;
	while (optind < argc) {
		if (mp_num_sds >= MPATH_MAX_DEVS) {
			fprintf(stderr, "Too many multipath device URLs\n");
			print_usage();
			free(testname_re);
			return 10;
		}

		mp_sds[mp_num_sds] = malloc(sizeof(struct scsi_device));
		memset(mp_sds[mp_num_sds], '\0', sizeof(struct scsi_device));
		mp_sds[mp_num_sds]->sgio_fd = -1;

		if (!strncmp(argv[optind], "iscsi://", 8)) {
			mp_sds[mp_num_sds]->iscsi_url = strdup(argv[optind++]);
#ifdef HAVE_SG_IO
		} else {
			mp_sds[mp_num_sds]->sgio_dev = strdup(argv[optind++]);
#endif
		}
		mp_num_sds++;
	}

	/* So that we can override iscsi_queue_pdu in tests
	 * and replace or mutate the blob that we are about to write to the
	 * wire.
	 * This allows such tests to do their mutates and then call out
	 * to the real queueing function once they have modified the data.
	 */
	real_iscsi_queue_pdu = dlsym(RTLD_NEXT, "iscsi_queue_pdu");

	if ((mp_num_sds == 0) || (mp_sds[0]->iscsi_url == NULL
					&& mp_sds[0]->sgio_dev == NULL)) {
#ifdef HAVE_SG_IO
		fprintf(stderr, "You must specify either an iSCSI URL or a device file\n");
#else
		fprintf(stderr, "You must specify an iSCSI URL\n");
#endif
		print_usage();
		if (testname_re)
			free(testname_re);
		return 10;
	}

	/* sd remains an alias for the first device */
	sd = mp_sds[0];

	for (i = 0; i < mp_num_sds; i++) {
		res = connect_scsi_device(mp_sds[i], initiatorname1);
		if (res < 0) {
			fprintf(stderr,
				"Failed to connect to SCSI device %d\n", i);
			goto err_sds_free;
		}
	}

	if (mp_num_sds > 1) {
		/* check that all multipath sds identify as the same LU */
		res = mpath_check_matching_ids(mp_num_sds, mp_sds);
		if (res < 0) {
			fprintf(stderr, "multipath devices don't match\n");
			goto err_sds_free;
		}
	}

	/*
	 * find the size of the LUN
	 * All devices support readcapacity10 but only some support
	 * readcapacity16
	 */
	task = NULL;
	readcapacity10(sd, &task, 0, 0, EXPECT_STATUS_GOOD);
	if (task == NULL) {
		printf("Failed to send READCAPACITY10 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY10 command: failed with sense. %s\n", sd->error_str);
		scsi_free_scsi_task(task);
		goto err_sds_free;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data.\n");
		scsi_free_scsi_task(task);
		goto err_sds_free;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba + 1;
	scsi_free_scsi_task(task);

	rc16_task = NULL;
	readcapacity16(sd, &rc16_task, 96, EXPECT_STATUS_GOOD);
	if (rc16_task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (rc16_task->status == SCSI_STATUS_GOOD) {
		rc16 = scsi_datain_unmarshall(rc16_task);
		if (rc16 == NULL) {
			printf("failed to unmarshall READCAPACITY16 data. %s\n", sd->error_str);
			scsi_free_scsi_task(rc16_task);
			goto err_sds_free;
		}
		block_size = rc16->block_length;
		num_blocks = rc16->returned_lba + 1;
		lbppb = 1 << rc16->lbppbe;
	}

	inq_task = NULL;
	inquiry(sd, &inq_task, 0, 0, 64, EXPECT_STATUS_GOOD);
	if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
		printf("Inquiry command failed : %s\n", sd->error_str);
		goto err_sds_free;
	}
	full_size = scsi_datain_getfullsize(inq_task);
	if (full_size > inq_task->datain.size) {
		scsi_free_scsi_task(inq_task);

		/* we need more data for the full list */
		inq_task = NULL;
		inquiry(sd, &inq_task, 0, 0, full_size, EXPECT_STATUS_GOOD);
		if (inq_task == NULL) {
			printf("Inquiry command failed : %s\n", sd->error_str);
			goto err_sds_free;
		}
	}
	inq = scsi_datain_unmarshall(inq_task);
	if (inq == NULL) {
		printf("failed to unmarshall inquiry datain blob\n");
		scsi_free_scsi_task(inq_task);
		goto err_sds_free;
	}

	sbc3_support = 0;
	for (i = 0; i < 8; i++) {
		if (inq->version_descriptor[i] == 0x04C0) {
			sbc3_support = 1;
		}
	}

	/* try reading block limits vpd */
	inq_bl_task = NULL;
	inquiry(sd, &inq_bl_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 64, EXPECT_STATUS_GOOD);
	if (inq_bl_task && inq_bl_task->status != SCSI_STATUS_GOOD) {
		scsi_free_scsi_task(inq_bl_task);
		inq_bl_task = NULL;
	}
	if (inq_bl_task) {
		full_size = scsi_datain_getfullsize(inq_bl_task);
		if (full_size > inq_bl_task->datain.size) {
			scsi_free_scsi_task(inq_bl_task);

			inq_bl_task = NULL;
			inquiry(sd, &inq_bl_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, full_size,
				EXPECT_STATUS_GOOD);
			if (inq_bl_task == NULL) {
				printf("Inquiry command failed : %s\n", sd->error_str);
				goto err_sds_free;
			}
		}

		inq_bl = scsi_datain_unmarshall(inq_bl_task);
		if (inq_bl == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	/* try reading block device characteristics vpd */
	inquiry(sd, &inq_bdc_task, 1, SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS, 255,
		EXPECT_STATUS_GOOD);
	if (inq_bdc_task == NULL || inq_bdc_task->status != SCSI_STATUS_GOOD) {
		printf("Failed to read Block Device Characteristics page\n");
	} else {
		inq_bdc = scsi_datain_unmarshall(inq_bdc_task);
		if (inq_bdc == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	/* if thin provisioned we also need to read the VPD page for it */
	if (rc16 && rc16->lbpme != 0){
		inq_lbp_task = NULL;
		inquiry(sd, &inq_lbp_task, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 64,
			EXPECT_STATUS_GOOD);
		if (inq_lbp_task == NULL || inq_lbp_task->status != SCSI_STATUS_GOOD) {
			printf("Inquiry command failed : %s\n", sd->error_str);
			goto err_sds_free;
		}
		full_size = scsi_datain_getfullsize(inq_lbp_task);
		if (full_size > inq_lbp_task->datain.size) {
			scsi_free_scsi_task(inq_lbp_task);

			/* we need more data for the full list */
			inq_lbp_task = NULL;
			inquiry(sd, &inq_lbp_task, 1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
				full_size, EXPECT_STATUS_GOOD);
			if (inq_lbp_task == NULL) {
				printf("Inquiry command failed : %s\n", sd->error_str);
				goto err_sds_free;
			}
		}

		inq_lbp = scsi_datain_unmarshall(inq_lbp_task);
		if (inq_lbp == NULL) {
			printf("failed to unmarshall inquiry datain blob\n");
			goto err_sds_free;
		}
	}

	rsop_task = NULL;
	report_supported_opcodes(sd, &rsop_task, 1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0, 65535,
				 EXPECT_STATUS_GOOD);
	if (rsop_task == NULL) {
		printf("Failed to send REPORT_SUPPORTED_OPCODES command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (rsop_task->status == SCSI_STATUS_GOOD) {
		rsop = scsi_datain_unmarshall(rsop_task);
		if (rsop == NULL) {
			printf("failed to unmarshall REPORT_SUPPORTED_OPCODES data.\n");
			scsi_free_scsi_task(rsop_task);
			rsop_task = NULL;
		}
	}

	/* check if the device is write protected or not */
	task = NULL;
	modesense6(sd, &task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
		   EXPECT_STATUS_GOOD);
	if (task == NULL) {
		printf("Failed to send MODE_SENSE6 command: %s\n", sd->error_str);
		goto err_sds_free;
	}
	if (task->status == SCSI_STATUS_GOOD) {
		struct scsi_mode_sense *ms;

		ms = scsi_datain_unmarshall(task);
		if (ms == NULL) {
			printf("failed to unmarshall mode sense datain blob\n");
			scsi_free_scsi_task(task);
			goto err_sds_free;
		}
		readonly = !!(ms->device_specific_parameter & 0x80);
	}
	scsi_free_scsi_task(task);

	if (maxsectbytes) {
		maximum_transfer_length = maxsectbytes / block_size;
		printf("Bus transfer size is limited to %d bytes. Clamping "
		       "max transfers accordingly.\n", maxsectbytes);
	}

	if (CU_initialize_registry() != 0) {
		fprintf(stderr, "error: unable to initialize test registry\n");
		goto err_sds_free;
	}
	if (CU_is_test_running()) {
		fprintf(stderr, "error: test suite(s) already running!?\n");
		exit(1);
	}

	parse_and_add_tests(testname_re);
	if (testname_re)
		free(testname_re);

	CU_basic_set_mode(mode);
	CU_set_error_action(error_action);
	printf("\n");

	/*
	 * this actually runs the tests ...
	 */

	if (xml_mode) {
	  CU_list_tests_to_file();
	  CU_automated_run_tests();
	} else {
	  res = CU_basic_run_tests();
	  printf("Tests completed with return value: %d\n", res);
	}

	CU_cleanup_registry();

	if (inq_task != NULL) {
		scsi_free_scsi_task(inq_task);
	}
	if (inq_bl_task != NULL) {
		scsi_free_scsi_task(inq_bl_task);
	}
	if (inq_lbp_task != NULL) {
		scsi_free_scsi_task(inq_lbp_task);
	}
	if (inq_bdc_task != NULL) {
		scsi_free_scsi_task(inq_bdc_task);
	}
	if (rc16_task != NULL) {
		scsi_free_scsi_task(rc16_task);
	}
	if (rsop_task != NULL) {
		scsi_free_scsi_task(rsop_task);
	}
	for (i = 0; i < mp_num_sds; i++) {
		free_scsi_device(mp_sds[i]);
	}

	return 0;

err_sds_free:
	for (i = 0; i < mp_num_sds; i++) {
		free_scsi_device(mp_sds[i]);
	}
	return -1;
}
Example #3
0
File: main.c Project: Prajna/xnu
int main( int argc, const char * argv[] ) 
{
	#pragma unused(argc)
	#pragma unused(argv)
	int				my_tests_count, i;
	int				err;
	int				my_failures = 0;
	int				list_the_tests = 0;
	const char *	my_targetp;
	time_t			my_start_time, my_end_time;
	struct stat		my_stat_buf;
	char			my_buffer[64];
	/* vars for XILog */
#if !TARGET_OS_EMBEDDED
	XILogRef		logRef;
	char			*logPath = "";
	char			*config = NULL;
	int				echo = 0;
	int				xml = 0;
#endif
	sranddev( );				/* set up seed for our random name generator */
	g_cmd_namep = argv[0];
	
	/* NOTE - code in create_target_directory will append '/' if it is necessary */
	my_targetp = getenv("TMPDIR");
	if ( my_targetp == NULL )
		my_targetp = "/tmp";
	
	/* make sure our executable is owned by root and has set uid bit */
	err = stat( g_cmd_namep, &my_stat_buf );
	if ( err != 0 ) {
		err = errno;
		printf( "stat call on our executable failed -  \"%s\" \n", g_cmd_namep );
		printf( " failed with error %d - \"%s\" \n", err, strerror( err) );
		exit( -1 );
	}
	if ( my_stat_buf.st_uid != 0 || (my_stat_buf.st_mode & S_ISUID) == 0 ) {
		printf( "executable file -  \"%s\" \n", g_cmd_namep );
		printf( "does not have correct owner (must be root) or setuid bit is not set \n" );
		exit( -1 );
	}
	
	/* parse input parameters */
	for ( i = 1; i < argc; i++ ) {
		if ( strcmp( argv[i], "-u" ) == 0 ) {
			usage( );
		}
		if ( strcmp( argv[i], "-t" ) == 0 ||
			 strcmp( argv[i], "-target" ) == 0 ) {
			if ( ++i >= argc ) {
				printf( "invalid target parameter \n" );
				usage( );
			}
			/* verify our target directory exists */
			my_targetp = argv[i];
			err = stat( my_targetp, &my_stat_buf );
			if ( err != 0 || S_ISDIR(my_stat_buf.st_mode) == 0 ) {
				printf( "invalid target path \n" );
				if ( err != 0 ) {
					printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
				}
				usage( );
			}
			continue;
		}
		if ( strcmp( argv[i], "-f" ) == 0 ||
			 strcmp( argv[i], "-failures" ) == 0 ) {
			if ( ++i >= argc ) {
				printf( "invalid failures parameter \n" );
				usage( );
			}

			/* get our max number of failures */
			g_max_failures = strtol( argv[i], NULL, 10 );
			continue;
		}
		if ( strcmp( argv[i], "-l" ) == 0 ||
			 strcmp( argv[i], "-list" ) == 0 ) {
			/* list all the tests this tool will do.
			 */
			list_the_tests = 1;
			continue;
		}
		if ( strcmp( argv[i], "-r" ) == 0 ||
			 strcmp( argv[i], "-run" ) == 0 ) {
			if ( ++i >= argc ) {
				printf( "invalid run tests parameter \n" );
				usage( );
			}

			/* get which tests to run */
			if ( parse_tests_to_run( argc, argv, &i ) != 0 ) {
				printf( "invalid run tests parameter \n" );
				usage( );
			}
			continue;
		}
		if ( strcmp( argv[i], "-s" ) == 0 ||
			 strcmp( argv[i], "-skip" ) == 0 ) {
			/* set that want to skip the setuid related tests - this is useful for debgugging since since I can't  
			 * get setuid tests to work while in gdb.
			 */
			g_skip_setuid_tests = 1;
			continue;
		}
#if !TARGET_OS_EMBEDDED	
		if ( strcmp( argv[i], "-x" ) == 0 ||
			 strcmp( argv[i], "-xilog" ) == 0 ) {
			g_xilog_active = 1;
			continue;
		}
#endif
		printf( "invalid argument \"%s\" \n", argv[i] );
		usage( );
	}

	/* done parsing.
	 */

/* Check if we are running under testbots */
#if RUN_UNDER_TESTBOTS
g_testbots_active = 1;
#endif
	/* Code added to run xnu_quick_test under testbots */
	if ( g_testbots_active == 1 ) {
	printf("[TEST] xnu_quick_test \n");	/* Declare the beginning of test suite */
	}
    
	/* Populate groups list if we're in single user mode */
	if (setgroups_if_single_user()) {
		return 1;
	}
    
	if ( list_the_tests != 0 ) {
		list_all_tests( );
		return 0;
	}
#if !TARGET_OS_EMBEDDED
	if (g_xilog_active == 1) {	
		logRef = XILogOpenLogExtended( logPath, "xnu_quick_test", "com.apple.coreos", 
										config, xml, echo, NULL, "ResultOwner", 
										"com.apple.coreos", NULL );
		if( logRef == NULL )  {
			fprintf(stderr,"Couldn't create log: %s",logPath);
			exit(-1);
		}
	}
#endif
	
	/* build a test target directory that we use as our path to create any test
	 * files and directories.
	 */
	create_target_directory( my_targetp );
	printf( "Will allow %ld failures before testing is aborted \n", g_max_failures );
	
	my_start_time = time( NULL );
	printf( "\nBegin testing - %s \n", ctime_r( &my_start_time, &my_buffer[0] ) );
	printf( "Current architecture is %s\n", current_arch() );

	/* Code added to run xnu_quick_test under testbots */
        if ( g_testbots_active == 1 ) {
        printf("[PASS] xnu_quick_test started\n");     
        }
		
	/* run each test that is marked to run in our table until we complete all of them or
	 * hit the maximum number of failures.
	 */
	my_tests_count = (sizeof( g_tests ) / sizeof( g_tests[0] ));
	for ( i = 0; i < (my_tests_count - 1); i++ ) {
		int				my_err;
		test_entryp		my_testp;

		my_testp = &g_tests[i];
		if ( my_testp->test_run_it == 0 || my_testp->test_routine == NULL )
			continue;
#if !TARGET_OS_EMBEDDED	
		if (g_xilog_active == 1) {	
			XILogBeginTestCase( logRef, my_testp->test_infop, my_testp->test_infop );	
			XILogMsg( "test #%d - %s \n", (i + 1), my_testp->test_infop );
		}
#endif
		printf( "test #%d - %s \n", (i + 1), my_testp->test_infop );
		fflush(stdout);
		my_err = my_testp->test_routine( my_testp->test_input );
		if ( my_err != 0 ) {
			printf("\t--> FAILED \n");
#if !TARGET_OS_EMBEDDED	
			if (g_xilog_active == 1) {	
				XILogMsg("SysCall %s failed", my_testp->test_infop);
				XILogErr("Result %d", my_err);
			}
#endif
			my_failures++;
			if ( my_failures > g_max_failures ) {
#if !TARGET_OS_EMBEDDED	
				if (g_xilog_active == 1) {
					XILogMsg("Reached the maximum number of failures - Aborting xnu_quick_test.");
					XILogEndTestCase( logRef, kXILogTestPassOnErrorLevel );
				}
#endif
				printf( "\n Reached the maximum number of failures - Aborting xnu_quick_test. \n" );
	                        /* Code added to run xnu_quick_test under testbots */
        	                if ( g_testbots_active == 1 ) {
				printf("[FAIL] %s \n", my_testp->test_infop);
				}	
				goto exit_this_routine;
			}
			/* Code added to run xnu_quick_test under testbots */
			if ( g_testbots_active == 1 ) {
				printf("[FAIL] %s \n", my_testp->test_infop);
			}			
#if !TARGET_OS_EMBEDDED	
			if (g_xilog_active == 1) {
				XILogEndTestCase( logRef, kXILogTestPassOnErrorLevel );
			}
#endif
			continue;
		}
#if !TARGET_OS_EMBEDDED	
		if (g_xilog_active == 1) {	
			XILogEndTestCase(logRef, kXILogTestPassOnErrorLevel);
		}
#endif
		/* Code added to run xnu_quick_test under testbots */
		if ( g_testbots_active == 1 ) {
		printf("[PASS] %s \n", my_testp->test_infop);
		}	
	}
	
exit_this_routine:
	my_end_time = time( NULL );
	printf( "\nEnd testing - %s \n", ctime_r( &my_end_time, &my_buffer[0] ) );

	/* clean up our test directory */
	rmdir( &g_target_path[0] );	

#if !TARGET_OS_EMBEDDED	
	if (g_xilog_active == 1) {	
		XILogCloseLog(logRef);
	}
#endif
	
    return 0;
} /* main */
Example #4
0
int main( int argc, const char * argv[] ) 
{
	#pragma unused(argc)
	#pragma unused(argv)
	int				my_tests_count, i;
	int				err;
	int				my_failures = 0;
	int				list_the_tests = 0;
	const char *	my_targetp;
	time_t			my_start_time, my_end_time;
	struct stat		my_stat_buf;
	char			my_buffer[64];
	uid_t		sudo_uid = 0;
	const char *	sudo_uid_env;
	gid_t		sudo_gid;
	const char *	sudo_gid_env;
	sranddev( );				/* set up seed for our random name generator */
	g_cmd_namep = argv[0];

	/* make sure SIGCHLD is not ignored, so wait4 calls work */
	signal(SIGCHLD, SIG_DFL);

	/* NOTE - code in create_target_directory will append '/' if it is necessary */
	my_targetp = getenv("TMPDIR");
	if ( my_targetp == NULL )
		my_targetp = "/tmp";
	
	/* make sure we are running as root */
	if ( ( getuid() != 0 ) || ( geteuid() != 0 ) ) {
		printf( "Test must be run as root\n", g_cmd_namep );
		exit( -1 );
	}

	sudo_uid_env = getenv("SUDO_UID");
	if ( sudo_uid_env ) {
		sudo_uid = strtol(sudo_uid_env, NULL, 10);
	}

	/* switch real uid to a non_root user, while keeping effective uid as root */
	if ( sudo_uid != 0 ) {
		setreuid( sudo_uid, 0 );
	}
	else {
		/* Default to 501 if no sudo uid found */
		setreuid( 501, 0 );
	}

	/* restore the gid if run through sudo */
	sudo_gid_env = getenv("SUDO_GID");
	if ( sudo_gid_env ) {
		sudo_gid = strtol(sudo_gid_env, NULL, 10);
	}
	
	if ( getgid() == 0 ) {

		if ( sudo_gid != 0 ) {
			setgid( sudo_gid );
		}
		else {
			/* Default to 20 if no sudo gid found */
			setgid( 20 );
		}
	}

	/* parse input parameters */
	for ( i = 1; i < argc; i++ ) {
		if ( strcmp( argv[i], "-u" ) == 0 ) {
			usage( );
		}
		if ( strcmp( argv[i], "-t" ) == 0 ||
			 strcmp( argv[i], "-target" ) == 0 ) {
			if ( ++i >= argc ) {
				printf( "invalid target parameter \n" );
				usage( );
			}
			/* verify our target directory exists */
			my_targetp = argv[i];
			err = stat( my_targetp, &my_stat_buf );
			if ( err != 0 || S_ISDIR(my_stat_buf.st_mode) == 0 ) {
				printf( "invalid target path \n" );
				if ( err != 0 ) {
					printf( "stat call failed with error %d - \"%s\" \n", errno, strerror( errno) );
				}
				usage( );
			}
			continue;
		}
		if ( strcmp( argv[i], "-f" ) == 0 ||
			 strcmp( argv[i], "-failures" ) == 0 ) {
			if ( ++i >= argc ) {
				printf( "invalid failures parameter \n" );
				usage( );
			}

			/* get our max number of failures */
			g_max_failures = strtol( argv[i], NULL, 10 );
			continue;
		}
		if ( strcmp( argv[i], "-l" ) == 0 ||
			 strcmp( argv[i], "-list" ) == 0 ) {
			/* list all the tests this tool will do.
			 */
			list_the_tests = 1;
			continue;
		}
		if ( strcmp( argv[i], "-r" ) == 0 ||
			 strcmp( argv[i], "-run" ) == 0 ) {
			if ( ++i >= argc ) {
				printf( "invalid run tests parameter \n" );
				usage( );
			}

			/* get which tests to run */
			if ( parse_tests_to_run( argc, argv, &i ) != 0 ) {
				printf( "invalid run tests parameter \n" );
				usage( );
			}
			continue;
		}
		if ( strcmp( argv[i], "-s" ) == 0 ||
			 strcmp( argv[i], "-skip" ) == 0 ) {
			/* set that want to skip the setuid related tests - this is useful for debgugging since since I can't  
			 * get setuid tests to work while in gdb.
			 */
			g_skip_setuid_tests = 1;
			continue;
		}
		if ( strcmp( argv[i], "-testbot" ) == 0 ) {
			g_testbots_active = 1;
			continue;
		}
		printf( "invalid argument \"%s\" \n", argv[i] );
		usage( );
	}

	/* done parsing.
	 */

/* Check if we are running under testbots */
#if RUN_UNDER_TESTBOTS
g_testbots_active = 1;
#endif
	/* Code added to run xnu_quick_test under testbots */
	if ( g_testbots_active == 1 ) {
		printf("[TEST] xnu_quick_test \n");	/* Declare the beginning of test suite */
	}

	/* Populate groups list if we're in single user mode */
	if (setgroups_if_single_user()) {
		return 1;
	}
	if ( list_the_tests != 0 ) {
		list_all_tests( );
		return 0;
	}
	
	/* build a test target directory that we use as our path to create any test
	 * files and directories.
	 */
	create_target_directory( my_targetp );
	printf( "Will allow %ld failures before testing is aborted \n", g_max_failures );
	
	my_start_time = time( NULL );
	printf( "\nBegin testing - %s \n", ctime_r( &my_start_time, &my_buffer[0] ) );
	printf( "Current architecture is %s\n", current_arch() );

	/* Code added to run xnu_quick_test under testbots */
		
	/* run each test that is marked to run in our table until we complete all of them or
	 * hit the maximum number of failures.
	 */
	my_tests_count = (sizeof( g_tests ) / sizeof( g_tests[0] ));
	for ( i = 0; i < (my_tests_count - 1); i++ ) {
		int				my_err;
		test_entryp		my_testp;

		my_testp = &g_tests[i];
		if ( my_testp->test_run_it == 0 || my_testp->test_routine == NULL )
			continue;

		if ( g_testbots_active == 1 ) {
			printf("[BEGIN] %s \n", my_testp->test_infop);
		}

		printf( "test #%d - %s \n", (i + 1), my_testp->test_infop );
		fflush(stdout);
		my_err = my_testp->test_routine( my_testp->test_input );
		if ( my_err != 0 ) {
			printf("\t--> FAILED \n");
			printf("SysCall %s failed", my_testp->test_infop);
			printf("Result %d", my_err);
			my_failures++;
			if ( my_failures > g_max_failures ) {
				printf( "\n Reached the maximum number of failures - Aborting xnu_quick_test. \n" );
	                        /* Code added to run xnu_quick_test under testbots */
        	                if ( g_testbots_active == 1 ) {
					printf("[FAIL] %s \n", my_testp->test_infop);
				}	
				goto exit_this_routine;
			}
			/* Code added to run xnu_quick_test under testbots */
			if ( g_testbots_active == 1 ) {
				printf("\n[FAIL] %s \n", my_testp->test_infop);
			}			
			continue;
		}
		/* Code added to run xnu_quick_test under testbots */
		if ( g_testbots_active == 1 ) {
			printf("[PASS] %s \n", my_testp->test_infop);
		}	
	}
	
exit_this_routine:
	my_end_time = time( NULL );
	printf( "\nEnd testing - %s \n", ctime_r( &my_end_time, &my_buffer[0] ) );

	/* clean up our test directory */
	rmdir( &g_target_path[0] );	

	/* exit non zero if there are any failures */
	return my_failures != 0;
} /* main */