Ejemplo n.º 1
0
static int fail_all_paths(int fd)
{
        unsigned char fail_paths_pg[118];
        struct rdac_legacy_page *rdac_page;
        int res;
        char b[80];

        memset(fail_paths_pg, 0, 118);
        memcpy(fail_paths_pg, mode6_hdr, 4);
        memcpy(fail_paths_pg + 4, block_descriptor, 8);
        rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
        rdac_page->page_code = RDAC_CONTROLLER_PAGE | 0x40;
        rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
        rdac_page->quiescence = RDAC_QUIESCENCE_TIME;
        rdac_page->options = RDAC_FORCE_QUIESCENCE;
        rdac_page->current_mode_lsb = RDAC_FAIL_ALL_PATHS;

        res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
                                 fail_paths_pg, 118,
                                 1, (do_verbose ? 2 : 0));

        switch (res) {
        case 0:
                if (do_verbose)
                        fprintf(stderr, "fail paths successful\n");
                break;
        default:
                sg_get_category_sense_str(res, sizeof(b), b, do_verbose);
                fprintf(stderr, "fail paths failed: %s\n", b);
                break;
        }

        return res;
}
Ejemplo n.º 2
0
/* Returns 0 if successful */
static int
process_read_long(int sg_fd, bool do_16, bool pblock, bool correct,
                  uint64_t llba, void * data_out, int xfer_len, int verbose)
{
    int offset, res;
    const char * ten_or;
    char b[80];

    if (do_16)
        res = sg_ll_read_long16(sg_fd, pblock, correct, llba, data_out,
                                xfer_len, &offset, true, verbose);
    else
        res = sg_ll_read_long10(sg_fd, pblock, correct, (unsigned int)llba,
                                data_out, xfer_len, &offset, true, verbose);
    ten_or = do_16 ? "16" : "10";
    switch (res) {
    case 0:
        break;
    case SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO:
        pr2serr("<<< device indicates 'xfer_len' should be %d >>>\n",
                xfer_len - offset);
        break;
    default:
        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("  SCSI READ LONG (%s): %s\n", ten_or, b);
        break;
    }
    return res;
}
Ejemplo n.º 3
0
static int fail_all_paths(int fd, int use_6_byte)
{
        unsigned char fail_paths_pg[308];
        struct rdac_legacy_page *rdac_page;
        struct rdac_expanded_page *rdac_page_exp;
        struct rdac_page_common *rdac_common = NULL;

        int res;
        char b[80];

        memset(fail_paths_pg, 0, 308);
        if (use_6_byte) {
                memcpy(fail_paths_pg, mode6_hdr, 4);
                memcpy(fail_paths_pg + 4, block_descriptor, 8);
                rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
                rdac_page->page_code = RDAC_CONTROLLER_PAGE;
                rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
                rdac_common = &rdac_page->attr;
        } else {
                memcpy(fail_paths_pg, mode10_hdr, 8);
                rdac_page_exp = (struct rdac_expanded_page *)
                                (fail_paths_pg + 8);
                rdac_page_exp->page_code = RDAC_CONTROLLER_PAGE | 0x40;
                rdac_page_exp->subpage_code = 0x1;
                rdac_page_exp->page_length[0] =
                                EXPANDED_LUN_SPACE_PAGE_LEN >> 8;
                rdac_page_exp->page_length[1] =
                                EXPANDED_LUN_SPACE_PAGE_LEN & 0xFF;
                rdac_common = &rdac_page_exp->attr;
        }

        rdac_common->current_mode_lsb =  RDAC_FAIL_ALL_PATHS;
        rdac_common->quiescence = RDAC_QUIESCENCE_TIME;
        rdac_common->options = RDAC_FORCE_QUIESCENCE;

        if (use_6_byte) {
                res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
                                        fail_paths_pg, 118,
                                        1, (do_verbose ? 2 : 0));
        } else {
                res = sg_ll_mode_select10(fd, 1 /* pf */, 0 /* sp */,
                                        fail_paths_pg, 308,
                                        1, (do_verbose ? 2: 0));
        }

        switch (res) {
        case 0:
                if (do_verbose)
                        fprintf(stderr, "fail paths successful\n");
                break;
        default:
                sg_get_category_sense_str(res, sizeof(b), b, do_verbose);
                fprintf(stderr, "fail paths failed: %s\n", b);
                break;
        }

        return res;
}
Ejemplo n.º 4
0
/* Get expected extended self-test time from mode page 0xa (for '-e') */
static int
do_modes_0a(int sg_fd, void * resp, int mx_resp_len, int noisy, int mode6,
            int verbose)
{
    int res;

    if (mode6)
        res = sg_ll_mode_sense6(sg_fd, 1 /* dbd */, 0 /* pc */, 0xa /* page */,
                                0, resp, mx_resp_len, noisy, verbose);
    else
        res = sg_ll_mode_sense10(sg_fd, 0 /* llbaa */, 1 /* dbd */, 0, 0xa, 0,
                                 resp, mx_resp_len, noisy, verbose);
    if (res) {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        fprintf(stderr, "Mode sense (%s): %s\n", (mode6 ? "6" : "10"), b);
    }
    return res;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
int
main(int argc, char * argv[])
{
    int64_t skip = 0;
    int64_t seek = 0;
    int ibs = 0;
    int obs = 0;
    int bpt = DEF_BLOCKS_PER_TRANSFER;
    int bpt_given = 0;
    char str[STR_SZ];
    char * key;
    char * buf;
    char inf[INOUTF_SZ];
    int in_type = FT_OTHER;
    char outf[INOUTF_SZ];
    int out_type = FT_OTHER;
    int res, k, t;
    int infd, outfd, blocks;
    unsigned char * wrkPos;
    unsigned char * wrkBuff = NULL;
    unsigned char * wrkMmap = NULL;
    int64_t in_num_sect = -1;
    int in_res_sz = 0;
    int64_t out_num_sect = -1;
    int out_res_sz = 0;
    int scsi_cdbsz_in = DEF_SCSI_CDBSZ;
    int scsi_cdbsz_out = DEF_SCSI_CDBSZ;
    int cdbsz_given = 0;
    int do_coe = 0;     /* dummy, just accept + ignore */
    int do_sync = 0;
    int num_dio_not_done = 0;
    int in_sect_sz, out_sect_sz;
    int n, flags;
    char ebuff[EBUFF_SZ];
    char b[80];
    int blocks_per;
    size_t psz;
    struct flags_t in_flags;
    struct flags_t out_flags;
    int ret = 0;

#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
    psz = sysconf(_SC_PAGESIZE); /* POSIX.1 (was getpagesize()) */
#else
    psz = 4096;     /* give up, pick likely figure */
#endif
    inf[0] = '\0';
    outf[0] = '\0';
    memset(&in_flags, 0, sizeof(in_flags));
    memset(&out_flags, 0, sizeof(out_flags));

    for (k = 1; k < argc; k++) {
        if (argv[k])
            strncpy(str, argv[k], STR_SZ);
        else
            continue;
        for (key = str, buf = key; *buf && *buf != '=';)
            buf++;
        if (*buf)
            *buf++ = '\0';
        if (0 == strcmp(key,"bpt")) {
            bpt = sg_get_num(buf);
            if (-1 == bpt) {
                pr2serr(ME "bad argument to 'bpt'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            bpt_given = 1;
        } else if (0 == strcmp(key,"bs")) {
            blk_sz = sg_get_num(buf);
            if (-1 == blk_sz) {
                pr2serr(ME "bad argument to 'bs'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"cdbsz")) {
            scsi_cdbsz_in = sg_get_num(buf);
            scsi_cdbsz_out = scsi_cdbsz_in;
            cdbsz_given = 1;
        } else if (0 == strcmp(key,"coe")) {
            do_coe = sg_get_num(buf);   /* dummy, just accept + ignore */
            if (do_coe) {
                ;    /* unused, dummy to suppress warning */
            }
        } else if (0 == strcmp(key,"count")) {
            if (0 != strcmp("-1", buf)) {
                dd_count = sg_get_llnum(buf);
                if (-1LL == dd_count) {
                    pr2serr(ME "bad argument to 'count'\n");
                    return SG_LIB_SYNTAX_ERROR;
                }
            }   /* treat 'count=-1' as calculate count (same as not given) */
        } else if (0 == strcmp(key,"dio"))
            out_flags.dio = sg_get_num(buf);
        else if (0 == strcmp(key,"fua")) {
            n = sg_get_num(buf);
            if (n & 1)
                out_flags.fua = 1;
            if (n & 2)
                in_flags.fua = 1;
        } else if (0 == strcmp(key,"ibs")) {
            ibs = sg_get_num(buf);
            if (-1 == ibs) {
                pr2serr(ME "bad argument to 'ibs'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (strcmp(key,"if") == 0) {
            if ('\0' != inf[0]) {
                pr2serr("Second 'if=' argument??\n");
                return SG_LIB_SYNTAX_ERROR;
            } else
                strncpy(inf, buf, INOUTF_SZ);
        } else if (0 == strcmp(key, "iflag")) {
            if (process_flags(buf, &in_flags)) {
                pr2serr(ME "bad argument to 'iflag'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (strcmp(key,"of") == 0) {
            if ('\0' != outf[0]) {
                pr2serr("Second 'of=' argument??\n");
                return SG_LIB_SYNTAX_ERROR;
            } else
                strncpy(outf, buf, INOUTF_SZ);
        } else if (0 == strcmp(key, "oflag")) {
            if (process_flags(buf, &out_flags)) {
                pr2serr(ME "bad argument to 'oflag'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"obs")) {
            obs = sg_get_num(buf);
            if (-1 == obs) {
                pr2serr(ME "bad argument to 'obs'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"seek")) {
            seek = sg_get_llnum(buf);
            if (-1LL == seek) {
                pr2serr(ME "bad argument to 'seek'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"skip")) {
            skip = sg_get_llnum(buf);
            if (-1LL == skip) {
                pr2serr(ME "bad argument to 'skip'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"sync"))
            do_sync = sg_get_num(buf);
        else if (0 == strcmp(key,"time"))
            do_time = sg_get_num(buf);
        else if (0 == strncmp(key, "verb", 4))
            verbose = sg_get_num(buf);
        else if ((0 == strncmp(key, "--help", 7)) ||
                 (0 == strcmp(key, "-h")) || (0 == strcmp(key, "-?"))) {
            usage();
            return 0;
        } else if ((0 == strncmp(key, "--vers", 6)) ||
                   (0 == strcmp(key, "-V"))) {
            pr2serr(ME ": %s\n", version_str);
            return 0;
        }
        else {
            pr2serr("Unrecognized option '%s'\n", key);
            pr2serr("For more information use '--help'\n");
            return SG_LIB_SYNTAX_ERROR;
        }
    }
    if (blk_sz <= 0) {
        blk_sz = DEF_BLOCK_SIZE;
        pr2serr("Assume default 'bs' (block size) of %d bytes\n", blk_sz);
    }
    if ((ibs && (ibs != blk_sz)) || (obs && (obs != blk_sz))) {
        pr2serr("If 'ibs' or 'obs' given must be same as 'bs'\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }
    if ((skip < 0) || (seek < 0)) {
        pr2serr("skip and seek cannot be negative\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if ((out_flags.append > 0) && (seek > 0)) {
        pr2serr("Can't use both append and seek switches\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (bpt < 1) {
        pr2serr("bpt must be greater than 0\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    /* defaulting transfer size to 128*2048 for CD/DVDs is too large
       for the block layer in lk 2.6 and results in an EIO on the
       SG_IO ioctl. So reduce it in that case. */
    if ((blk_sz >= 2048) && (0 == bpt_given))
        bpt = DEF_BLOCKS_PER_2048TRANSFER;

#ifdef SG_DEBUG
    pr2serr(ME "if=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%" PRId64
            "\n", inf, skip, outf, seek, dd_count);
#endif
    install_handler (SIGINT, interrupt_handler);
    install_handler (SIGQUIT, interrupt_handler);
    install_handler (SIGPIPE, interrupt_handler);
    install_handler (SIGUSR1, siginfo_handler);

    infd = STDIN_FILENO;
    outfd = STDOUT_FILENO;
    if (inf[0] && ('-' != inf[0])) {
        in_type = dd_filetype(inf);
        if (verbose)
            pr2serr(" >> Input file type: %s\n",
                    dd_filetype_str(in_type, ebuff));

        if (FT_ERROR == in_type) {
            pr2serr(ME "unable to access %s\n", inf);
            return SG_LIB_FILE_ERROR;
        } else if (FT_ST == in_type) {
            pr2serr(ME "unable to use scsi tape device %s\n", inf);
            return SG_LIB_FILE_ERROR;
        } else if (FT_SG == in_type) {
            flags = O_RDWR | O_NONBLOCK;
            if (in_flags.direct)
                flags |= O_DIRECT;
            if (in_flags.excl)
                flags |= O_EXCL;
            if (in_flags.dsync)
                flags |= O_SYNC;
            if ((infd = open(inf, flags)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                         ME "could not open %s for sg reading", inf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
            res = ioctl(infd, SG_GET_VERSION_NUM, &t);
            if ((res < 0) || (t < 30122)) {
                pr2serr(ME "sg driver prior to 3.1.22\n");
                return SG_LIB_FILE_ERROR;
            }
            in_res_sz = blk_sz * bpt;
            if (0 != (in_res_sz % psz)) /* round up to next page */
                in_res_sz = ((in_res_sz / psz) + 1) * psz;
            if (ioctl(infd, SG_GET_RESERVED_SIZE, &t) < 0) {
                perror(ME "SG_GET_RESERVED_SIZE error");
                return SG_LIB_FILE_ERROR;
            }
            if (t < MIN_RESERVED_SIZE)
                t = MIN_RESERVED_SIZE;
            if (in_res_sz > t) {
                if (ioctl(infd, SG_SET_RESERVED_SIZE, &in_res_sz) < 0) {
                    perror(ME "SG_SET_RESERVED_SIZE error");
                    return SG_LIB_FILE_ERROR;
                }
            }
            wrkMmap = (unsigned char *)mmap(NULL, in_res_sz,
                                            PROT_READ | PROT_WRITE, MAP_SHARED, infd, 0);
            if (MAP_FAILED == wrkMmap) {
                snprintf(ebuff, EBUFF_SZ,
                         ME "error using mmap() on file: %s", inf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
        } else {
            flags = O_RDONLY;
            if (in_flags.direct)
                flags |= O_DIRECT;
            if (in_flags.excl)
                flags |= O_EXCL;
            if (in_flags.dsync)
                flags |= O_SYNC;
            if ((infd = open(inf, flags)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                         ME "could not open %s for reading", inf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
            else if (skip > 0) {
                off64_t offset = skip;

                offset *= blk_sz;       /* could exceed 32 bits here! */
                if (lseek64(infd, offset, SEEK_SET) < 0) {
                    snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to "
                             "required position on %s", inf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
                if (verbose)
                    pr2serr("  >> skip: lseek64 SEEK_SET, byte offset=0x%"
                            PRIx64 "\n", (uint64_t)offset);
            }
        }
    }

    if (outf[0] && ('-' != outf[0])) {
        out_type = dd_filetype(outf);
        if (verbose)
            pr2serr(" >> Output file type: %s\n",
                    dd_filetype_str(out_type, ebuff));

        if (FT_ST == out_type) {
            pr2serr(ME "unable to use scsi tape device %s\n", outf);
            return SG_LIB_FILE_ERROR;
        }
        else if (FT_SG == out_type) {
            flags = O_RDWR | O_NONBLOCK;
            if (out_flags.direct)
                flags |= O_DIRECT;
            if (out_flags.excl)
                flags |= O_EXCL;
            if (out_flags.dsync)
                flags |= O_SYNC;
            if ((outfd = open(outf, flags)) < 0) {
                snprintf(ebuff, EBUFF_SZ, ME "could not open %s for "
                         "sg writing", outf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
            res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
            if ((res < 0) || (t < 30122)) {
                pr2serr(ME "sg driver prior to 3.1.22\n");
                return SG_LIB_FILE_ERROR;
            }
            if (ioctl(outfd, SG_GET_RESERVED_SIZE, &t) < 0) {
                perror(ME "SG_GET_RESERVED_SIZE error");
                return SG_LIB_FILE_ERROR;
            }
            if (t < MIN_RESERVED_SIZE)
                t = MIN_RESERVED_SIZE;
            out_res_sz = blk_sz * bpt;
            if (out_res_sz > t) {
                if (ioctl(outfd, SG_SET_RESERVED_SIZE, &out_res_sz) < 0) {
                    perror(ME "SG_SET_RESERVED_SIZE error");
                    return SG_LIB_FILE_ERROR;
                }
            }
            if (NULL == wrkMmap) {
                wrkMmap = (unsigned char *)mmap(NULL, out_res_sz,
                                                PROT_READ | PROT_WRITE, MAP_SHARED, outfd, 0);
                if (MAP_FAILED == wrkMmap) {
                    snprintf(ebuff, EBUFF_SZ,
                             ME "error using mmap() on file: %s", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
            }
        }
        else if (FT_DEV_NULL == out_type)
            outfd = -1; /* don't bother opening */
        else {
            if (FT_RAW != out_type) {
                flags = O_WRONLY | O_CREAT;
                if (out_flags.direct)
                    flags |= O_DIRECT;
                if (out_flags.excl)
                    flags |= O_EXCL;
                if (out_flags.dsync)
                    flags |= O_SYNC;
                if (out_flags.append)
                    flags |= O_APPEND;
                if ((outfd = open(outf, flags, 0666)) < 0) {
                    snprintf(ebuff, EBUFF_SZ,
                             ME "could not open %s for writing", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
            }
            else {
                if ((outfd = open(outf, O_WRONLY)) < 0) {
                    snprintf(ebuff, EBUFF_SZ, ME "could not open %s "
                             "for raw writing", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
            }
            if (seek > 0) {
                off64_t offset = seek;

                offset *= blk_sz;       /* could exceed 32 bits here! */
                if (lseek64(outfd, offset, SEEK_SET) < 0) {
                    snprintf(ebuff, EBUFF_SZ, ME "couldn't seek to "
                             "required position on %s", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
                if (verbose)
                    pr2serr("   >> seek: lseek64 SEEK_SET, byte offset=0x%"
                            PRIx64 "\n", (uint64_t)offset);
            }
        }
    }
    if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
        pr2serr("Won't default both IFILE to stdin _and_ OFILE to as "
                "stdout\n");
        pr2serr("For more information use '--help'\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (dd_count < 0) {
        in_num_sect = -1;
        if (FT_SG == in_type) {
            res = scsi_read_capacity(infd, &in_num_sect, &in_sect_sz);
            if (SG_LIB_CAT_UNIT_ATTENTION == res) {
                pr2serr("Unit attention(in), continuing\n");
                res = scsi_read_capacity(infd, &in_num_sect, &in_sect_sz);
            } else if (SG_LIB_CAT_ABORTED_COMMAND == res) {
                pr2serr("Aborted command(in), continuing\n");
                res = scsi_read_capacity(infd, &in_num_sect, &in_sect_sz);
            }
            if (0 != res) {
                sg_get_category_sense_str(res, sizeof(b), b, verbose);
                pr2serr("Read capacity (if=%s): %s\n", inf, b);
                in_num_sect = -1;
            }
        } else if (FT_BLOCK == in_type) {
            if (0 != read_blkdev_capacity(infd, &in_num_sect, &in_sect_sz)) {
                pr2serr("Unable to read block capacity on %s\n", inf);
                in_num_sect = -1;
            }
            if (blk_sz != in_sect_sz) {
                pr2serr("block size on %s confusion; bs=%d, from device=%d\n",
                        inf, blk_sz, in_sect_sz);
                in_num_sect = -1;
            }
        }
        if (in_num_sect > skip)
            in_num_sect -= skip;

        out_num_sect = -1;
        if (FT_SG == out_type) {
            res = scsi_read_capacity(outfd, &out_num_sect, &out_sect_sz);
            if (SG_LIB_CAT_UNIT_ATTENTION == res) {
                pr2serr("Unit attention(out), continuing\n");
                res = scsi_read_capacity(outfd, &out_num_sect, &out_sect_sz);
            } else if (SG_LIB_CAT_ABORTED_COMMAND == res) {
                pr2serr("Aborted command(out), continuing\n");
                res = scsi_read_capacity(outfd, &out_num_sect, &out_sect_sz);
            }
            if (0 != res) {
                sg_get_category_sense_str(res, sizeof(b), b, verbose);
                pr2serr("Read capacity (of=%s): %s\n", inf, b);
                out_num_sect = -1;
            }
        } else if (FT_BLOCK == out_type) {
            if (0 != read_blkdev_capacity(outfd, &out_num_sect,
                                          &out_sect_sz)) {
                pr2serr("Unable to read block capacity on %s\n", outf);
                out_num_sect = -1;
            }
            if (blk_sz != out_sect_sz) {
                pr2serr("block size on %s confusion: bs=%d, from device=%d\n",
                        outf, blk_sz, out_sect_sz);
                out_num_sect = -1;
            }
        }
        if (out_num_sect > seek)
            out_num_sect -= seek;
#ifdef SG_DEBUG
        pr2serr("Start of loop, count=%" PRId64 ", in_num_sect=%" PRId64 ", "
                "out_num_sect=%" PRId64 "\n", dd_count, in_num_sect,
                out_num_sect);
#endif
        if (in_num_sect > 0) {
            if (out_num_sect > 0)
                dd_count = (in_num_sect > out_num_sect) ? out_num_sect :
                           in_num_sect;
            else
                dd_count = in_num_sect;
        }
        else
            dd_count = out_num_sect;
    }

    if (dd_count < 0) {
        pr2serr("Couldn't calculate count, please give one\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (! cdbsz_given) {
        if ((FT_SG == in_type) && (MAX_SCSI_CDBSZ != scsi_cdbsz_in) &&
                (((dd_count + skip) > UINT_MAX) || (bpt > USHRT_MAX))) {
            pr2serr("Note: SCSI command size increased to 16 bytes (for "
                    "'if')\n");
            scsi_cdbsz_in = MAX_SCSI_CDBSZ;
        }
        if ((FT_SG == out_type) && (MAX_SCSI_CDBSZ != scsi_cdbsz_out) &&
                (((dd_count + seek) > UINT_MAX) || (bpt > USHRT_MAX))) {
            pr2serr("Note: SCSI command size increased to 16 bytes (for "
                    "'of')\n");
            scsi_cdbsz_out = MAX_SCSI_CDBSZ;
        }
    }

    if (out_flags.dio && (FT_SG != in_type)) {
        out_flags.dio = 0;
        pr2serr(">>> dio only performed on 'of' side when 'if' is an sg "
                "device\n");
    }
    if (out_flags.dio) {
        int fd;
        char c;

        if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) {
            if (1 == read(fd, &c, 1)) {
                if ('0' == c)
                    pr2serr(">>> %s set to '0' but should be set to '1' for "
                            "direct IO\n", proc_allow_dio);
            }
            close(fd);
        }
    }

    if (wrkMmap) {
        wrkPos = wrkMmap;
    } else {
        if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
            wrkBuff = (unsigned char *)malloc(blk_sz * bpt + psz);
            if (0 == wrkBuff) {
                pr2serr("Not enough user memory for raw\n");
                return SG_LIB_FILE_ERROR;
            }
            /* perhaps use posix_memalign() instead */
            wrkPos = (unsigned char *)(((uintptr_t)wrkBuff + psz - 1) &
                                       (~(psz - 1)));
        }
        else {
            wrkBuff = (unsigned char *)malloc(blk_sz * bpt);
            if (0 == wrkBuff) {
                pr2serr("Not enough user memory\n");
                return SG_LIB_FILE_ERROR;
            }
            wrkPos = wrkBuff;
        }
    }

    blocks_per = bpt;
#ifdef SG_DEBUG
    pr2serr("Start of loop, count=%" PRId64 ", blocks_per=%d\n", dd_count,
            blocks_per);
#endif
    if (do_time) {
        start_tm.tv_sec = 0;
        start_tm.tv_usec = 0;
        gettimeofday(&start_tm, NULL);
        start_tm_valid = 1;
    }
    req_count = dd_count;

    if (verbose && (dd_count > 0) && (0 == out_flags.dio) &&
            (FT_SG == in_type) && (FT_SG == out_type))
        pr2serr("Since both 'if' and 'of' are sg devices, only do mmap-ed "
                "transfers on 'if'\n");

    while (dd_count > 0) {
        blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
        if (FT_SG == in_type) {
            ret = sg_read(infd, wrkPos, blocks, skip, blk_sz, scsi_cdbsz_in,
                          in_flags.fua, in_flags.dpo, 1);
            if ((SG_LIB_CAT_UNIT_ATTENTION == ret) ||
                    (SG_LIB_CAT_ABORTED_COMMAND == ret)) {
                pr2serr("Unit attention or aborted command, continuing "
                        "(r)\n");
                ret = sg_read(infd, wrkPos, blocks, skip, blk_sz,
                              scsi_cdbsz_in, in_flags.fua, in_flags.dpo, 1);
            }
            if (0 != ret) {
                pr2serr("sg_read failed, skip=%" PRId64 "\n", skip);
                break;
            }
            else
                in_full += blocks;
        }
        else {
            while (((res = read(infd, wrkPos, blocks * blk_sz)) < 0) &&
                    ((EINTR == errno) || (EAGAIN == errno)))
                ;
            if (verbose > 2)
                pr2serr("read(unix): count=%d, res=%d\n", blocks * blk_sz,
                        res);
            if (ret < 0) {
                snprintf(ebuff, EBUFF_SZ, ME "reading, skip=%" PRId64 " ",
                         skip);
                perror(ebuff);
                ret = -1;
                break;
            }
            else if (res < blocks * blk_sz) {
                dd_count = 0;
                blocks = res / blk_sz;
                if ((res % blk_sz) > 0) {
                    blocks++;
                    in_partial++;
                }
            }
            in_full += blocks;
        }

        if (0 == blocks)
            break;      /* read nothing so leave loop */

        if (FT_SG == out_type) {
            int do_mmap = (FT_SG == in_type) ? 0 : 1;
            int dio_res = out_flags.dio;

            ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz, scsi_cdbsz_out,
                           out_flags.fua, out_flags.dpo, do_mmap, &dio_res);
            if ((SG_LIB_CAT_UNIT_ATTENTION == ret) ||
                    (SG_LIB_CAT_ABORTED_COMMAND == ret)) {
                pr2serr("Unit attention or aborted command, continuing (w)\n");
                dio_res = out_flags.dio;
                ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz,
                               scsi_cdbsz_out, out_flags.fua, out_flags.dpo,
                               do_mmap, &dio_res);
            }
            if (0 != ret) {
                pr2serr("sg_write failed, seek=%" PRId64 "\n", seek);
                break;
            }
            else {
                out_full += blocks;
                if (out_flags.dio && (0 == dio_res))
                    num_dio_not_done++;
            }
        }
        else if (FT_DEV_NULL == out_type)
            out_full += blocks; /* act as if written out without error */
        else {
            while (((res = write(outfd, wrkPos, blocks * blk_sz)) < 0) &&
                    ((EINTR == errno) || (EAGAIN == errno)))
                ;
            if (verbose > 2)
                pr2serr("write(unix): count=%d, res=%d\n", blocks * blk_sz,
                        res);
            if (res < 0) {
                snprintf(ebuff, EBUFF_SZ, ME "writing, seek=%" PRId64 " ",
                         seek);
                perror(ebuff);
                break;
            }
            else if (res < blocks * blk_sz) {
                pr2serr("output file probably full, seek=%" PRId64 " ", seek);
                blocks = res / blk_sz;
                out_full += blocks;
                if ((res % blk_sz) > 0)
                    out_partial++;
                break;
            }
            else
                out_full += blocks;
        }
        if (dd_count > 0)
            dd_count -= blocks;
        skip += blocks;
        seek += blocks;
    }

    if (do_time)
        calc_duration_throughput(0);
    if (do_sync) {
        if (FT_SG == out_type) {
            pr2serr(">> Synchronizing cache on %s\n", outf);
            res = sg_ll_sync_cache_10(outfd, 0, 0, 0, 0, 0, 0, 0);
            if (SG_LIB_CAT_UNIT_ATTENTION == res) {
                pr2serr("Unit attention(out), continuing\n");
                res = sg_ll_sync_cache_10(outfd, 0, 0, 0, 0, 0, 0, 0);
            }
            if (0 != res) {
                sg_get_category_sense_str(res, sizeof(b), b, verbose);
                pr2serr("Synchronize cache(out): %s\n", b);
            }
        }
    }

    if (wrkBuff) free(wrkBuff);
    if (STDIN_FILENO != infd)
        close(infd);
    if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
        close(outfd);
    if (0 != dd_count) {
        pr2serr("Some error occurred,");
        if (0 == ret)
            ret = SG_LIB_CAT_OTHER;
    }
    print_stats();
    if (sum_of_resids)
        pr2serr(">> Non-zero sum of residual counts=%d\n", sum_of_resids);
    if (num_dio_not_done)
        pr2serr(">> dio requested but _not_ done %d times\n",
                num_dio_not_done);
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
int
main(int argc, char * argv[])
{
    bool do_raw = false;
    bool readonly = false;
    bool verbose_given = false;
    bool version_given = false;
    int sg_fd, k, m, res, c;
    int do_hex = 0;
    int verbose = 0;
    int ret = 0;
    uint32_t max_block_size;
    uint16_t min_block_size;
    const char * device_name = NULL;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hHrRvV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'r':
            do_raw = true;
            break;
        case 'R':
            readonly = true;
            break;
        case 'v':
            verbose_given = true;
            ++verbose;
            break;
        case 'V':
            version_given = true;
            break;
        default:
            pr2serr("invalid option -%c ??\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");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    sg_fd = sg_cmds_open_device(device_name, 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 the_end2;
    }

    memset(readBlkLmtBuff, 0x0, 6);
    res = sg_ll_read_block_limits(sg_fd, readBlkLmtBuff, 6, true, verbose);
    ret = res;
    if (0 == res) {
      if (do_hex) {
        hex2stdout(readBlkLmtBuff, sizeof(readBlkLmtBuff), 1);
        goto the_end;
      } else if (do_raw) {
        dStrRaw((const char *)readBlkLmtBuff, sizeof(readBlkLmtBuff));
        goto the_end;
      }

      max_block_size = sg_get_unaligned_be32(readBlkLmtBuff + 0);
      min_block_size = sg_get_unaligned_be16(readBlkLmtBuff + 4);
      k = min_block_size / 1024;
      pr2serr("Read Block Limits results:\n");
      pr2serr("\tMinimum block size: %u byte(s)",
              (unsigned int)min_block_size);
      if (k != 0)
        pr2serr(", %d KB", k);
      pr2serr("\n");
      k = max_block_size / 1024;
      m = max_block_size / 1048576;
      pr2serr("\tMaximum block size: %u byte(s)",
              (unsigned int)max_block_size);
      if (k != 0)
        pr2serr(", %d KB", k);
      if (m != 0)
        pr2serr(", %d MB", m);
      pr2serr("\n");
    } else {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("Read block limits: %s\n", b);
        if (0 == verbose)
            pr2serr("    try '-v' option for more information\n");
    }

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);
    }
the_end2:
    if (0 == verbose) {
        if (! sg_if_can2stderr("sg_read_block_limits failed: ", ret))
            pr2serr("Some error occurred, try again with '-v' or '-vv' for "
                    "more information\n");
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
int
main(int argc, char *argv[])
{
    int ret = 0;
    int res_cat, status, slen, k, ret2;
    int sg_fd = -1;
    struct sg_pt_base *ptvp = NULL;
    unsigned char sense_buffer[32];
    unsigned char * dxfer_buffer_in = NULL;
    unsigned char * dxfer_buffer_out = NULL;
    unsigned char *wrkBuf = NULL;
    struct opts_t opts;
    struct opts_t * op;
    char b[128];

    op = &opts;
    memset(op, 0, sizeof(opts));
    op->timeout = DEFAULT_TIMEOUT;
    ret = process_cl(op, argc, argv);
    if (ret != 0) {
        usage();
        goto done;
    } else if (op->do_help) {
        usage();
        goto done;
    } else if (op->do_version) {
        version();
        goto done;
    }

    sg_fd = scsi_pt_open_device(op->device_name, op->readonly,
                                op->do_verbose);
    if (sg_fd < 0) {
        fprintf(stderr, "%s: %s\n", op->device_name, safe_strerror(-sg_fd));
        ret = SG_LIB_FILE_ERROR;
        goto done;
    }

    ptvp = construct_scsi_pt_obj();
    if (ptvp == NULL) {
        fprintf(stderr, "out of memory\n");
        ret = SG_LIB_CAT_OTHER;
        goto done;
    }
    if (op->do_verbose) {
        fprintf(stderr, "    cdb to send: ");
        for (k = 0; k < op->cdb_length; ++k)
            fprintf(stderr, "%02x ", op->cdb[k]);
        fprintf(stderr, "\n");
        if (op->do_verbose > 2) {
            sg_get_command_name(op->cdb, 0, sizeof(b) - 1, b);
            b[sizeof(b) - 1] = '\0';
            fprintf(stderr, "    Command name: %s\n", b);
        }
    }
    set_scsi_pt_cdb(ptvp, op->cdb, op->cdb_length);
    set_scsi_pt_sense(ptvp, sense_buffer, sizeof(sense_buffer));

    if (op->do_dataout) {
        dxfer_buffer_out = fetch_dataout(op);
        if (dxfer_buffer_out == NULL) {
            ret = SG_LIB_CAT_OTHER;
            goto done;
        }
        set_scsi_pt_data_out(ptvp, dxfer_buffer_out, op->dataout_len);
    }
    if (op->do_datain) {
        dxfer_buffer_in = my_memalign(op->datain_len, &wrkBuf);
        if (dxfer_buffer_in == NULL) {
            perror("malloc");
            ret = SG_LIB_CAT_OTHER;
            goto done;
        }
        set_scsi_pt_data_in(ptvp, dxfer_buffer_in, op->datain_len);
    }

    ret = do_scsi_pt(ptvp, sg_fd, op->timeout, op->do_verbose);
    if (ret > 0) {
        if (SCSI_PT_DO_BAD_PARAMS == ret) {
            fprintf(stderr, "do_scsi_pt: bad pass through setup\n");
            ret = SG_LIB_CAT_OTHER;
        } else if (SCSI_PT_DO_TIMEOUT == ret) {
            fprintf(stderr, "do_scsi_pt: timeout\n");
            ret = SG_LIB_CAT_TIMEOUT;
        } else
            ret = SG_LIB_CAT_OTHER;
        goto done;
    } else if (ret < 0) {
        fprintf(stderr, "do_scsi_pt: %s\n", safe_strerror(-ret));
        ret = SG_LIB_CAT_OTHER;
        goto done;
    }

    slen = 0;
    res_cat = get_scsi_pt_result_category(ptvp);
    switch (res_cat) {
    case SCSI_PT_RESULT_GOOD:
        ret = 0;
        break;
    case SCSI_PT_RESULT_SENSE:
        slen = get_scsi_pt_sense_len(ptvp);
        ret = sg_err_category_sense(sense_buffer, slen);
        break;
    case SCSI_PT_RESULT_TRANSPORT_ERR:
        get_scsi_pt_transport_err_str(ptvp, sizeof(b), b);
        fprintf(stderr, ">>> transport error: %s\n", b);
        ret = SG_LIB_CAT_OTHER;
        break;
    case SCSI_PT_RESULT_OS_ERR:
        get_scsi_pt_os_err_str(ptvp, sizeof(b), b);
        fprintf(stderr, ">>> os error: %s\n", b);
        ret = SG_LIB_CAT_OTHER;
        break;
    default:
        fprintf(stderr, ">>> unknown pass through result category (%d)\n",
                res_cat);
        ret = SG_LIB_CAT_OTHER;
        break;
    }

    status = get_scsi_pt_status_response(ptvp);
    fprintf(stderr, "SCSI Status: ");
    sg_print_scsi_status(status);
    fprintf(stderr, "\n\n");
    if ((SAM_STAT_CHECK_CONDITION == status) && (! op->no_sense)) {
        if (SCSI_PT_RESULT_SENSE != res_cat)
            slen = get_scsi_pt_sense_len(ptvp);
        if (0 == slen)
            fprintf(stderr, ">>> Strange: status is CHECK CONDITION but no "
                    "Sense Information\n");
        else {
            fprintf(stderr, "Sense Information:\n");
            sg_print_sense(NULL, sense_buffer, slen, (op->do_verbose > 0));
            fprintf(stderr, "\n");
        }
    }
    if (SAM_STAT_RESERVATION_CONFLICT == status)
        ret = SG_LIB_CAT_RES_CONFLICT;

    if (op->do_datain) {
        int data_len = op->datain_len - get_scsi_pt_resid(ptvp);

        if (ret && !(SG_LIB_CAT_RECOVERED == ret ||
                     SG_LIB_CAT_NO_SENSE == ret))
            fprintf(stderr, "Error %d occurred, no data received\n", ret);
        else if (data_len == 0) {
            fprintf(stderr, "No data received\n");
        } else {
            if (op->datain_file == NULL && !op->datain_binary) {
                fprintf(stderr, "Received %d bytes of data:\n", data_len);
                dStrHexErr((const char *)dxfer_buffer_in, data_len, 0);
            } else {
                const char * cp = "stdout";

                if (op->datain_file &&
                    ! ((1 == strlen(op->datain_file)) &&
                       ('-' == op->datain_file[0])))
                    cp = op->datain_file;
                fprintf(stderr, "Writing %d bytes of data to %s\n", data_len,
                        cp);
                ret2 = write_dataout(op->datain_file, dxfer_buffer_in,
                                     data_len);
                if (0 != ret2) {
                    if (0 == ret)
                        ret = ret2;
                    goto done;
                }
            }
        }
    }

done:
    if (op->do_verbose) {
        sg_get_category_sense_str(ret, sizeof(b), b, op->do_verbose - 1);
        fprintf(stderr, "%s\n", b);
    }
    if (wrkBuf)
        free(wrkBuf);
    if (ptvp)
        destruct_scsi_pt_obj(ptvp);
    if (sg_fd >= 0)
        scsi_pt_close_device(sg_fd);
    return ret;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
int main(int argc, char * argv[])
{
        unsigned char rsp_buff[MX_ALLOC_LEN];
        char **argptr;
        char * file_name = 0;
        int res, fd, k, lun = -1;
        int fail_all = 0;
        int fail_path = 0;
        int ret = 0;

        if (argc < 2) {
                usage ();
                return SG_LIB_SYNTAX_ERROR;
        }

        for (k = 1; k < argc; ++k) {
                argptr = argv + k;
                if (!strcmp (*argptr, "-v"))
                        ++do_verbose;
                else if (!strncmp(*argptr, "-f=",3)) {
                        ++fail_path;
                        lun = strtoul(*argptr + 3, NULL, 0);
                }
                else if (!strcmp(*argptr, "-a")) {
                        ++fail_all;
                }
                else if (!strcmp(*argptr, "-V")) {
                        fprintf(stderr, "sg_rdac version: %s\n", version_str);
                        return 0;
                }
                else if (*argv[k] == '-') {
                        fprintf(stderr, "Unrecognized switch: %s\n", argv[k]);
                        file_name = 0;
                        break;
                }
                else if (0 == file_name)
                        file_name = argv[k];
                else {
                        fprintf(stderr, "too many arguments\n");
                        file_name = 0;
                        break;
                }
        }
        if (0 == file_name) {
                usage();
                return SG_LIB_SYNTAX_ERROR;
        }

        fd = sg_cmds_open_device(file_name, 0 /* rw */, do_verbose);
        if (fd < 0) {
                fprintf(stderr, "open error: %s: %s\n", file_name,
                        safe_strerror(-fd));
                usage();
                return SG_LIB_FILE_ERROR;
        }

        if (fail_all) {
                res = fail_all_paths(fd);
        } else if (fail_path) {
                res = fail_this_path(fd, lun);
        } else {
                res = sg_ll_mode_sense6(fd, /*DBD*/ 0, /* page control */0,
                                        0x2c, 0, rsp_buff, 252,
                                        1, do_verbose);

                if (!res) {
                        if (do_verbose)
                                dump_mode_page(rsp_buff, rsp_buff[0]);
                        print_rdac_mode(rsp_buff);
                } else {
                        if (SG_LIB_CAT_INVALID_OP == res)
                                fprintf(stderr, ">>>>>> try again without "
                                        "the '-6' switch for a 10 byte MODE "
                                        "SENSE command\n");
                        else if (SG_LIB_CAT_ILLEGAL_REQ == res)
                                fprintf(stderr, "mode sense: invalid field "
                                        "in cdb (perhaps subpages or page "
                                        "control (PC) not supported)\n");
                        else {
                                char b[80];

                                sg_get_category_sense_str(res, sizeof(b), b,
                                                          do_verbose);
                                fprintf(stderr, "mode sense failed: %s\n", b);
                        }
                }
        }
        ret = res;

        res = sg_cmds_close_device(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;
}
Ejemplo n.º 14
0
int
main(int argc, char * argv[])
{
    bool allow = false;
    bool verbose_given = false;
    bool version_given = false;
    int sg_fd, res, c;
    int prevent = -1;
    int verbose = 0;
    const char * device_name = NULL;
    int ret = 0;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "ahp:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'a':
            allow = true;
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'p':
           prevent = sg_get_num(optarg);
           if ((prevent < 0) || (prevent > 3)) {
                pr2serr("bad argument to '--prevent'\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 (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");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }
    if (allow && (prevent >= 0)) {
        pr2serr("can't give both '--allow' and '--prevent='\n");
        usage();
        return SG_LIB_CONTRADICT;
    }
    if (allow)
        prevent = 0;
    else if (prevent < 0)
        prevent = 1;    /* default is to prevent, as utility name suggests */

    sg_fd = sg_cmds_open_device(device_name, false /* rw */, 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 fini;
    }
    res = sg_ll_prevent_allow(sg_fd, prevent, true, verbose);
    ret = res;
    if (res) {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("Prevent allow medium removal: %s\n", b);
    }
    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);
    }
fini:
    if (0 == verbose) {
        if (! sg_if_can2stderr("sg_prevent failed: ", ret))
            pr2serr("Some error occurred, try again with '-v' "
                    "or '-vv' for more information\n");
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
Ejemplo n.º 15
0
int main(int argc, char * argv[])
{
    int sg_fd, res, c;
    int64_t count = 0;
    unsigned int num_lb = 0;
    int do_16 = 0;
    int group = 0;
    int64_t lba = 0;
    int immed = 0;
    int sync_nv = 0;
    int to_secs = DEF_PT_TIMEOUT;
    int verbose = 0;
    const char * device_name = NULL;
    int ret = 0;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "c:g:hil:sSt:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'c':
            count = sg_get_llnum(optarg);
            if ((count < 0) || (count > UINT_MAX)) {
                pr2serr("bad argument to '--count'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            num_lb = (unsigned int)count;
            break;
        case 'g':
            group = sg_get_num(optarg);
            if ((group < 0) || (group > 31)) {
                pr2serr("bad argument to '--group'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'i':
            immed = 1;
            break;
        case 'l':
            lba = sg_get_llnum(optarg);
            if (lba < 0) {
                pr2serr("bad argument to '--lba'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 's':
            sync_nv = 1;
            break;
        case 'S':
            do_16 = 1;
            break;
        case 't':
            to_secs = sg_get_num(optarg);
            if (to_secs < 0) {
                pr2serr("bad argument to '--timeout'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            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 SG_LIB_SYNTAX_ERROR;
    }
    sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose);
    if (sg_fd < 0) {
        pr2serr("open error: %s: %s\n", device_name,
                safe_strerror(-sg_fd));
        return SG_LIB_FILE_ERROR;
    }

    if (do_16)
        res = ll_sync_cache_16(sg_fd, sync_nv, immed, group, lba, num_lb,
                               to_secs, 1, verbose);
    else
        res = sg_ll_sync_cache_10(sg_fd, sync_nv, immed, group,
                                  (unsigned int)lba, num_lb, 1, verbose);
    ret = res;
    if (res) {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("Synchronize cache failed: %s\n", b);
    }

    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;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
int
main(int argc, char * argv[])
{
    int sg_fd, res, c;
    int do_origin = 0;
    int do_set = 0;
    int do_srep = 0;
    int do_raw = 0;
    int readonly = 0;
    bool secs_given = false;
    int verbose = 0;
    uint64_t secs = 0;
    uint64_t msecs = 0;
    int64_t ll;
    const char * device_name = NULL;
    const char * cmd_name;
    int ret = 0;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hm:orRs:SvV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'm':
            ll = sg_get_llnum(optarg);
            if (-1 == ll) {
                pr2serr("bad argument to '--milliseconds=MS'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            msecs = (uint64_t)ll;
            ++do_set;
            break;
        case 'o':
            ++do_origin;
            break;
        case 'r':
            ++do_raw;
            break;
        case 'R':
            ++readonly;
            break;
        case 's':
            ll = sg_get_llnum(optarg);
            if (-1 == ll) {
                pr2serr("bad argument to '--seconds=SEC'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            secs = (uint64_t)ll;
            ++do_set;
            secs_given = true;
            break;
        case 'S':
            ++do_srep;
            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 (do_set > 1) {
        pr2serr("either --milliseconds=MS or --seconds=SEC may be given, "
                "not both\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    if (NULL == device_name) {
        pr2serr("missing device name!\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    sg_fd = sg_cmds_open_device(device_name, readonly, verbose);
    if (sg_fd < 0) {
        pr2serr("open error: %s: %s\n", device_name,
                safe_strerror(-sg_fd));
        return SG_LIB_FILE_ERROR;
    }

    memset(d_buff, 0, 12);
    if (do_set) {
        cmd_name = "Set timestamp";
        sg_put_unaligned_be48(secs_given ? (secs * 1000) : msecs, d_buff + 4);
        res = sg_ll_set_timestamp(sg_fd, d_buff, 12, 1, verbose);
    } else {
        cmd_name = "Report timestamp";
        res = sg_ll_rep_timestamp(sg_fd, d_buff, 12, NULL, 1, verbose);
        if (0 == res) {
            if (do_raw)
                dStrRaw((const char *)d_buff, 12);
            else {
                int len = sg_get_unaligned_be16(d_buff + 0);
                if (len < 8)
                    pr2serr("timestamp parameter data length too short, "
                            "expect >= 10, got %d\n", len + 2);
                else {
                    if (do_origin)
                        printf("Device clock %s\n",
                               ts_origin_arr[0x7 & d_buff[2]]);
                    msecs = sg_get_unaligned_be48(d_buff + 4);
                    printf("%" PRIu64 "\n", do_srep ? (msecs / 1000) : msecs);
                }
            }
        }
    }
    ret = res;
    if (res) {
        if (SG_LIB_CAT_INVALID_OP == res)
            pr2serr("%s command not supported\n", cmd_name);
        else {
            char b[80];

            sg_get_category_sense_str(res, sizeof(b), b, verbose);
            pr2serr("%s command: %s\n", cmd_name, b);
        }
    }

    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;
}
Ejemplo n.º 18
0
/* Returns number of TURs performed */
static int
loop_turs(struct sg_pt_base * ptvp, struct loop_res_t * resp,
          struct opts_t * op)
{
    int k, res;
    int vb = op->verbose;
    char b[80];

    if (op->do_low) {
        int rs, n, sense_cat;
        uint8_t cdb[6];
        uint8_t sense_b[32];

        for (k = 0; k < op->do_number; ++k) {
            /* Might get Unit Attention on first invocation */
            memset(cdb, 0, sizeof(cdb));    /* TUR's cdb is 6 zeros */
            set_scsi_pt_cdb(ptvp, cdb, sizeof(cdb));
            set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
            rs = do_scsi_pt(ptvp, -1, DEF_PT_TIMEOUT, vb);
            n = sg_cmds_process_resp(ptvp, "Test unit ready", rs, (0 == k),
                                     vb, &sense_cat);
            if (-1 == n) {
                resp->ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
                return k;
            } else if (-2 == n) {
                switch (sense_cat) {
                case SG_LIB_CAT_RECOVERED:
                case SG_LIB_CAT_NO_SENSE:
                    break;
                case SG_LIB_CAT_NOT_READY:
                    ++resp->num_errs;
                    if (1 ==  op->do_number) {
                        resp->ret = sense_cat;
                        printf("device not ready\n");
                        resp->reported = true;
                    }
                    break;
                case SG_LIB_CAT_UNIT_ATTENTION:
                    ++resp->num_errs;
                    if (vb) {
                        pr2serr("Ignoring Unit attention (sense key)\n");
                        resp->reported = true;
                    }
                    break;
                default:
                    ++resp->num_errs;
                    if (1 == op->do_number) {
                        resp->ret = sense_cat;
                        sg_get_category_sense_str(sense_cat, sizeof(b), b, vb);
                        printf("%s\n", b);
                        resp->reported = true;
                        return k;
                    }
                    break;
                }
            }
            clear_scsi_pt_obj(ptvp);
        }
        return k;
    } else {
        for (k = 0; k < op->do_number; ++k) {
            /* Might get Unit Attention on first invocation */
            res = sg_ll_test_unit_ready_pt(ptvp, k, (0 == k), vb);
            if (res) {
                ++resp->num_errs;
                resp->ret = res;
                if (1 == op->do_number) {
                    if (SG_LIB_CAT_NOT_READY == res)
                        printf("device not ready\n");
                    else {
                        sg_get_category_sense_str(res, sizeof(b), b, vb);
                        printf("%s\n", b);
                    }
                    resp->reported = true;
                    break;
                }
            }
        }
        return k;
    }
}
Ejemplo n.º 19
0
static int
prin_work(int sg_fd, const struct opts_t * op)
{
    int k, j, num, add_len, add_desc_len;
    int res = 0;
    unsigned int pr_gen;
    uint8_t * bp;
    uint8_t * pr_buff = NULL;
    uint8_t * free_pr_buff = NULL;

    pr_buff = sg_memalign(op->alloc_len, 0 /* page aligned */, &free_pr_buff,
                          false);
    if (NULL == pr_buff) {
        pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
                op->alloc_len);
        return sg_convert_errno(ENOMEM);
    }
    res = sg_ll_persistent_reserve_in(sg_fd, op->prin_sa, pr_buff,
                                      op->alloc_len, true, op->verbose);
    if (res) {
        char b[64];
        char bb[80];

        if (op->prin_sa < num_prin_sa_strs)
            snprintf(b, sizeof(b), "%s", prin_sa_strs[op->prin_sa]);
        else
            snprintf(b, sizeof(b), "service action=0x%x", op->prin_sa);

        if (SG_LIB_CAT_INVALID_OP == res)
            pr2serr("PR in (%s): command not supported\n", b);
        else if (SG_LIB_CAT_ILLEGAL_REQ == res)
            pr2serr("PR in (%s): bad field in cdb or parameter list (perhaps "
                    "unsupported service action)\n", b);
        else {
            sg_get_category_sense_str(res, sizeof(bb), bb, op->verbose);
            pr2serr("PR in (%s): %s\n", b, bb);
        }
        goto fini;
    }
    if (PRIN_RCAP_SA == op->prin_sa) {
        if (8 != pr_buff[1]) {
            pr2serr("Unexpected response for PRIN Report Capabilities\n");
            if (op->hex)
                hex2stdout(pr_buff, pr_buff[1], 1);
            res = SG_LIB_CAT_MALFORMED;
            goto fini;
        }
        if (op->hex)
            hex2stdout(pr_buff, 8, 1);
        else {
            printf("Report capabilities response:\n");
            printf("  Replace Lost Reservation Capable(RLR_C): %d\n",
                   !!(pr_buff[2] & 0x80));      /* added spc4r26 */
            printf("  Compatible Reservation Handling(CRH): %d\n",
                   !!(pr_buff[2] & 0x10));
            printf("  Specify Initiator Ports Capable(SIP_C): %d\n",
                   !!(pr_buff[2] & 0x8));
            printf("  All Target Ports Capable(ATP_C): %d\n",
                   !!(pr_buff[2] & 0x4));
            printf("  Persist Through Power Loss Capable(PTPL_C): %d\n",
                   !!(pr_buff[2] & 0x1));
            printf("  Type Mask Valid(TMV): %d\n", !!(pr_buff[3] & 0x80));
            printf("  Allow Commands: %d\n", (pr_buff[3] >> 4) & 0x7);
            printf("  Persist Through Power Loss Active(PTPL_A): %d\n",
                   !!(pr_buff[3] & 0x1));
            if (pr_buff[3] & 0x80) {
                printf("    Support indicated in Type mask:\n");
                printf("      %s: %d\n", pr_type_strs[7],
                       !!(pr_buff[4] & 0x80));  /* WR_EX_AR */
                printf("      %s: %d\n", pr_type_strs[6],
                       !!(pr_buff[4] & 0x40));  /* EX_AC_RO */
                printf("      %s: %d\n", pr_type_strs[5],
                       !!(pr_buff[4] & 0x20));  /* WR_EX_RO */
                printf("      %s: %d\n", pr_type_strs[3],
                       !!(pr_buff[4] & 0x8));   /* EX_AC */
                printf("      %s: %d\n", pr_type_strs[1],
                       !!(pr_buff[4] & 0x2));   /* WR_EX */
                printf("      %s: %d\n", pr_type_strs[8],
                       !!(pr_buff[5] & 0x1));   /* EX_AC_AR */
            }
        }
    } else {
Ejemplo n.º 20
0
int
main(int argc, char * argv[])
{
    bool verbose_given = false;
    bool version_given = false;
    int sg_fd = -1;
    int res, c;
    unsigned int ctl = 0;
    unsigned int time_tnth = 0;
    int verbose = 0;
    const char * device_name = NULL;
    int ret = 0;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "c:ht:vV", long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'c':
            if ((1 != sscanf(optarg, "%4u", &ctl)) || (ctl > 3)) {
                pr2serr("--ctl= expects a number from 0 to 3\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 't':
            if ((1 != sscanf(optarg, "%4u", &time_tnth)) ||
                (time_tnth > 255)) {
                pr2serr("--time= expects a number from 0 to 255\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 (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;
    }

    sg_fd = sg_cmds_open_device(device_name, false, 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;
    }

    res = sg_ll_background_control(sg_fd, ctl, time_tnth, true, verbose);
    ret = res;
    if (res) {
        if (SG_LIB_CAT_INVALID_OP == res)
            pr2serr("%s command not supported\n", cmd_name);
        else {
            char b[80];

            sg_get_category_sense_str(res, sizeof(b), b, verbose);
            pr2serr("%s command: %s\n", cmd_name, b);
        }
    }

fini:
    if (0 == verbose) {
        if (! sg_if_can2stderr("sg_bg_ctl failed: ", ret))
            pr2serr("Some error occurred, try again with '-v' or '-vv' for "
                    "more information\n");
    }
    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);
        }
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
0
static int fail_this_path(int fd, int lun, int use_6_byte)
{
    unsigned char fail_paths_pg[308];
    struct rdac_legacy_page *rdac_page;
    struct rdac_expanded_page *rdac_page_exp;
    struct rdac_page_common *rdac_common = NULL;
    int res;
    char b[80];

    if (use_6_byte && lun > 32) {
        pr2serr("must use 10 byte cdb to fail luns over 32\n");
        return -1;
    }

    memset(fail_paths_pg, 0, 308);
    if (use_6_byte) {
        memcpy(fail_paths_pg, mode6_hdr, 4);
        memcpy(fail_paths_pg + 4, block_descriptor, 8);
        rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
        rdac_page->page_code = RDAC_CONTROLLER_PAGE;
        rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
        rdac_common = &rdac_page->attr;
        memset(rdac_page->lun_table, 0x0, 32);
        rdac_page->lun_table[lun] = 0x81;
    } else {
        memcpy(fail_paths_pg, mode10_hdr, 8);
        rdac_page_exp = (struct rdac_expanded_page *)
                        (fail_paths_pg + 8);
        rdac_page_exp->page_code = RDAC_CONTROLLER_PAGE | 0x40;
        rdac_page_exp->subpage_code = 0x1;
        sg_put_unaligned_be16(EXPANDED_LUN_SPACE_PAGE_LEN,
                              rdac_page_exp->page_length + 0);
        rdac_common = &rdac_page_exp->attr;
        memset(rdac_page_exp->lun_table, 0x0, 256);
        rdac_page_exp->lun_table[lun] = 0x81;
    }

    rdac_common->current_mode_lsb =  RDAC_FAIL_SELECTED_PATHS;
    rdac_common->quiescence = RDAC_QUIESCENCE_TIME;
    rdac_common->options = RDAC_FORCE_QUIESCENCE;

    if (use_6_byte) {
        res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
                                 fail_paths_pg, 118,
                                 1, (do_verbose ? 2 : 0));
    } else {
        res = sg_ll_mode_select10(fd, 1 /* pf */, 0 /* sp */,
                                  fail_paths_pg, 308,
                                  1, (do_verbose ? 2: 0));
    }

    switch (res) {
    case 0:
        if (do_verbose)
            pr2serr("fail paths successful\n");
        break;
    default:
        sg_get_category_sense_str(res, sizeof(b), b, do_verbose);
        pr2serr("fail paths page (lun=%d) failed: %s\n", lun, b);
        break;
    }

    return res;
}