Exemplo n.º 1
0
int
main(int argc, char *argv[])
{
    int k;
    int ret = 0;
    unsigned int ui;
    size_t s;
    struct opts_t opts;
    char b[2048];
    FILE * fp = NULL;
    const char * cp;

    memset(&opts, 0, sizeof(opts));
    memset(b, 0, sizeof(b));
    ret = process_cl(&opts, argc, argv);
    if (ret != 0) {
        usage();
        return ret;
    } else if (opts.do_help) {
        usage();
        return 0;
    } else if (opts.do_version) {
        pr2serr("version: %s\n", version_str);
        return 0;
    }


    if (opts.do_status) {
        sg_get_scsi_status_str(opts.sstatus, sizeof(b) - 1, b);
        printf("SCSI status: %s\n", b);
    }

    if ((0 == opts.sense_len) && opts.no_space_str) {
        if (opts.do_verbose > 2)
            pr2serr("no_space str: %s\n", opts.no_space_str);
        cp = opts.no_space_str;
        for (k = 0; isxdigit(cp[k]) && isxdigit(cp[k + 1]); k += 2) {
            if (1 != sscanf(cp + k, "%2x", &ui)) {
                pr2serr("bad no_space hex string: %s\n", cp);
                return SG_LIB_SYNTAX_ERROR;
            }
            opts.sense[opts.sense_len++] = (unsigned char)ui;
        }
    }

    if ((0 == opts.sense_len) && (! opts.do_binary) && (! opts.do_file)) {
        if (opts.do_status)
            return 0;
        pr2serr(">> Need sense data on the command line or in a file\n\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }
    if (opts.sense_len && (opts.do_binary || opts.do_file)) {
        pr2serr(">> Need sense data on command line or in a file, not "
                "both\n\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (opts.do_binary && opts.do_file) {
        pr2serr(">> Either a binary file or a ASCII hexadecimal, file not "
                "both\n\n");
        return SG_LIB_SYNTAX_ERROR;
    }

    if (opts.do_binary) {
        fp = fopen(opts.fname, "r");
        if (NULL == fp) {
            pr2serr("unable to open file: %s\n", opts.fname);
            return SG_LIB_SYNTAX_ERROR;
        }
        s = fread(opts.sense, 1, MAX_SENSE_LEN, fp);
        fclose(fp);
        if (0 == s) {
            pr2serr("read nothing from file: %s\n", opts.fname);
            return SG_LIB_SYNTAX_ERROR;
        }
        opts.sense_len = s;
    } else if (opts.do_file) {
        ret = f2hex_arr(opts.fname, opts.no_space, opts.sense,
                        &opts.sense_len, MAX_SENSE_LEN);
        if (ret) {
            pr2serr("unable to decode ASCII hex from file: %s\n", opts.fname);
            return SG_LIB_SYNTAX_ERROR;
        }
    }

    if (opts.sense_len) {
        if (opts.wfname) {
            if ((fp = fopen(opts.wfname, "w"))) {
                write2wfn(fp, &opts);
                fclose(fp);
            } else {
                perror("open");
                pr2serr("trying to write to %s\n", opts.wfname);
            }
        }
        sg_get_sense_str(NULL, opts.sense, opts.sense_len, opts.do_verbose,
                         sizeof(b) - 1, b);
        printf("%s\n", b);
    }

    return 0;
}
Exemplo n.º 2
0
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;
}