diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2015-05-12 04:21:05 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2015-05-12 04:21:05 +0000 |
commit | 77c837a07783a4e63b7f4a85852f55a112b994e0 (patch) | |
tree | 59ea0b252047bccea1e04c5ceeed3ccec04465c5 /lib/sg_cmds_basic.c | |
parent | f54b2fbd8e1cc79cf1bafe9516a4771f88be29a7 (diff) | |
download | sg3_utils-77c837a07783a4e63b7f4a85852f55a112b994e0.tar.gz |
sg_lib: Linux: ENXIO errno --> SG_LIB_CAT_NOT_READY; asc/ascq codes --> T10 20150423
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@644 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib/sg_cmds_basic.c')
-rw-r--r-- | lib/sg_cmds_basic.c | 148 |
1 files changed, 89 insertions, 59 deletions
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c index b42d8969..89fe3ffc 100644 --- a/lib/sg_cmds_basic.c +++ b/lib/sg_cmds_basic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2014 Douglas Gilbert. + * Copyright (c) 1999-2015 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. @@ -16,6 +16,7 @@ #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> #include <string.h> #include <unistd.h> #include "sg_lib.h" @@ -26,8 +27,13 @@ #include "config.h" #endif +/* Needs to be after config.h */ +#ifdef SG_LIB_LINUX +#include <errno.h> +#endif + -static const char * version_str = "1.69 20141006"; +static const char * version_str = "1.70 20150511"; #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ @@ -55,11 +61,37 @@ sg_cmds_version() return version_str; } +#ifdef __GNUC__ +static int pr2ws(const char * fmt, ...) + __attribute__ ((format (printf, 1, 2))); +#else +static int pr2ws(const char * fmt, ...); +#endif + + +static int +pr2ws(const char * fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vfprintf(sg_warnings_strm ? sg_warnings_strm : stderr, fmt, args); + va_end(args); + return n; +} + /* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. */ int sg_cmds_open_device(const char * device_name, int 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); } @@ -114,12 +146,12 @@ sg_cmds_process_helper(const char * leadin, int mx_di_len, int resid, if (verbose || n) { sg_get_sense_str(leadin, sbp, slen, (verbose > 1), sizeof(b), b); - fprintf(sg_warnings_strm, "%s", b); + pr2ws("%s", b); if ((mx_di_len > 0) && (resid > 0)) { got = mx_di_len - resid; if ((verbose > 2) || check_data_in || (got > 0)) - fprintf(sg_warnings_strm, " pass-through requested %d " - "bytes (data-in) but got %d bytes\n", mx_di_len, got); + pr2ws(" pass-through requested %d bytes (data-in) but " + "got %d bytes\n", mx_di_len, got); } } if (o_sense_cat) @@ -146,24 +178,36 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, int got, cat, duration, slen, resid, resp_code, sstat; char b[1024]; - if (NULL == sg_warnings_strm) - sg_warnings_strm = stderr; if (NULL == leadin) leadin = ""; if (pt_res < 0) { +#ifdef SG_LIB_LINUX + if (verbose) + pr2ws("%s: pass through os error: %s\n", leadin, + safe_strerror(-pt_res)); + if ((-ENXIO == pt_res) && o_sense_cat) { + if (verbose > 2) + pr2ws("map ENXIO to SG_LIB_CAT_NOT_READY\n"); + *o_sense_cat = SG_LIB_CAT_NOT_READY; + return -2; + } else if (noisy && (0 == verbose)) + pr2ws("%s: pass through os error: %s\n", leadin, + safe_strerror(-pt_res)); +#else if (noisy || verbose) - fprintf(sg_warnings_strm, "%s: pass through os error: %s\n", - leadin, safe_strerror(-pt_res)); + pr2ws("%s: pass through os error: %s\n", leadin, + safe_strerror(-pt_res)); +#endif return -1; } else if (SCSI_PT_DO_BAD_PARAMS == pt_res) { - fprintf(sg_warnings_strm, "%s: bad pass through setup\n", leadin); + pr2ws("%s: bad pass through setup\n", leadin); return -1; } else if (SCSI_PT_DO_TIMEOUT == pt_res) { - fprintf(sg_warnings_strm, "%s: pass through timeout\n", leadin); + pr2ws("%s: pass through timeout\n", leadin); return -1; } if ((verbose > 2) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0)) - fprintf(sg_warnings_strm, " duration=%d ms\n", duration); + pr2ws(" duration=%d ms\n", duration); resid = (mx_di_len > 0) ? get_scsi_pt_resid(ptvp) : 0; slen = get_scsi_pt_sense_len(ptvp); switch ((cat = get_scsi_pt_result_category(ptvp))) { @@ -184,9 +228,8 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, if (mx_di_len > 0) { got = mx_di_len - resid; if ((verbose > 1) && (resid > 0)) - fprintf(sg_warnings_strm, " %s: pass-through requested " - "%d bytes (data-in) but got %d bytes\n", leadin, - mx_di_len, got); + pr2ws(" %s: pass-through requested %d bytes (data-in) " + "but got %d bytes\n", leadin, mx_di_len, got); return got; } else return 0; @@ -199,7 +242,7 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, } if (verbose || noisy) { sg_get_scsi_status_str(sstat, sizeof(b), b); - fprintf(sg_warnings_strm, "%s: scsi status: %s\n", leadin, b); + pr2ws("%s: scsi status: %s\n", leadin, b); } return -1; case SCSI_PT_RESULT_SENSE: @@ -208,7 +251,7 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, case SCSI_PT_RESULT_TRANSPORT_ERR: if (verbose || noisy) { get_scsi_pt_transport_err_str(ptvp, sizeof(b), b); - fprintf(sg_warnings_strm, "%s: transport: %s\n", leadin, b); + pr2ws("%s: transport: %s\n", leadin, b); } if ((SAM_STAT_CHECK_CONDITION == get_scsi_pt_status_response(ptvp)) && (slen > 0)) @@ -219,12 +262,11 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, case SCSI_PT_RESULT_OS_ERR: if (verbose || noisy) { get_scsi_pt_os_err_str(ptvp, sizeof(b), b); - fprintf(sg_warnings_strm, "%s: os: %s\n", leadin, b); + pr2ws("%s: os: %s\n", leadin, b); } return -1; default: - fprintf(sg_warnings_strm, "%s: unknown pass through result " - "category (%d)\n", leadin, cat); + pr2ws("%s: unknown pass through result category (%d)\n", leadin, cat); return -1; } } @@ -249,13 +291,11 @@ sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp, /* 16 bit allocation length (was 8) is a recent SPC-3 addition */ inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); inqCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff); - if (NULL == sg_warnings_strm) - sg_warnings_strm = stderr; if (verbose) { - fprintf(sg_warnings_strm, " inquiry cdb: "); + pr2ws(" inquiry cdb: "); for (k = 0; k < INQUIRY_CMDLEN; ++k) - fprintf(sg_warnings_strm, "%02x ", inqCmdBlk[k]); - fprintf(sg_warnings_strm, "\n"); + pr2ws("%02x ", inqCmdBlk[k]); + pr2ws("\n"); } if (resp && (mx_resp_len > 0)) { up = (unsigned char *)resp; @@ -265,7 +305,7 @@ sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp, } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { - fprintf(sg_warnings_strm, "inquiry: out of memory\n"); + pr2ws("inquiry: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, inqCmdBlk, sizeof(inqCmdBlk)); @@ -290,16 +330,15 @@ sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp, } } else if (ret < 4) { if (verbose) - fprintf(sg_warnings_strm, "inquiry: got too few " - "bytes (%d)\n", ret); + pr2ws("inquiry: got too few bytes (%d)\n", ret); ret = SG_LIB_CAT_MALFORMED; } else ret = 0; if (resid > 0) { if (resid > mx_resp_len) { - fprintf(sg_warnings_strm, "inquiry: resid (%d) should never " - "exceed requested len=%d\n", resid, mx_resp_len); + pr2ws("inquiry: resid (%d) should never exceed requested " + "len=%d\n", resid, mx_resp_len); return ret ? ret : SG_LIB_CAT_MALFORMED; } /* zero unfilled section of response buffer */ @@ -327,19 +366,17 @@ sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data, inq_data->peripheral_type = 0x1f; } inqCmdBlk[4] = (unsigned char)sizeof(inq_resp); - if (NULL == sg_warnings_strm) - sg_warnings_strm = stderr; if (verbose) { - fprintf(sg_warnings_strm, " inquiry cdb: "); + pr2ws(" inquiry cdb: "); for (k = 0; k < INQUIRY_CMDLEN; ++k) - fprintf(sg_warnings_strm, "%02x ", inqCmdBlk[k]); - fprintf(sg_warnings_strm, "\n"); + pr2ws("%02x ", inqCmdBlk[k]); + pr2ws("\n"); } memset(inq_resp, 0, sizeof(inq_resp)); inq_resp[0] = 0x7f; /* defensive prefill */ ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { - fprintf(sg_warnings_strm, "inquiry: out of memory\n"); + pr2ws("inquiry: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, inqCmdBlk, sizeof(inqCmdBlk)); @@ -362,8 +399,7 @@ sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data, } } else if (ret < 4) { if (verbose) - fprintf(sg_warnings_strm, "inquiry: got too few " - "bytes (%d)\n", ret); + pr2ws("inquiry: got too few bytes (%d)\n", ret); ret = SG_LIB_CAT_MALFORMED; } else ret = 0; @@ -400,18 +436,16 @@ sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress, unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; - if (NULL == sg_warnings_strm) - sg_warnings_strm = stderr; if (verbose) { - fprintf(sg_warnings_strm, " test unit ready cdb: "); + pr2ws(" test unit ready cdb: "); for (k = 0; k < TUR_CMDLEN; ++k) - fprintf(sg_warnings_strm, "%02x ", turCmdBlk[k]); - fprintf(sg_warnings_strm, "\n"); + pr2ws("%02x ", turCmdBlk[k]); + pr2ws("\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { - fprintf(sg_warnings_strm, "test unit ready: out of memory\n"); + pr2ws("test unit ready: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, turCmdBlk, sizeof(turCmdBlk)); @@ -470,23 +504,21 @@ sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len, if (desc) rsCmdBlk[1] |= 0x1; - if (NULL == sg_warnings_strm) - sg_warnings_strm = stderr; if (mx_resp_len > 0xff) { - fprintf(sg_warnings_strm, "mx_resp_len cannot exceed 255\n"); + pr2ws("mx_resp_len cannot exceed 255\n"); return -1; } rsCmdBlk[4] = mx_resp_len & 0xff; if (verbose) { - fprintf(sg_warnings_strm, " Request Sense cmd: "); + pr2ws(" Request Sense cmd: "); for (k = 0; k < REQUEST_SENSE_CMDLEN; ++k) - fprintf(sg_warnings_strm, "%02x ", rsCmdBlk[k]); - fprintf(sg_warnings_strm, "\n"); + pr2ws("%02x ", rsCmdBlk[k]); + pr2ws("\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { - fprintf(sg_warnings_strm, "request sense: out of memory\n"); + pr2ws("request sense: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rsCmdBlk, sizeof(rsCmdBlk)); @@ -510,8 +542,8 @@ sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len, } else { if ((mx_resp_len >= 8) && (ret < 8)) { if (verbose) - fprintf(sg_warnings_strm, " request sense: got %d " - "bytes in response, too short\n", ret); + pr2ws(" request sense: got %d bytes in response, too " + "short\n", ret); ret = -1; } else ret = 0; @@ -537,18 +569,16 @@ sg_ll_report_luns(int sg_fd, int select_report, void * resp, int mx_resp_len, rlCmdBlk[7] = (mx_resp_len >> 16) & 0xff; rlCmdBlk[8] = (mx_resp_len >> 8) & 0xff; rlCmdBlk[9] = mx_resp_len & 0xff; - if (NULL == sg_warnings_strm) - sg_warnings_strm = stderr; if (verbose) { - fprintf(sg_warnings_strm, " report luns cdb: "); + pr2ws(" report luns cdb: "); for (k = 0; k < REPORT_LUNS_CMDLEN; ++k) - fprintf(sg_warnings_strm, "%02x ", rlCmdBlk[k]); - fprintf(sg_warnings_strm, "\n"); + pr2ws("%02x ", rlCmdBlk[k]); + pr2ws("\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { - fprintf(sg_warnings_strm, "report luns: out of memory\n"); + pr2ws("report luns: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rlCmdBlk, sizeof(rlCmdBlk)); |