static int write_dataout(const char *filename, unsigned char *buf, int len) { int ret = SG_LIB_FILE_ERROR; int fd; if ((filename == NULL) || ((1 == strlen(filename)) && ('-' == filename[0]))) fd = STDOUT_FILENO; else { fd = creat(filename, 0666); if (fd < 0) { perror(filename); goto bail; } } if (sg_set_binary_mode(fd) < 0) { perror("sg_set_binary_mode"); goto bail; } if (write(fd, buf, len) != len) { perror(filename ? filename : "stdout"); goto bail; } ret = 0; bail: if (fd >= 0 && fd != STDOUT_FILENO) close(fd); return ret; }
static unsigned char * fetch_dataout(struct opts_t * op) { unsigned char *buf = NULL; unsigned char *wrkBuf = NULL; int fd, len; int ok = 0; if (op->dataout_file) { fd = open(op->dataout_file, O_RDONLY); if (fd < 0) { perror(op->dataout_file); goto bail; } } else { fd = STDIN_FILENO; } if (sg_set_binary_mode(fd) < 0) { perror("sg_set_binary_mode"); goto bail; } if (op->dataout_offset > 0) { if (skip(fd, op->dataout_offset) != 0) { goto bail; } } buf = my_memalign(op->dataout_len, &wrkBuf); if (buf == NULL) { perror("malloc"); goto bail; } len = read(fd, buf, op->dataout_len); if (len < 0) { perror("Failed to read input data"); goto bail; } else if (len < op->dataout_len) { fprintf(stderr, "EOF on input file/stream\n"); goto bail; } ok = 1; bail: if (fd >= 0 && fd != STDIN_FILENO) close(fd); if (!ok) { if (wrkBuf) free(wrkBuf); return NULL; } return buf; }
/* Returns file descriptor ( >= 0) if successfule. Else a negated sg3_utils * error code is returned. */ static int open_if(const char * fn, int got_stdin) { int fd, err; if (got_stdin) fd = STDIN_FILENO; else { fd = open(fn, O_RDONLY); if (fd < 0) { err = errno; pr2serr(ME "open error: %s: %s\n", fn, safe_strerror(err)); return -sg_convert_errno(err); } } if (sg_set_binary_mode(fd) < 0) { perror("sg_set_binary_mode"); return -SG_LIB_FILE_ERROR; } return fd; }
int main(int argc, char * argv[]) { bool do_long = false; bool o_readonly = false; bool do_raw = false; bool verbose_given = false; bool version_given = false; int res, c, len, k; int sg_fd = -1; int do_help = 0; int do_hex = 0; int rb_id = 0; int rb_len = 4; int rb_mode = 0; int rb_mode_sp = 0; int resid = 0; int verbose = 0; int ret = 0; int64_t ll; uint64_t rb_offset = 0; const char * device_name = NULL; uint8_t * resp; const struct mode_s * mp; while (1) { int option_index = 0; c = getopt_long(argc, argv, "hHi:l:Lm:o:rRS:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': case '?': ++do_help; break; case 'H': ++do_hex; break; case 'i': rb_id = sg_get_num(optarg); if ((rb_id < 0) || (rb_id > 255)) { pr2serr("argument to '--id' should be in the range 0 to " "255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'l': rb_len = sg_get_num(optarg); if (rb_len < 0) { pr2serr("bad argument to '--length'\n"); return SG_LIB_SYNTAX_ERROR; } if (rb_len > 0xffffff) { pr2serr("argument to '--length' must be <= 0xffffff\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'L': do_long = true; break; case 'm': if (isdigit(*optarg)) { rb_mode = sg_get_num(optarg); if ((rb_mode < 0) || (rb_mode > 31)) { pr2serr("argument to '--mode' should be in the range 0 " "to 31\n"); return SG_LIB_SYNTAX_ERROR; } } else { len = strlen(optarg); for (mp = modes; mp->mode_string; ++mp) { if (0 == strncmp(mp->mode_string, optarg, len)) { rb_mode = mp->mode; break; } } if (NULL == mp->mode_string) { print_modes(); return SG_LIB_SYNTAX_ERROR; } } break; case 'o': ll = sg_get_llnum(optarg); if (ll < 0) { pr2serr("bad argument to '--offset'\n"); return SG_LIB_SYNTAX_ERROR; } rb_offset = ll; break; case 'r': do_raw = true; break; case 'R': o_readonly = true; break; case 'S': rb_mode_sp = sg_get_num(optarg); if ((rb_mode_sp < 0) || (rb_mode_sp > 7)) { pr2serr("expected argument to '--specific' to be 0 to 7\n"); return SG_LIB_SYNTAX_ERROR; } 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 (do_help) { if (do_help > 1) { usage(); pr2serr("\n"); print_modes(); } else usage(); return 0; } 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 (NULL == device_name) { pr2serr("Missing device name!\n\n"); usage(); return SG_LIB_SYNTAX_ERROR; } len = rb_len ? rb_len : 8; resp = (uint8_t *)malloc(len); if (NULL == resp) { pr2serr("unable to allocate %d bytes on the heap\n", len); return SG_LIB_CAT_OTHER; } memset(resp, 0, len); if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); ret = SG_LIB_FILE_ERROR; goto fini; } } #ifdef SG_LIB_WIN32 #ifdef SG_LIB_WIN32_DIRECT if (verbose > 4) pr2serr("Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif #endif sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { if (verbose) pr2serr("open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = sg_convert_errno(-sg_fd); goto fini; } if (do_long) res = sg_ll_read_buffer_16(sg_fd, rb_mode, rb_mode_sp, rb_id, rb_offset, resp, rb_len, &resid, true, verbose); else if (rb_offset > 0xffffff) { pr2serr("--offset value is too large for READ BUFFER(10), try " "--16\n"); ret = SG_LIB_SYNTAX_ERROR; goto fini; } else res = sg_ll_read_buffer_10(sg_fd, rb_mode, rb_mode_sp, rb_id, (uint32_t)rb_offset, resp, rb_len, &resid, true, verbose); if (0 != res) { char b[80]; ret = res; if (res > 0) { sg_get_category_sense_str(res, sizeof(b), b, verbose); pr2serr("Read buffer(%d) failed: %s\n", (do_long ? 16 : 10), b); } goto fini; } if (resid > 0) rb_len -= resid; /* got back less than requested */ if (rb_len > 0) { if (do_raw) dStrRaw(resp, rb_len); else if (do_hex || (rb_len < 4)) hex2stdout((const uint8_t *)resp, rb_len, ((do_hex > 1) ? 0 : 1)); else { switch (rb_mode) { case MODE_DESCRIPTOR: k = sg_get_unaligned_be24(resp + 1); printf("OFFSET BOUNDARY: %d, Buffer offset alignment: " "%d-byte\n", resp[0], (1 << resp[0])); printf("BUFFER CAPACITY: %d (0x%x)\n", k, k); break; case MODE_ECHO_BDESC: k = sg_get_unaligned_be16(resp + 2) & 0x1fff; printf("EBOS:%d\n", resp[0] & 1 ? 1 : 0); printf("Echo buffer capacity: %d (0x%x)\n", k, k); break; default: hex2stdout((const uint8_t *)resp, rb_len, (verbose > 1 ? 0 : 1)); break; } } } fini: if (resp) free(resp); 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_read_buffer failed: ", ret)) pr2serr("Some error occurred, try again with '-v' " "or '-vv' for more information\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, res, c, len, k, n, got_stdin, is_reg, rsp_len, verb, last; int infd = -1; int do_help = 0; const char * device_name = NULL; const char * file_name = NULL; unsigned char * dmp = NULL; unsigned char * dip = NULL; char * cp; char ebuff[EBUFF_SZ]; struct stat a_stat; struct dout_buff_t dout; struct opts_t opts; struct opts_t * op; const struct mode_s * mp; uint32_t gen_code = 0; int ret = 0; op = &opts; memset(op, 0, sizeof(opts)); memset(&dout, 0, sizeof(dout)); while (1) { int option_index = 0; c = getopt_long(argc, argv, "b:hi:I:l:m:No:s:S:t:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'b': op->bpw = sg_get_num(optarg); if (op->bpw < 0) { pr2serr("argument to '--bpw' should be in a positive " "number\n"); return SG_LIB_SYNTAX_ERROR; } if ((cp = strchr(optarg, ','))) { if (0 == strncmp("act", cp + 1, 3)) ++op->bpw_then_activate; } break; case 'h': case '?': ++do_help; break; case 'i': op->mc_id = sg_get_num(optarg); if ((op->mc_id < 0) || (op->mc_id > 255)) { pr2serr("argument to '--id' should be in the range 0 to " "255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'I': file_name = optarg; break; case 'l': op->mc_len = sg_get_num(optarg); if (op->mc_len < 0) { pr2serr("bad argument to '--length'\n"); return SG_LIB_SYNTAX_ERROR; } op->mc_len_given = 1; break; case 'm': if (isdigit(*optarg)) { op->mc_mode = sg_get_num(optarg); if ((op->mc_mode < 0) || (op->mc_mode > 255)) { pr2serr("argument to '--mode' should be in the range 0 " "to 255\n"); return SG_LIB_SYNTAX_ERROR; } } else { len = strlen(optarg); for (mp = mode_arr; mp->mode_string; ++mp) { if (0 == strncmp(mp->mode_string, optarg, len)) { op->mc_mode = mp->mode; break; } } if (! mp->mode_string) { print_modes(); return SG_LIB_SYNTAX_ERROR; } } break; case 'N': ++op->mc_non; break; case 'o': op->mc_offset = sg_get_num(optarg); if (op->mc_offset < 0) { pr2serr("bad argument to '--offset'\n"); return SG_LIB_SYNTAX_ERROR; } if (0 != (op->mc_offset % 4)) { pr2serr("'--offset' value needs to be a multiple of 4\n"); return SG_LIB_SYNTAX_ERROR; } break; case 's': op->mc_skip = sg_get_num(optarg); if (op->mc_skip < 0) { pr2serr("bad argument to '--skip'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'S': op->mc_subenc = sg_get_num(optarg); if ((op->mc_subenc < 0) || (op->mc_subenc > 255)) { pr2serr("expected argument to '--subenc' to be 0 to 255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 't': op->mc_tlen = sg_get_num(optarg); if (op->mc_tlen < 0) { pr2serr("bad argument to '--tlength'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'v': ++op->verbose; break; case 'V': pr2serr(ME "version: %s\n", version_str); return 0; default: pr2serr("unrecognised option code 0x%x ??\n", c); usage(); return SG_LIB_SYNTAX_ERROR; } } if (do_help) { if (do_help > 1) { usage(); pr2serr("\n"); print_modes(); } else usage(); return 0; } 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; } } if (NULL == device_name) { pr2serr("missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if ((op->mc_len > 0) && (op->bpw > op->mc_len)) { pr2serr("trim chunk size (CS) to be the same as LEN\n"); op->bpw = op->mc_len; } #ifdef SG_LIB_WIN32 #ifdef SG_LIB_WIN32_DIRECT if (op->verbose > 4) pr2serr("Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif #endif sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, op->verbose); if (sg_fd < 0) { pr2serr(ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } if (file_name && ((MODE_DNLD_STATUS == op->mc_mode) || (MODE_ACTIVATE_MC == op->mc_mode))) pr2serr("ignoring --in=FILE option\n"); else if (file_name) { got_stdin = (0 == strcmp(file_name, "-")) ? 1 : 0; if (got_stdin) infd = STDIN_FILENO; else { if ((infd = open(file_name, O_RDONLY)) < 0) { snprintf(ebuff, EBUFF_SZ, ME "could not open %s for reading", file_name); perror(ebuff); ret = SG_LIB_FILE_ERROR; goto fini; } else if (sg_set_binary_mode(infd) < 0) perror("sg_set_binary_mode"); } if ((0 == fstat(infd, &a_stat)) && S_ISREG(a_stat.st_mode)) { is_reg = 1; if (0 == op->mc_len) { if (op->mc_skip >= a_stat.st_size) { pr2serr("skip exceeds file size of %d bytes\n", (int)a_stat.st_size); ret = SG_LIB_FILE_ERROR; goto fini; } op->mc_len = (int)(a_stat.st_size) - op->mc_skip; } } else { is_reg = 0; if (0 == op->mc_len) op->mc_len = DEF_XFER_LEN; } if (op->mc_len > MAX_XFER_LEN) { pr2serr("file size or requested length (%d) exceeds " "MAX_XFER_LEN of %d bytes\n", op->mc_len, MAX_XFER_LEN); ret = SG_LIB_FILE_ERROR; goto fini; } if (NULL == (dmp = (unsigned char *)malloc(op->mc_len))) { pr2serr(ME "out of memory (to hold microcode)\n"); ret = SG_LIB_CAT_OTHER; goto fini; } /* Don't remember why this is preset to 0xff, from write_buffer */ memset(dmp, 0xff, op->mc_len); if (op->mc_skip > 0) { if (! is_reg) { if (got_stdin) pr2serr("Can't skip on stdin\n"); else pr2serr(ME "not a 'regular' file so can't apply skip\n"); ret = SG_LIB_FILE_ERROR; goto fini; } if (lseek(infd, op->mc_skip, SEEK_SET) < 0) { snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to " "required position on %s", file_name); perror(ebuff); ret = SG_LIB_FILE_ERROR; goto fini; } } res = read(infd, dmp, op->mc_len); if (res < 0) { snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", file_name); perror(ebuff); ret = SG_LIB_FILE_ERROR; goto fini; } if (res < op->mc_len) { if (op->mc_len_given) { pr2serr("tried to read %d bytes from %s, got %d bytes\n", op->mc_len, file_name, res); pr2serr("pad with 0xff bytes and continue\n"); } else { if (op->verbose) { pr2serr("tried to read %d bytes from %s, got %d " "bytes\n", op->mc_len, file_name, res); pr2serr("will send %d bytes", res); if ((op->bpw > 0) && (op->bpw < op->mc_len)) pr2serr(", %d bytes per WRITE BUFFER command\n", op->bpw); else pr2serr("\n"); } op->mc_len = res; } } if (! got_stdin) close(infd); infd = -1; } else if (! ((MODE_DNLD_STATUS == op->mc_mode) || (MODE_ACTIVATE_MC == op->mc_mode))) { pr2serr("need --in=FILE option with given mode\n"); ret = SG_LIB_SYNTAX_ERROR; goto fini; } if (op->mc_tlen < op->mc_len) op->mc_tlen = op->mc_len; if (op->mc_non && (MODE_DNLD_STATUS == op->mc_mode)) { pr2serr("Do nothing because '--non' given so fetching the Download " "microcode status\ndpage might be dangerous\n"); goto fini; } if (NULL == (dip = (unsigned char *)malloc(DEF_DI_LEN))) { pr2serr(ME "out of memory (data-in buffer)\n"); ret = SG_LIB_CAT_OTHER; goto fini; } memset(dip, 0, DEF_DI_LEN); verb = (op->verbose > 1) ? op->verbose - 1 : 0; /* Fetch Download microcode status dpage for generation code ++ */ res = sg_ll_receive_diag(sg_fd, 1 /* pcv */, DPC_DOWNLOAD_MICROCODE, dip, DEF_DI_LEN, 1, verb); if (0 == res) { rsp_len = sg_get_unaligned_be16(dip + 2) + 4; if (rsp_len > DEF_DI_LEN) { pr2serr("<<< warning response buffer too small [%d but need " "%d]>>>\n", DEF_DI_LEN, rsp_len); rsp_len = DEF_DI_LEN; } if (rsp_len < 8) { pr2serr("Download microcode status dpage too short\n"); ret = SG_LIB_CAT_OTHER; goto fini; } } else { ret = res; goto fini; } gen_code = sg_get_unaligned_be32(dip + 4); if (MODE_DNLD_STATUS == op->mc_mode) { ses_download_code_sdg(dip, rsp_len, gen_code); goto fini; } else if (MODE_ACTIVATE_MC == op->mc_mode) { res = send_then_receive(sg_fd, gen_code, 0, NULL, 0, &dout, dip, 1, op); ret = res; goto fini; } res = 0; if (op->bpw > 0) { for (k = 0, last = 0; k < op->mc_len; k += n) { n = op->mc_len - k; if (n > op->bpw) n = op->bpw; else last = 1; if (op->verbose) pr2serr("bpw loop: mode=0x%x, id=%d, off_off=%d, len=%d, " "last=%d\n", op->mc_mode, op->mc_id, k, n, last); res = send_then_receive(sg_fd, gen_code, k, dmp + k, n, &dout, dip, last, op); if (res) break; } if (op->bpw_then_activate && (0 == res)) { op->mc_mode = MODE_ACTIVATE_MC; if (op->verbose) pr2serr("sending Activate deferred microcode [0xf]\n"); res = send_then_receive(sg_fd, gen_code, 0, NULL, 0, &dout, dip, 1, op); } } else { if (op->verbose) pr2serr("single: mode=0x%x, id=%d, offset=%d, len=%d\n", op->mc_mode, op->mc_id, op->mc_offset, op->mc_len); res = send_then_receive(sg_fd, gen_code, 0, dmp, op->mc_len, &dout, dip, 1, op); } if (res) ret = res; fini: if ((infd >= 0) && (! got_stdin)) close(infd); if (dmp) free(dmp); if (dout.doutp) free(dout.doutp); res = sg_cmds_close_device(sg_fd); if (res < 0) { pr2serr("close error: %s\n", safe_strerror(-res)); if (0 == ret) return SG_LIB_FILE_ERROR; } if (ret && (0 == op->verbose)) { if (SG_LIB_CAT_INVALID_OP == ret) pr2serr("%sRECEIVE DIAGNOSTIC RESULTS command not supported\n", ((MODE_DNLD_STATUS == op->mc_mode) ? "" : "SEND DIAGNOSTIC or ")); else if (ret > 0) pr2serr("Failed, exit status %d\n", ret); else if (ret < 0) pr2serr("Some error occurred\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { bool do_packet = false; bool do_ident = false; bool do_raw = false; bool o_readonly = false; bool ck_cond = false; /* set to true to read register(s) back */ bool extend = false; /* set to true to send 48 bit LBA with command */ bool verbose_given = false; bool version_given = false; int c, res; int sg_fd = -1; int cdb_len = SAT_ATA_PASS_THROUGH16_LEN; int do_hex = 0; int verbose = 0; int ret = 0; const char * device_name = NULL; while (1) { int option_index = 0; c = getopt_long(argc, argv, "cehHil:prRvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': ck_cond = true; break; case 'e': extend = true; break; case 'h': case '?': usage(); return 0; case 'H': ++do_hex; break; case 'i': do_ident = true; break; case 'l': cdb_len = sg_get_num(optarg); switch (cdb_len) { case 12: case 16: case 32: break; default: pr2serr("argument to '--len' should be 12, 16 or 32\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'p': do_packet = true; break; case 'r': do_raw = true; break; case 'R': o_readonly = true; 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 (NULL == device_name) { pr2serr("Missing device name!\n\n"); usage(); return 1; } if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } if ((sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose)) < 0) { if (verbose) pr2serr("error opening file: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = sg_convert_errno(-sg_fd); goto fini; } ret = do_identify_dev(sg_fd, do_packet, cdb_len, ck_cond, extend, do_ident, do_hex, do_raw, verbose); 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_sat_identify failed: ", ret)) pr2serr("Some error occurred, try again with '-v' " "or '-vv' for more information\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, k, j, off, res, c, report_len, tgt_port_count; unsigned char reportTgtGrpBuff[REPORT_TGT_GRP_BUFF_LEN]; unsigned char * ucp; int decode = 0; int hex = 0; int raw = 0; int o_readonly = 0; int verbose = 0; int extended = 0; const char * device_name = NULL; int ret = 0; while (1) { int option_index = 0; c = getopt_long(argc, argv, "dehHrRvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'd': decode = 1; break; case 'e': extended = 1; break; case 'h': case '?': usage(); return 0; case 'H': hex = 1; break; case 'r': raw = 1; break; case 'R': ++o_readonly; break; case 'v': ++verbose; break; case 'V': fprintf(stderr, "Version: %s\n", version_str); return 0; default: fprintf(stderr, "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) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if (NULL == device_name) { fprintf(stderr, "missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { fprintf(stderr, "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } memset(reportTgtGrpBuff, 0x0, sizeof(reportTgtGrpBuff)); /* trunc = 0; */ res = sg_ll_report_tgt_prt_grp2(sg_fd, reportTgtGrpBuff, sizeof(reportTgtGrpBuff), extended, 1, verbose); ret = res; if (0 == res) { report_len = (reportTgtGrpBuff[0] << 24) + (reportTgtGrpBuff[1] << 16) + (reportTgtGrpBuff[2] << 8) + reportTgtGrpBuff[3] + 4; if (report_len > (int)sizeof(reportTgtGrpBuff)) { /* trunc = 1; */ fprintf(stderr, " <<report too long for internal buffer," " output truncated\n"); report_len = (int)sizeof(reportTgtGrpBuff); } if (raw) { dStrRaw((const char *)reportTgtGrpBuff, report_len); goto err_out; } if (verbose) printf("Report list length = %d\n", report_len); if (hex) { if (verbose) printf("\nOutput response in hex:\n"); dStrHex((const char *)reportTgtGrpBuff, report_len, 1); goto err_out; } printf("Report target port groups:\n"); ucp = reportTgtGrpBuff + 4; if (extended) { if (0x10 != (ucp[0] & 0x70)) { fprintf(stderr, " <<invalid extended header format\n"); goto err_out; } printf(" Implicit transition time: %d\n", ucp[1]); ucp += 4; } for (k = ucp - reportTgtGrpBuff; k < report_len; k += off, ucp += off) { printf(" target port group id : 0x%x , Pref=%d, Rtpg_fmt=%d\n", (ucp[2] << 8) + ucp[3], !!(ucp[0] & 0x80), (ucp[0] >> 4) & 0x07); printf(" target port group asymmetric access state : "); printf("0x%02x", ucp[0] & 0x0f); if (decode) decode_tpgs_state(ucp[0] & 0x0f); printf("\n"); printf(" T_SUP : %d, ", !!(ucp[1] & 0x80)); printf("O_SUP : %d, ", !!(ucp[1] & 0x40)); printf("LBD_SUP : %d, ", !!(ucp[1] & 0x10)); printf("U_SUP : %d, ", !!(ucp[1] & 0x08)); printf("S_SUP : %d, ", !!(ucp[1] & 0x04)); printf("AN_SUP : %d, ", !!(ucp[1] & 0x02)); printf("AO_SUP : %d\n", !!(ucp[1] & 0x01)); printf(" status code : "); printf("0x%02x", ucp[5]); if (decode) decode_status(ucp[5]); printf("\n"); printf(" vendor unique status : "); printf("0x%02x\n", ucp[6]); printf(" target port count : "); tgt_port_count = ucp[7]; printf("%02x\n", tgt_port_count); for (j = 0; j < tgt_port_count * 4; j += 4) { if (0 == j) printf(" Relative target port ids:\n"); printf(" 0x%02x\n", (ucp[8 + j + 2] << 8) + ucp[8 + j + 3]); } off = 8 + j; } } else if (SG_LIB_CAT_INVALID_OP == res)
int main(int argc, const char ** argv) { char buff[8192]; int num = 8192; long start = 0; int res, k, u, len, n; int inFile = STDIN_FILENO; int doHelp = 0; int doHex = 0; int noAddr = 0; int doVersion = 0; int hasFilename = 0; int ret = 0; const char * cp; for (k = 1; k < argc; k++) { cp = argv[k]; len = strlen(cp); if (0 == strncmp("-b=", cp, 3)) { res = sscanf(cp + 3, "%d", &u); if ((1 != res) || (u < 1)) { fprintf(stderr, "Bad value after '-b=' option\n"); usage(); return 1; } bytes_per_line = u; } else if ((len > 1) && ('-' == cp[0]) && ('-' != cp[1])) { res = 0; n = num_chs_in_str(cp + 1, len - 1, 'h'); doHelp += n; res += n; n = num_chs_in_str(cp + 1, len - 1, 'H'); doHex += n; res += n; n = num_chs_in_str(cp + 1, len - 1, 'N'); noAddr += n; res += n; n = num_chs_in_str(cp + 1, len - 1, 'V'); doVersion += n; res += n; n = num_chs_in_str(cp + 1, len - 1, '?'); doHelp += n; res += n; if (0 == res) { fprintf(stderr, "No option recognized in str: %s\n", cp); usage(); return 1; } } else if (0 == strcmp("-?", argv[k])) ++doHelp; else if (*argv[k] == '-') { fprintf(stderr, "unknown switch: %s\n", argv[k]); usage(); return 1; } else { hasFilename = 1; break; } } if (doVersion) { printf("%s\n", version_str); return 0; } if (doHelp) { usage(); return 0; } /* Make sure num to fetch is integral multiple of bytes_per_line */ if (0 != (num % bytes_per_line)) num = (num / bytes_per_line) * bytes_per_line; if (hasFilename) { for ( ; k < argc; k++) { inFile = open(argv[k], O_RDONLY); if (inFile < 0) { fprintf(stderr, "Couldn't open file: %s\n", argv[k]); ret = 1; } else { sg_set_binary_mode(inFile); start = 0; if (! doHex) printf("ASCII hex dump of file: %s\n", argv[k]); while ((res = read(inFile, buff, num)) > 0) { if (doHex) dStrHexOnly(buff, res, start, noAddr); else dStrHex(buff, res, start, noAddr); start += (long)res; } } close(inFile); } } else { sg_set_binary_mode(inFile); while ((res = read(inFile, buff, num)) > 0) { if (doHex) dStrHexOnly(buff, res, start, noAddr); else dStrHex(buff, res, start, noAddr); start += (long)res; } } return ret; }
int main(int argc, char * argv[]) { int sg_fd, k, j, res, c, rlen, num_descs; int do_brief = 0; int do_hex = 0; int64_t ll; uint64_t lba = 0; uint64_t d_lba = 0; uint32_t d_blocks = 0; int maxlen = DEF_GLBAS_BUFF_LEN; int do_raw = 0; int o_readonly = 0; int verbose = 0; const char * device_name = NULL; const unsigned char * ucp; int ret = 0; while (1) { int option_index = 0; c = getopt_long(argc, argv, "bhHl:m:rRvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'b': ++do_brief; break; case 'h': case '?': usage(); return 0; case 'H': ++do_hex; break; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { fprintf(stderr, "bad argument to '--lba'\n"); return SG_LIB_SYNTAX_ERROR; } lba = (uint64_t)ll; break; case 'm': maxlen = sg_get_num(optarg); if ((maxlen < 0) || (maxlen > MAX_GLBAS_BUFF_LEN)) { fprintf(stderr, "argument to '--maxlen' should be %d or " "less\n", MAX_GLBAS_BUFF_LEN); return SG_LIB_SYNTAX_ERROR; } break; case 'r': ++do_raw; break; case 'R': ++o_readonly; break; case 'v': ++verbose; break; case 'V': fprintf(stderr, "version: %s\n", version_str); return 0; default: fprintf(stderr, "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) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if (NULL == device_name) { fprintf(stderr, "missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (maxlen > DEF_GLBAS_BUFF_LEN) { glbasBuffp = (unsigned char *)calloc(maxlen, 1); if (NULL == glbasBuffp) { fprintf(stderr, "unable to allocate %d bytes on heap\n", maxlen); return SG_LIB_SYNTAX_ERROR; } } if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); ret = SG_LIB_FILE_ERROR; goto free_buff; } } sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { fprintf(stderr, "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = SG_LIB_FILE_ERROR; goto free_buff; } res = sg_ll_get_lba_status(sg_fd, lba, glbasBuffp, maxlen, 1, verbose); ret = res; if (0 == res) { /* in sbc3r25 offset for calculating the 'parameter data length' * (rlen variable below) was reduced from 8 to 4. */ if (maxlen >= 4) rlen = (glbasBuffp[0] << 24) + (glbasBuffp[1] << 16) + (glbasBuffp[2] << 8) + glbasBuffp[3] + 4; else rlen = maxlen; k = (rlen > maxlen) ? maxlen : rlen; if (do_raw) { dStrRaw((const char *)glbasBuffp, k); goto the_end; } if (do_hex) { dStrHex((const char *)glbasBuffp, k, 1); goto the_end; } if (maxlen < 4) { if (verbose) fprintf(stderr, "Exiting because allocation length (maxlen) " " less than 4\n"); goto the_end; } if ((verbose > 1) || (verbose && (rlen > maxlen))) { fprintf(stderr, "response length %d bytes\n", rlen); if (rlen > maxlen) fprintf(stderr, " ... which is greater than maxlen " "(allocation length %d), truncation\n", maxlen); } if (rlen > maxlen) rlen = maxlen; if (do_brief > 1) { if (rlen < 24) { fprintf(stderr, "Need maxlen and response length to " " be at least 24, have %d bytes\n", rlen); ret = SG_LIB_CAT_OTHER; goto the_end; } res = decode_lba_status_desc(glbasBuffp + 8, &d_lba, &d_blocks); if ((res < 0) || (res > 15)) { fprintf(stderr, "first LBA status descriptor returned %d " "??\n", res); ret = SG_LIB_CAT_OTHER; goto the_end; } if ((lba < d_lba) || (lba >= (d_lba + d_blocks))) { fprintf(stderr, "given LBA not in range of first " "descriptor:\n" " descriptor LBA: 0x"); for (j = 0; j < 8; ++j) fprintf(stderr, "%02x", glbasBuffp[8 + j]); fprintf(stderr, " blocks: 0x%x p_status: %d\n", (unsigned int)d_blocks, res); ret = SG_LIB_CAT_OTHER; goto the_end; } printf("%d\n", res); goto the_end; } if (rlen < 24) { printf("No complete LBA status descriptors available\n"); goto the_end; } num_descs = (rlen - 8) / 16; if (verbose) fprintf(stderr, "%d complete LBA status descriptors found\n", num_descs); for (ucp = glbasBuffp + 8, k = 0; k < num_descs; ucp += 16, ++k) { res = decode_lba_status_desc(ucp, &d_lba, &d_blocks); if ((res < 0) || (res > 15)) fprintf(stderr, "descriptor %d: bad LBA status descriptor " "returned %d\n", k + 1, res); if (do_brief) { printf("0x"); for (j = 0; j < 8; ++j) printf("%02x", ucp[j]); printf(" 0x%x %d\n", (unsigned int)d_blocks, res); } else { printf("descriptor LBA: 0x"); for (j = 0; j < 8; ++j) printf("%02x", ucp[j]); printf(" blocks: %u", (unsigned int)d_blocks); switch (res) { case 0: printf(" mapped\n"); break; case 1: printf(" deallocated\n"); break; case 2: printf(" anchored\n"); break; default: printf(" Provisioning status: %d\n", res); break; } } } if ((num_descs * 16) + 8 < rlen) fprintf(stderr, "incomplete trailing LBA status descriptors " "found\n"); } else if (SG_LIB_CAT_INVALID_OP == res) fprintf(stderr, "Get LBA Status command not supported\n"); else if (SG_LIB_CAT_ILLEGAL_REQ == res) fprintf(stderr, "Get LBA Status command: bad field in cdb\n"); else { char b[80]; sg_get_category_sense_str(res, sizeof(b), b, verbose); fprintf(stderr, "Get LBA Status command: %s\n", b); } the_end: res = sg_cmds_close_device(sg_fd); if (res < 0) { fprintf(stderr, "close error: %s\n", safe_strerror(-res)); if (0 == ret) ret = SG_LIB_FILE_ERROR; } free_buff: if (glbasBuffp && (glbasBuffp != glbasBuff)) free(glbasBuffp); return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
/* Read ASCII hex bytes or binary from fname (a file named '-' taken as * stdin). If reading ASCII hex then there should be either one entry per * line or a comma, space or tab separated list of bytes. If no_space is * set then a string of ACSII hex digits is expected, 2 per byte. Everything * from and including a '#' on a line is ignored. Returns 0 if ok, or 1 if * error. */ static int f2hex_arr(const char * fname, int as_binary, int no_space, uint8_t * mp_arr, int * mp_arr_len, int max_arr_len) { int fn_len, in_len, k, j, m, split_line, fd, has_stdin; unsigned int h; const char * lcp; FILE * fp; char line[512]; char carry_over[4]; int off = 0; if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len)) return 1; fn_len = strlen(fname); if (0 == fn_len) return 1; has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */ if (as_binary) { if (has_stdin) { fd = STDIN_FILENO; if (sg_set_binary_mode(STDIN_FILENO) < 0) perror("sg_set_binary_mode"); } else { fd = open(fname, O_RDONLY); if (fd < 0) { pr2serr("unable to open binary file %s: %s\n", fname, safe_strerror(errno)); return 1; } else if (sg_set_binary_mode(fd) < 0) perror("sg_set_binary_mode"); } k = read(fd, mp_arr, max_arr_len); if (k <= 0) { if (0 == k) pr2serr("read 0 bytes from binary file %s\n", fname); else pr2serr("read from binary file %s: %s\n", fname, safe_strerror(errno)); if (! has_stdin) close(fd); return 1; } *mp_arr_len = k; if (! has_stdin) close(fd); return 0; } else { /* So read the file as ASCII hex */ if (has_stdin) fp = stdin; else { fp = fopen(fname, "r"); if (NULL == fp) { pr2serr("Unable to open %s for reading\n", fname); return 1; } } } carry_over[0] = 0; for (j = 0; j < 512; ++j) { if (NULL == fgets(line, sizeof(line), fp)) break; in_len = strlen(line); if (in_len > 0) { if ('\n' == line[in_len - 1]) { --in_len; line[in_len] = '\0'; split_line = 0; } else split_line = 1; } if (in_len < 1) { carry_over[0] = 0; continue; } if (carry_over[0]) { if (isxdigit(line[0])) { carry_over[1] = line[0]; carry_over[2] = '\0'; if (1 == sscanf(carry_over, "%4x", &h)) mp_arr[off - 1] = h; /* back up and overwrite */ else { pr2serr("%s: carry_over error ['%s'] around line %d\n", __func__, carry_over, j + 1); goto bad; } lcp = line + 1; --in_len; } else lcp = line; carry_over[0] = 0; } else lcp = line; m = strspn(lcp, " \t"); if (m == in_len) continue; lcp += m; in_len -= m; if ('#' == *lcp) continue; k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t"); if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) { pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1, m + k + 1); goto bad; } if (no_space) { for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1)); ++k, lcp += 2) { if (1 != sscanf(lcp, "%2x", &h)) { pr2serr("%s: bad hex number in line %d, pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); goto bad; } if ((off + k) >= max_arr_len) { pr2serr("%s: array length exceeded\n", __func__); goto bad; } mp_arr[off + k] = h; } if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1)))) carry_over[0] = *lcp; off += k; } else { for (k = 0; k < 1024; ++k) { if (1 == sscanf(lcp, "%4x", &h)) { if (h > 0xff) { pr2serr("%s: hex number larger than 0xff in line %d, " "pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); goto bad; } if (split_line && (1 == strlen(lcp))) { /* single trailing hex digit might be a split pair */ carry_over[0] = *lcp; } if ((off + k) >= max_arr_len) { pr2serr("%s: array length exceeded\n", __func__); goto bad; } mp_arr[off + k] = h; lcp = strpbrk(lcp, " ,\t"); if (NULL == lcp) break; lcp += strspn(lcp, " ,\t"); if ('\0' == *lcp) break; } else { if (('#' == *lcp) || ('\r' == *lcp)) { --k; break; } pr2serr("%s: error in line %d, at pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); goto bad; } } off += (k + 1); } } *mp_arr_len = off; if (stdin != fp) fclose(fp); return 0; bad: if (stdin != fp) fclose(fp); return 1; }
int main(int argc, char * argv[]) { bool do_one_segment = false; bool o_readonly = false; bool do_raw = false; bool verbose_given = false; bool version_given = false; int k, res, c, rlen; int sg_fd = -1; int do_hex = 0; int maxlen = DEF_REFER_BUFF_LEN; int verbose = 0; int desc = 0; int ret = 0; int64_t ll; uint64_t lba = 0; const char * device_name = NULL; const uint8_t * bp; uint8_t * referralBuffp = referralBuff; uint8_t * free_referralBuffp = NULL; while (1) { int option_index = 0; c = getopt_long(argc, argv, "hHl:m:rRsvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': case '?': usage(); return 0; case 'H': ++do_hex; break; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { pr2serr("bad argument to '--lba'\n"); return SG_LIB_SYNTAX_ERROR; } lba = (uint64_t)ll; break; case 'm': maxlen = sg_get_num(optarg); if ((maxlen < 0) || (maxlen > MAX_REFER_BUFF_LEN)) { pr2serr("argument to '--maxlen' should be %d or less\n", MAX_REFER_BUFF_LEN); return SG_LIB_SYNTAX_ERROR; } break; case 's': do_one_segment = true; break; case 'r': do_raw = true; break; case 'R': o_readonly = true; 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 (NULL == device_name) { pr2serr("No DEVICE argument given\n\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (maxlen > DEF_REFER_BUFF_LEN) { referralBuffp = (uint8_t *)sg_memalign(maxlen, 0, &free_referralBuffp, verbose > 3); if (NULL == referralBuffp) { pr2serr("unable to allocate %d bytes on heap\n", maxlen); return sg_convert_errno(ENOMEM); } } if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); ret = SG_LIB_FILE_ERROR; goto free_buff; } } sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { if (verbose) pr2serr("open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = sg_convert_errno(-sg_fd); goto free_buff; } res = sg_ll_report_referrals(sg_fd, lba, do_one_segment, referralBuffp, maxlen, true, verbose); ret = res; if (0 == res) { if (maxlen >= 4) /* * This is strictly speaking incorrect. However, the * spec reserved bytes 0 and 1, so some implementations * might want to use them to increase the number of * possible user segments. * And maybe someone takes a pity and updates the spec ... */ rlen = sg_get_unaligned_be32(referralBuffp + 0) + 4; else rlen = maxlen; k = (rlen > maxlen) ? maxlen : rlen; if (do_raw) { dStrRaw(referralBuffp, k); goto the_end; } if (do_hex) { hex2stdout(referralBuffp, k, 1); goto the_end; } if (maxlen < 4) { if (verbose) pr2serr("Exiting because allocation length (maxlen) less " "than 4\n"); goto the_end; } if ((verbose > 1) || (verbose && (rlen > maxlen))) { pr2serr("response length %d bytes\n", rlen); if (rlen > maxlen) pr2serr(" ... which is greater than maxlen (allocation " "length %d), truncation\n", maxlen); } if (rlen > maxlen) rlen = maxlen; bp = referralBuffp + 4; k = 0; printf("Report referrals:\n"); while (k < rlen - 4) { printf(" descriptor %d:\n", desc); res = decode_referral_desc(bp + k, rlen - 4 - k); if (res < 0) { pr2serr("bad user data segment referral descriptor\n"); break; } k += res; desc++; } } else { char b[80]; sg_get_category_sense_str(res, sizeof(b), b, verbose); pr2serr("Report Referrals command failed: %s\n", b); } the_end: 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); } free_buff: if (free_referralBuffp) free(free_referralBuffp); if (0 == verbose) { if (! sg_if_can2stderr("sg_referrals failed: ", ret)) pr2serr("Some error occurred, try again with '-v' " "or '-vv' for more information\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, c, res; const char * device_name = NULL; int cdb_len = SAT_ATA_PASS_THROUGH16_LEN; int do_packet = 0; int do_hex = 0; int do_indent = 0; int do_raw = 0; int o_readonly = 0; int verbose = 0; int ck_cond = 0; /* set to 1 to read register(s) back */ int extend = 0; /* set to 1 to send 48 bit LBA with command */ int ret = 0; while (1) { int option_index = 0; c = getopt_long(argc, argv, "cehHil:prRvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': ++ck_cond; break; case 'e': ++extend; break; case 'h': case '?': usage(); return 0; case 'H': ++do_hex; break; case 'i': ++do_indent; break; case 'l': cdb_len = sg_get_num(optarg); if (! ((cdb_len == 12) || (cdb_len == 16))) { pr2serr("argument to '--len' should be 12 or 16\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'p': ++do_packet; break; case 'r': ++do_raw; break; case 'R': ++o_readonly; break; case 'v': ++verbose; break; case 'V': pr2serr("version: %s\n", version_str); return 0; 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; } } if (NULL == device_name) { pr2serr("missing device name!\n"); usage(); return 1; } if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } if ((sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose)) < 0) { pr2serr("error opening file: %s: %s\n", device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } ret = do_identify_dev(sg_fd, do_packet, cdb_len, ck_cond, extend, do_indent, do_hex, do_raw, verbose); res = sg_cmds_close_device(sg_fd); if (res < 0) { pr2serr("close error: %s\n", safe_strerror(-res)); if (0 == ret) return SG_LIB_FILE_ERROR; } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, outfd, res, c; unsigned char * readLongBuff = NULL; void * rawp = NULL; int correct = 0; int xfer_len = 520; int do_16 = 0; int pblock = 0; uint64_t llba = 0; int readonly = 0; int verbose = 0; int64_t ll; int got_stdout; const char * device_name = NULL; char out_fname[256]; char ebuff[EBUFF_SZ]; int ret = 0; memset(out_fname, 0, sizeof out_fname); while (1) { int option_index = 0; c = getopt_long(argc, argv, "chl:o:prSvVx:", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': correct = 1; break; case 'h': case '?': usage(); return 0; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { fprintf(stderr, "bad argument to '--lba'\n"); return SG_LIB_SYNTAX_ERROR; } llba = (uint64_t)ll; break; case 'o': strncpy(out_fname, optarg, sizeof(out_fname) - 1); break; case 'p': pblock = 1; break; case 'r': ++readonly; break; case 'S': do_16 = 1; break; case 'v': ++verbose; break; case 'V': fprintf(stderr, ME "version: %s\n", version_str); return 0; case 'x': xfer_len = sg_get_num(optarg); if (-1 == xfer_len) { fprintf(stderr, "bad argument to '--xfer_len'\n"); return SG_LIB_SYNTAX_ERROR; } break; default: fprintf(stderr, "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) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if (NULL == device_name) { fprintf(stderr, "missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (xfer_len >= MAX_XFER_LEN){ fprintf(stderr, "xfer_len (%d) is out of range ( < %d)\n", xfer_len, MAX_XFER_LEN); usage(); return SG_LIB_SYNTAX_ERROR; } sg_fd = sg_cmds_open_device(device_name, readonly, verbose); if (sg_fd < 0) { fprintf(stderr, ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } if (NULL == (rawp = malloc(MAX_XFER_LEN))) { fprintf(stderr, ME "out of memory\n"); sg_cmds_close_device(sg_fd); return SG_LIB_SYNTAX_ERROR; } readLongBuff = (unsigned char *)rawp; memset(rawp, 0x0, MAX_XFER_LEN); fprintf(stderr, ME "issue read long (%s) to device %s\n xfer_len=%d " "(0x%x), lba=%" PRIu64 " (0x%" PRIx64 "), correct=%d\n", (do_16 ? "16" : "10"), device_name, xfer_len, xfer_len, llba, llba, correct); if ((ret = process_read_long(sg_fd, do_16, pblock, correct, llba, readLongBuff, xfer_len, verbose))) goto err_out; if ('\0' == out_fname[0]) dStrHex((const char *)rawp, xfer_len, 0); else { got_stdout = (0 == strcmp(out_fname, "-")) ? 1 : 0; if (got_stdout) outfd = STDOUT_FILENO; else { if ((outfd = open(out_fname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { snprintf(ebuff, EBUFF_SZ, ME "could not open %s for writing", out_fname); perror(ebuff); goto err_out; } } if (sg_set_binary_mode(outfd) < 0) { perror("sg_set_binary_mode"); goto err_out; } res = write(outfd, readLongBuff, xfer_len); if (res < 0) { snprintf(ebuff, EBUFF_SZ, ME "couldn't write to %s", out_fname); perror(ebuff); goto err_out; } if (! got_stdout) close(outfd); } err_out: if (rawp) free(rawp); res = sg_cmds_close_device(sg_fd); if (res < 0) { fprintf(stderr, "close error: %s\n", safe_strerror(-res)); if (0 == ret) return SG_LIB_FILE_ERROR; } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, res, c, num, nread, infd; int64_t ll; int dpo = 0; int bytchk = 0; int ndo = 0; char *ref_data = NULL; int vrprotect = 0; int64_t count = 1; int64_t orig_count; int bpc = 128; int bpc_given = 0; int got_stdin = 0; int group = 0; uint64_t lba = 0; uint64_t orig_lba; int quiet = 0; int readonly = 0; int verbose = 0; int verify16 = 0; const char * device_name = NULL; const char * file_name = NULL; const char * vc; int ret = 0; unsigned int info = 0; uint64_t info64 = 0; char ebuff[EBUFF_SZ]; while (1) { int option_index = 0; c = getopt_long(argc, argv, "b:B:c:dE:g:hi:l:n:P:qrSvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'b': bpc = sg_get_num(optarg); if (bpc < 1) { fprintf(stderr, "bad argument to '--bpc'\n"); return SG_LIB_SYNTAX_ERROR; } ++bpc_given; break; case 'c': count = sg_get_llnum(optarg); if (count < 0) { fprintf(stderr, "bad argument to '--count'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'd': dpo = 1; break; case 'E': bytchk = sg_get_num(optarg); if ((bytchk < 1) || (bytchk > 3)) { fprintf(stderr, "bad argument to '--ebytchk'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'g': group = sg_get_num(optarg); if ((group < 0) || (group > 31)) { fprintf(stderr, "bad argument to '--group'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'h': case '?': usage(); return 0; case 'i': file_name = optarg; break; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { fprintf(stderr, "bad argument to '--lba'\n"); return SG_LIB_SYNTAX_ERROR; } lba = (uint64_t)ll; break; case 'n': case 'B': /* undocumented, old --bytchk=NDO option */ ndo = sg_get_num(optarg); if (ndo < 1) { fprintf(stderr, "bad argument to '--ndo'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'P': vrprotect = sg_get_num(optarg); if (-1 == vrprotect) { fprintf(stderr, "bad argument to '--vrprotect'\n"); return SG_LIB_SYNTAX_ERROR; } if ((vrprotect < 0) || (vrprotect > 7)) { fprintf(stderr, "'--vrprotect' requires a value from 0 to " "7 (inclusive)\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'q': ++quiet; break; case 'r': ++readonly; break; case 'S': ++verify16; break; case 'v': ++verbose; break; case 'V': fprintf(stderr, ME "version: %s\n", version_str); return 0; default: fprintf(stderr, "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) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if (ndo > 0) { if (0 == bytchk) bytchk = 1; if (bpc_given && (bpc != count)) fprintf(stderr, "'bpc' argument ignored, using --bpc=%" PRIu64 "\n", count); if (count > 0x7fffffffLL) { fprintf(stderr, "count exceed 31 bits, way too large\n"); return SG_LIB_SYNTAX_ERROR; } if ((3 == bytchk) && (1 != count)) { fprintf(stderr, "count must be 1 when bytchk=3\n"); return SG_LIB_SYNTAX_ERROR; } bpc = (int)count; } else if (bytchk > 0) { fprintf(stderr, "when the 'ebytchk=BCH' option is given, " "then '--bytchk=NDO' must also be given\n"); return SG_LIB_SYNTAX_ERROR; } if ((bpc > 0xffff) && (0 == verify16)) { fprintf(stderr, "'%s' exceeds 65535, so use VERIFY(16)\n", (ndo > 0) ? "count" : "bpc"); ++verify16; } if (((lba + count - 1) > 0xffffffffLLU) && (0 == verify16)) { fprintf(stderr, "'lba' exceed 32 bits, so use VERIFY(16)\n"); ++verify16; } if ((group > 0) && (0 == verify16)) fprintf(stderr, "group number ignored with VERIFY(10) command, " "use the --16 option\n"); orig_count = count; orig_lba = lba; if (ndo > 0) { ref_data = (char *)malloc(ndo); if (NULL == ref_data) { fprintf(stderr, "failed to allocate %d byte buffer\n", ndo); return SG_LIB_FILE_ERROR; } if ((NULL == file_name) || (0 == strcmp(file_name, "-"))) { ++got_stdin; infd = STDIN_FILENO; if (sg_set_binary_mode(STDIN_FILENO) < 0) perror("sg_set_binary_mode"); } else { if ((infd = open(file_name, O_RDONLY)) < 0) { snprintf(ebuff, EBUFF_SZ, ME "could not open %s for reading", file_name); perror(ebuff); ret = SG_LIB_FILE_ERROR; goto err_out; } else if (sg_set_binary_mode(infd) < 0) perror("sg_set_binary_mode"); } if (verbose && got_stdin) fprintf(stderr, "about to wait on STDIN\n"); for (nread = 0; nread < ndo; nread += res) { res = read(infd, ref_data + nread, ndo - nread); if (res <= 0) { fprintf(stderr, "reading from %s failed at file offset=%d\n", (got_stdin ? "stdin" : file_name), nread); ret = SG_LIB_FILE_ERROR; goto err_out; } } if (! got_stdin) close(infd); } if (NULL == device_name) { fprintf(stderr, "missing device name!\n"); usage(); ret = SG_LIB_SYNTAX_ERROR; goto err_out; } sg_fd = sg_cmds_open_device(device_name, readonly, verbose); if (sg_fd < 0) { fprintf(stderr, ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = SG_LIB_FILE_ERROR; goto err_out; } vc = verify16 ? "VERIFY(16)" : "VERIFY(10)"; for (; count > 0; count -= bpc, lba += bpc) { num = (count > bpc) ? bpc : count; if (verify16) res = sg_ll_verify16(sg_fd, vrprotect, dpo, bytchk, lba, num, group, ref_data, ndo, &info64, !quiet , verbose); else res = sg_ll_verify10(sg_fd, vrprotect, dpo, bytchk, (unsigned int)lba, num, ref_data, ndo, &info, !quiet, verbose); if (0 != res) { char b[80]; ret = res; switch (res) { case SG_LIB_CAT_ILLEGAL_REQ: fprintf(stderr, "bad field in %s cdb, near lba=0x%" PRIx64 "\n", vc, lba); break; case SG_LIB_CAT_MEDIUM_HARD: fprintf(stderr, "%s medium or hardware error near " "lba=0x%" PRIx64 "\n", vc, lba); break; case SG_LIB_CAT_MEDIUM_HARD_WITH_INFO: if (verify16) fprintf(stderr, "%s medium or hardware error, reported " "lba=0x%" PRIx64 "\n", vc, info64); else fprintf(stderr, "%s medium or hardware error, reported " "lba=0x%x\n", vc, info); break; case SG_LIB_CAT_MISCOMPARE: if ((0 == quiet) || verbose) fprintf(stderr, "%s reported MISCOMPARE\n", vc); break; default: sg_get_category_sense_str(res, sizeof(b), b, verbose); fprintf(stderr, "%s: %s\n", vc, b); fprintf(stderr, " failed near lba=%" PRIu64 " [0x%" PRIx64 "]\n", lba, lba); break; } break; } } if (verbose && (0 == ret) && (orig_count > 1)) fprintf(stderr, "Verified %" PRId64 " [0x%" PRIx64 "] blocks from " "lba %" PRIu64 " [0x%" PRIx64 "]\n without error\n", orig_count, (uint64_t)orig_count, orig_lba, orig_lba); res = sg_cmds_close_device(sg_fd); if (res < 0) { fprintf(stderr, "close error: %s\n", safe_strerror(-res)); if (0 == ret) ret = SG_LIB_FILE_ERROR; } err_out: if (ref_data) free(ref_data); return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { bool last, got_stdin, is_reg; bool want_file = false; bool verbose_given = false; bool version_given = false; int res, c, len, k, n, rsp_len, resid, act_len, din_len, verb; int sg_fd = -1; int infd = -1; int do_help = 0; int ret = 0; uint32_t gen_code = 0; const char * device_name = NULL; const char * file_name = NULL; uint8_t * dmp = NULL; uint8_t * dip = NULL; uint8_t * free_dip = NULL; char * cp; char ebuff[EBUFF_SZ]; struct stat a_stat; struct dout_buff_t dout; struct opts_t opts; struct opts_t * op; const struct mode_s * mp; op = &opts; memset(op, 0, sizeof(opts)); memset(&dout, 0, sizeof(dout)); din_len = DEF_DIN_LEN; while (1) { int option_index = 0; c = getopt_long(argc, argv, "b:dehi:I:l:m:No:s:S:t:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'b': op->bpw = sg_get_num(optarg); if (op->bpw < 0) { pr2serr("argument to '--bpw' should be in a positive " "number\n"); return SG_LIB_SYNTAX_ERROR; } if ((cp = strchr(optarg, ','))) { if (0 == strncmp("act", cp + 1, 3)) op->bpw_then_activate = true; } break; case 'd': op->dry_run = true; break; case 'e': op->ealsd = true; break; case 'h': case '?': ++do_help; break; case 'i': op->mc_id = sg_get_num_nomult(optarg); if ((op->mc_id < 0) || (op->mc_id > 255)) { pr2serr("argument to '--id' should be in the range 0 to " "255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'I': file_name = optarg; break; case 'l': op->mc_len = sg_get_num(optarg); if (op->mc_len < 0) { pr2serr("bad argument to '--length'\n"); return SG_LIB_SYNTAX_ERROR; } op->mc_len_given = true; break; case 'm': if (isdigit(*optarg)) { op->mc_mode = sg_get_num_nomult(optarg); if ((op->mc_mode < 0) || (op->mc_mode > 255)) { pr2serr("argument to '--mode' should be in the range 0 " "to 255\n"); return SG_LIB_SYNTAX_ERROR; } } else { len = strlen(optarg); for (mp = mode_arr; mp->mode_string; ++mp) { if (0 == strncmp(mp->mode_string, optarg, len)) { op->mc_mode = mp->mode; break; } } if (! mp->mode_string) { print_modes(); return SG_LIB_SYNTAX_ERROR; } } break; case 'N': op->mc_non = true; break; case 'o': op->mc_offset = sg_get_num(optarg); if (op->mc_offset < 0) { pr2serr("bad argument to '--offset'\n"); return SG_LIB_SYNTAX_ERROR; } if (0 != (op->mc_offset % 4)) { pr2serr("'--offset' value needs to be a multiple of 4\n"); return SG_LIB_SYNTAX_ERROR; } break; case 's': op->mc_skip = sg_get_num(optarg); if (op->mc_skip < 0) { pr2serr("bad argument to '--skip'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'S': op->mc_subenc = sg_get_num_nomult(optarg); if ((op->mc_subenc < 0) || (op->mc_subenc > 255)) { pr2serr("expected argument to '--subenc' to be 0 to 255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 't': op->mc_tlen = sg_get_num(optarg); if (op->mc_tlen < 0) { pr2serr("bad argument to '--tlength'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'v': verbose_given = true; ++op->verbose; break; case 'V': version_given = true; break; default: pr2serr("unrecognised option code 0x%x ??\n", c); usage(); return SG_LIB_SYNTAX_ERROR; } } if (do_help) { if (do_help > 1) { usage(); pr2serr("\n"); print_modes(); } else usage(); return 0; } 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; op->verbose = 0; } else if (! verbose_given) { pr2serr("set '-vv'\n"); op->verbose = 2; } else pr2serr("keep verbose=%d\n", op->verbose); #else if (verbose_given && version_given) pr2serr("Not in DEBUG mode, so '-vV' has no special action\n"); #endif if (version_given) { pr2serr(ME "version: %s\n", version_str); return 0; } if (NULL == device_name) { pr2serr("missing device name!\n\n"); usage(); return SG_LIB_SYNTAX_ERROR; } switch (op->mc_mode) { case MODE_DNLD_MC_OFFS: case MODE_DNLD_MC_OFFS_SAVE: case MODE_DNLD_MC_OFFS_DEFER: want_file = true; break; case MODE_DNLD_STATUS: case MODE_ACTIVATE_MC: case MODE_ABORT_MC: want_file = false; break; default: pr2serr("%s: mc_mode=0x%x, continue for now\n", __func__, op->mc_mode); break; } if ((op->mc_len > 0) && (op->bpw > op->mc_len)) { pr2serr("trim chunk size (CS) to be the same as LEN\n"); op->bpw = op->mc_len; } if ((op->mc_offset > 0) && (op->bpw > 0)) { op->mc_offset = 0; pr2serr("WARNING: --offset= ignored (set back to 0) when --bpw= " "argument given (and > 0)\n"); } #ifdef SG_LIB_WIN32 #ifdef SG_LIB_WIN32_DIRECT if (op->verbose > 4) pr2serr("Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif #endif sg_fd = sg_cmds_open_device(device_name, false /* rw */, op->verbose); if (sg_fd < 0) { if (op->verbose) pr2serr(ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = sg_convert_errno(-sg_fd); goto fini; } if (file_name && (! want_file)) pr2serr("ignoring --in=FILE option\n"); else if (file_name) { got_stdin = (0 == strcmp(file_name, "-")); if (got_stdin) infd = STDIN_FILENO; else { if ((infd = open(file_name, O_RDONLY)) < 0) { ret = sg_convert_errno(errno); snprintf(ebuff, EBUFF_SZ, ME "could not open %s for reading", file_name); perror(ebuff); goto fini; } else if (sg_set_binary_mode(infd) < 0) perror("sg_set_binary_mode"); } if ((0 == fstat(infd, &a_stat)) && S_ISREG(a_stat.st_mode)) { is_reg = true; if (0 == op->mc_len) { if (op->mc_skip >= a_stat.st_size) { pr2serr("skip exceeds file size of %d bytes\n", (int)a_stat.st_size); ret = SG_LIB_FILE_ERROR; goto fini; } op->mc_len = (int)(a_stat.st_size) - op->mc_skip; } } else { is_reg = false; if (0 == op->mc_len) op->mc_len = DEF_XFER_LEN; } if (op->mc_len > MAX_XFER_LEN) { pr2serr("file size or requested length (%d) exceeds " "MAX_XFER_LEN of %d bytes\n", op->mc_len, MAX_XFER_LEN); ret = SG_LIB_FILE_ERROR; goto fini; } if (NULL == (dmp = (uint8_t *)malloc(op->mc_len))) { pr2serr(ME "out of memory to hold microcode read from FILE\n"); ret = SG_LIB_CAT_OTHER; goto fini; } /* Don't remember why this is preset to 0xff, from write_buffer */ memset(dmp, 0xff, op->mc_len); if (op->mc_skip > 0) { if (! is_reg) { if (got_stdin) pr2serr("Can't skip on stdin\n"); else pr2serr(ME "not a 'regular' file so can't apply skip\n"); ret = SG_LIB_FILE_ERROR; goto fini; } if (lseek(infd, op->mc_skip, SEEK_SET) < 0) { ret = sg_convert_errno(errno); snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to " "required position on %s", file_name); perror(ebuff); goto fini; } } res = read(infd, dmp, op->mc_len); if (res < 0) { ret = sg_convert_errno(errno); snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", file_name); perror(ebuff); goto fini; } if (res < op->mc_len) { if (op->mc_len_given) { pr2serr("tried to read %d bytes from %s, got %d bytes\n", op->mc_len, file_name, res); pr2serr("pad with 0xff bytes and continue\n"); } else { if (op->verbose) { pr2serr("tried to read %d bytes from %s, got %d " "bytes\n", op->mc_len, file_name, res); pr2serr("will send %d bytes", res); if ((op->bpw > 0) && (op->bpw < op->mc_len)) pr2serr(", %d bytes per WRITE BUFFER command\n", op->bpw); else pr2serr("\n"); } op->mc_len = res; } } if (! got_stdin) close(infd); infd = -1; } else if (want_file) { pr2serr("need --in=FILE option with given mode\n"); ret = SG_LIB_CONTRADICT; goto fini; } if (op->mc_tlen < op->mc_len) op->mc_tlen = op->mc_len; if (op->mc_non && (MODE_DNLD_STATUS == op->mc_mode)) { pr2serr("Do nothing because '--non' given so fetching the Download " "microcode status\ndpage might be dangerous\n"); goto fini; } dip = sg_memalign(din_len, 0, &free_dip, op->verbose > 3); if (NULL == dip) { pr2serr(ME "out of memory (data-in buffer)\n"); ret = SG_LIB_CAT_OTHER; goto fini; } verb = (op->verbose > 1) ? op->verbose - 1 : 0; /* Fetch Download microcode status dpage for generation code ++ */ if (op->dry_run) { n = sizeof(dummy_rd_resp); n = (n < din_len) ? n : din_len; memcpy(dip, dummy_rd_resp, n); resid = din_len - n; res = 0; } else res = sg_ll_receive_diag_v2(sg_fd, true /* pcv */, DPC_DOWNLOAD_MICROCODE, dip, din_len, 0 /*default timeout */, &resid, true, verb); if (0 == res) { rsp_len = sg_get_unaligned_be16(dip + 2) + 4; act_len = din_len - resid; if (rsp_len > din_len) { pr2serr("<<< warning response buffer too small [%d but need " "%d]>>>\n", din_len, rsp_len); rsp_len = din_len; } if (rsp_len > act_len) { pr2serr("<<< warning response too short [actually got %d but " "need %d]>>>\n", act_len, rsp_len); rsp_len = act_len; } if (rsp_len < 8) { pr2serr("Download microcode status dpage too short\n"); ret = SG_LIB_CAT_OTHER; goto fini; } if ((op->verbose > 2) || (op->dry_run && op->verbose)) pr2serr("rec diag(ini): rsp_len=%d, num_sub-enc=%u " "rec_gen_code=%u\n", rsp_len, dip[1], sg_get_unaligned_be32(dip + 4)); } else { ret = res; goto fini; } gen_code = sg_get_unaligned_be32(dip + 4); if (MODE_DNLD_STATUS == op->mc_mode) { show_download_mc_sdg(dip, rsp_len, gen_code); goto fini; } else if (! want_file) { /* ACTIVATE and ABORT */ res = send_then_receive(sg_fd, gen_code, 0, NULL, 0, &dout, dip, din_len, true, op); ret = res; goto fini; } res = 0; if (op->bpw > 0) { for (k = 0, last = false; k < op->mc_len; k += n) { n = op->mc_len - k; if (n > op->bpw) n = op->bpw; else last = true; if (op->verbose) pr2serr("bpw loop: mode=0x%x, id=%d, off_off=%d, len=%d, " "last=%d\n", op->mc_mode, op->mc_id, k, n, last); res = send_then_receive(sg_fd, gen_code, k, dmp + k, n, &dout, dip, din_len, last, op); if (res) break; } if (op->bpw_then_activate && (0 == res)) { op->mc_mode = MODE_ACTIVATE_MC; if (op->verbose) pr2serr("sending Activate deferred microcode [0xf]\n"); res = send_then_receive(sg_fd, gen_code, 0, NULL, 0, &dout, dip, din_len, true, op); } } else { if (op->verbose) pr2serr("single: mode=0x%x, id=%d, offset=%d, len=%d\n", op->mc_mode, op->mc_id, op->mc_offset, op->mc_len); res = send_then_receive(sg_fd, gen_code, 0, dmp, op->mc_len, &dout, dip, din_len, true, op); } if (res) ret = res; fini: if ((infd >= 0) && (! got_stdin)) close(infd); if (dmp) free(dmp); if (dout.free_doutp) free(dout.free_doutp); if (free_dip) free(free_dip); 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 == op->verbose) { if (! sg_if_can2stderr("sg_ses_mocrocode failed: ", ret)) pr2serr("Some error occurred, try again with '-v' " "or '-vv' for more information\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, res, c, len, resid, rlen, in_len; unsigned int ra_len; int ret = 0; const char * device_name = NULL; const char * fname = NULL; unsigned char * rabp = NULL; struct opts_t opts; struct opts_t * op; char b[80]; op = &opts; memset(op, 0, sizeof(opts)); op->filter = -1; while (1) { int option_index = 0; c = getopt_long(argc, argv, "ceE:f:F:hHi:l:m:p:qrRs:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': ++op->cache; break; case 'e': ++op->enumerate; break; case 'E': op->ea = sg_get_num(optarg); if ((op->ea < 0) || (op->ea > 65535)) { pr2serr("bad argument to '--ea=EA', expect 0 to 65535\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'f': op->filter = sg_get_num(optarg); if ((op->filter < -3) || (op->filter > 65535)) { pr2serr("bad argument to '--filter=FL', expect -3 to " "65535\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'F': op->fai = sg_get_num(optarg); if ((op->fai < 0) || (op->fai > 65535)) { pr2serr("bad argument to '--first=FAI', expect 0 to 65535\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'h': case '?': usage(); return 0; case 'H': ++op->do_hex; break; case 'i': fname = optarg; break; case 'l': op->lvn = sg_get_num(optarg); if ((op->lvn < 0) || (op->lvn > 255)) { pr2serr("bad argument to '--lvn=LVN', expect 0 to 255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'm': op->maxlen = sg_get_num(optarg); if ((op->maxlen < 0) || (op->maxlen > MAX_RATTR_BUFF_LEN)) { pr2serr("argument to '--maxlen' should be %d or " "less\n", MAX_RATTR_BUFF_LEN); return SG_LIB_SYNTAX_ERROR; } break; case 'p': op->pn = sg_get_num(optarg); if ((op->pn < 0) || (op->pn > 255)) { pr2serr("bad argument to '--pn=PN', expect 0 to 255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'q': ++op->quiet; break; case 'r': ++op->do_raw; break; case 'R': ++op->o_readonly; break; case 's': if (isdigit(*optarg)) { op->sa = sg_get_num(optarg); if ((op->sa < 0) || (op->sa > 63)) { pr2serr("bad argument to '--sa=SA', expect 0 to 63\n"); return SG_LIB_SYNTAX_ERROR; } } else { res = find_sa_acron(optarg); if (res < 0) { enum_sa_acrons(); return SG_LIB_SYNTAX_ERROR; } op->sa = res; } break; case 'v': ++op->verbose; break; case 'V': pr2serr("version: %s\n", version_str); return 0; 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; } } if (op->enumerate) { enum_attributes(); printf("\n"); enum_sa_acrons(); return 0; } if (fname && device_name) { pr2serr("since '--in=FN' given, ignoring DEVICE\n"); device_name = NULL; } if (0 == op->maxlen) op->maxlen = DEF_RATTR_BUFF_LEN; rabp = (unsigned char *)calloc(1, op->maxlen); if (NULL == rabp) { pr2serr("unable to calloc %d bytes\n", op->maxlen); return SG_LIB_CAT_OTHER; } if (NULL == device_name) { if (fname) { if (f2hex_arr(fname, op->do_raw, 0, rabp, &in_len, op->maxlen)) { ret = SG_LIB_FILE_ERROR; goto clean_up; } if (op->do_raw) op->do_raw = 0; /* can interfere on decode */ if (in_len < 4) { pr2serr("--in=%s only decoded %d bytes (needs 4 at least)\n", fname, in_len); ret = SG_LIB_SYNTAX_ERROR; goto clean_up; } decode_all_sa_s(rabp, in_len, op); goto clean_up; } pr2serr("missing device name!\n"); usage(); ret = SG_LIB_SYNTAX_ERROR; goto clean_up; } if (op->do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); ret = SG_LIB_FILE_ERROR; goto clean_up; } } sg_fd = sg_cmds_open_device(device_name, op->o_readonly, op->verbose); if (sg_fd < 0) { pr2serr("open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = SG_LIB_FILE_ERROR; goto clean_up; } res = sg_ll_read_attr(sg_fd, rabp, &resid, op); ret = res; if (0 == res) { rlen = op->maxlen - resid; if (rlen < 4) { pr2serr("Response length (%d) too short\n", rlen); ret = SG_LIB_CAT_MALFORMED; goto close_then_end; } if ((op->sa <= RA_HIGHEST_SA) && (op->sa != RA_SMC2_SA)) { ra_len = ((RA_LV_LIST_SA == op->sa) || (RA_PART_LIST_SA == op->sa)) ? (unsigned int)sg_get_unaligned_be16(rabp + 0) : sg_get_unaligned_be32(rabp + 0) + 2; ra_len += 2; } else ra_len = rlen; if ((int)ra_len > rlen) { if (op->verbose) pr2serr("ra_len available is %d, response length is %d\n", ra_len, rlen); len = rlen; } else len = (int)ra_len; if (op->do_raw) { dStrRaw((const char *)rabp, len); goto close_then_end; } decode_all_sa_s(rabp, len, op); } else if (SG_LIB_CAT_INVALID_OP == res) pr2serr("Read attribute command not supported\n"); else { sg_get_category_sense_str(res, sizeof(b), b, op->verbose); pr2serr("Read attribute command: %s\n", b); } close_then_end: res = sg_cmds_close_device(sg_fd); if (res < 0) { pr2serr("close error: %s\n", safe_strerror(-res)); if (0 == ret) ret = SG_LIB_FILE_ERROR; } clean_up: if (rabp) free(rabp); return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, k, num, len, res, md_len, bd_len, longlba, page_num, spf; char ebuff[EBUFF_SZ]; const char * descp; unsigned char * rsp_buff = NULL; unsigned char def_rsp_buff[DEF_ALLOC_LEN]; unsigned char * malloc_rsp_buff = NULL; int rsp_buff_size = DEF_ALLOC_LEN; int ret = 0; int density_code_off, t_proto, inq_pdt, inq_byte6, resp_mode6; int num_ua_pages; unsigned char * ucp; unsigned char uc; struct sg_simple_inquiry_resp inq_out; char pdt_name[64]; struct opts_t opts; memset(&opts, 0, sizeof(opts)); opts.pg_code = -1; res = process_cl(&opts, argc, argv); if (res) return SG_LIB_SYNTAX_ERROR; if (opts.do_help) { usage_for(&opts); return 0; } if (opts.do_version) { fprintf(stderr, "Version string: %s\n", version_str); return 0; } if (NULL == opts.device_name) { if (opts.do_list) { if ((opts.pg_code < 0) || (opts.pg_code > PG_CODE_MAX)) { printf(" Assume peripheral device type: disk\n"); list_page_codes(0, 0, -1); } else { printf(" peripheral device type: %s\n", sg_get_pdt_str(opts.pg_code, sizeof(pdt_name), pdt_name)); if (opts.subpg_code_set) list_page_codes(opts.pg_code, 0, opts.subpg_code); else list_page_codes(opts.pg_code, 0, -1); } return 0; } fprintf(stderr, "No DEVICE argument given\n"); usage_for(&opts); return SG_LIB_SYNTAX_ERROR; } if (opts.do_examine && (opts.pg_code >= 0)) { fprintf(stderr, "can't give '-e' and a page number\n"); return SG_LIB_SYNTAX_ERROR; } if ((opts.do_six) && (opts.do_llbaa)) { fprintf(stderr, "LLBAA not defined for MODE SENSE 6, try " "without '-L'\n"); return SG_LIB_SYNTAX_ERROR; } if (opts.maxlen > 0) { if (opts.do_six && (opts.maxlen > 255)) { fprintf(stderr, "For Mode Sense (6) maxlen cannot exceed " "255\n"); return SG_LIB_SYNTAX_ERROR; } if (opts.maxlen > DEF_ALLOC_LEN) { malloc_rsp_buff = (unsigned char *)malloc(opts.maxlen); if (NULL == malloc_rsp_buff) { fprintf(stderr, "Unable to malloc maxlen=%d bytes\n", opts.maxlen); return SG_LIB_SYNTAX_ERROR; } rsp_buff = malloc_rsp_buff; } else rsp_buff = def_rsp_buff; rsp_buff_size = opts.maxlen; } else { /* maxlen == 0 */ rsp_buff_size = opts.do_six ? DEF_6_ALLOC_LEN : DEF_ALLOC_LEN; rsp_buff = def_rsp_buff; } /* If no pages or list selected than treat as 'a' */ if (! ((opts.pg_code >= 0) || opts.do_all || opts.do_list || opts.do_examine)) opts.do_all = 1; if (opts.do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } if ((sg_fd = sg_cmds_open_device(opts.device_name, 1 /* ro */, opts.do_verbose)) < 0) { fprintf(stderr, "error opening file: %s: %s\n", opts.device_name, safe_strerror(-sg_fd)); if (malloc_rsp_buff) free(malloc_rsp_buff); return SG_LIB_FILE_ERROR; } if (sg_simple_inquiry(sg_fd, &inq_out, 1, opts.do_verbose)) { fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n", opts.device_name); ret = SG_LIB_CAT_OTHER; goto finish; } inq_pdt = inq_out.peripheral_type; inq_byte6 = inq_out.byte_6; if (0 == opts.do_raw) printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n", inq_out.vendor, inq_out.product, inq_out.revision, sg_get_pdt_str(inq_pdt, sizeof(pdt_name), pdt_name), inq_pdt); if (opts.do_list) { if (opts.subpg_code_set) list_page_codes(inq_pdt, inq_byte6, opts.subpg_code); else list_page_codes(inq_pdt, inq_byte6, -1); goto finish; } if (opts.do_examine) { ret = examine_pages(sg_fd, inq_pdt, inq_byte6, &opts); goto finish; } if (PG_CODE_ALL == opts.pg_code) { if (0 == opts.do_all) ++opts.do_all; } else if (opts.do_all) opts.pg_code = PG_CODE_ALL; if (opts.do_all > 1) opts.subpg_code = SPG_CODE_ALL; if (opts.do_raw > 1) { if (opts.do_all) { if (opts.opt_new) fprintf(stderr, "'-R' requires a specific (sub)page, not " "all\n"); else fprintf(stderr, "'-r' requires a specific (sub)page, not " "all\n"); usage_for(&opts); ret = SG_LIB_SYNTAX_ERROR; goto finish; } } memset(rsp_buff, 0, sizeof(rsp_buff)); if (opts.do_six) { res = sg_ll_mode_sense6(sg_fd, opts.do_dbd, opts.page_control, opts.pg_code, opts.subpg_code, rsp_buff, rsp_buff_size, 1, opts.do_verbose); if (SG_LIB_CAT_INVALID_OP == res) fprintf(stderr, ">>>>>> try again without the '-6' " "switch for a 10 byte MODE SENSE command\n"); } else { res = sg_ll_mode_sense10(sg_fd, opts.do_llbaa, opts.do_dbd, opts.page_control, opts.pg_code, opts.subpg_code, rsp_buff, rsp_buff_size, 1, opts.do_verbose); if (SG_LIB_CAT_INVALID_OP == res) fprintf(stderr, ">>>>>> try again with a '-6' " "switch for a 6 byte MODE SENSE command\n"); } if (SG_LIB_CAT_ILLEGAL_REQ == res) { if (opts.subpg_code > 0) fprintf(stderr, "invalid field in cdb (perhaps subpages " "not supported)\n"); else if (opts.page_control > 0) fprintf(stderr, "invalid field in cdb (perhaps " "page control (PC) not supported)\n"); else fprintf(stderr, "invalid field in cdb (perhaps " "page 0x%x not supported)\n", opts.pg_code); } else if (SG_LIB_CAT_NOT_READY == res) fprintf(stderr, "device not ready\n"); else if (SG_LIB_CAT_UNIT_ATTENTION == res) fprintf(stderr, "unit attention\n"); else if (SG_LIB_CAT_ABORTED_COMMAND == res) fprintf(stderr, "aborted command\n"); ret = res; if (0 == res) { int medium_type, specific, headerlen; ret = 0; resp_mode6 = opts.do_six; if (opts.do_flexible) { num = rsp_buff[0]; if (opts.do_six && (num < 3)) resp_mode6 = 0; if ((0 == opts.do_six) && (num > 5)) { if ((num > 11) && (0 == (num % 2)) && (0 == rsp_buff[4]) && (0 == rsp_buff[5]) && (0 == rsp_buff[6])) { rsp_buff[1] = num; rsp_buff[0] = 0; fprintf(stderr, ">>> msense(10) but resp[0]=%d and " "not msense(6) response so fix length\n", num); } else resp_mode6 = 1; } } if ((! opts.do_raw) && (1 != opts.do_hex)) { if (resp_mode6 == opts.do_six) printf("Mode parameter header from MODE SENSE(%s):\n", (opts.do_six ? "6" : "10")); else printf(" >>> Mode parameter header from MODE SENSE(%s),\n" " decoded as %s byte response:\n", (opts.do_six ? "6" : "10"), (resp_mode6 ? "6" : "10")); } if (resp_mode6) { headerlen = 4; md_len = rsp_buff[0] + 1; bd_len = rsp_buff[3]; medium_type = rsp_buff[1]; specific = rsp_buff[2]; longlba = 0; } else { headerlen = 8; md_len = (rsp_buff[0] << 8) + rsp_buff[1] + 2; bd_len = (rsp_buff[6] << 8) + rsp_buff[7]; medium_type = rsp_buff[2]; specific = rsp_buff[3]; longlba = rsp_buff[4] & 1; } if ((bd_len + headerlen) > md_len) { fprintf(stderr, "Invalid block descriptor length=%d, ignore\n", bd_len); bd_len = 0; } if (opts.do_raw) { if (1 == opts.do_raw) dStrRaw((const char *)rsp_buff, md_len); else { ucp = rsp_buff + bd_len + headerlen; md_len -= bd_len + headerlen; spf = ((ucp[0] & 0x40) ? 1 : 0); len = (spf ? ((ucp[2] << 8) + ucp[3] + 4) : (ucp[1] + 2)); len = (len < md_len) ? len : md_len; for (k = 0; k < len; ++k) printf("%02x\n", ucp[k]); } goto finish; } if (1 == opts.do_hex) { dStrHex((const char *)rsp_buff, md_len, 1); goto finish; } else if (opts.do_hex > 1) dStrHex((const char *)rsp_buff, headerlen, 1); if (0 == inq_pdt) printf(" Mode data length=%d, medium type=0x%.2x, WP=%d," " DpoFua=%d, longlba=%d\n", md_len, medium_type, !!(specific & 0x80), !!(specific & 0x10), longlba); else printf(" Mode data length=%d, medium type=0x%.2x, specific" " param=0x%.2x, longlba=%d\n", md_len, medium_type, specific, longlba); if (md_len > rsp_buff_size) { printf("Only fetched %d bytes of response, truncate output\n", rsp_buff_size); md_len = rsp_buff_size; if (bd_len + headerlen > rsp_buff_size) bd_len = rsp_buff_size - headerlen; } if (! opts.do_dbout) { printf(" Block descriptor length=%d\n", bd_len); if (bd_len > 0) { len = 8; density_code_off = 0; num = bd_len; if (longlba) { printf("> longlba direct access device block " "descriptors:\n"); len = 16; density_code_off = 8; } else if (0 == inq_pdt) { printf("> Direct access device block descriptors:\n"); density_code_off = 4; } else printf("> General mode parameter block descriptors:\n"); ucp = rsp_buff + headerlen; while (num > 0) { printf(" Density code=0x%x\n", *(ucp + density_code_off)); dStrHex((const char *)ucp, len, 1); ucp += len; num -= len; } printf("\n"); } } ucp = rsp_buff + bd_len + headerlen; /* start of mode page(s) */ md_len -= bd_len + headerlen; /* length of mode page(s) */ num_ua_pages = 0; for (k = 0; md_len > 0; ++k) { /* got mode page(s) */ if ((k > 0) && (! opts.do_all) && (SPG_CODE_ALL != opts.subpg_code)) { fprintf(stderr, "Unexpectedly received extra mode page " "responses, ignore\n"); break; } uc = *ucp; spf = ((uc & 0x40) ? 1 : 0); len = (spf ? ((ucp[2] << 8) + ucp[3] + 4) : (ucp[1] + 2)); page_num = ucp[0] & PG_CODE_MASK; if (0x0 == page_num) { ++num_ua_pages; if((num_ua_pages > 3) && (md_len > 0xa00)) { fprintf(stderr, ">>> Seen 3 unit attention pages " "(only one should be at end)\n and mpage " "length=%d, looks malformed, try '-f' option\n", md_len); break; } } if (opts.do_hex) { if (spf) printf(">> page_code=0x%x, subpage_code=0x%x, page_cont" "rol=%d\n", page_num, ucp[1], opts.page_control); else printf(">> page_code=0x%x, page_control=%d\n", page_num, opts.page_control); } else { descp = NULL; if ((0x18 == page_num) || (0x19 == page_num)) { t_proto = (spf ? ucp[5] : ucp[2]) & 0xf; descp = find_page_code_desc(page_num, (spf ? ucp[1] : 0), inq_pdt, inq_byte6, t_proto); } else descp = find_page_code_desc(page_num, (spf ? ucp[1] : 0), inq_pdt, inq_byte6, -1); if (NULL == descp) { if (spf) snprintf(ebuff, EBUFF_SZ, "0x%x, subpage_code: 0x%x", page_num, ucp[1]); else snprintf(ebuff, EBUFF_SZ, "0x%x", page_num); } if (descp) printf(">> %s, page_control: %s\n", descp, pg_control_str_arr[opts.page_control]); else printf(">> page_code: %s, page_control: %s\n", ebuff, pg_control_str_arr[opts.page_control]); } num = (len > md_len) ? md_len : len; if ((k > 0) && (num > 256)) { num = 256; fprintf(stderr, ">>> page length (%d) > 256 bytes, unlikely " "trim\n Try '-f' option\n", len); } dStrHex((const char *)ucp, num , 1); ucp += len; md_len -= len; } } finish: sg_cmds_close_device(sg_fd); if (malloc_rsp_buff) free(malloc_rsp_buff); return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int res, c, len, k; int sg_fd = -1; int do_help = 0; int do_hex = 0; int do_long = 0; int o_readonly = 0; int rb_id = 0; int rb_len = 4; int rb_mode = 0; int rb_mode_sp = 0; int64_t ll; uint64_t rb_offset = 0; int do_raw = 0; int resid = 0; int verbose = 0; int ret = 0; const char * device_name = NULL; unsigned char * resp; const struct mode_s * mp; while (1) { int option_index = 0; c = getopt_long(argc, argv, "hHi:l:Lm:o:rRS:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': case '?': ++do_help; break; case 'H': ++do_hex; break; case 'i': rb_id = sg_get_num(optarg); if ((rb_id < 0) || (rb_id > 255)) { fprintf(stderr, "argument to '--id' should be in the range " "0 to 255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'l': rb_len = sg_get_num(optarg); if (rb_len < 0) { fprintf(stderr, "bad argument to '--length'\n"); return SG_LIB_SYNTAX_ERROR; } if (rb_len > 0xffffff) { fprintf(stderr, "argument to '--length' must be <= " "0xffffff\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'L': ++do_long; break; case 'm': if (isdigit(*optarg)) { rb_mode = sg_get_num(optarg); if ((rb_mode < 0) || (rb_mode > 31)) { fprintf(stderr, "argument to '--mode' should be in the " "range 0 to 31\n"); return SG_LIB_SYNTAX_ERROR; } } else { len = strlen(optarg); for (mp = modes; mp->mode_string; ++mp) { if (0 == strncmp(mp->mode_string, optarg, len)) { rb_mode = mp->mode; break; } } if (NULL == mp) { print_modes(); return SG_LIB_SYNTAX_ERROR; } } break; case 'o': ll = sg_get_llnum(optarg); if (ll < 0) { fprintf(stderr, "bad argument to '--offset'\n"); return SG_LIB_SYNTAX_ERROR; } rb_offset = ll; break; case 'r': ++do_raw; break; case 'R': ++o_readonly; break; case 'S': rb_mode_sp = sg_get_num(optarg); if ((rb_mode_sp < 0) || (rb_mode_sp > 7)) { fprintf(stderr, "expected argument to '--specific' to be 0 " "to 7\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'v': ++verbose; break; case 'V': fprintf(stderr, "version: %s\n", version_str); return 0; default: fprintf(stderr, "unrecognised option code 0x%x ??\n", c); usage(); return SG_LIB_SYNTAX_ERROR; } } if (do_help) { if (do_help > 1) { usage(); fprintf(stderr, "\n"); print_modes(); } else usage(); return 0; } if (optind < argc) { if (NULL == device_name) { device_name = argv[optind]; ++optind; } if (optind < argc) { for (; optind < argc; ++optind) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if (NULL == device_name) { fprintf(stderr, "missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (rb_len > 0) { resp = (unsigned char *)malloc(rb_len); if (NULL == resp) { fprintf(stderr, "unable to allocate %d bytes on the heap\n", rb_len); return SG_LIB_CAT_OTHER; } memset(resp, 0, rb_len); } else resp = NULL; if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); ret = SG_LIB_FILE_ERROR; goto fini; } } #ifdef SG_LIB_WIN32 #ifdef SG_LIB_WIN32_DIRECT if (verbose > 4) fprintf(stderr, "Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif #endif sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { fprintf(stderr, "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = SG_LIB_FILE_ERROR; goto fini; } if (do_long) res = ll_read_buffer_16(sg_fd, rb_mode, rb_mode_sp, rb_id, rb_offset, resp, rb_len, &resid, 1, verbose); else if (rb_offset > 0xffffff) { fprintf(stderr, "--offset value is too large for READ BUFFER(10), " "try --16\n"); ret = SG_LIB_SYNTAX_ERROR; goto fini; } else res = ll_read_buffer_10(sg_fd, rb_mode, rb_mode_sp, rb_id, (uint32_t)rb_offset, resp, rb_len, &resid, 1, verbose); if (0 != res) { char b[80]; ret = res; if (res > 0) { sg_get_category_sense_str(res, sizeof(b), b, verbose); fprintf(stderr, "Read buffer(%d) failed: %s\n", (do_long ? 16 : 10), b); } goto fini; } if (resid > 0) rb_len -= resid; /* got back less than requested */ if (rb_len > 0) { if (do_raw) dStrRaw((const char *)resp, rb_len); else if (do_hex || (rb_len < 4)) dStrHex((const char *)resp, rb_len, ((do_hex > 1) ? 0 : 1)); else { switch (rb_mode) { case MODE_DESCRIPTOR: k = (resp[1] << 16) | (resp[2] << 8) | resp[3]; printf("OFFSET BOUNDARY: %d, Buffer offset alignment: " "%d-byte\n", resp[0], (1 << resp[0])); printf("BUFFER CAPACITY: %d (0x%x)\n", k, k); break; case MODE_ECHO_BDESC: k = ((resp[2] & 0x1F) << 8) | resp[3]; printf("EBOS:%d\n", resp[0] & 1 ? 1 : 0); printf("Echo buffer capacity: %d (0x%x)\n", k, k); break; default: dStrHex((const char *)resp, rb_len, (verbose > 1 ? 0 : 1)); break; } } } fini: if (resp) free(resp); if (sg_fd >= 0) { res = sg_cmds_close_device(sg_fd); if (res < 0) { fprintf(stderr, "close error: %s\n", safe_strerror(-res)); if (0 == ret) return SG_LIB_FILE_ERROR; } } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { bool got_stdin = false; bool if_given = false; bool lba_given = false; bool num_given = false; bool prot_en; int res, c, infd, act_cdb_len, vb, err; int sg_fd = -1; int ret = -1; uint32_t block_size; int64_t ll; const char * device_name = NULL; struct opts_t * op; uint8_t * wBuff = NULL; uint8_t * free_wBuff = NULL; char ebuff[EBUFF_SZ]; char b[80]; uint8_t resp_buff[RCAP16_RESP_LEN]; struct opts_t opts; struct stat a_stat; op = &opts; memset(op, 0, sizeof(opts)); op->numblocks = DEF_WS_NUMBLOCKS; op->pref_cdb_size = DEF_WS_CDB_SIZE; op->timeout = DEF_TIMEOUT_SECS; while (1) { int option_index = 0; c = getopt_long(argc, argv, "ag:hi:l:Ln:NPRSt:TUvVw:x:", long_options, &option_index); if (c == -1) break; switch (c) { case 'a': op->anchor = true; break; case 'g': op->grpnum = sg_get_num(optarg); if ((op->grpnum < 0) || (op->grpnum > 63)) { pr2serr("bad argument to '--grpnum'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'h': case '?': usage(); return 0; case 'i': strncpy(op->ifilename, optarg, sizeof(op->ifilename) - 1); op->ifilename[sizeof(op->ifilename) - 1] = '\0'; if_given = true; break; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { pr2serr("bad argument to '--lba'\n"); return SG_LIB_SYNTAX_ERROR; } op->lba = (uint64_t)ll; lba_given = true; break; case 'L': op->lbdata = true; break; case 'n': op->numblocks = sg_get_num(optarg); if (op->numblocks < 0) { pr2serr("bad argument to '--num'\n"); return SG_LIB_SYNTAX_ERROR; } num_given = true; break; case 'N': op->ndob = true; break; case 'P': op->pbdata = true; break; case 'R': op->want_ws10 = true; break; case 'S': if (DEF_WS_CDB_SIZE != op->pref_cdb_size) { pr2serr("only one '--10', '--16' or '--32' please\n"); return SG_LIB_CONTRADICT; } op->pref_cdb_size = 16; break; case 't': op->timeout = sg_get_num(optarg); if (op->timeout < 0) { pr2serr("bad argument to '--timeout'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'T': if (DEF_WS_CDB_SIZE != op->pref_cdb_size) { pr2serr("only one '--10', '--16' or '--32' please\n"); return SG_LIB_CONTRADICT; } op->pref_cdb_size = 32; break; case 'U': op->unmap = true; break; case 'v': op->verbose_given = true; ++op->verbose; break; case 'V': op->version_given = true; break; case 'w': op->wrprotect = sg_get_num(optarg); if ((op->wrprotect < 0) || (op->wrprotect > 7)) { pr2serr("bad argument to '--wrprotect'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'x': op->xfer_len = sg_get_num(optarg); if (op->xfer_len < 0) { pr2serr("bad argument to '--xferlen'\n"); return SG_LIB_SYNTAX_ERROR; } 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; } } if (op->want_ws10 && (DEF_WS_CDB_SIZE != op->pref_cdb_size)) { pr2serr("only one '--10', '--16' or '--32' please\n"); return SG_LIB_CONTRADICT; } #ifdef DEBUG pr2serr("In DEBUG mode, "); if (op->verbose_given && op->version_given) { pr2serr("but override: '-vV' given, zero verbose and continue\n"); op->verbose_given = false; op->version_given = false; op->verbose = 0; } else if (! op->verbose_given) { pr2serr("set '-vv'\n"); op->verbose = 2; } else pr2serr("keep verbose=%d\n", op->verbose); #else if (op->verbose_given && op->version_given) pr2serr("Not in DEBUG mode, so '-vV' has no special action\n"); #endif if (op->version_given) { pr2serr(ME "version: %s\n", version_str); return 0; } if (NULL == device_name) { pr2serr("Missing device name!\n\n"); usage(); return SG_LIB_SYNTAX_ERROR; } vb = op->verbose; if ((! if_given) && (! lba_given) && (! num_given)) { pr2serr("As a precaution, one of '--in=', '--lba=' or '--num=' is " "required\n"); return SG_LIB_CONTRADICT; } if (op->ndob) { if (if_given) { pr2serr("Can't have both --ndob and '--in='\n"); return SG_LIB_CONTRADICT; } if (0 != op->xfer_len) { pr2serr("With --ndob only '--xferlen=0' (or not given) is " "acceptable\n"); return SG_LIB_CONTRADICT; } } else if (op->ifilename[0]) { got_stdin = (0 == strcmp(op->ifilename, "-")); if (! got_stdin) { memset(&a_stat, 0, sizeof(a_stat)); if (stat(op->ifilename, &a_stat) < 0) { err = errno; if (vb) pr2serr("unable to stat(%s): %s\n", op->ifilename, safe_strerror(err)); return sg_convert_errno(err); } if (op->xfer_len <= 0) op->xfer_len = (int)a_stat.st_size; } } sg_fd = sg_cmds_open_device(device_name, false /* rw */, vb); if (sg_fd < 0) { if (op->verbose) pr2serr(ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = sg_convert_errno(-sg_fd); goto err_out; } if (! op->ndob) { prot_en = false; if (0 == op->xfer_len) { res = sg_ll_readcap_16(sg_fd, false /* pmi */, 0 /* llba */, resp_buff, RCAP16_RESP_LEN, true, (vb ? (vb - 1): 0)); if (SG_LIB_CAT_UNIT_ATTENTION == res) { pr2serr("Read capacity(16) unit attention, try again\n"); res = sg_ll_readcap_16(sg_fd, false, 0, resp_buff, RCAP16_RESP_LEN, true, (vb ? (vb - 1): 0)); } if (0 == res) { if (vb > 3) hex2stderr(resp_buff, RCAP16_RESP_LEN, 1); block_size = sg_get_unaligned_be32(resp_buff + 8); prot_en = !!(resp_buff[12] & 0x1); op->xfer_len = block_size; if (prot_en && (op->wrprotect > 0)) op->xfer_len += 8; } else if ((SG_LIB_CAT_INVALID_OP == res) || (SG_LIB_CAT_ILLEGAL_REQ == res)) { if (vb) pr2serr("Read capacity(16) not supported, try Read " "capacity(10)\n"); res = sg_ll_readcap_10(sg_fd, false /* pmi */, 0 /* lba */, resp_buff, RCAP10_RESP_LEN, true, (vb ? (vb - 1): 0)); if (0 == res) { if (vb > 3) hex2stderr(resp_buff, RCAP10_RESP_LEN, 1); block_size = sg_get_unaligned_be32(resp_buff + 4); op->xfer_len = block_size; } else { sg_get_category_sense_str(res, sizeof(b), b, vb); pr2serr("Read capacity(10): %s\n", b); pr2serr("Unable to calculate block size\n"); } } else if (vb) { sg_get_category_sense_str(res, sizeof(b), b, vb); pr2serr("Read capacity(16): %s\n", b); pr2serr("Unable to calculate block size\n"); } } if (op->xfer_len < 1) { pr2serr("unable to deduce block size, please give '--xferlen=' " "argument\n"); ret = SG_LIB_SYNTAX_ERROR; goto err_out; } if (op->xfer_len > MAX_XFER_LEN) { pr2serr("'--xferlen=%d is out of range ( want <= %d)\n", op->xfer_len, MAX_XFER_LEN); ret = SG_LIB_SYNTAX_ERROR; goto err_out; } wBuff = (uint8_t *)sg_memalign(op->xfer_len, 0, &free_wBuff, vb > 3); if (NULL == wBuff) { pr2serr("unable to allocate %d bytes of memory with " "sg_memalign()\n", op->xfer_len); ret = sg_convert_errno(ENOMEM); goto err_out; } if (op->ifilename[0]) { if (got_stdin) { infd = STDIN_FILENO; if (sg_set_binary_mode(STDIN_FILENO) < 0) perror("sg_set_binary_mode"); } else { if ((infd = open(op->ifilename, O_RDONLY)) < 0) { ret = sg_convert_errno(errno); snprintf(ebuff, EBUFF_SZ, ME "could not open %.400s for " "reading", op->ifilename); perror(ebuff); goto err_out; } else if (sg_set_binary_mode(infd) < 0) perror("sg_set_binary_mode"); } res = read(infd, wBuff, op->xfer_len); if (res < 0) { ret = sg_convert_errno(errno); snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %.400s", op->ifilename); perror(ebuff); if (! got_stdin) close(infd); goto err_out; } if (res < op->xfer_len) { pr2serr("tried to read %d bytes from %s, got %d bytes\n", op->xfer_len, op->ifilename, res); pr2serr(" so pad with 0x0 bytes and continue\n"); } if (! got_stdin) close(infd); } else { if (vb) pr2serr("Default data-out buffer set to %d zeros\n", op->xfer_len); if (prot_en && (op->wrprotect > 0)) { /* default for protection is 0xff, rest get 0x0 */ memset(wBuff + op->xfer_len - 8, 0xff, 8); if (vb) pr2serr(" ... apart from last 8 bytes which are set to " "0xff\n"); } } } ret = do_write_same(sg_fd, op, wBuff, &act_cdb_len); if (ret) { sg_get_category_sense_str(ret, sizeof(b), b, vb); pr2serr("Write same(%d): %s\n", act_cdb_len, b); } err_out: if (free_wBuff) free(free_wBuff); 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 == op->verbose) { if (! sg_if_can2stderr("sg_write_same failed: ", ret)) pr2serr("Some error occurred, try again with '-v' " "or '-vv' for more information\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { bool correct = false; bool do_16 = false; bool pblock = false; bool readonly = false; bool got_stdout; bool verbose_given = false; bool version_given = false; int outfd, res, c; int sg_fd = -1; int ret = 0; int xfer_len = 520; int verbose = 0; uint64_t llba = 0; int64_t ll; uint8_t * readLongBuff = NULL; uint8_t * rawp = NULL; uint8_t * free_rawp = NULL; const char * device_name = NULL; char out_fname[256]; char ebuff[EBUFF_SZ]; memset(out_fname, 0, sizeof out_fname); while (1) { int option_index = 0; c = getopt_long(argc, argv, "chl:o:prSvVx:", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': correct = true; break; case 'h': case '?': usage(); return 0; case 'l': ll = sg_get_llnum(optarg); if (-1 == ll) { pr2serr("bad argument to '--lba'\n"); return SG_LIB_SYNTAX_ERROR; } llba = (uint64_t)ll; break; case 'o': strncpy(out_fname, optarg, sizeof(out_fname) - 1); break; case 'p': pblock = true; break; case 'r': readonly = true; break; case 'S': do_16 = true; break; case 'v': verbose_given = true; ++verbose; break; case 'V': version_given = true; break; case 'x': xfer_len = sg_get_num(optarg); if (-1 == xfer_len) { pr2serr("bad argument to '--xfer_len'\n"); return SG_LIB_SYNTAX_ERROR; } 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(ME "version: %s\n", version_str); return 0; } if (NULL == device_name) { pr2serr("Missing device name!\n\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (xfer_len >= MAX_XFER_LEN){ pr2serr("xfer_len (%d) is out of range ( < %d)\n", xfer_len, MAX_XFER_LEN); usage(); return SG_LIB_SYNTAX_ERROR; } sg_fd = sg_cmds_open_device(device_name, readonly, verbose); if (sg_fd < 0) { if (verbose) pr2serr(ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); ret = sg_convert_errno(-sg_fd); goto err_out; } if (NULL == (rawp = (uint8_t *)sg_memalign(MAX_XFER_LEN, 0, &free_rawp, false))) { if (verbose) pr2serr(ME "out of memory\n"); ret = sg_convert_errno(ENOMEM); goto err_out; } readLongBuff = (uint8_t *)rawp; memset(rawp, 0x0, MAX_XFER_LEN); pr2serr(ME "issue read long (%s) to device %s\n xfer_len=%d (0x%x), " "lba=%" PRIu64 " (0x%" PRIx64 "), correct=%d\n", (do_16 ? "16" : "10"), device_name, xfer_len, xfer_len, llba, llba, (int)correct); if ((ret = process_read_long(sg_fd, do_16, pblock, correct, llba, readLongBuff, xfer_len, verbose))) goto err_out; if ('\0' == out_fname[0]) hex2stdout((const uint8_t *)rawp, xfer_len, 0); else { got_stdout = (0 == strcmp(out_fname, "-")); if (got_stdout) outfd = STDOUT_FILENO; else { if ((outfd = open(out_fname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { snprintf(ebuff, EBUFF_SZ, ME "could not open %s for writing", out_fname); perror(ebuff); goto err_out; } } if (sg_set_binary_mode(outfd) < 0) { perror("sg_set_binary_mode"); goto err_out; } res = write(outfd, readLongBuff, xfer_len); if (res < 0) { snprintf(ebuff, EBUFF_SZ, ME "couldn't write to %s", out_fname); perror(ebuff); goto err_out; } if (! got_stdout) close(outfd); } err_out: if (free_rawp) free(free_rawp); 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_read_long failed: ", ret)) pr2serr("Some error occurred, try again with '-v' " "or '-vv' for more information\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { int sg_fd, c, ret, peri_type, no_hex_raw; int res = SG_LIB_CAT_OTHER; const char * device_name = NULL; char ebuff[EBUFF_SZ]; unsigned char *rb_buff; int do_config = 0; int do_status = 0; int do_slots = 0; int do_flags = 0; int do_usage = 0; int do_hex = 0; int do_raw = 0; int verbose = 0; int do_insertions = 0; const char * cp; char buff[48]; char b[80]; struct sg_simple_inquiry_resp inq_resp; const char op_name[] = "READ BUFFER"; while (1) { int option_index = 0; c = getopt_long(argc, argv, "cdfhHirsuvV?", long_options, &option_index); if (c == -1) break; switch (c) { case 'c': do_config = 1; break; case 'd': do_slots = 1; break; case 'f': do_flags = 1; break; case 'h': case '?': usage(); return 0; case 'H': ++do_hex; break; case 'i': do_insertions = 1; break; case 'r': ++do_raw; break; case 's': do_status = 1; break; case 'u': do_usage = 1; break; case 'v': ++verbose; break; case 'V': pr2serr("Version string: %s\n", version_str); exit(0); 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; } } if (NULL == device_name) { pr2serr("missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } if ((sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose)) < 0) { snprintf(ebuff, EBUFF_SZ, "sg_safte: error opening file: %s (rw)", device_name); perror(ebuff); return SG_LIB_FILE_ERROR; } no_hex_raw = ((0 == do_hex) && (0 == do_raw)); if (no_hex_raw) { if (0 == sg_simple_inquiry(sg_fd, &inq_resp, 1, verbose)) { printf(" %.8s %.16s %.4s\n", inq_resp.vendor, inq_resp.product, inq_resp.revision); peri_type = inq_resp.peripheral_type; cp = sg_get_pdt_str(peri_type, sizeof(buff), buff); if (strlen(cp) > 0) printf(" Peripheral device type: %s\n", cp); else printf(" Peripheral device type: 0x%x\n", peri_type); } else { pr2serr("sg_safte: %s doesn't respond to a SCSI INQUIRY\n", device_name); return SG_LIB_CAT_OTHER; } } rb_buff = (unsigned char *)malloc(buf_capacity); if (!rb_buff) goto err_out; memset(rb_buff, 0, buf_capacity); res = read_safte_configuration(sg_fd, rb_buff, buf_capacity, verbose); switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: goto err_out; } if (1 == do_raw) { dStrRaw((const char *)rb_buff, buf_capacity); goto finish; } if (1 == do_hex) { dStrHex((const char *)rb_buff, buf_capacity, 1); goto finish; } if (do_config && no_hex_raw) print_safte_configuration(); if (do_status) { res = do_safte_encl_status(sg_fd, do_hex, do_raw, verbose); switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: goto err_out; } } if (do_usage) { res = do_safte_usage_statistics(sg_fd, do_hex, do_raw, verbose); switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: goto err_out; } } if (do_insertions) { res = do_safte_slot_insertions(sg_fd, do_hex, do_raw, verbose); switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: goto err_out; } } if (do_slots) { res = do_safte_slot_status(sg_fd, do_hex, do_raw, verbose); switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: goto err_out; } } if (do_flags) { res = do_safte_global_flags(sg_fd, do_hex, do_raw, verbose); switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: goto err_out; } } finish: res = 0; err_out: switch (res) { case 0: case SG_LIB_CAT_RECOVERED: break; default: sg_get_category_sense_str(res, sizeof(b), b, verbose); pr2serr("%s failed: %s\n", op_name, b); break; } ret = res; res = sg_cmds_close_device(sg_fd); if (res < 0) { pr2serr("close error: %s\n", safe_strerror(-res)); if (0 == ret) return SG_LIB_FILE_ERROR; } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }
int main(int argc, char * argv[]) { bool bpw_then_activate = false; bool dry_run = false; bool got_stdin = false; bool wb_len_given = false; int sg_fd, infd, res, c, len, k, n; int bpw = 0; int do_help = 0; int ret = 0; int verbose = 0; int wb_id = 0; int wb_len = 0; int wb_mode = 0; int wb_offset = 0; int wb_skip = 0; int wb_timeout = DEF_PT_TIMEOUT; int wb_mspec = 0; const char * device_name = NULL; const char * file_name = NULL; unsigned char * dop = NULL; char * cp; const struct mode_s * mp; char ebuff[EBUFF_SZ]; while (1) { int option_index = 0; c = getopt_long(argc, argv, "b:dhi:I:l:m:o:rs:S:t:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'b': bpw = sg_get_num(optarg); if (bpw < 0) { pr2serr("argument to '--bpw' should be in a positive " "number\n"); return SG_LIB_SYNTAX_ERROR; } if ((cp = strchr(optarg, ','))) { if (0 == strncmp("act", cp + 1, 3)) bpw_then_activate = true; } break; case 'd': dry_run = true; break; case 'h': case '?': ++do_help; break; case 'i': wb_id = sg_get_num(optarg); if ((wb_id < 0) || (wb_id > 255)) { pr2serr("argument to '--id' should be in the range 0 to " "255\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'I': file_name = optarg; break; case 'l': wb_len = sg_get_num(optarg); if (wb_len < 0) { pr2serr("bad argument to '--length'\n"); return SG_LIB_SYNTAX_ERROR; } wb_len_given = true; break; case 'm': if (isdigit(*optarg)) { wb_mode = sg_get_num(optarg); if ((wb_mode < 0) || (wb_mode > 31)) { pr2serr("argument to '--mode' should be in the range 0 " "to 31\n"); return SG_LIB_SYNTAX_ERROR; } } else { len = strlen(optarg); for (mp = mode_arr; mp->mode_string; ++mp) { if (0 == strncmp(mp->mode_string, optarg, len)) { wb_mode = mp->mode; break; } } if (! mp->mode_string) { print_modes(); return SG_LIB_SYNTAX_ERROR; } } break; case 'o': wb_offset = sg_get_num(optarg); if (wb_offset < 0) { pr2serr("bad argument to '--offset'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'r': /* --read-stdin and --raw (previous name) */ file_name = "-"; break; case 's': wb_skip = sg_get_num(optarg); if (wb_skip < 0) { pr2serr("bad argument to '--skip'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'S': wb_mspec = sg_get_num(optarg); if ((wb_mspec < 0) || (wb_mspec > 7)) { pr2serr("expected argument to '--specific' to be 0 to 7\n"); return SG_LIB_SYNTAX_ERROR; } break; case 't': wb_timeout = sg_get_num(optarg); if (wb_timeout < 0) { pr2serr("Invalid argument to '--timeout'\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'v': ++verbose; break; case 'V': pr2serr(ME "version: %s\n", version_str); return 0; default: pr2serr("unrecognised option code 0x%x ??\n", c); usage(); return SG_LIB_SYNTAX_ERROR; } } if (do_help) { if (do_help > 1) { usage(); pr2serr("\n"); print_modes(); } else usage(); return 0; } 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; } } if (NULL == device_name) { pr2serr("missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if ((wb_len > 0) && (bpw > wb_len)) { pr2serr("trim chunk size (CS) to be the same as LEN\n"); bpw = wb_len; } #ifdef SG_LIB_WIN32 #ifdef SG_LIB_WIN32_DIRECT if (verbose > 4) pr2serr("Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif #endif sg_fd = sg_cmds_open_device(device_name, false /* rw */, verbose); if (sg_fd < 0) { pr2serr(ME "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } if (file_name || (wb_len > 0)) { if (0 == wb_len) wb_len = DEF_XFER_LEN; if (NULL == (dop = (unsigned char *)malloc(wb_len))) { pr2serr(ME "out of memory\n"); ret = SG_LIB_SYNTAX_ERROR; goto err_out; } memset(dop, 0xff, wb_len); if (file_name) { got_stdin = (0 == strcmp(file_name, "-")); if (got_stdin) { if (wb_skip > 0) { pr2serr("Can't skip on stdin\n"); ret = SG_LIB_FILE_ERROR; goto err_out; } infd = STDIN_FILENO; } else { if ((infd = open(file_name, O_RDONLY)) < 0) { snprintf(ebuff, EBUFF_SZ, ME "could not open %s for reading", file_name); perror(ebuff); ret = SG_LIB_FILE_ERROR; goto err_out; } else if (sg_set_binary_mode(infd) < 0) perror("sg_set_binary_mode"); if (wb_skip > 0) { if (lseek(infd, wb_skip, SEEK_SET) < 0) { snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to " "required position on %s", file_name); perror(ebuff); close(infd); ret = SG_LIB_FILE_ERROR; goto err_out; } } } res = read(infd, dop, wb_len); if (res < 0) { snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", file_name); perror(ebuff); if (! got_stdin) close(infd); ret = SG_LIB_FILE_ERROR; goto err_out; } if (res < wb_len) { if (wb_len_given) { pr2serr("tried to read %d bytes from %s, got %d bytes\n", wb_len, file_name, res); pr2serr("pad with 0xff bytes and continue\n"); } else { if (verbose) { pr2serr("tried to read %d bytes from %s, got %d " "bytes\n", wb_len, file_name, res); pr2serr("will write %d bytes", res); if ((bpw > 0) && (bpw < wb_len)) pr2serr(", %d bytes per WRITE BUFFER command\n", bpw); else pr2serr("\n"); } wb_len = res; } } if (! got_stdin) close(infd); } } res = 0; if (bpw > 0) { for (k = 0; k < wb_len; k += n) { n = wb_len - k; if (n > bpw) n = bpw; if (verbose) pr2serr("sending write buffer, mode=0x%x, mspec=%d, id=%d, " " offset=%d, len=%d\n", wb_mode, wb_mspec, wb_id, wb_offset + k, n); if (dry_run) { if (verbose) pr2serr("skipping WRITE BUFFER command due to " "--dry-run\n"); res = 0; } else res = sg_ll_write_buffer_v2(sg_fd, wb_mode, wb_mspec, wb_id, wb_offset + k, dop + k, n, wb_timeout, true, verbose); if (res) break; } if (bpw_then_activate) { if (verbose) pr2serr("sending Activate deferred microcode [0xf]\n"); if (dry_run) { if (verbose) pr2serr("skipping WRITE BUFFER(ACTIVATE) command due to " "--dry-run\n"); res = 0; } else res = sg_ll_write_buffer_v2(sg_fd, MODE_ACTIVATE_MC, 0 /* buffer_id */, 0 /* buffer_offset */, 0, NULL, 0, wb_timeout, true, verbose); } } else { if (verbose) pr2serr("sending single write buffer, mode=0x%x, mpsec=%d, " "id=%d, offset=%d, len=%d\n", wb_mode, wb_mspec, wb_id, wb_offset, wb_len); if (dry_run) { if (verbose) pr2serr("skipping WRITE BUFFER(all in one) command due to " "--dry-run\n"); res = 0; } else res = sg_ll_write_buffer_v2(sg_fd, wb_mode, wb_mspec, wb_id, wb_offset, dop, wb_len, wb_timeout, true, verbose); } if (0 != res) { char b[80]; ret = res; sg_get_category_sense_str(res, sizeof(b), b, verbose); pr2serr("Write buffer failed: %s\n", b); } err_out: if (dop) free(dop); res = sg_cmds_close_device(sg_fd); if (res < 0) { pr2serr("close error: %s\n", safe_strerror(-res)); if (0 == ret) return SG_LIB_FILE_ERROR; } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; }