static void usage_for(const struct opts_t * optsp) { if (optsp->opt_new) usage(); else usage_old(); }
/* Processes command line options according to old option format. Returns * 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) { int k, jmp_out, plen, num, n; unsigned int u, uu; const char * cp; for (k = 1; k < argc; ++k) { cp = argv[k]; plen = strlen(cp); if (plen <= 0) continue; if ('-' == *cp) { for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) { switch (*cp) { case '6': ++optsp->do_six; break; case 'a': ++optsp->do_all; break; case 'A': optsp->do_all += 2; break; case 'd': ++optsp->do_dbd; break; case 'D': ++optsp->do_dbout; break; case 'e': ++optsp->do_examine; break; case 'f': ++optsp->do_flexible; break; case 'h': case 'H': optsp->do_hex += 2; break; case 'l': ++optsp->do_list; break; case 'L': ++optsp->do_llbaa; break; case 'N': optsp->opt_new = 1; return 0; case 'O': break; case 'r': optsp->do_raw += 2; break; case 'v': ++optsp->do_verbose; break; case 'V': ++optsp->do_version; break; case '?': ++optsp->do_help; break; default: jmp_out = 1; break; } if (jmp_out) break; } if (plen <= 0) continue; if (0 == strncmp("c=", cp, 2)) { num = sscanf(cp + 2, "%x", &u); if ((1 != num) || (u > 3)) { fprintf(stderr, "Bad page control after 'c=' option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } optsp->page_control = u; } else if (0 == strncmp("m=", cp, 2)) { num = sscanf(cp + 2, "%d", &n); if ((1 != num) || (n < 0) || (n > 65535)) { fprintf(stderr, "Bad argument after 'm=' option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } optsp->maxlen = n; } else if (0 == strncmp("p=", cp, 2)) { if (NULL == strchr(cp + 2, ',')) { num = sscanf(cp + 2, "%x", &u); if ((1 != num) || (u > 63)) { fprintf(stderr, "Bad page code value after 'p=' " "option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } optsp->pg_code = u; } else if (2 == sscanf(cp + 2, "%x,%x", &u, &uu)) { if (uu > 255) { fprintf(stderr, "Bad sub page code value after 'p=' " "option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } optsp->pg_code = u; optsp->subpg_code = uu; optsp->subpg_code_set = 1; } else { fprintf(stderr, "Bad page code, subpage code sequence " "after 'p=' option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strncmp("subp=", cp, 5)) { num = sscanf(cp + 5, "%x", &u); if ((1 != num) || (u > 255)) { fprintf(stderr, "Bad sub page code after 'subp=' " "option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } optsp->subpg_code = u; optsp->subpg_code_set = 1; if (-1 == optsp->pg_code) optsp->pg_code = 0; } else if (0 == strncmp("-old", cp, 4)) ; else if (jmp_out) { fprintf(stderr, "Unrecognized option: %s\n", cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == optsp->device_name) optsp->device_name = cp; else { fprintf(stderr, "too many arguments, got: %s, not expecting: " "%s\n", optsp->device_name, cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } return 0; }
int main(int argc, char * argv[]) { int sg_fd, k, num, rsp_len, res; unsigned char rsp_buff[MX_ALLOC_LEN]; int rsp_buff_size = MX_ALLOC_LEN; int read_in_len = 0; const char * cp; unsigned char read_in[MX_ALLOC_LEN]; int ret = 0; struct opts_t opts; memset(&opts, 0, sizeof(opts)); res = process_cl(&opts, argc, argv); if (res) return SG_LIB_SYNTAX_ERROR; if (opts.do_help) { if (opts.opt_new) usage(); else usage_old(); return 0; } if (opts.do_version) { fprintf(stderr, "Version string: %s\n", version_str); return 0; } if (NULL == opts.device_name) { fprintf(stderr, "No DEVICE argument given\n"); if (opts.opt_new) usage(); else usage_old(); return SG_LIB_SYNTAX_ERROR; } if (opts.do_raw) { if (build_diag_page(opts.raw_arg, read_in, &read_in_len, sizeof(read_in))) { if (opts.opt_new) { printf("Bad sequence after '--raw=' option\n"); usage(); } else { printf("Bad sequence after '-raw=' option\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } } if ((opts.do_doff || opts.do_uoff) && (! opts.do_deftest)) { if (opts.opt_new) { printf("setting --doff or --uoff only useful when -t is set\n"); usage(); } else { printf("setting -doff or -uoff only useful when -t is set\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } if ((opts.do_selftest > 0) && opts.do_deftest) { if (opts.opt_new) { printf("either set --selftest=SF or --test (not both)\n"); usage(); } else { printf("either set -s=SF or -t (not both)\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } if (opts.do_raw) { if ((opts.do_selftest > 0) || opts.do_deftest || opts.do_extdur || opts.do_list) { if (opts.opt_new) { printf("'--raw=' cannot be used with self-tests, '-e' or " "'-l'\n"); usage(); } else { printf("'-raw=' cannot be used with self-tests, '-e' or " "'-l'\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } if (! opts.do_pf) { if (opts.opt_new) printf(">>> warning, '--pf' probably should be used with " "'--raw='\n"); else printf(">>> warning, '-pf' probably should be used with " "'-raw='\n"); } } if (NULL == opts.device_name) { if (opts.do_list) { list_page_codes(); return 0; } fprintf(stderr, "No DEVICE argument given\n"); if (opts.opt_new) usage(); else usage_old(); return SG_LIB_SYNTAX_ERROR; } if ((sg_fd = sg_cmds_open_device(opts.device_name, 0 /* rw */, opts.do_verbose)) < 0) { fprintf(stderr, ME "error opening file: %s: %s\n", opts.device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } if (opts.do_extdur) { res = do_modes_0a(sg_fd, rsp_buff, 32, 1, 0, opts.do_verbose); if (0 == res) { /* Assume mode sense(10) response without block descriptors */ num = (rsp_buff[0] << 8) + rsp_buff[1] - 6; if (num >= 0xc) { int secs; secs = (rsp_buff[18] << 8) + rsp_buff[19]; #ifdef SG_LIB_MINGW printf("Expected extended self-test duration=%d seconds " "(%g minutes)\n", secs, secs / 60.0); #else printf("Expected extended self-test duration=%d seconds " "(%.2f minutes)\n", secs, secs / 60.0); #endif } else printf("Extended self-test duration not available\n"); } else { ret = res; printf("Extended self-test duration (mode page 0xa) failed\n"); goto err_out9; } } else if (opts.do_list) { memset(rsp_buff, 0, sizeof(rsp_buff)); res = do_senddiag(sg_fd, 0, 1 /* pf */, 0, 0, 0, rsp_buff, 4, 1, opts.do_verbose); if (0 == res) { if (0 == sg_ll_receive_diag(sg_fd, 0, 0, rsp_buff, rsp_buff_size, 1, opts.do_verbose)) { printf("Supported diagnostic pages response:\n"); rsp_len = (rsp_buff[2] << 8) + rsp_buff[3] + 4; if (opts.do_hex) dStrHex((const char *)rsp_buff, rsp_len, 1); else { for (k = 0; k < (rsp_len - 4); ++k) { cp = find_page_code_desc(rsp_buff[k + 4]); printf(" 0x%02x %s\n", rsp_buff[k + 4], (cp ? cp : "<unknown>")); } } } else { ret = res; fprintf(stderr, "RECEIVE DIAGNOSTIC RESULTS command " "failed\n"); goto err_out9; } } else { ret = res; goto err_out; } } else if (opts.do_raw) { res = do_senddiag(sg_fd, 0, opts.do_pf, 0, 0, 0, read_in, read_in_len, 1, opts.do_verbose); if (res) { ret = res; goto err_out; } } else { res = do_senddiag(sg_fd, opts.do_selftest, opts.do_pf, opts.do_deftest, opts.do_doff, opts.do_uoff, NULL, 0, 1, opts.do_verbose); if (0 == res) { if ((5 == opts.do_selftest) || (6 == opts.do_selftest)) printf("Foreground self-test returned GOOD status\n"); else if (opts.do_deftest && (! opts.do_doff) && (! opts.do_uoff)) printf("Default self-test returned GOOD status\n"); } else { ret = res; goto err_out; } } res = sg_cmds_close_device(sg_fd); if ((res < 0) && (0 == ret)) return SG_LIB_SYNTAX_ERROR; return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; err_out: if (SG_LIB_CAT_UNIT_ATTENTION == res) fprintf(stderr, "SEND DIAGNOSTIC, unit attention\n"); else if (SG_LIB_CAT_ABORTED_COMMAND == res) fprintf(stderr, "SEND DIAGNOSTIC, aborted command\n"); else if (SG_LIB_CAT_NOT_READY == res) fprintf(stderr, "SEND DIAGNOSTIC, device not " "ready\n"); else fprintf(stderr, "SEND DIAGNOSTIC command, failed\n"); err_out9: if (opts.do_verbose < 2) fprintf(stderr, " try again with '-vv' for more information\n"); res = sg_cmds_close_device(sg_fd); if ((res < 0) && (0 == ret)) return SG_LIB_FILE_ERROR; return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) { int k, jmp_out, plen, num; unsigned int u; const char * cp; for (k = 1; k < argc; ++k) { cp = argv[k]; plen = strlen(cp); if (plen <= 0) continue; if ('-' == *cp) { for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) { switch (*cp) { case 'd': if (0 == strncmp("doff", cp, 4)) { optsp->do_doff = 1; cp += 3; plen -= 3; } else jmp_out = 1; break; case 'e': optsp->do_extdur = 1; break; case 'h': case 'H': ++optsp->do_hex; break; case 'l': ++optsp->do_list; break; case 'N': optsp->opt_new = 1; return 0; case 'O': break; case 'p': if (0 == strncmp("pf", cp, 2)) { optsp->do_pf = 1; ++cp; --plen; } else jmp_out = 1; break; case 't': optsp->do_deftest = 1; break; case 'u': if (0 == strncmp("uoff", cp, 4)) { optsp->do_uoff = 1; cp += 3; plen -= 3; } else jmp_out = 1; break; case 'v': ++optsp->do_verbose; break; case 'V': ++optsp->do_version; break; case '?': ++optsp->do_help; break; default: jmp_out = 1; break; } if (jmp_out) break; } if (plen <= 0) continue; if (0 == strncmp("raw=", cp, 4)) { optsp->raw_arg = cp + 4; optsp->do_raw = 1; } else if (0 == strncmp("s=", cp, 2)) { num = sscanf(cp + 2, "%x", &u); if ((1 != num) || (u > 7)) { printf("Bad page code after '-s=' option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } optsp->do_selftest = u; } else if (0 == strncmp("-old", cp, 5)) ; else if (jmp_out) { fprintf(stderr, "Unrecognized option: %s\n", cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == optsp->device_name) optsp->device_name = cp; else { fprintf(stderr, "too many arguments, got: %s, not expecting: " "%s\n", optsp->device_name, cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } return 0; }
int main(int argc, char * argv[]) { int sg_fd, k, num, rsp_len, res, rsp_buff_size, pg; int read_in_len = 0; int ret = 0; struct opts_t opts; struct opts_t * op; unsigned char * rsp_buff = NULL; const char * cp; unsigned char * read_in = NULL; op = &opts; memset(op, 0, sizeof(opts)); op->maxlen = DEF_ALLOC_LEN; op->page_code = -1; res = process_cl(op, argc, argv); if (res) return SG_LIB_SYNTAX_ERROR; if (op->do_help) { if (op->opt_new) usage(); else usage_old(); return 0; } if (op->do_version) { fprintf(stderr, "Version string: %s\n", version_str); return 0; } rsp_buff_size = op->maxlen; if (NULL == op->device_name) { if (op->do_list) { list_page_codes(); return 0; } fprintf(stderr, "No DEVICE argument given\n"); if (op->opt_new) usage(); else usage_old(); return SG_LIB_SYNTAX_ERROR; } if (op->do_raw) { read_in = (unsigned char *)calloc(op->maxlen, 1); if (NULL == read_in) { fprintf(stderr, "unable to allocate %d bytes\n", op->maxlen); return SG_LIB_CAT_OTHER; } if (build_diag_page(op->raw_arg, read_in, &read_in_len, op->maxlen)) { if (op->opt_new) { printf("Bad sequence after '--raw=' option\n"); usage(); } else { printf("Bad sequence after '-raw=' option\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } } if ((op->do_doff || op->do_uoff) && (! op->do_deftest)) { if (op->opt_new) { printf("setting --doff or --uoff only useful when -t is set\n"); usage(); } else { printf("setting -doff or -uoff only useful when -t is set\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } if ((op->do_selftest > 0) && op->do_deftest) { if (op->opt_new) { printf("either set --selftest=SF or --test (not both)\n"); usage(); } else { printf("either set -s=SF or -t (not both)\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } if (op->do_raw) { if ((op->do_selftest > 0) || op->do_deftest || op->do_extdur || op->do_list) { if (op->opt_new) { printf("'--raw=' cannot be used with self-tests, '-e' or " "'-l'\n"); usage(); } else { printf("'-raw=' cannot be used with self-tests, '-e' or " "'-l'\n"); usage_old(); } return SG_LIB_SYNTAX_ERROR; } if (! op->do_pf) { if (op->opt_new) printf(">>> warning, '--pf' probably should be used with " "'--raw='\n"); else printf(">>> warning, '-pf' probably should be used with " "'-raw='\n"); } } #ifdef SG_LIB_WIN32 #ifdef SG_LIB_WIN32_DIRECT if (op->do_verbose > 4) fprintf(stderr, "Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); if (op->maxlen >= 16384) scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif #endif if ((sg_fd = sg_cmds_open_device(op->device_name, 0 /* rw */, op->do_verbose)) < 0) { fprintf(stderr, ME "error opening file: %s: %s\n", op->device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } rsp_buff = (unsigned char *)calloc(op->maxlen, 1); if (NULL == rsp_buff) { fprintf(stderr, "unable to allocate %d bytes (2)\n", op->maxlen); return SG_LIB_CAT_OTHER; } if (op->do_extdur) { res = do_modes_0a(sg_fd, rsp_buff, 32, 1, 0, op->do_verbose); if (0 == res) { /* Assume mode sense(10) response without block descriptors */ num = sg_get_unaligned_be16(rsp_buff) - 6; if (num >= 0xc) { int secs; secs = sg_get_unaligned_be16(rsp_buff + 18); #ifdef SG_LIB_MINGW printf("Expected extended self-test duration=%d seconds " "(%g minutes)\n", secs, secs / 60.0); #else printf("Expected extended self-test duration=%d seconds " "(%.2f minutes)\n", secs, secs / 60.0); #endif } else printf("Extended self-test duration not available\n"); } else { ret = res; printf("Extended self-test duration (mode page 0xa) failed\n"); goto err_out9; } } else if ((op->do_list) || (op->page_code >= 0x0)) { pg = op->page_code; if (pg < 0) res = do_senddiag(sg_fd, 0, 1 /* pf */, 0, 0, 0, rsp_buff, 4, 1, op->do_verbose); else res = 0; if (0 == res) { if (0 == sg_ll_receive_diag(sg_fd, (pg >= 0x0), ((pg >= 0x0) ? pg : 0), rsp_buff, rsp_buff_size, 1, op->do_verbose)) { rsp_len = sg_get_unaligned_be16(rsp_buff + 2) + 4; if (op->do_hex > 1) dStrHex((const char *)rsp_buff, rsp_len, (2 == op->do_hex) ? 0 : -1); else if (pg < 0x1) { printf("Supported diagnostic pages response:\n"); if (op->do_hex) dStrHex((const char *)rsp_buff, rsp_len, 1); else { for (k = 0; k < (rsp_len - 4); ++k) { cp = find_page_code_desc(rsp_buff[k + 4]); printf(" 0x%02x %s\n", rsp_buff[k + 4], (cp ? cp : "<unknown>")); } } } else { cp = find_page_code_desc(pg); if (cp) printf("%s diagnostic page [0x%x] response in " "hex:\n", cp, pg); else printf("diagnostic page 0x%x response in hex:\n", pg); dStrHex((const char *)rsp_buff, rsp_len, 1); } } else { ret = res; fprintf(stderr, "RECEIVE DIAGNOSTIC RESULTS command " "failed\n"); goto err_out9; } } else { ret = res; goto err_out; } } else if (op->do_raw) { res = do_senddiag(sg_fd, 0, op->do_pf, 0, 0, 0, read_in, read_in_len, 1, op->do_verbose); if (res) { ret = res; goto err_out; } } else { res = do_senddiag(sg_fd, op->do_selftest, op->do_pf, op->do_deftest, op->do_doff, op->do_uoff, NULL, 0, 1, op->do_verbose); if (0 == res) { if ((5 == op->do_selftest) || (6 == op->do_selftest)) printf("Foreground self-test returned GOOD status\n"); else if (op->do_deftest && (! op->do_doff) && (! op->do_uoff)) printf("Default self-test returned GOOD status\n"); } else { ret = res; goto err_out; } } res = sg_cmds_close_device(sg_fd); if ((res < 0) && (0 == ret)) return SG_LIB_SYNTAX_ERROR; return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; err_out: if (SG_LIB_CAT_UNIT_ATTENTION == res) fprintf(stderr, "SEND DIAGNOSTIC, unit attention\n"); else if (SG_LIB_CAT_ABORTED_COMMAND == res) fprintf(stderr, "SEND DIAGNOSTIC, aborted command\n"); else if (SG_LIB_CAT_NOT_READY == res) fprintf(stderr, "SEND DIAGNOSTIC, device not " "ready\n"); else fprintf(stderr, "SEND DIAGNOSTIC command, failed\n"); err_out9: if (op->do_verbose < 2) fprintf(stderr, " try again with '-vv' for more information\n"); res = sg_cmds_close_device(sg_fd); if ((res < 0) && (0 == ret)) return SG_LIB_FILE_ERROR; if (read_in) free(read_in); if (rsp_buff) free(rsp_buff); return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
static int old_parse_cmd_line(struct opts_t * op, int argc, char * argv[]) { bool jmp_out; int k, plen; const char * cp; for (k = 1; k < argc; ++k) { cp = argv[k]; plen = strlen(cp); if (plen <= 0) continue; if ('-' == *cp) { for (--plen, ++cp, jmp_out = false; plen > 0; --plen, ++cp) { switch (*cp) { case 'l': op->do_low = true; return 0; case 'N': op->opts_new = true; return 0; case 'O': break; case 'p': op->do_progress = true; break; case 't': op->do_time = true; break; case 'v': op->verbose_given = true; ++op->verbose; break; case 'V': op->version_given = true; break; case '?': usage_old(); return 0; default: jmp_out = true; break; } if (jmp_out) break; } if (plen <= 0) continue; if (0 == strncmp("n=", cp, 2)) { op->do_number = sg_get_num(cp + 2); if (op->do_number <= 0) { printf("Couldn't decode number after 'n=' option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strncmp("-old", cp, 4)) ; else if (jmp_out) { pr2serr("Unrecognized option: %s\n", cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == op->device_name) op->device_name = cp; else { pr2serr("too many arguments, got: %s, not expecting: %s\n", op->device_name, cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } return 0; }
static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) { int k, jmp_out, plen; const char * cp; for (k = 1; k < argc; ++k) { cp = argv[k]; plen = strlen(cp); if (plen <= 0) continue; if ('-' == *cp) { for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) { switch (*cp) { case 'N': optsp->opt_new = 1; return 0; case 'O': break; case 'p': ++optsp->do_progress; break; case 't': ++optsp->do_time; break; case 'v': ++optsp->do_verbose; break; case 'V': ++optsp->do_verbose; break; case '?': usage_old(); return 0; default: jmp_out = 1; break; } if (jmp_out) break; } if (plen <= 0) continue; if (0 == strncmp("n=", cp, 2)) { optsp->do_number = sg_get_num(cp + 2); if (optsp->do_number <= 0) { printf("Couldn't decode number after 'n=' option\n"); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strncmp("-old", cp, 4)) ; else if (jmp_out) { fprintf(stderr, "Unrecognized option: %s\n", cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } else if (0 == optsp->device_name) optsp->device_name = cp; else { fprintf(stderr, "too many arguments, got: %s, not expecting: " "%s\n", optsp->device_name, cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } } return 0; }