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; }
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; }
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 */
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 */