/* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. */ int sg_cmds_open_device(const char * device_name, bool read_only, int verbose) { /* The following 2 lines are temporary. It is to avoid a NULL pointer * crash when an old utility is used with a newer library built after * the sg_warnings_strm cleanup */ if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; return scsi_pt_open_device(device_name, read_only, verbose); }
/* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. */ int sg_cmds_open_device(const char * device_name, bool read_only, int verbose) { return scsi_pt_open_device(device_name, read_only, verbose); }
int main(int argc, char * argv[]) { int sg_fd, k, ok, dsize, res, duration, resid, cat, got, slen; unsigned char inq_cdb [INQ_CMD_LEN] = {0x12, 0, 0, 0, INQ_REPLY_LEN, 0}; unsigned char tur_cdb [TUR_CMD_LEN] = {0x00, 0, 0, 0, 0, 0}; unsigned char inqBuff[INQ_REPLY_LEN]; char * file_name = 0; char b[512]; unsigned char sense_b[32]; int verbose = 0; struct sg_pt_base * ptvp; for (k = 1; k < argc; ++k) { if (0 == strcmp("-v", argv[k])) verbose = 1; else if (0 == strcmp("-vv", argv[k])) verbose = 2; else if (0 == strcmp("-vvv", argv[k])) verbose = 3; else if (*argv[k] == '-') { printf("Unrecognized switch: %s\n", argv[k]); file_name = 0; break; } else if (0 == file_name) file_name = argv[k]; else { printf("too many arguments\n"); file_name = 0; break; } } if (0 == file_name) { printf("Usage: 'sg_simple5 [-v|-vv|-vvv] <device>'\n"); return 1; } sg_fd = scsi_pt_open_device(file_name, 1 /* ro */, 0); /* N.B. An access mode of O_RDWR is required for some SCSI commands */ if (sg_fd < 0) { fprintf(stderr, "error opening file: %s: %s\n", file_name, safe_strerror(-sg_fd)); return 1; } dsize = sizeof(inqBuff); ok = 0; ptvp = construct_scsi_pt_obj(); /* one object per command */ if (NULL == ptvp) { fprintf(stderr, "sg_simple5: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, inqBuff, dsize); res = do_scsi_pt(ptvp, sg_fd, CMD_TIMEOUT_SECS, verbose); if (res < 0) { fprintf(stderr, " pass through os error: %s\n", safe_strerror(-res)); goto finish_inq; } else if (SCSI_PT_DO_BAD_PARAMS == res) { fprintf(stderr, " bad pass through setup\n"); goto finish_inq; } else if (SCSI_PT_DO_TIMEOUT == res) { fprintf(stderr, " pass through timeout\n"); goto finish_inq; } if ((verbose > 1) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0)) fprintf(stderr, " duration=%d ms\n", duration); resid = get_scsi_pt_resid(ptvp); switch ((cat = get_scsi_pt_result_category(ptvp))) { case SCSI_PT_RESULT_GOOD: got = dsize - resid; if (verbose && (resid > 0)) fprintf(stderr, " requested %d bytes but " "got %d bytes)\n", dsize, got); break; case SCSI_PT_RESULT_STATUS: /* other than GOOD and CHECK CONDITION */ if (verbose) { sg_get_scsi_status_str(get_scsi_pt_status_response(ptvp), sizeof(b), b); fprintf(stderr, " scsi status: %s\n", b); } goto finish_inq; case SCSI_PT_RESULT_SENSE: slen = get_scsi_pt_sense_len(ptvp); if (verbose) { sg_get_sense_str("", sense_b, slen, (verbose > 1), sizeof(b), b); fprintf(stderr, "%s", b); } if (verbose && (resid > 0)) { got = dsize - resid; if ((verbose) || (got > 0)) fprintf(stderr, " requested %d bytes but " "got %d bytes\n", dsize, got); } goto finish_inq; case SCSI_PT_RESULT_TRANSPORT_ERR: if (verbose) { get_scsi_pt_transport_err_str(ptvp, sizeof(b), b); fprintf(stderr, " transport: %s", b); } goto finish_inq; case SCSI_PT_RESULT_OS_ERR: if (verbose) { get_scsi_pt_os_err_str(ptvp, sizeof(b), b); fprintf(stderr, " os: %s", b); } goto finish_inq; default: fprintf(stderr, " unknown pass through result " "category (%d)\n", cat); goto finish_inq; } ok = 1; finish_inq: destruct_scsi_pt_obj(ptvp); if (ok) { /* output result if it is available */ char * p = (char *)inqBuff; printf("Some of the INQUIRY command's results:\n"); printf(" %.8s %.16s %.4s\n", p + 8, p + 16, p + 32); } ok = 0; /* Now prepare TEST UNIT READY command */ ptvp = construct_scsi_pt_obj(); /* one object per command */ if (NULL == ptvp) { fprintf(stderr, "sg_simple5: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, tur_cdb, sizeof(tur_cdb)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); /* no data in or out */ res = do_scsi_pt(ptvp, sg_fd, CMD_TIMEOUT_SECS, verbose); if (res < 0) { fprintf(stderr, " pass through os error: %s\n", safe_strerror(-res)); goto finish_inq; } else if (SCSI_PT_DO_BAD_PARAMS == res) { fprintf(stderr, " bad pass through setup\n"); goto finish_inq; } else if (SCSI_PT_DO_TIMEOUT == res) { fprintf(stderr, " pass through timeout\n"); goto finish_inq; } if ((verbose > 1) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0)) fprintf(stderr, " duration=%d ms\n", duration); resid = get_scsi_pt_resid(ptvp); switch ((cat = get_scsi_pt_result_category(ptvp))) { case SCSI_PT_RESULT_GOOD: break; case SCSI_PT_RESULT_STATUS: /* other than GOOD and CHECK CONDITION */ if (verbose) { sg_get_scsi_status_str(get_scsi_pt_status_response(ptvp), sizeof(b), b); fprintf(stderr, " scsi status: %s\n", b); } goto finish_tur; case SCSI_PT_RESULT_SENSE: slen = get_scsi_pt_sense_len(ptvp); if (verbose) { sg_get_sense_str("", sense_b, slen, (verbose > 1), sizeof(b), b); fprintf(stderr, "%s", b); } goto finish_tur; case SCSI_PT_RESULT_TRANSPORT_ERR: if (verbose) { get_scsi_pt_transport_err_str(ptvp, sizeof(b), b); fprintf(stderr, " transport: %s", b); } goto finish_tur; case SCSI_PT_RESULT_OS_ERR: if (verbose) { get_scsi_pt_os_err_str(ptvp, sizeof(b), b); fprintf(stderr, " os: %s", b); } goto finish_tur; default: fprintf(stderr, " unknown pass through result " "category (%d)\n", cat); goto finish_tur; } ok = 1; finish_tur: destruct_scsi_pt_obj(ptvp); if (ok) printf("Test Unit Ready successful so unit is ready!\n"); else printf("Test Unit Ready failed so unit may _not_ be ready!\n"); scsi_pt_close_device(sg_fd); return 0; }
int main(int argc, char *argv[]) { int ret = 0; int res_cat, status, slen, k, ret2; int sg_fd = -1; struct sg_pt_base *ptvp = NULL; unsigned char sense_buffer[32]; unsigned char * dxfer_buffer_in = NULL; unsigned char * dxfer_buffer_out = NULL; unsigned char *wrkBuf = NULL; struct opts_t opts; struct opts_t * op; char b[128]; op = &opts; memset(op, 0, sizeof(opts)); op->timeout = DEFAULT_TIMEOUT; ret = process_cl(op, argc, argv); if (ret != 0) { usage(); goto done; } else if (op->do_help) { usage(); goto done; } else if (op->do_version) { version(); goto done; } sg_fd = scsi_pt_open_device(op->device_name, op->readonly, op->do_verbose); if (sg_fd < 0) { fprintf(stderr, "%s: %s\n", op->device_name, safe_strerror(-sg_fd)); ret = SG_LIB_FILE_ERROR; goto done; } ptvp = construct_scsi_pt_obj(); if (ptvp == NULL) { fprintf(stderr, "out of memory\n"); ret = SG_LIB_CAT_OTHER; goto done; } if (op->do_verbose) { fprintf(stderr, " cdb to send: "); for (k = 0; k < op->cdb_length; ++k) fprintf(stderr, "%02x ", op->cdb[k]); fprintf(stderr, "\n"); if (op->do_verbose > 2) { sg_get_command_name(op->cdb, 0, sizeof(b) - 1, b); b[sizeof(b) - 1] = '\0'; fprintf(stderr, " Command name: %s\n", b); } } set_scsi_pt_cdb(ptvp, op->cdb, op->cdb_length); set_scsi_pt_sense(ptvp, sense_buffer, sizeof(sense_buffer)); if (op->do_dataout) { dxfer_buffer_out = fetch_dataout(op); if (dxfer_buffer_out == NULL) { ret = SG_LIB_CAT_OTHER; goto done; } set_scsi_pt_data_out(ptvp, dxfer_buffer_out, op->dataout_len); } if (op->do_datain) { dxfer_buffer_in = my_memalign(op->datain_len, &wrkBuf); if (dxfer_buffer_in == NULL) { perror("malloc"); ret = SG_LIB_CAT_OTHER; goto done; } set_scsi_pt_data_in(ptvp, dxfer_buffer_in, op->datain_len); } ret = do_scsi_pt(ptvp, sg_fd, op->timeout, op->do_verbose); if (ret > 0) { if (SCSI_PT_DO_BAD_PARAMS == ret) { fprintf(stderr, "do_scsi_pt: bad pass through setup\n"); ret = SG_LIB_CAT_OTHER; } else if (SCSI_PT_DO_TIMEOUT == ret) { fprintf(stderr, "do_scsi_pt: timeout\n"); ret = SG_LIB_CAT_TIMEOUT; } else ret = SG_LIB_CAT_OTHER; goto done; } else if (ret < 0) { fprintf(stderr, "do_scsi_pt: %s\n", safe_strerror(-ret)); ret = SG_LIB_CAT_OTHER; goto done; } slen = 0; res_cat = get_scsi_pt_result_category(ptvp); switch (res_cat) { case SCSI_PT_RESULT_GOOD: ret = 0; break; case SCSI_PT_RESULT_SENSE: slen = get_scsi_pt_sense_len(ptvp); ret = sg_err_category_sense(sense_buffer, slen); break; case SCSI_PT_RESULT_TRANSPORT_ERR: get_scsi_pt_transport_err_str(ptvp, sizeof(b), b); fprintf(stderr, ">>> transport error: %s\n", b); ret = SG_LIB_CAT_OTHER; break; case SCSI_PT_RESULT_OS_ERR: get_scsi_pt_os_err_str(ptvp, sizeof(b), b); fprintf(stderr, ">>> os error: %s\n", b); ret = SG_LIB_CAT_OTHER; break; default: fprintf(stderr, ">>> unknown pass through result category (%d)\n", res_cat); ret = SG_LIB_CAT_OTHER; break; } status = get_scsi_pt_status_response(ptvp); fprintf(stderr, "SCSI Status: "); sg_print_scsi_status(status); fprintf(stderr, "\n\n"); if ((SAM_STAT_CHECK_CONDITION == status) && (! op->no_sense)) { if (SCSI_PT_RESULT_SENSE != res_cat) slen = get_scsi_pt_sense_len(ptvp); if (0 == slen) fprintf(stderr, ">>> Strange: status is CHECK CONDITION but no " "Sense Information\n"); else { fprintf(stderr, "Sense Information:\n"); sg_print_sense(NULL, sense_buffer, slen, (op->do_verbose > 0)); fprintf(stderr, "\n"); } } if (SAM_STAT_RESERVATION_CONFLICT == status) ret = SG_LIB_CAT_RES_CONFLICT; if (op->do_datain) { int data_len = op->datain_len - get_scsi_pt_resid(ptvp); if (ret && !(SG_LIB_CAT_RECOVERED == ret || SG_LIB_CAT_NO_SENSE == ret)) fprintf(stderr, "Error %d occurred, no data received\n", ret); else if (data_len == 0) { fprintf(stderr, "No data received\n"); } else { if (op->datain_file == NULL && !op->datain_binary) { fprintf(stderr, "Received %d bytes of data:\n", data_len); dStrHexErr((const char *)dxfer_buffer_in, data_len, 0); } else { const char * cp = "stdout"; if (op->datain_file && ! ((1 == strlen(op->datain_file)) && ('-' == op->datain_file[0]))) cp = op->datain_file; fprintf(stderr, "Writing %d bytes of data to %s\n", data_len, cp); ret2 = write_dataout(op->datain_file, dxfer_buffer_in, data_len); if (0 != ret2) { if (0 == ret) ret = ret2; goto done; } } } } done: if (op->do_verbose) { sg_get_category_sense_str(ret, sizeof(b), b, op->do_verbose - 1); fprintf(stderr, "%s\n", b); } if (wrkBuf) free(wrkBuf); if (ptvp) destruct_scsi_pt_obj(ptvp); if (sg_fd >= 0) scsi_pt_close_device(sg_fd); return ret; }