From 2e225c87784735360e9619766efe06782179a86a Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sat, 25 Jun 2022 04:05:14 +0000 Subject: sg_rem_rest_elem: new utility for removing or restoring elements; bug fixes git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@955 6180dd3e-e324-4e3e-922d-17de1ae2f315 --- src/Makefile.am | 12 +- src/Makefile.in | 78 +++++++----- src/sg_decode_sense.c | 105 ++++++++++++---- src/sg_format.c | 85 ++----------- src/sg_get_elem_status.c | 33 +++-- src/sg_get_lba_status.c | 242 +++++++++++++++++++++++++----------- src/sg_opcodes.c | 81 ++++++------ src/sg_rem_rest_elem.c | 317 +++++++++++++++++++++++++++++++++++++++++++++++ src/sg_rep_zones.c | 121 +++++++++--------- src/sg_requests.c | 17 +-- src/sg_sanitize.c | 32 +---- src/sg_unmap.c | 45 ++----- src/sg_vpd.c | 2 +- src/sg_vpd_vendor.c | 2 +- src/sg_zone.c | 64 ++++++---- 15 files changed, 817 insertions(+), 419 deletions(-) create mode 100644 src/sg_rem_rest_elem.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 676f61fa..034f171d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,9 +4,9 @@ bin_PROGRAMS = \ sg_get_config sg_get_elem_status sg_get_lba_status sg_ident sg_inq \ sg_logs sg_luns sg_modes sg_opcodes sg_persist sg_prevent sg_raw \ sg_rdac sg_read_attr sg_read_block_limits sg_read_buffer \ - sg_read_long sg_readcap sg_reassign sg_referrals sg_rep_density \ - sg_rep_pip sg_rep_zones sg_requests sg_reset_wp sg_rmsn sg_rtpg \ - sg_safte sg_sanitize sg_sat_identify sg_sat_phy_event \ + sg_read_long sg_readcap sg_reassign sg_referrals sg_rem_rest_elem \ + sg_rep_density sg_rep_pip sg_rep_zones sg_requests sg_reset_wp \ + sg_rmsn sg_rtpg sg_safte sg_sanitize sg_sat_identify sg_sat_phy_event \ sg_sat_read_gplog sg_sat_set_features sg_seek sg_senddiag sg_ses \ sg_ses_microcode sg_start sg_stpg sg_stream_ctl sg_sync sg_timestamp \ sg_turs sg_unmap sg_verify sg_vpd sg_wr_mode sg_write_buffer \ @@ -131,16 +131,18 @@ sg_read_long_LDADD = ../lib/libsgutils2.la sg_reassign_LDADD = ../lib/libsgutils2.la -sg_requests_LDADD = ../lib/libsgutils2.la - sg_referrals_LDADD = ../lib/libsgutils2.la +sg_rem_rest_elem_LDADD = ../lib/libsgutils2.la + sg_rep_density_LDADD = ../lib/libsgutils2.la sg_rep_pip_LDADD = ../lib/libsgutils2.la sg_rep_zones_LDADD = ../lib/libsgutils2.la +sg_requests_LDADD = ../lib/libsgutils2.la + sg_reset_wp_LDADD = ../lib/libsgutils2.la sg_rmsn_LDADD = ../lib/libsgutils2.la diff --git a/src/Makefile.in b/src/Makefile.in index 8e7c9a7f..a71b2ca7 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -97,8 +97,9 @@ bin_PROGRAMS = sg_bg_ctl$(EXEEXT) sg_compare_and_write$(EXEEXT) \ sg_raw$(EXEEXT) sg_rdac$(EXEEXT) sg_read_attr$(EXEEXT) \ sg_read_block_limits$(EXEEXT) sg_read_buffer$(EXEEXT) \ sg_read_long$(EXEEXT) sg_readcap$(EXEEXT) sg_reassign$(EXEEXT) \ - sg_referrals$(EXEEXT) sg_rep_density$(EXEEXT) \ - sg_rep_pip$(EXEEXT) sg_rep_zones$(EXEEXT) sg_requests$(EXEEXT) \ + sg_referrals$(EXEEXT) sg_rem_rest_elem$(EXEEXT) \ + sg_rep_density$(EXEEXT) sg_rep_pip$(EXEEXT) \ + sg_rep_zones$(EXEEXT) sg_requests$(EXEEXT) \ sg_reset_wp$(EXEEXT) sg_rmsn$(EXEEXT) sg_rtpg$(EXEEXT) \ sg_safte$(EXEEXT) sg_sanitize$(EXEEXT) \ sg_sat_identify$(EXEEXT) sg_sat_phy_event$(EXEEXT) \ @@ -246,6 +247,9 @@ sg_reassign_DEPENDENCIES = ../lib/libsgutils2.la sg_referrals_SOURCES = sg_referrals.c sg_referrals_OBJECTS = sg_referrals.$(OBJEXT) sg_referrals_DEPENDENCIES = ../lib/libsgutils2.la +sg_rem_rest_elem_SOURCES = sg_rem_rest_elem.c +sg_rem_rest_elem_OBJECTS = sg_rem_rest_elem.$(OBJEXT) +sg_rem_rest_elem_DEPENDENCIES = ../lib/libsgutils2.la sg_rep_density_SOURCES = sg_rep_density.c sg_rep_density_OBJECTS = sg_rep_density.$(OBJEXT) sg_rep_density_DEPENDENCIES = ../lib/libsgutils2.la @@ -408,13 +412,13 @@ am__depfiles_remade = ./$(DEPDIR)/sg_bg_ctl.Po \ ./$(DEPDIR)/sg_read_block_limits.Po \ ./$(DEPDIR)/sg_read_buffer.Po ./$(DEPDIR)/sg_read_long.Po \ ./$(DEPDIR)/sg_readcap.Po ./$(DEPDIR)/sg_reassign.Po \ - ./$(DEPDIR)/sg_referrals.Po ./$(DEPDIR)/sg_rep_density.Po \ - ./$(DEPDIR)/sg_rep_pip.Po ./$(DEPDIR)/sg_rep_zones.Po \ - ./$(DEPDIR)/sg_requests.Po ./$(DEPDIR)/sg_reset.Po \ - ./$(DEPDIR)/sg_reset_wp.Po ./$(DEPDIR)/sg_rmsn.Po \ - ./$(DEPDIR)/sg_rtpg.Po ./$(DEPDIR)/sg_safte.Po \ - ./$(DEPDIR)/sg_sanitize.Po ./$(DEPDIR)/sg_sat_identify.Po \ - ./$(DEPDIR)/sg_sat_phy_event.Po \ + ./$(DEPDIR)/sg_referrals.Po ./$(DEPDIR)/sg_rem_rest_elem.Po \ + ./$(DEPDIR)/sg_rep_density.Po ./$(DEPDIR)/sg_rep_pip.Po \ + ./$(DEPDIR)/sg_rep_zones.Po ./$(DEPDIR)/sg_requests.Po \ + ./$(DEPDIR)/sg_reset.Po ./$(DEPDIR)/sg_reset_wp.Po \ + ./$(DEPDIR)/sg_rmsn.Po ./$(DEPDIR)/sg_rtpg.Po \ + ./$(DEPDIR)/sg_safte.Po ./$(DEPDIR)/sg_sanitize.Po \ + ./$(DEPDIR)/sg_sat_identify.Po ./$(DEPDIR)/sg_sat_phy_event.Po \ ./$(DEPDIR)/sg_sat_read_gplog.Po \ ./$(DEPDIR)/sg_sat_set_features.Po \ ./$(DEPDIR)/sg_scan_linux.Po ./$(DEPDIR)/sg_scan_win32.Po \ @@ -458,17 +462,18 @@ SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c sg_dd.c \ sg_map26.c sg_modes.c sg_opcodes.c sg_persist.c sg_prevent.c \ sg_raw.c sg_rbuf.c sg_rdac.c sg_read.c sg_read_attr.c \ sg_read_block_limits.c sg_read_buffer.c sg_read_long.c \ - sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_density.c \ - sg_rep_pip.c sg_rep_zones.c sg_requests.c sg_reset.c \ - sg_reset_wp.c sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c \ - sg_sat_identify.c sg_sat_phy_event.c sg_sat_read_gplog.c \ - sg_sat_set_features.c $(sg_scan_SOURCES) sg_seek.c \ - sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c \ - sg_stream_ctl.c sg_sync.c sg_test_rwbuf.c sg_timestamp.c \ - sg_turs.c sg_unmap.c sg_verify.c $(sg_vpd_SOURCES) \ - sg_wr_mode.c sg_write_buffer.c sg_write_long.c sg_write_same.c \ - sg_write_verify.c sg_write_x.c sg_xcopy.c sg_z_act_query.c \ - sg_zone.c sginfo.c sgm_dd.c sgp_dd.c + sg_readcap.c sg_reassign.c sg_referrals.c sg_rem_rest_elem.c \ + sg_rep_density.c sg_rep_pip.c sg_rep_zones.c sg_requests.c \ + sg_reset.c sg_reset_wp.c sg_rmsn.c sg_rtpg.c sg_safte.c \ + sg_sanitize.c sg_sat_identify.c sg_sat_phy_event.c \ + sg_sat_read_gplog.c sg_sat_set_features.c $(sg_scan_SOURCES) \ + sg_seek.c sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c \ + sg_stpg.c sg_stream_ctl.c sg_sync.c sg_test_rwbuf.c \ + sg_timestamp.c sg_turs.c sg_unmap.c sg_verify.c \ + $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \ + sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \ + sg_xcopy.c sg_z_act_query.c sg_zone.c sginfo.c sgm_dd.c \ + sgp_dd.c DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \ sg_dd.c sg_decode_sense.c sg_emc_trespass.c sg_format.c \ sg_get_config.c sg_get_elem_status.c sg_get_lba_status.c \ @@ -476,17 +481,18 @@ DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \ sg_map26.c sg_modes.c sg_opcodes.c sg_persist.c sg_prevent.c \ sg_raw.c sg_rbuf.c sg_rdac.c sg_read.c sg_read_attr.c \ sg_read_block_limits.c sg_read_buffer.c sg_read_long.c \ - sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_density.c \ - sg_rep_pip.c sg_rep_zones.c sg_requests.c sg_reset.c \ - sg_reset_wp.c sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c \ - sg_sat_identify.c sg_sat_phy_event.c sg_sat_read_gplog.c \ - sg_sat_set_features.c $(am__sg_scan_SOURCES_DIST) sg_seek.c \ - sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c \ - sg_stream_ctl.c sg_sync.c sg_test_rwbuf.c sg_timestamp.c \ - sg_turs.c sg_unmap.c sg_verify.c $(sg_vpd_SOURCES) \ - sg_wr_mode.c sg_write_buffer.c sg_write_long.c sg_write_same.c \ - sg_write_verify.c sg_write_x.c sg_xcopy.c sg_z_act_query.c \ - sg_zone.c sginfo.c sgm_dd.c sgp_dd.c + sg_readcap.c sg_reassign.c sg_referrals.c sg_rem_rest_elem.c \ + sg_rep_density.c sg_rep_pip.c sg_rep_zones.c sg_requests.c \ + sg_reset.c sg_reset_wp.c sg_rmsn.c sg_rtpg.c sg_safte.c \ + sg_sanitize.c sg_sat_identify.c sg_sat_phy_event.c \ + sg_sat_read_gplog.c sg_sat_set_features.c \ + $(am__sg_scan_SOURCES_DIST) sg_seek.c sg_senddiag.c sg_ses.c \ + sg_ses_microcode.c sg_start.c sg_stpg.c sg_stream_ctl.c \ + sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \ + sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \ + sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \ + sg_xcopy.c sg_z_act_query.c sg_zone.c sginfo.c sgm_dd.c \ + sgp_dd.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -691,11 +697,12 @@ sg_read_block_limits_LDADD = ../lib/libsgutils2.la sg_read_buffer_LDADD = ../lib/libsgutils2.la sg_read_long_LDADD = ../lib/libsgutils2.la sg_reassign_LDADD = ../lib/libsgutils2.la -sg_requests_LDADD = ../lib/libsgutils2.la sg_referrals_LDADD = ../lib/libsgutils2.la +sg_rem_rest_elem_LDADD = ../lib/libsgutils2.la sg_rep_density_LDADD = ../lib/libsgutils2.la sg_rep_pip_LDADD = ../lib/libsgutils2.la sg_rep_zones_LDADD = ../lib/libsgutils2.la +sg_requests_LDADD = ../lib/libsgutils2.la sg_reset_wp_LDADD = ../lib/libsgutils2.la sg_rmsn_LDADD = ../lib/libsgutils2.la sg_rtpg_LDADD = ../lib/libsgutils2.la @@ -939,6 +946,10 @@ sg_referrals$(EXEEXT): $(sg_referrals_OBJECTS) $(sg_referrals_DEPENDENCIES) $(EX @rm -f sg_referrals$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sg_referrals_OBJECTS) $(sg_referrals_LDADD) $(LIBS) +sg_rem_rest_elem$(EXEEXT): $(sg_rem_rest_elem_OBJECTS) $(sg_rem_rest_elem_DEPENDENCIES) $(EXTRA_sg_rem_rest_elem_DEPENDENCIES) + @rm -f sg_rem_rest_elem$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sg_rem_rest_elem_OBJECTS) $(sg_rem_rest_elem_LDADD) $(LIBS) + sg_rep_density$(EXEEXT): $(sg_rep_density_OBJECTS) $(sg_rep_density_DEPENDENCIES) $(EXTRA_sg_rep_density_DEPENDENCIES) @rm -f sg_rep_density$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sg_rep_density_OBJECTS) $(sg_rep_density_LDADD) $(LIBS) @@ -1141,6 +1152,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_readcap.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_reassign.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_referrals.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rem_rest_elem.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_density.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_pip.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_zones.Po@am__quote@ # am--include-marker @@ -1376,6 +1388,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/sg_readcap.Po -rm -f ./$(DEPDIR)/sg_reassign.Po -rm -f ./$(DEPDIR)/sg_referrals.Po + -rm -f ./$(DEPDIR)/sg_rem_rest_elem.Po -rm -f ./$(DEPDIR)/sg_rep_density.Po -rm -f ./$(DEPDIR)/sg_rep_pip.Po -rm -f ./$(DEPDIR)/sg_rep_zones.Po @@ -1496,6 +1509,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/sg_readcap.Po -rm -f ./$(DEPDIR)/sg_reassign.Po -rm -f ./$(DEPDIR)/sg_referrals.Po + -rm -f ./$(DEPDIR)/sg_rem_rest_elem.Po -rm -f ./$(DEPDIR)/sg_rep_density.Po -rm -f ./$(DEPDIR)/sg_rep_pip.Po -rm -f ./$(DEPDIR)/sg_rep_zones.Po diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c index 76e5f6f9..160544be 100644 --- a/src/sg_decode_sense.c +++ b/src/sg_decode_sense.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2021 Douglas Gilbert. + * Copyright (c) 2010-2022 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. @@ -30,7 +30,9 @@ #include "sg_unaligned.h" -static const char * version_str = "1.25 20211119"; +static const char * version_str = "1.27 20220624"; + +#define MY_NAME "sg_decode_sense" #define MAX_SENSE_LEN 4096 /* max descriptor format actually: 255+8 */ @@ -44,6 +46,7 @@ static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"hex", no_argument, 0, 'H'}, {"in", required_argument, 0, 'i'}, /* don't advertise */ + {"json", optional_argument, 0, 'j'}, {"inhex", required_argument, 0, 'i'}, /* same as --file */ {"nodecode", no_argument, 0, 'N'}, {"nospace", no_argument, 0, 'n'}, @@ -73,6 +76,7 @@ struct opts_t { int verbose; const char * wfname; const char * no_space_str; + sgj_state json_st; uint8_t sense[MAX_SENSE_LEN + 4]; }; @@ -85,10 +89,10 @@ usage() pr2serr("Usage: sg_decode_sense [--binary=BFN] [--cdb] [--err=ES] " "[--file=HFN]\n" " [--help] [--hex] [--inhex=HFN] " - "[--nodecode]\n" - " [--nospace] [--status=SS] [--verbose] " - "[--version]\n" - " [--write=WFN] H1 H2 H3 ...\n" + "[--json[=JO]]\n" + " [--nodecode] [--nospace] [--status=SS] " + "[--verbose]\n" + " [--version] [--write=WFN] H1 H2 H3 ...\n" " where:\n" " --binary=BFN|-b BFN BFN is a file name to read sense " "data in\n" @@ -106,8 +110,16 @@ usage() " --hex|-H used together with --write=WFN, to " "write out\n" " C language style ASCII hex (instead " - "of binary)\n" + "of binary).\n" + " Otherwise don't decode, output incoming " + "data in\n" + " hex (used '-HH' or '-HHH' for different " + "formats)\n" " --inhex=HFN|-i HFN same as action as --file=HFN\n" + " --json[=JO]|-j[JO] output in JSON instead of human " + "readable text.\n" + " Optional argument JO see sg3_utils " + "manpage\n" " --nodecode|-N do not decode, may be neither sense " "nor cdb\n" " --nospace|-n no spaces or other separators between " @@ -138,7 +150,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[]) char *endptr; while (1) { - c = getopt_long(argc, argv, "b:ce:f:hHi:nNs:vVw:", long_options, + c = getopt_long(argc, argv, "b:ce:f:hHi:j::nNs:vVw:", long_options, NULL); if (c == -1) break; @@ -178,6 +190,9 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[]) case '?': op->do_help = true; return 0; + case 'H': + op->hex_count++; + break; case 'i': if (op->fname) { pr2serr("expect only one '--binary=BFN', '--file=HFN' or " @@ -187,8 +202,12 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[]) op->file_given = true; op->fname = optarg; break; - case 'H': - op->hex_count++; + case 'j': + if (! sgj_init_state(&op->json_st, optarg)) { + pr2serr("bad argument to --json= option, unrecognized " + "character '%c'\n", op->json_st.first_bad_char); + return SG_LIB_SYNTAX_ERROR; + } break; case 'n': op->no_space = true; @@ -298,6 +317,7 @@ write2wfn(FILE * fp, struct opts_t * op) int main(int argc, char *argv[]) { + bool as_json; int k, err, blen; int ret = 0; unsigned int ui; @@ -305,6 +325,9 @@ main(int argc, char *argv[]) struct opts_t * op; FILE * fp = NULL; const char * cp; + sgj_state * jsp; + sgj_opaque_p jop = NULL; + sgj_opaque_p jo2p; char b[2048]; struct opts_t opts; @@ -341,6 +364,10 @@ main(int argc, char *argv[]) usage(); return 0; } + as_json = op->json_st.pr_as_json; + jsp = &op->json_st; + if (as_json) + jop = sgj_start(MY_NAME, version_str, argc, argv, jsp); if (op->err_given) { char d[128]; @@ -368,29 +395,35 @@ main(int argc, char *argv[]) isxdigit((uint8_t)cp[k + 1]); k += 2) { if (1 != sscanf(cp + k, "%2x", &ui)) { pr2serr("bad no_space hex string: %s\n", cp); - return SG_LIB_SYNTAX_ERROR; + ret = SG_LIB_SYNTAX_ERROR; + goto fini; } op->sense[op->sense_len++] = (uint8_t)ui; } } if ((0 == op->sense_len) && (! op->do_binary) && (! op->file_given)) { - if (op->do_status) - return 0; + if (op->do_status) { + ret = 0; + goto fini; + } pr2serr(">> Need sense/cdb/arbitrary data on the command line or " "in a file\n\n"); usage(); - return SG_LIB_SYNTAX_ERROR; + ret = SG_LIB_SYNTAX_ERROR; + goto fini; } if (op->sense_len && (op->do_binary || op->file_given)) { pr2serr(">> Need sense data on command line or in a file, not " "both\n\n"); - return SG_LIB_CONTRADICT; + ret = SG_LIB_CONTRADICT; + goto fini; } if (op->do_binary && op->file_given) { pr2serr(">> Either a binary file or a ASCII hexadecimal, file not " "both\n\n"); - return SG_LIB_CONTRADICT; + ret = SG_LIB_CONTRADICT; + goto fini; } if (op->do_binary) { @@ -399,13 +432,15 @@ main(int argc, char *argv[]) err = errno; pr2serr("unable to open file: %s: %s\n", op->fname, safe_strerror(err)); - return sg_convert_errno(err); + ret = sg_convert_errno(err); + goto fini; } s = fread(op->sense, 1, MAX_SENSE_LEN, fp); fclose(fp); if (0 == s) { pr2serr("read nothing from file: %s\n", op->fname); - return SG_LIB_SYNTAX_ERROR; + ret = SG_LIB_SYNTAX_ERROR; + goto fini; } op->sense_len = s; } else if (op->file_given) { @@ -413,7 +448,7 @@ main(int argc, char *argv[]) &op->sense_len, MAX_SENSE_LEN); if (ret) { pr2serr("unable to decode ASCII hex from file: %s\n", op->fname); - return ret; + goto fini; } } @@ -463,11 +498,39 @@ main(int argc, char *argv[]) sg_get_opcode_sa_name(opcode, sa, 0, blen, b); printf("%s\n", b); } else { - sg_get_sense_str(NULL, op->sense, op->sense_len, - op->verbose, blen, b); + if (as_json) + sgj_get_sense(jsp, jop, op->sense, op->sense_len); + else + sg_get_sense_str(NULL, op->sense, op->sense_len, + op->verbose, blen, b); printf("%s\n", b); } } fini: + if (as_json) { + +#if 0 +// <<<< testing +// uint8_t dd[] = {0x1, 0x0, 0x0, 0x6, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + +uint8_t dd[] = {0x01, 0x00, 0x00, 0x16, 0x11, 0x22, 0x33, 0x44 , 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, + 0xdd, 0xee, 0xff, 0xed, 0xcb, 0xa9, 0x87, 0x65 , 0x43, 0x21}; + +// uint8_t dd[] = {0x2, 0x1, 0x0, 0x14, +// 0x41, 0x42, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, +// 0x58, 0x59, 0x5a, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; + +// uint8_t dd[] = {0x01, 0x03, 0x00, 0x08, 0x51, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; +// uint8_t dd[] = {0x01, 0x03, 0x00, 0x10, 0x61, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0xee, 0xdd}; + +jo2p = sgj_new_named_object(jsp, jop, "designation_descriptor"); +sgj_get_designation_descriptor(jsp, jo2p, dd, sizeof(dd)); +// <<<< end of testing +#endif + + if (0 == op->hex_count) + sgj_pr2file(&op->json_st, NULL, ret, stdout); + sgj_finish(jsp); + } return ret; } diff --git a/src/sg_format.c b/src/sg_format.c index 6c963af2..8703b1d5 100644 --- a/src/sg_format.c +++ b/src/sg_format.c @@ -40,7 +40,7 @@ #include "sg_pr2serr.h" #include "sg_pt.h" -static const char * version_str = "1.66 20220211"; +static const char * version_str = "1.67 20220607"; #define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */ @@ -58,17 +58,6 @@ static const char * version_str = "1.66 20220211"; true -> request sense */ #define MAX_BUFF_SZ 252 -#if defined(MSC_VER) || defined(__MINGW32__) -#define HAVE_MS_SLEEP -#endif - -#ifdef HAVE_MS_SLEEP -#include -#define sleep_for(seconds) Sleep( (seconds) * 1000) -#else -#define sleep_for(seconds) sleep(seconds) -#endif - /* FORMAT UNIT (SBC) and FORMAT MEDIUM (SSC) share the same opcode */ #define SG_FORMAT_MEDIUM_CMD 0x4 #define SG_FORMAT_MEDIUM_CMDLEN 6 @@ -508,7 +497,7 @@ scsi_format_unit(int fd, const struct opts_t * op) POLL_DURATION_SECS; if (! op->poll_type) { for(first = true; ; first = false) { - sleep_for(poll_wait_secs); + sg_sleep_secs(poll_wait_secs); progress = -1; res = sg_ll_test_unit_ready_progress(fd, 0, &progress, true, (vb > 1) ? (vb - 1) : 0); @@ -537,7 +526,7 @@ scsi_format_unit(int fd, const struct opts_t * op) return sg_convert_errno(ENOMEM); } for(first = true; ; first = false) { - sleep_for(poll_wait_secs); + sg_sleep_secs(poll_wait_secs); memset(reqSense, 0x0, MAX_BUFF_SZ); res = sg_ll_request_sense(fd, false, reqSense, MAX_BUFF_SZ, false, @@ -629,7 +618,7 @@ scsi_format_medium(int fd, const struct opts_t * op) } if (! op->poll_type) { for(first = true; ; first = false) { - sleep_for(POLL_DURATION_SECS); + sg_sleep_secs(POLL_DURATION_SECS); progress = -1; res = sg_ll_test_unit_ready_progress(fd, 0, &progress, true, (vb > 1) ? (vb - 1) : 0); @@ -658,7 +647,7 @@ scsi_format_medium(int fd, const struct opts_t * op) return sg_convert_errno(ENOMEM); } for(first = true; ; first = false) { - sleep_for(POLL_DURATION_SECS); + sg_sleep_secs(POLL_DURATION_SECS); memset(reqSense, 0x0, MAX_BUFF_SZ); res = sg_ll_request_sense(fd, false, reqSense, MAX_BUFF_SZ, false, @@ -748,7 +737,7 @@ scsi_format_with_preset(int fd, const struct opts_t * op) } if (! op->poll_type) { for(first = true; ; first = false) { - sleep_for(POLL_DURATION_SECS); + sg_sleep_secs(POLL_DURATION_SECS); progress = -1; res = sg_ll_test_unit_ready_progress(fd, 0, &progress, true, (vb > 1) ? (vb - 1) : 0); @@ -777,7 +766,7 @@ scsi_format_with_preset(int fd, const struct opts_t * op) return sg_convert_errno(ENOMEM); } for(first = true; ; first = false) { - sleep_for(POLL_DURATION_SECS); + sg_sleep_secs(POLL_DURATION_SECS); memset(reqSense, 0x0, MAX_BUFF_SZ); res = sg_ll_request_sense(fd, false, reqSense, MAX_BUFF_SZ, false, @@ -1680,24 +1669,8 @@ again_sp_false: if (op->format) { format_only: - if (op->quick) - goto skip_f_unit_reconsider; - printf("\nA FORMAT UNIT will commence in 15 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA FORMAT UNIT will commence in 10 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA FORMAT UNIT will commence in 5 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); -skip_f_unit_reconsider: + if (! op->quick) + sg_warn_and_wait("FORMAT UNIT", op->device_name, true); res = scsi_format_unit(fd, op); ret = res; if (res) { @@ -1712,24 +1685,8 @@ skip_f_unit_reconsider: format_med: if (! op->poll_type_given) /* SSC-5 specifies REQUEST SENSE polling */ op->poll_type = true; - if (op->quick) - goto skip_f_med_reconsider; - printf("\nA FORMAT MEDIUM will commence in 15 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA FORMAT MEDIUM will commence in 10 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA FORMAT MEDIUM will commence in 5 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); -skip_f_med_reconsider: + if (! op->quick) + sg_warn_and_wait("FORMAT MEDIUM", op->device_name, true); res = scsi_format_medium(fd, op); ret = res; if (res) { @@ -1740,24 +1697,8 @@ skip_f_med_reconsider: goto out; format_with_pre: - if (op->quick) - goto skip_f_with_pre_reconsider; - printf("\nA FORMAT WITH PRESET will commence in 15 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA FORMAT WITH PRESET will commence in 10 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA FORMAT WITH PRESET will commence in 5 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", - op->device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); -skip_f_with_pre_reconsider: + if (! op->quick) + sg_warn_and_wait("FORMAT WITH PRESET", op->device_name, true); res = scsi_format_with_preset(fd, op); ret = res; if (res) { diff --git a/src/sg_get_elem_status.c b/src/sg_get_elem_status.c index 47e18a99..fc46608a 100644 --- a/src/sg_get_elem_status.c +++ b/src/sg_get_elem_status.c @@ -37,11 +37,10 @@ * given SCSI device. */ -static const char * version_str = "1.10 20220527"; /* sbc5r01 */ +static const char * version_str = "1.11 20220616"; /* sbc5r01 */ #define MY_NAME "sg_get_elem_status" - #ifndef UINT32_MAX #define UINT32_MAX ((uint32_t)-1) #endif @@ -549,12 +548,12 @@ start_response: goto fini; } - sgj_pr_twin_vi(jsp, jop, 0, "Number of descriptors", - SGJ_SEP_COLON_1_SPACE, num_desc); - sgj_pr_twin_vi(jsp, jop, 0, "Number of descriptors returned", - SGJ_SEP_COLON_1_SPACE, num_desc_ret); - sgj_pr_twin_vi(jsp, jop, 0, "Identifier of element being depopulated", - SGJ_SEP_COLON_1_SPACE, id_elem_depop); + sgj_pr_hr_js_vi(jsp, jop, 0, "Number of descriptors", + SGJ_SEP_COLON_1_SPACE, num_desc); + sgj_pr_hr_js_vi(jsp, jop, 0, "Number of descriptors returned", + SGJ_SEP_COLON_1_SPACE, num_desc_ret); + sgj_pr_hr_js_vi(jsp, jop, 0, "Identifier of element being depopulated", + SGJ_SEP_COLON_1_SPACE, id_elem_depop); if (rlen < 64) { sgj_pr_hr(jsp, "No complete physical element status descriptors " "available\n"); @@ -575,18 +574,18 @@ start_response: decode_elem_status_desc(bp, &a_ped); if (jsp->pr_as_json) { jo2p = sgj_new_unattached_object(jsp); - sgj_add_name_pair_ihex(jsp, jo2p, "element_identifier", - (int64_t)a_ped.elem_id); + sgj_add_nv_ihex(jsp, jo2p, "element_identifier", + (int64_t)a_ped.elem_id); cp = (1 == a_ped.phys_elem_type) ? "storage" : "reserved"; - sgj_add_name_pair_istr(jsp, jo2p, "physical_element_type", - a_ped.phys_elem_type, "meaning", cp); + sgj_add_nv_istr(jsp, jo2p, "physical_element_type", + a_ped.phys_elem_type, "meaning", cp); j = a_ped.phys_elem_health; fetch_health_str(j, b, blen); - sgj_add_name_pair_istr(jsp, jo2p, "physical_element_health", j, - "meaning", b); - sgj_add_name_pair_ihex(jsp, jo2p, "associated_capacity", - (int64_t)a_ped.assoc_cap); - sgj_add_val_o(jsp, jap, NULL /* name */, jo2p); + sgj_add_nv_istr(jsp, jo2p, "physical_element_health", j, + "meaning", b); + sgj_add_nv_ihex(jsp, jo2p, "associated_capacity", + (int64_t)a_ped.assoc_cap); + sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p); } else if (do_brief) { sgj_pr_hr(jsp, "%u: %u,%u\n", a_ped.elem_id, a_ped.phys_elem_type, a_ped.phys_elem_health); diff --git a/src/sg_get_lba_status.c b/src/sg_get_lba_status.c index 6a905793..1612aaac 100644 --- a/src/sg_get_lba_status.c +++ b/src/sg_get_lba_status.c @@ -35,14 +35,16 @@ * device. */ -static const char * version_str = "1.25 20220520"; /* sbc4r15 */ +static const char * version_str = "1.27 20220616"; /* sbc5r01 */ + +#define MY_NAME "sg_get_lba_status" #ifndef UINT32_MAX #define UINT32_MAX ((uint32_t)-1) #endif #define MAX_GLBAS_BUFF_LEN (1024 * 1024) -#define DEF_GLBAS_BUFF_LEN 24 +#define DEF_GLBAS_BUFF_LEN 1024 #define MIN_MAXLEN 16 static uint8_t glbasFixedBuff[DEF_GLBAS_BUFF_LEN]; @@ -52,12 +54,14 @@ static struct option long_options[] = { {"16", no_argument, 0, 'S'}, {"32", no_argument, 0, 'T'}, {"brief", no_argument, 0, 'b'}, + {"blockhex", no_argument, 0, 'B'}, {"element-id", required_argument, 0, 'e'}, {"element_id", required_argument, 0, 'e'}, {"help", no_argument, 0, 'h'}, {"hex", no_argument, 0, 'H'}, {"in", required_argument, 0, 'i'}, /* silent, same as --inhex= */ {"inhex", required_argument, 0, 'i'}, + {"json", optional_argument, 0, 'j'}, {"lba", required_argument, 0, 'l'}, {"maxlen", required_argument, 0, 'm'}, {"raw", no_argument, 0, 'r'}, @@ -74,17 +78,20 @@ static struct option long_options[] = { static void usage() { - pr2serr("Usage: sg_get_lba_status [--16] [--32][--brief] " - "[--element-id=EI]\n" - " [--help] [--hex] [--inhex=FN] " - "[--lba=LBA]\n" - " [--maxlen=LEN] [--raw] [--readonly]\n" + pr2serr("Usage: sg_get_lba_status [--16] [--32] [--blockhex] " + "[--brief]\n" + " [--element-id=EI] [--help] [--hex] " + "[--inhex=FN]\n" + " [--lba=LBA] [--maxlen=LEN] [--raw] " + "[--readonly]\n" " [--report-type=RT] [--scan-len=SL] " "[--verbose]\n" " [--version] DEVICE\n" " where:\n" " --16|-S use GET LBA STATUS(16) cdb (def)\n" " --32|-T use GET LBA STATUS(32) cdb\n" + " --blockhex|-B outputs the (number of) blocks field " + " in hex\n" " --brief|-b a descriptor per line:\n" " \n" @@ -98,6 +105,8 @@ usage() "DEVICE,\n" " assumed to be ASCII hex or, if --raw, " "in binary\n" + " --json[=JO]|-j[JO] output in JSON instead of human " + "readable text\n" " --lba=LBA|-l LBA starting LBA (logical block address) " "(def: 0)\n" " --maxlen=LEN|-m LEN max response length (allocation " @@ -122,8 +131,10 @@ usage() " --verbose|-v increase verbosity\n" " --version|-V print version string and exit\n\n" "Performs a SCSI GET LBA STATUS(16) or GET LBA STATUS(32) " - "command (SBC-3 and\nSBC-4). If --inhex=FN is given then " - "contents of FN is assumed to be a response\nto this command.\n" + "command (SBC-3 and\nSBC-4). The --element-id=EI and the " + "--scan-len=SL fields are only active\non the 32 byte cdb " + "variant. If --inhex=FN is given then contents of FN is\n" + "assumed to be a response to this command.\n" ); } @@ -159,6 +170,49 @@ decode_lba_status_desc(const uint8_t * bp, uint64_t * slbap, return bp[12] & 0xf; } +static char * +get_prov_status_str(int ps, char * b, int blen) +{ + switch (ps) { + case 0: + sg_scnpr(b, blen, "mapped (or unknown)"); + break; + case 1: + sg_scnpr(b, blen, "deallocated"); + break; + case 2: + sg_scnpr(b, blen, "anchored"); + break; + case 3: + sg_scnpr(b, blen, "mapped"); /* sbc4r12 */ + break; + case 4: + sg_scnpr(b, blen, "unknown"); /* sbc4r12 */ + break; + default: + sg_scnpr(b, blen, "unknown provisioning status: %d", ps); + break; + } + return b; +} + +static char * +get_add_status_str(int as, char * b, int blen) +{ + switch (as) { + case 0: + sg_scnpr(b, blen, "%s", ""); + break; + case 1: + sg_scnpr(b, blen, "may contain unrecovered errors"); + break; + default: + sg_scnpr(b, blen, "unknown additional status: %d", as); + break; + } + return b; +} + int main(int argc, char * argv[]) @@ -170,8 +224,9 @@ main(int argc, char * argv[]) bool o_readonly = false; bool verbose_given = false; bool version_given = false; - int k, j, res, c, rlen, num_descs, completion_cond, in_len; + int k, j, res, c, n, rlen, num_descs, completion_cond, in_len; int sg_fd = -1; + int blockhex = 0; int do_brief = 0; int do_hex = 0; int ret = 0; @@ -190,12 +245,22 @@ main(int argc, char * argv[]) const uint8_t * bp; uint8_t * glbasBuffp = glbasFixedBuff; uint8_t * free_glbasBuffp = NULL; + sgj_opaque_p jop = NULL; + sgj_opaque_p jo2p = NULL; + sgj_opaque_p jap = NULL; + sgj_state json_st = {0}; + sgj_state * jsp = &json_st; + char b[144]; + static const size_t blen = sizeof(b); + static const char * prov_stat_s = "Provisoning status"; + static const char * add_stat_s = "Additional status"; + static const char * compl_cond_s = "Completion condition"; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "be:hi:Hl:m:rRs:St:TvV", long_options, - &option_index); + c = getopt_long(argc, argv, "bBe:hi:j::Hl:m:rRs:St:TvV", + long_options, &option_index); if (c == -1) break; @@ -203,6 +268,9 @@ main(int argc, char * argv[]) case 'b': ++do_brief; break; + case 'B': + ++blockhex; + break; case 'e': ll = sg_get_llnum(optarg); if ((ll < 0) || (ll > UINT32_MAX)) { @@ -221,6 +289,13 @@ main(int argc, char * argv[]) case 'i': in_fn = optarg; break; + case 'j': + if (! sgj_init_state(&json_st, optarg)) { + pr2serr("bad argument to --json= option, unrecognized " + "character '%c'\n", json_st.first_bad_char); + return SG_LIB_SYNTAX_ERROR; + } + break; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { @@ -318,6 +393,8 @@ main(int argc, char * argv[]) pr2serr("version: %s\n", version_str); return 0; } + if (jsp->pr_as_json) + jop = sgj_start(MY_NAME, version_str, argc, argv, jsp); if (maxlen > DEF_GLBAS_BUFF_LEN) { glbasBuffp = (uint8_t *)sg_memalign(maxlen, 0, &free_glbasBuffp, @@ -416,10 +493,10 @@ start_response: goto fini; } if (do_hex) { - if (do_hex > 2) - hex2stdout(glbasBuffp, k, -1); - else - hex2stdout(glbasBuffp, k, (2 == do_hex) ? 0 : 1); + if (do_hex > 2) + hex2stdout(glbasBuffp, k, -1); + else + hex2stdout(glbasBuffp, k, (2 == do_hex) ? 0 : 1); goto fini; } if (maxlen < 4) { @@ -438,9 +515,9 @@ start_response: rlen = maxlen; if (do_brief > 1) { - if (rlen < 24) { - pr2serr("Need maxlen and response length to be at least 24, " - "have %d bytes\n", rlen); + if (rlen > DEF_GLBAS_BUFF_LEN) { + pr2serr("Need maxlen and response length to be at least %d, " + "have %d bytes\n", DEF_GLBAS_BUFF_LEN, rlen); ret = SG_LIB_CAT_OTHER; goto fini; } @@ -462,92 +539,111 @@ start_response: ret = SG_LIB_CAT_OTHER; goto fini; } - printf("%d\n", res); + sgj_pr_hr(jsp,"p_status: %d add_status: 0x%x\n", res, + (unsigned int)add_status); + if (jsp->pr_as_json) { + sgj_add_nv_i(jsp, jop, prov_stat_s, res); + sgj_add_nv_i(jsp, jop, add_stat_s, add_status); + } goto fini; } if (rlen < 24) { - printf("No complete LBA status descriptors available\n"); + sgj_pr_hr(jsp, "No complete LBA status descriptors available\n"); goto fini; } num_descs = (rlen - 8) / 16; completion_cond = (*(glbasBuffp + 7) >> 1) & 7; /* added sbc4r14 */ if (do_brief) - printf("Completion condition=%d\n", completion_cond); + sgj_pr_hr_js_vi(jsp, jop, 0, compl_cond_s, + SGJ_SEP_EQUAL_NO_SPACE, completion_cond); else { switch (completion_cond) { case 0: - printf("No indication of the completion condition\n"); + snprintf(b, blen, "No indication of the completion condition"); break; case 1: - printf("Command completed due to meeting allocation length " - "(--maxlen=LEN (def 24))\n"); + snprintf(b, blen, "Command completed due to meeting allocation " + "length"); break; case 2: - printf("Command completed due to meeting scan length " - "(--scan-len=SL)\n"); + snprintf(b, blen, "Command completed due to meeting scan length"); break; case 3: - printf("Command completed due to meeting capacity of " - "medium\n"); + snprintf(b, blen, "Command completed due to meeting capacity of " + "medium"); break; default: - printf("Command completion is reserved [%d]\n", + snprintf(b, blen, "Command completion is reserved [%d]", completion_cond); break; } + sgj_pr_hr(jsp, "%s\n", b); + sgj_add_nv_istr(jsp, jop, compl_cond_s, completion_cond, + NULL /* "meaning" */, b); } - printf("RTP=%d\n", *(glbasBuffp + 7) & 0x1); /* added sbc4r12 */ + sgj_pr_hr_js_vi(jsp, jop, 0, "RTP", SGJ_SEP_EQUAL_NO_SPACE, + *(glbasBuffp + 7) & 0x1); /* added sbc4r12 */ if (verbose) pr2serr("%d complete LBA status descriptors found\n", num_descs); + if (jsp->pr_as_json) + jap = sgj_new_named_array(jsp, jop, "lba_status_descriptor"); + for (bp = glbasBuffp + 8, k = 0; k < num_descs; bp += 16, ++k) { res = decode_lba_status_desc(bp, &d_lba, &d_blocks, &add_status); if ((res < 0) || (res > 15)) pr2serr("descriptor %d: bad LBA status descriptor returned " "%d\n", k + 1, res); + if (jsp->pr_as_json) + jo2p = sgj_new_unattached_object(jsp); if (do_brief) { - printf("0x"); + n = 0; + n += sg_scnpr(b + n, blen - n, "0x"); for (j = 0; j < 8; ++j) - printf("%02x", bp[j]); - printf(" 0x%x %d %d\n", (unsigned int)d_blocks, res, - add_status); + n += sg_scnpr(b + n, blen - n, "%02x", bp[j]); + if ((0 == blockhex) || (1 == (blockhex % 2))) + n += sg_scnpr(b + n, blen - n, " 0x%x %d %d", + (unsigned int)d_blocks, res, add_status); + else + n += sg_scnpr(b + n, blen - n, " %u %d %d", + (unsigned int)d_blocks, res, add_status); + sgj_pr_hr(jsp, "%s\n", b); + sgj_add_nv_ihex(jsp, jo2p, "lba", d_lba); + sgj_add_nv_ihex(jsp, jo2p, "blocks", d_blocks); + sgj_add_nv_i(jsp, jo2p, prov_stat_s, res); + sgj_add_nv_i(jsp, jo2p, add_stat_s, add_status); } else { - printf("[%d] LBA: 0x", k + 1); - for (j = 0; j < 8; ++j) - printf("%02x", bp[j]); - printf(" blocks: %10u", (unsigned int)d_blocks); - switch (res) { - case 0: - printf(" mapped (or unknown)"); - break; - case 1: - printf(" deallocated"); - break; - case 2: - printf(" anchored"); - break; - case 3: - printf(" mapped"); /* sbc4r12 */ - break; - case 4: - printf(" unknown"); /* sbc4r12 */ - break; - default: - printf(" Provisioning status: %d", res); - break; - } - switch (add_status) { - case 0: - printf("\n"); - break; - case 1: - printf(" [may return unrecovered errors]\n"); - break; - default: - printf(" [add_status: 0x%x]\n", (unsigned int)add_status); - break; + if (jsp->pr_as_json) { + sgj_add_nv_ihex(jsp, jo2p, "lba", d_lba); + sgj_add_nv_ihex(jsp, jo2p, "blocks", d_blocks); + sgj_add_nv_istr(jsp, jo2p, prov_stat_s, res, NULL, + get_prov_status_str(res, b, blen)); + sgj_add_nv_istr(jsp, jo2p, add_stat_s, add_status, NULL, + get_add_status_str(add_status, b, blen)); + } else { + char c[64]; + + n = 0; + n += sg_scnpr(b + n, blen - n, "[%d] LBA: 0x", k + 1); + for (j = 0; j < 8; ++j) + n += sg_scnpr(b + n, blen - n, "%02x", bp[j]); + if (1 == (blockhex % 2)) { + + snprintf(c, sizeof(c), "0x%x", d_blocks); + n += sg_scnpr(b + n, blen - n, " blocks: %10s", c); + } else + n += sg_scnpr(b + n, blen - n, " blocks: %10u", + (unsigned int)d_blocks); + get_prov_status_str(res, c, sizeof(c)); + n += sg_scnpr(b + n, blen - n, " %s", c); + get_add_status_str(add_status, c, sizeof(c)); + if (strlen(c) > 0) + n += sg_scnpr(b + n, blen - n, " [%s]", c); + sgj_pr_hr(jsp, "%s\n", b); } } + if (jsp->pr_as_json) + sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p); } if ((num_descs * 16) + 8 < rlen) pr2serr("incomplete trailing LBA status descriptors found\n"); @@ -581,5 +677,11 @@ fini: pr2serr("Some error occurred, try again with '-v' or '-vv' for " "more information\n"); } - return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; + ret = (ret >= 0) ? ret : SG_LIB_CAT_OTHER; + if (jsp->pr_as_json) { + if (0 == do_hex) + sgj_pr2file(jsp, NULL, ret, stdout); + sgj_finish(jsp); + } + return ret; } diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c index 9d6f6c06..4eaa5bae 100644 --- a/src/sg_opcodes.c +++ b/src/sg_opcodes.c @@ -33,7 +33,7 @@ #include "sg_pt.h" -static const char * version_str = "0.82 20220528"; /* spc6r06 */ +static const char * version_str = "0.83 20220616"; /* spc6r06 */ #define MY_NAME "sg_opcodes" @@ -852,22 +852,22 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op, } if (jsp->pr_as_json) { snprintf(b, blen, "0x%x", opcode); - sgj_add_val_s(jsp, jop, "operation_code", b); + sgj_add_nv_s(jsp, jop, "operation_code", b); if (sa_v) { snprintf(b, blen, "0x%x", serv_act); - sgj_add_val_s(jsp, jop, "service_action", b); + sgj_add_nv_s(jsp, jop, "service_action", b); } if (name_buff[0]) - sgj_add_val_s(jsp, jop, "name", name_buff); - sgj_add_val_i(jsp, jop, "rwcdlp", (byt5 >> 6) & 0x1); - sgj_add_val_i(jsp, jop, "mlu", (byt5 >> 4) & 0x3); - sgj_add_val_i(jsp, jop, "cdlp", (byt5 >> 2) & 0x3); - sgj_add_val_i(jsp, jop, "ctdp", (byt5 >> 1) & 0x1); - sgj_add_val_i(jsp, jop, "servactv", byt5 & 0x1); - sgj_add_val_i(jsp, jop, "cdb_length", - sg_get_unaligned_be16(bp + 6)); - - sgj_add_val_o(jsp, jap, NULL /* implies an array add */, jop); + sgj_add_nv_s(jsp, jop, "name", name_buff); + sgj_add_nv_i(jsp, jop, "rwcdlp", (byt5 >> 6) & 0x1); + sgj_add_nv_i(jsp, jop, "mlu", (byt5 >> 4) & 0x3); + sgj_add_nv_i(jsp, jop, "cdlp", (byt5 >> 2) & 0x3); + sgj_add_nv_i(jsp, jop, "ctdp", (byt5 >> 1) & 0x1); + sgj_add_nv_i(jsp, jop, "servactv", byt5 & 0x1); + sgj_add_nv_i(jsp, jop, "cdb_length", + sg_get_unaligned_be16(bp + 6)); + + sgj_add_nv_o(jsp, jap, NULL /* implies an array add */, jop); } if (op->do_mask && ptvp) { @@ -903,8 +903,8 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op, l = strlen(b2p); if ((l > 0) && (' ' == b2p[l - 1])) b2p[l - 1] = '\0'; - sgj_add_val_i(jsp, jo2p, "cdb_size", cdb_sz); - sgj_add_val_s(jsp, jo2p, "cdb_usage_data", b2p); + sgj_add_nv_i(jsp, jo2p, "cdb_size", cdb_sz); + sgj_add_nv_s(jsp, jo2p, "cdb_usage_data", b2p); } } } else @@ -942,9 +942,9 @@ decode_cmd_timeout_desc(uint8_t * dp, int max_b_len, char * b, else snprintf(b, max_b_len, "nominal timeout: %u secs, ", timeout); if (jsp->pr_as_json) { - sgj_add_val_i(jsp, jsp->userp, "command_specific", dp[3]); - sgj_add_val_i(jsp, jsp->userp, - "nominal_command_processing_timeout", timeout); + sgj_add_nv_i(jsp, jsp->userp, "command_specific", dp[3]); + sgj_add_nv_i(jsp, jsp->userp, "nominal_command_processing_timeout", + timeout); } len = strlen(b); max_b_len -= len; @@ -955,8 +955,7 @@ decode_cmd_timeout_desc(uint8_t * dp, int max_b_len, char * b, else snprintf(b, max_b_len, "recommended timeout: %u secs", timeout); if (jsp->pr_as_json) - sgj_add_val_i(jsp, jsp->userp, - "recommended_command_timeout", timeout); + sgj_add_nv_i(jsp, jsp->userp, "recommended_command_timeout", timeout); return; } @@ -1072,25 +1071,25 @@ list_one(uint8_t * rsoc_buff, int cd_len, int rep_opts, int l; snprintf(b, blen, "0x%x", op->opcode); - sgj_add_val_s(jsp, jop, "operation_code", b); + sgj_add_nv_s(jsp, jop, "operation_code", b); if (rep_opts > 1) { snprintf(b, blen, "0x%x", op->servact); - sgj_add_val_s(jsp, jop, "service_action", b); + sgj_add_nv_s(jsp, jop, "service_action", b); } - sgj_add_val_i(jsp, jop, "rwcdlp", rwcdlp); - sgj_add_val_i(jsp, jop, "ctdp", ctdp); - sgj_add_val_i(jsp, jop, "mlu", mlu); - sgj_add_val_i(jsp, jop, "cdlp", cdlp); - sgj_add_val_i(jsp, jop, "support", support); - sgj_add_val_s(jsp, jop, "support_str", cp); - sgj_add_val_i(jsp, jop, "cdb_size", cd_len); + sgj_add_nv_i(jsp, jop, "rwcdlp", rwcdlp); + sgj_add_nv_i(jsp, jop, "ctdp", ctdp); + sgj_add_nv_i(jsp, jop, "mlu", mlu); + sgj_add_nv_i(jsp, jop, "cdlp", cdlp); + sgj_add_nv_i(jsp, jop, "support", support); + sgj_add_nv_s(jsp, jop, "support_str", cp); + sgj_add_nv_i(jsp, jop, "cdb_size", cd_len); n = 0; for (k = 0; k < cd_len; ++k) n += sg_scnpr(b + n, blen - n, "%.2x ", rsoc_buff[k + 4]); l = strlen(b); if ((l > 0) && (' ' == b[l - 1])) b[l - 1] = '\0'; - sgj_add_val_s(jsp, jop, "cdb_usage_data", b); + sgj_add_nv_s(jsp, jop, "cdb_usage_data", b); } if (ctdp) { jsp->userp = sgj_new_named_object(jsp, jsp->basep, @@ -1370,17 +1369,17 @@ start_response: goto fini; } if (jsp->pr_as_json) { - sgj_add_val_b(jsp, jop, "ats", rsoc_buff[0] & 0x80); - sgj_add_val_b(jsp, jop, "atss", rsoc_buff[0] & 0x40); - sgj_add_val_b(jsp, jop, "cacas", rsoc_buff[0] & 0x20); - sgj_add_val_b(jsp, jop, "ctss", rsoc_buff[0] & 0x10); - sgj_add_val_b(jsp, jop, "lurs", rsoc_buff[0] & 0x8); - sgj_add_val_b(jsp, jop, "qts", rsoc_buff[0] & 0x4); - sgj_add_val_b(jsp, jop, "trs", rsoc_buff[0] & 0x2); - sgj_add_val_b(jsp, jop, "ws", rsoc_buff[0] & 0x1); - sgj_add_val_b(jsp, jop, "qaes", rsoc_buff[1] & 0x4); - sgj_add_val_b(jsp, jop, "qtss", rsoc_buff[1] & 0x2); - sgj_add_val_b(jsp, jop, "itnrs", rsoc_buff[1] & 0x1); + sgj_add_nv_b(jsp, jop, "ats", rsoc_buff[0] & 0x80); + sgj_add_nv_b(jsp, jop, "atss", rsoc_buff[0] & 0x40); + sgj_add_nv_b(jsp, jop, "cacas", rsoc_buff[0] & 0x20); + sgj_add_nv_b(jsp, jop, "ctss", rsoc_buff[0] & 0x10); + sgj_add_nv_b(jsp, jop, "lurs", rsoc_buff[0] & 0x8); + sgj_add_nv_b(jsp, jop, "qts", rsoc_buff[0] & 0x4); + sgj_add_nv_b(jsp, jop, "trs", rsoc_buff[0] & 0x2); + sgj_add_nv_b(jsp, jop, "ws", rsoc_buff[0] & 0x1); + sgj_add_nv_b(jsp, jop, "qaes", rsoc_buff[1] & 0x4); + sgj_add_nv_b(jsp, jop, "qtss", rsoc_buff[1] & 0x2); + sgj_add_nv_b(jsp, jop, "itnrs", rsoc_buff[1] & 0x1); if (! jsp->pr_output) goto fini; } diff --git a/src/sg_rem_rest_elem.c b/src/sg_rem_rest_elem.c new file mode 100644 index 00000000..46af7287 --- /dev/null +++ b/src/sg_rem_rest_elem.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2022 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. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define __STDC_FORMAT_MACROS 1 +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "sg_lib.h" +#include "sg_lib_data.h" +#include "sg_pt.h" +#include "sg_cmds_basic.h" +#include "sg_unaligned.h" +#include "sg_pr2serr.h" + +/* A utility program originally written for the Linux OS SCSI subsystem. + * + * This program issues one of the following SCSI commands: + * - REMOVE ELEMENT AND TRUNCATE + * - RESTORE ELEMENTS AND REBUILD + */ + +static const char * version_str = "1.00 20220610"; + +#define REMOVE_ELEM_SA 0x18 +#define RESTORE_ELEMS_SA 0x19 + +#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ +#define DEF_PT_TIMEOUT 60 /* 60 seconds */ + + +static struct option long_options[] = { + {"capacity", required_argument, 0, 'c'}, + {"element", required_argument, 0, 'e'}, + {"help", no_argument, 0, 'h'}, + {"quick", no_argument, 0, 'q'}, + {"remove", no_argument, 0, 'r'}, + {"restore", no_argument, 0, 'R'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {0, 0, 0, 0}, +}; + +static const char * remove_cmd_s = "Remove element and truncate"; +static const char * restore_cmd_s = "Restore elements and rebuild"; + + +static void +usage() +{ + pr2serr("Usage: " + "sg_rem_rest_elem [--capacity=RC] [--element=EID] [--help] " + "[--quick]\n" + " [--remove] [--restore] [--verbose] " + "[--version]\n" + " DEVICE\n"); + pr2serr(" where:\n" + " --capacity=RC|-c RC RC is requested capacity (unit: " + "block; def: 0)\n" + " --element=EID|-e EID EID is the element identifier to " + "remove;\n" + " default is 0 which is an invalid " + "EID\n" + " --help|-h print out usage message\n" + " --quick|-q bypass 15 second warn and wait\n" + " --remove|-r issue REMOVE ELEMENT AND TRUNCATE " + "command\n" + " --restore|-R issue RESTORE ELEMENTS AND REBUILD " + "command\n" + " --verbose|-v increase verbosity\n" + " --version|-V print version string and exit\n\n" + "Performs a SCSI REMOVE ELEMENT AND TRUNCATE or RESTORE " + "ELEMENTS AND\nREBUILD command. Either the --remove or " + "--restore option needs to be given.\n"); +} + +/* Return of 0 -> success, various SG_LIB_CAT_* positive values or -1 -> + * other errors */ +static int +sg_ll_rem_rest_elem(int sg_fd, int sa, uint64_t req_cap, uint32_t e_id, + bool noisy, int verbose) +{ + int ret, res, sense_cat; + struct sg_pt_base * ptvp; + uint8_t sai16_cdb[16] = + {SG_SERVICE_ACTION_IN_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0}; + uint8_t sense_b[SENSE_BUFF_LEN] = {0}; + const char * cmd_name; + + sai16_cdb[1] = 0x1f & sa; + if (REMOVE_ELEM_SA == sa) { + sg_put_unaligned_be64(req_cap, sai16_cdb + 2); + sg_put_unaligned_be32(e_id, sai16_cdb + 10); + cmd_name = remove_cmd_s; + } else + cmd_name = restore_cmd_s; + if (verbose) { + char d[128]; + + pr2serr(" %s cdb: %s\n", cmd_name, + sg_get_command_str(sai16_cdb, 16, false, sizeof(d), d)); + } + + ptvp = construct_scsi_pt_obj(); + if (NULL == ptvp) { + pr2serr("%s: out of memory\n", cmd_name); + return -1; + } + set_scsi_pt_cdb(ptvp, sai16_cdb, sizeof(sai16_cdb)); + set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); + res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); + ret = sg_cmds_process_resp(ptvp, cmd_name, res, noisy, + verbose, &sense_cat); + if (-1 == ret) { + if (get_scsi_pt_transport_err(ptvp)) + ret = SG_LIB_TRANSPORT_ERROR; + else + ret = sg_convert_errno(get_scsi_pt_os_err(ptvp)); + } else if (-2 == ret) { + switch (sense_cat) { + case SG_LIB_CAT_RECOVERED: + case SG_LIB_CAT_NO_SENSE: + ret = 0; + break; + default: + ret = sense_cat; + break; + } + } else + ret = 0; + destruct_scsi_pt_obj(ptvp); + return ret; +} + + +int +main(int argc, char * argv[]) +{ + bool quick = false; + bool reat = false; + bool resar = false; + bool verbose_given = false; + bool version_given = false; + int res, c; + int sg_fd = -1; + int verbose = 0; + int ret = 0; + int sa = 0; + uint32_t e_id = 0; + uint64_t req_cap = 0; + int64_t ll; + const char * device_name = NULL; + const char * cmd_name; + + while (1) { + int option_index = 0; + + c = getopt_long(argc, argv, "c:e:hqrRvV", long_options, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'c': + ll = sg_get_llnum(optarg); + if (-1 == ll) { + pr2serr("--capacity= expects a numeric argument\n"); + return SG_LIB_SYNTAX_ERROR; + } + req_cap = (uint64_t)ll; + break; + case 'e': + ll = sg_get_llnum(optarg); + if ((ll < 0) || (ll > UINT32_MAX)) { + pr2serr("bad argument to '--element=EID'\n"); + return SG_LIB_SYNTAX_ERROR; + } + if (0 == ll) + pr2serr("Warning: 0 is an invalid element identifier\n"); + e_id = (uint64_t)ll; + break; + case 'h': + case '?': + usage(); + return 0; + case 'q': + quick = true; + break; + case 'r': + reat = true; + sa = REMOVE_ELEM_SA; + break; + case 'R': + resar = true; + sa = RESTORE_ELEMS_SA; + break; + case 'v': + verbose_given = true; + ++verbose; + break; + case 'V': + version_given = true; + break; + default: + pr2serr("unrecognised option code 0x%x ??\n", c); + usage(); + return SG_LIB_SYNTAX_ERROR; + } + } + if (optind < argc) { + if (NULL == device_name) { + device_name = argv[optind]; + ++optind; + } + if (optind < argc) { + for (; optind < argc; ++optind) + pr2serr("Unexpected extra argument: %s\n", + argv[optind]); + usage(); + return SG_LIB_SYNTAX_ERROR; + } + } + +#ifdef DEBUG + pr2serr("In DEBUG mode, "); + if (verbose_given && version_given) { + pr2serr("but override: '-vV' given, zero verbose and continue\n"); + verbose_given = false; + version_given = false; + verbose = 0; + } else if (! verbose_given) { + pr2serr("set '-vv'\n"); + verbose = 2; + } else + pr2serr("keep verbose=%d\n", verbose); +#else + if (verbose_given && version_given) + pr2serr("Not in DEBUG mode, so '-vV' has no special action\n"); +#endif + if (version_given) { + pr2serr("version: %s\n", version_str); + return 0; + } + + if (1 != ((int)reat + (int)resar)) { + pr2serr("One, and only one, of these options needs to be given:\n" + " --remove or --restore\n\n"); + usage(); + return SG_LIB_CONTRADICT; + } + cmd_name = reat ? remove_cmd_s : restore_cmd_s; + + if (NULL == device_name) { + pr2serr("missing device name!\n"); + usage(); + return SG_LIB_SYNTAX_ERROR; + } + + sg_fd = sg_cmds_open_device(device_name, false /* rw */, verbose); + if (sg_fd < 0) { + int err = -sg_fd; + if (verbose) + pr2serr("open error: %s: %s\n", device_name, + safe_strerror(err)); + ret = sg_convert_errno(err); + goto fini; + } + if (! quick) + sg_warn_and_wait(cmd_name, device_name, false); + + res = sg_ll_rem_rest_elem(sg_fd, sa, req_cap, e_id, true, verbose); + ret = res; + if (res) { + if (SG_LIB_CAT_INVALID_OP == res) + pr2serr("%s command not supported\n", cmd_name); + else { + char b[80]; + + sg_get_category_sense_str(res, sizeof(b), b, verbose); + pr2serr("%s command: %s\n", cmd_name, b); + } + } + +fini: + if (sg_fd >= 0) { + res = sg_cmds_close_device(sg_fd); + if (res < 0) { + pr2serr("close error: %s\n", safe_strerror(-res)); + if (0 == ret) + ret = sg_convert_errno(-res); + } + } + if (0 == verbose) { + if (! sg_if_can2stderr("sg_rem_rest_elem failed: ", ret)) + pr2serr("Some error occurred, try again with '-v' or '-vv' for " + "more information\n"); + } + return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; +} diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c index 0866cd8d..a8d4cbc9 100644 --- a/src/sg_rep_zones.c +++ b/src/sg_rep_zones.c @@ -40,7 +40,7 @@ * Based on zbc2r12.pdf */ -static const char * version_str = "1.38 20220511"; +static const char * version_str = "1.39 20220616"; #define MY_NAME "sg_rep_zones" @@ -395,28 +395,28 @@ prt_a_zn_desc(const uint8_t *bp, const struct opts_t * op, zc = (bp[1] >> 4) & 0xf; sg_get_zone_type_str(zt, sizeof(b), b); sgj_pr_hr(jsp, " Zone type: %s\n", b); - sgj_add_name_pair_istr(jsp, jop, "zone_type", zt, meaning_s, b); + sgj_add_nv_istr(jsp, jop, "zone_type", zt, meaning_s, b); zone_condition_str(zc, b, sizeof(b), op->vb); sgj_pr_hr(jsp, " Zone condition: %s\n", b); - sgj_add_name_pair_istr(jsp, jop, "zone_condition", zc, meaning_s, b); - sgj_pr_twin_vi(jsp, jop, 3, "PUEP", SGJ_SEP_COLON_1_SPACE, - !!(bp[1] & 0x4)); - sgj_pr_twin_vi(jsp, jop, 3, "NON_SEQ", SGJ_SEP_COLON_1_SPACE, - !!(bp[1] & 0x2)); - sgj_pr_twin_vi(jsp, jop, 3, "RESET", SGJ_SEP_COLON_1_SPACE, - !!(bp[1] & 0x1)); + sgj_add_nv_istr(jsp, jop, "zone_condition", zc, meaning_s, b); + sgj_pr_hr_js_vi(jsp, jop, 3, "PUEP", SGJ_SEP_COLON_1_SPACE, + !!(bp[1] & 0x4)); + sgj_pr_hr_js_vi(jsp, jop, 3, "NON_SEQ", SGJ_SEP_COLON_1_SPACE, + !!(bp[1] & 0x2)); + sgj_pr_hr_js_vi(jsp, jop, 3, "RESET", SGJ_SEP_COLON_1_SPACE, + !!(bp[1] & 0x1)); len = sg_get_unaligned_be64(bp + 8); sgj_pr_hr(jsp, " Zone Length: 0x%" PRIx64 "\n", len); - sgj_add_name_pair_ihex(jsp, jop, "zone_length", (int64_t)len); + sgj_add_nv_ihex(jsp, jop, "zone_length", (int64_t)len); lba = sg_get_unaligned_be64(bp + 16); sgj_pr_hr(jsp, " Zone start LBA: 0x%" PRIx64 "\n", lba); - sgj_add_name_pair_ihex(jsp, jop, "zone_start_lba", (int64_t)lba); + sgj_add_nv_ihex(jsp, jop, "zone_start_lba", (int64_t)lba); wp = sg_get_unaligned_be64(bp + 24); if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp))) sgj_pr_hr(jsp, " Write pointer LBA: -1\n"); else sgj_pr_hr(jsp, " Write pointer LBA: 0x%" PRIx64 "\n", wp); - sgj_add_name_pair_ihex(jsp, jop, "write_pointer_lba", (int64_t)wp); + sgj_add_nv_ihex(jsp, jop, "write_pointer_lba", (int64_t)wp); return lba + len; } @@ -457,12 +457,12 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len, "granularity"; sgj_pr_hr(jsp, " Same=%d: %s\n", same, same_desc_arr[same]); - sgj_add_name_pair_istr(jsp, jop, "same", same, meaning_s, - same_desc_arr[same]); + sgj_add_nv_istr(jsp, jop, "same", same, meaning_s, + same_desc_arr[same]); sgj_pr_hr(jsp, " Maximum LBA: 0x%" PRIx64 "\n\n", mx_lba); - sgj_add_name_pair_ihex(jsp, jop, "maximum_lba", mx_lba); + sgj_add_nv_ihex(jsp, jop, "maximum_lba", mx_lba); sgj_pr_hr(jsp, " %s: 0x%" PRIx64 "\n\n", rzslbag_s, rzslbag); - sgj_add_name_pair_ihex(jsp, jop, rzslbag_s, rzslbag); + sgj_add_nv_ihex(jsp, jop, rzslbag_s, rzslbag); } if (op->do_num > 0) num_zd = (num_zd > op->do_num) ? op->do_num : num_zd; @@ -483,7 +483,7 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len, } sgj_pr_hr(jsp, "From last descriptor in this response:\n"); sgj_pr_hr(jsp, " %s%d\n", zn_dnum_s, num_zd - 1); - sgj_add_val_i(jsp, jop, "zone_descriptor_index", num_zd - 1); + sgj_add_nv_i(jsp, jop, "zone_descriptor_index", num_zd - 1); ul = prt_a_zn_desc(bp, op, jsp, jop); if (ul > mx_lba) sgj_pr_hr(jsp, " >> This zone seems to be the last one\n"); @@ -514,15 +514,14 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len, else sgj_pr_hr(jsp, "0x%" PRIx64 "\n", wp); jo2p = sgj_new_unattached_object(jsp); - sgj_add_name_pair_ihex(jsp, jo2p, "write_pointer_lba", - (int64_t)wp); - sgj_add_val_o(jsp, jap, NULL /* name */, jo2p); + sgj_add_nv_ihex(jsp, jo2p, "write_pointer_lba", (int64_t)wp); + sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p); } continue; } jo2p = sgj_new_unattached_object(jsp); prt_a_zn_desc(bp, op, jsp, jo2p); - sgj_add_val_o(jsp, jap, NULL /* name */, jo2p); + sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p); } if ((op->do_num == 0) && (! op->wp_only) && (! op->do_hex)) { if ((64 + (REPORT_ZONES_DESC_LEN * (uint32_t)num_zd)) < decod_len) @@ -554,12 +553,12 @@ decode_rep_realms(const uint8_t * rzBuff, int act_len, nr_locator = sg_get_unaligned_be64(rzBuff + 12); else nr_locator = 0; - sgj_pr_twin_vi(jsp, jop, 0, "Realms_count", SGJ_SEP_EQUAL_NO_SPACE, - realms_count); - sgj_pr_twin_vi(jsp, jop, 0, "Realms_descriptor_length", - SGJ_SEP_EQUAL_NO_SPACE, r_desc_len); + sgj_pr_hr_js_vi(jsp, jop, 0, "Realms_count", SGJ_SEP_EQUAL_NO_SPACE, + realms_count); + sgj_pr_hr_js_vi(jsp, jop, 0, "Realms_descriptor_length", + SGJ_SEP_EQUAL_NO_SPACE, r_desc_len); sgj_pr_hr(jsp, "Next_realm_locator=0x%" PRIx64 "\n", nr_locator); - sgj_add_name_pair_ihex(jsp, jop, "Next_realm_locator", nr_locator); + sgj_add_nv_ihex(jsp, jop, "Next_realm_locator", nr_locator); if ((realms_count < 1) || (act_len < (64 + 16)) || (r_desc_len < 16)) { if (op->vb) { pr2serr("%s: exiting early because ", __func__); @@ -598,17 +597,17 @@ decode_rep_realms(const uint8_t * rzBuff, int act_len, sgj_opaque_p jo2p; jo2p = sgj_new_unattached_object(jsp); - sgj_pr_twin_vi(jsp, jo2p, 1, "Realms_id", SGJ_SEP_EQUAL_NO_SPACE, - sg_get_unaligned_be32(bp + 0)); + sgj_pr_hr_js_vi(jsp, jo2p, 1, "Realms_id", SGJ_SEP_EQUAL_NO_SPACE, + sg_get_unaligned_be32(bp + 0)); if (op->do_hex) { hex2stdout(bp, r_desc_len, -1); continue; } restrictions = sg_get_unaligned_be16(bp + 4); sgj_pr_hr(jsp, " realm_restrictions=0x%hu\n", restrictions); - sgj_add_name_pair_ihex(jsp, jo2p, "realm_restrictions", restrictions); - sgj_pr_twin_vi(jsp, jo2p, 3, "active_zone_domain_id", - SGJ_SEP_EQUAL_NO_SPACE, bp[7]); + sgj_add_nv_ihex(jsp, jo2p, "realm_restrictions", restrictions); + sgj_pr_hr_js_vi(jsp, jo2p, 3, "active_zone_domain_id", + SGJ_SEP_EQUAL_NO_SPACE, bp[7]); ja2p = sgj_new_named_array(jsp, jo2p, "realm_start_end_descriptors_list"); @@ -618,18 +617,16 @@ decode_rep_realms(const uint8_t * rzBuff, int act_len, jo3p = sgj_new_unattached_object(jsp); sgj_pr_hr(jsp, " zone_domain=%u\n", j); - sgj_add_val_i(jsp, jo3p, "corresponding_zone_domain_id", j); + sgj_add_nv_i(jsp, jo3p, "corresponding_zone_domain_id", j); lba = sg_get_unaligned_be64(zp + 0); sgj_pr_hr(jsp, " starting_lba=0x%" PRIx64 "\n", lba); - sgj_add_name_pair_ihex(jsp, jo3p, "realm_starting_lba", - (int64_t)lba); + sgj_add_nv_ihex(jsp, jo3p, "realm_starting_lba", (int64_t)lba); lba = sg_get_unaligned_be64(zp + 8); sgj_pr_hr(jsp, " ending_lba=0x%" PRIx64 "\n", lba); - sgj_add_name_pair_ihex(jsp, jo3p, "realm_ending_lba", - (int64_t)lba); - sgj_add_val_o(jsp, ja2p, NULL /* name */, jo3p); + sgj_add_nv_ihex(jsp, jo3p, "realm_ending_lba", (int64_t)lba); + sgj_add_nv_o(jsp, ja2p, NULL /* name */, jo3p); } - sgj_add_val_o(jsp, jap, NULL /* name */, jo2p); + sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p); } return 0; } @@ -658,16 +655,16 @@ decode_rep_zdomains(const uint8_t * rzBuff, int act_len, zd_locator = sg_get_unaligned_be64(rzBuff + 16); else zd_locator = 0; - sgj_pr_twin_vi(jsp, jop, 0, "Zone_domains_returned_list_length=", - SGJ_SEP_EQUAL_NO_SPACE, zd_ret_len); - sgj_pr_twin_vi(jsp, jop, 0, "Zone_domains_supported", - SGJ_SEP_EQUAL_NO_SPACE, zdoms_sup); - sgj_pr_twin_vi(jsp, jop, 0, "Zone_domains_reported", - SGJ_SEP_EQUAL_NO_SPACE, zdoms_rep); + sgj_pr_hr_js_vi(jsp, jop, 0, "Zone_domains_returned_list_length=", + SGJ_SEP_EQUAL_NO_SPACE, zd_ret_len); + sgj_pr_hr_js_vi(jsp, jop, 0, "Zone_domains_supported", + SGJ_SEP_EQUAL_NO_SPACE, zdoms_sup); + sgj_pr_hr_js_vi(jsp, jop, 0, "Zone_domains_reported", + SGJ_SEP_EQUAL_NO_SPACE, zdoms_rep); sgj_pr_hr(jsp, "Reporting_options=0x%x\n", zd_rep_opts); - sgj_add_name_pair_ihex(jsp, jop, "Reporting_options", zd_rep_opts); + sgj_add_nv_ihex(jsp, jop, "Reporting_options", zd_rep_opts); sgj_pr_hr(jsp, "Zone_domain_locator=0x%" PRIx64 "\n", zd_locator); - sgj_add_name_pair_ihex(jsp, jop, "Zone_domain_locator", zd_locator); + sgj_add_nv_ihex(jsp, jop, "Zone_domain_locator", zd_locator); der_zdoms = zd_len / 96; if (op->vb > 1) @@ -680,24 +677,24 @@ decode_rep_zdomains(const uint8_t * rzBuff, int act_len, sgj_opaque_p jo2p; jo2p = sgj_new_unattached_object(jsp); - sgj_pr_twin_vi(jsp, jo2p, 3, "zone_domain", - SGJ_SEP_EQUAL_NO_SPACE, bp[0]); + sgj_pr_hr_js_vi(jsp, jo2p, 3, "zone_domain", + SGJ_SEP_EQUAL_NO_SPACE, bp[0]); lba = sg_get_unaligned_be64(bp + 16); sgj_pr_hr(jsp, " zone_count=%" PRIu64 "\n", lba); - sgj_add_name_pair_ihex(jsp, jo2p, "zone_count", lba); + sgj_add_nv_ihex(jsp, jo2p, "zone_count", lba); lba = sg_get_unaligned_be64(bp + 24); sgj_pr_hr(jsp, " starting_lba=0x%" PRIx64 "\n", lba); - sgj_add_name_pair_ihex(jsp, jo2p, "starting_lba", lba); + sgj_add_nv_ihex(jsp, jo2p, "starting_lba", lba); lba = sg_get_unaligned_be64(bp + 32); sgj_pr_hr(jsp, " ending_lba=0x%" PRIx64 "\n", lba); - sgj_add_name_pair_ihex(jsp, jo2p, "ending_lba", lba); + sgj_add_nv_ihex(jsp, jo2p, "ending_lba", lba); sgj_pr_hr(jsp, " zone_domain_zone_type=0x%x\n", bp[40]); - sgj_add_name_pair_ihex(jsp, jo2p, "zone_domain_zone_type", bp[40]); - sgj_pr_twin_vi(jsp, jo2p, 5, "VZDZT", SGJ_SEP_EQUAL_NO_SPACE, - !!(0x2 & bp[42])); - sgj_pr_twin_vi(jsp, jo2p, 5, "SRB", SGJ_SEP_EQUAL_NO_SPACE, - !!(0x1 & bp[42])); - sgj_add_val_o(jsp, jap, NULL /* name */, jo2p); + sgj_add_nv_ihex(jsp, jo2p, "zone_domain_zone_type", bp[40]); + sgj_pr_hr_js_vi(jsp, jo2p, 5, "VZDZT", SGJ_SEP_EQUAL_NO_SPACE, + !!(0x2 & bp[42])); + sgj_pr_hr_js_vi(jsp, jo2p, 5, "SRB", SGJ_SEP_EQUAL_NO_SPACE, + !!(0x1 & bp[42])); + sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p); } return 0; } @@ -774,8 +771,8 @@ find_report_zones(int sg_fd, uint8_t * rzBuff, const char * cmd_name, } else { sgj_pr_hr(jsp, "Condition met at:\n"); sgj_pr_hr(jsp, " %s: %d\n", zn_dnum_s, zn_dnum); - sgj_add_val_b(jsp, jo2p, "met", true); - sgj_add_val_i(jsp, jo2p, "zone_descriptor_index", zn_dnum); + sgj_add_nv_b(jsp, jo2p, "met", true); + sgj_add_nv_i(jsp, jo2p, "zone_descriptor_index", zn_dnum); prt_a_zn_desc(bp, op, jsp, jo2p); } } else { @@ -783,8 +780,8 @@ find_report_zones(int sg_fd, uint8_t * rzBuff, const char * cmd_name, memset(b, 0xff, 64); hex2stdout((const uint8_t *)b, 64, -1); } else { - sgj_add_val_b(jsp, jo2p, "met", false); - sgj_add_val_i(jsp, jo2p, "zone_descriptor_index", zn_dnum); + sgj_add_nv_b(jsp, jo2p, "met", false); + sgj_add_nv_i(jsp, jo2p, "zone_descriptor_index", zn_dnum); if (num_rem < 1) sgj_pr_hr(jsp, "Condition NOT met, checked %d zones; " "next %s%u\n", op->do_num, zn_dnum_s, zn_dnum); @@ -1340,7 +1337,7 @@ main(int argc, char * argv[]) else if (op->do_realms) cmd_name = "Report realms"; if (as_json) - sgj_add_val_s(jsp, jop, "scsi_command_name", cmd_name); + sgj_add_nv_s(jsp, jop, "scsi_command_name", cmd_name); if ((op->serv_act != REPORT_ZONES_SA) && op->do_partial) { pr2serr("Can only use --partial with REPORT ZONES\n"); return SG_LIB_SYNTAX_ERROR; diff --git a/src/sg_requests.c b/src/sg_requests.c index ee0c0388..903c7ce8 100644 --- a/src/sg_requests.c +++ b/src/sg_requests.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2021 Douglas Gilbert. + * Copyright (c) 2004-2022 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. @@ -34,7 +34,7 @@ * This program issues the SCSI command REQUEST SENSE to the given SCSI device. */ -static const char * version_str = "1.39 20211114"; +static const char * version_str = "1.40 20220607"; #define MAX_REQS_RESP_LEN 255 #define DEF_REQS_RESP_LEN 252 @@ -45,17 +45,6 @@ static const char * version_str = "1.39 20211114"; #define REQUEST_SENSE_CMD 0x3 #define REQUEST_SENSE_CMDLEN 6 -/* Not all environments support the Unix sleep() */ -#if defined(MSC_VER) || defined(__MINGW32__) -#define HAVE_MS_SLEEP -#endif -#ifdef HAVE_MS_SLEEP -#include -#define sleep_for(seconds) Sleep( (seconds) * 1000) -#else -#define sleep_for(seconds) sleep(seconds) -#endif - #define ME "sg_requests: " @@ -309,7 +298,7 @@ main(int argc, char * argv[]) for (k = 0; k < num_rs; ++k) { act_din_len = 0; if (k > 0) - sleep_for(30); + sg_sleep_secs(30); set_scsi_pt_cdb(ptvp, rs_cdb, sizeof(rs_cdb)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); memset(rsBuff, 0x0, sizeof(rsBuff)); diff --git a/src/sg_sanitize.c b/src/sg_sanitize.c index 41db4bba..74c33f2f 100644 --- a/src/sg_sanitize.c +++ b/src/sg_sanitize.c @@ -33,19 +33,7 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -static const char * version_str = "1.18 20220127"; - -/* Not all environments support the Unix sleep() */ -#if defined(MSC_VER) || defined(__MINGW32__) -#define HAVE_MS_SLEEP -#endif -#ifdef HAVE_MS_SLEEP -#include -#define sleep_for(seconds) Sleep( (seconds) * 1000) -#else -#define sleep_for(seconds) sleep(seconds) -#endif - +static const char * version_str = "1.19 20220608"; #define ME "sg_sanitize: " @@ -720,20 +708,8 @@ main(int argc, char * argv[]) sg_put_unaligned_be16((uint16_t)op->ipl, wBuff + 2); } - if ((! op->quick) && (! op->fail)) { - printf("\nA SANITIZE will commence in 15 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA SANITIZE will commence in 10 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nA SANITIZE will commence in 5 seconds\n"); - printf(" ALL data on %s will be DESTROYED\n", device_name); - printf(" Press control-C to abort\n"); - sleep_for(5); - } + if ((! op->quick) && (! op->fail)) + sg_warn_and_wait("SANITIZE", device_name, true); ret = do_sanitize(sg_fd, op, wBuff, param_lst_len); if (ret) { @@ -747,7 +723,7 @@ main(int argc, char * argv[]) pr2serr("Due to --dry-run option, leave poll loop\n"); break; } - sleep_for(POLL_DURATION_SECS); + sg_sleep_secs(POLL_DURATION_SECS); memset(rsBuff, 0x0, sizeof(rsBuff)); res = sg_ll_request_sense(sg_fd, op->desc, rsBuff, sizeof(rsBuff), 1, vb); diff --git a/src/sg_unmap.c b/src/sg_unmap.c index 2deb71ad..c24c676a 100644 --- a/src/sg_unmap.c +++ b/src/sg_unmap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2018 Douglas Gilbert. + * Copyright (c) 2009-2022 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. @@ -29,16 +29,6 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -#if defined(MSC_VER) || defined(__MINGW32__) -#define HAVE_MS_SLEEP -#endif - -#ifdef HAVE_MS_SLEEP -#include -#define sleep_for(seconds) Sleep( (seconds) * 1000) -#else -#define sleep_for(seconds) sleep(seconds) -#endif /* A utility program originally written for the Linux OS SCSI subsystem. * @@ -46,7 +36,7 @@ * logical blocks. Note that DATA MAY BE LOST. */ -static const char * version_str = "1.17 20180628"; +static const char * version_str = "1.18 20220608"; #define DEF_TIMEOUT_SECS 60 @@ -676,25 +666,14 @@ main(int argc, char * argv[]) printf("%s is: %.8s %.16s %.4s\n", device_name, inq_resp.vendor, inq_resp.product, inq_resp.revision); - sleep_for(3); + sg_sleep_secs(3); if (to_end_of_device) - snprintf(b, sizeof(b), "LBA 0x%" PRIx64 " to end of %s " - "(0x%" PRIx64 ")", all_start, device_name, all_last); + snprintf(b, sizeof(b), "%s from LBA 0x%" PRIx64 " to end " + "(0x%" PRIx64 ")", device_name, all_start, all_last); else - snprintf(b, sizeof(b), "LBA 0x%" PRIx64 " to 0x%" PRIx64 - " on %s", all_start, all_last, device_name); - printf("\nAn UNMAP (a.k.a. trim) will commence in 15 seconds\n"); - printf(" ALL data from %s will be LOST\n", b); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nAn UNMAP will commence in 10 seconds\n"); - printf(" ALL data from %s will be LOST\n", b); - printf(" Press control-C to abort\n"); - sleep_for(5); - printf("\nAn UNMAP (a.k.a. trim) will commence in 5 seconds\n"); - printf(" ALL data from %s will be LOST\n", b); - printf(" Press control-C to abort\n"); - sleep_for(7); + snprintf(b, sizeof(b), "%s from LBA 0x%" PRIx64 " to 0x%" + PRIx64, device_name, all_start, all_last); + sg_warn_and_wait("UNMAP (a.k.a. trim)", b, false); } if (dry_run) { pr2serr("Doing dry-run, would have unmapped from LBA 0x%" PRIx64 @@ -757,19 +736,19 @@ retry: if (! do_force) { printf("%s is: %.8s %.16s %.4s\n", device_name, inq_resp.vendor, inq_resp.product, inq_resp.revision); - sleep_for(3); + sg_sleep_secs(3); printf("\nAn UNMAP (a.k.a. trim) will commence in 15 seconds\n"); printf(" Some data will be LOST\n"); printf(" Press control-C to abort\n"); - sleep_for(5); + sg_sleep_secs(5); printf("\nAn UNMAP will commence in 10 seconds\n"); printf(" Some data will be LOST\n"); printf(" Press control-C to abort\n"); - sleep_for(5); + sg_sleep_secs(5); printf("\nAn UNMAP (a.k.a. trim) will commence in 5 seconds\n"); printf(" Some data will be LOST\n"); printf(" Press control-C to abort\n"); - sleep_for(7); + sg_sleep_secs(7); } res = sg_ll_unmap_v2(sg_fd, anchor, grpnum, timeout, param_arr, param_len, true, vb); diff --git a/src/sg_vpd.c b/src/sg_vpd.c index 9350dbc6..20f74b5c 100644 --- a/src/sg_vpd.c +++ b/src/sg_vpd.c @@ -40,7 +40,7 @@ */ -static const char * version_str = "1.70 20220218"; /* spc6r06 + sbc5r01 */ +static const char * version_str = "1.71 20220608"; /* spc6r06 + sbc5r01 */ /* standard VPD pages, in ascending page number order */ #define VPD_SUPPORTED_VPDS 0x0 diff --git a/src/sg_vpd_vendor.c b/src/sg_vpd_vendor.c index d79ccc7d..a1a1a501 100644 --- a/src/sg_vpd_vendor.c +++ b/src/sg_vpd_vendor.c @@ -1558,6 +1558,6 @@ svpd_decode_vendor(int sg_fd, struct opts_t * op, int off) return 0; } } else - pr2serr("Vendor VPD page=0x%x failed to fetch", op->vpd_pn); + pr2serr("Vendor VPD page=0x%x failed to fetch\n", op->vpd_pn); return res; } diff --git a/src/sg_zone.c b/src/sg_zone.c index ff4dc366..e4540143 100644 --- a/src/sg_zone.c +++ b/src/sg_zone.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2021 Douglas Gilbert. + * Copyright (c) 2014-2022 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. @@ -32,12 +32,15 @@ /* A utility program originally written for the Linux OS SCSI subsystem. * - * - * This program issues a SCSI CLOSE ZONE, FINISH ZONE or OPEN ZONE command - * to the given SCSI device. Based on zbc-r04c.pdf . + * This program issues one of the following SCSI commands: + * - CLOSE ZONE + * - FINISH ZONE + * - OPEN ZONE + * - REMOVE ELEMENT AND MODIFY ZONES + * - SEQUENTIALIZE ZONE */ -static const char * version_str = "1.17 20211114"; +static const char * version_str = "1.18 20220609"; #define SG_ZONING_OUT_CMDLEN 16 #define CLOSE_ZONE_SA 0x1 @@ -58,6 +61,7 @@ static struct option long_options[] = { {"finish", no_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {"open", no_argument, 0, 'o'}, + {"quick", no_argument, 0, 'q'}, {"remove", no_argument, 0, 'r'}, {"reset-all", no_argument, 0, 'R'}, /* same as --all */ {"reset_all", no_argument, 0, 'R'}, @@ -68,14 +72,14 @@ static struct option long_options[] = { {0, 0, 0, 0}, }; -/* Indexed by service action */ +/* Indexed by service action of opcode 0x94 (Zone out) unless noted */ static const char * sa_name_arr[] = { "no SA=0", /* 0x0 */ "Close zone", "Finish zone", "Open zone", "-", "-", "-", "-", - "Zone activate", /* 0x8 */ + "-", "-", "-", "-", "-", "-", "-", @@ -84,7 +88,7 @@ static const char * sa_name_arr[] = { "-", "-", "-", "-", "-", "-", "-", "-", "-", - "Remove element and modify zones", /* 0x1a */ + "Remove element and modify zones", /* service action in(16), 0x1a */ }; @@ -94,10 +98,9 @@ usage() pr2serr("Usage: " "sg_zone [--all] [--close] [--count=ZC] [--element=EID] " "[--finish]\n" - " [--help] [--open] [--remove] " - "[--sequentialize] " - "[--verbose]\n" - " [--version] [--zone=ID] DEVICE\n"); + " [--help] [--open] [--quick] [--remove] " + "[--sequentialize]\n" + " [--verbose] [--version] [--zone=ID] DEVICE\n"); pr2serr(" where:\n" " --all|-a sets the ALL flag in the cdb\n" " --close|-c issue CLOSE ZONE command\n" @@ -109,6 +112,8 @@ usage() " --finish|-f issue FINISH ZONE command\n" " --help|-h print out usage message\n" " --open|-o issue OPEN ZONE command\n" + " --quick|-q bypass 15 second warn and wait " + "(for --remove)\n" " --remove|-r issue REMOVE ELEMENT AND MODIFY ZONES " "command\n" " --sequentialize|-S issue SEQUENTIALIZE ZONE command\n" @@ -116,11 +121,10 @@ usage() " --version|-V print version string and exit\n" " --zone=ID|-z ID ID is the starting LBA of the zone " "(def: 0)\n\n" - "Performs a SCSI OPEN ZONE, CLOSE ZONE, FINISH ZONE or " - "SEQUENTIALIZE\nZONE command. ID is decimal by default, for hex " - "use a leading '0x'\nor a trailing 'h'. Either --close, " - "--finish, --open, --remove or\n--sequentialize option needs to " - "be given.\n"); + "Performs a SCSI OPEN ZONE, CLOSE ZONE, FINISH ZONE, " + "REMOVE ELEMENT AND\nMODIFY ZONES or SEQUENTIALIZE ZONE " + "command. Either --close, --finish,\n--open, --remove or " + "--sequentialize option needs to be given.\n"); } /* Invokes the zone out command indicated by 'sa' (ZBC). Return of 0 @@ -139,7 +143,7 @@ sg_ll_zone_out(int sg_fd, int sa, uint64_t zid, uint16_t zc, bool all, zo_cdb[1] = 0x1f & sa; if (REM_ELEM_MOD_ZONES_SA == sa) { /* zid carries element identifier */ zo_cdb[0] = SG_SERVICE_ACTION_IN_16; /* N.B. changing opcode */ - sg_put_unaligned_be32((uint32_t)zid, zo_cdb + 10); + sg_put_unaligned_be32((uint32_t)zid, zo_cdb + 10); /* element id */ } else { sg_put_unaligned_be64(zid, zo_cdb + 2); sg_put_unaligned_be16(zc, zo_cdb + 12); @@ -194,7 +198,9 @@ main(int argc, char * argv[]) bool close = false; bool finish = false; bool open = false; + bool quick = false; bool reamz = false; + bool element_id_given = false; bool sequentialize = false; bool verbose_given = false; bool version_given = false; @@ -212,7 +218,7 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "acC:e:fhorRSvVz:", long_options, + c = getopt_long(argc, argv, "acC:e:fhoqrRSvVz:", long_options, &option_index); if (c == -1) break; @@ -243,7 +249,8 @@ main(int argc, char * argv[]) } if (0 == ll) pr2serr("Warning: 0 is an invalid element identifier\n"); - zid = (uint64_t)ll; + zid = (uint64_t)ll; /* putting element_id in zid */ + element_id_given = true; break; case 'f': finish = true; @@ -257,6 +264,9 @@ main(int argc, char * argv[]) open = true; sa = OPEN_ZONE_SA; break; + case 'q': + quick = true; + break; case 'r': reamz = true; sa = REM_ELEM_MOD_ZONES_SA; @@ -323,8 +333,15 @@ main(int argc, char * argv[]) if (1 != ((int)close + (int)finish + (int)open + (int)sequentialize + (int)reamz)) { - pr2serr("one of these options: --close, --finish, --open " - "--sequentialize and\n--remove must be given\n"); + pr2serr("One, and only one, of these options needs to be given:\n" + " --close, --finish, --open, --remove or --sequentialize " + "\n\n"); + usage(); + return SG_LIB_CONTRADICT; + } + if (element_id_given && (! reamz)) { + pr2serr("The --element=EID option should only be used with the " + "--remove option\n\n"); usage(); return SG_LIB_CONTRADICT; } @@ -345,6 +362,9 @@ main(int argc, char * argv[]) ret = sg_convert_errno(err); goto fini; } + if (reamz && (! quick)) + sg_warn_and_wait(sa_name_arr[REM_ELEM_MOD_ZONES_SA], device_name, + false); res = sg_ll_zone_out(sg_fd, sa, zid, zc, all, true, verbose); ret = res; -- cgit v1.2.3