Пример #1
0
int
main(int argc, const char ** argv)
{
    char buff[8192];
    int num = 8192;
    long start = 0;
    int res, k, u, len, n;
    int inFile = STDIN_FILENO;
    int doHelp = 0;
    int doHex = 0;
    int noAddr = 0;
    int doVersion = 0;
    int hasFilename = 0;
    int ret = 0;
    const char * cp;

    for (k = 1; k < argc; k++) {
        cp = argv[k];
        len = strlen(cp);
        if (0 == strncmp("-b=", cp, 3)) {
            res = sscanf(cp + 3, "%d", &u);
            if ((1 != res) || (u < 1)) {
                fprintf(stderr, "Bad value after '-b=' option\n");
                usage();
                return 1;
            }
            bytes_per_line = u;
        } else if ((len > 1) && ('-' == cp[0]) && ('-' != cp[1])) {
            res = 0;
            n = num_chs_in_str(cp + 1, len - 1, 'h');
            doHelp += n;
            res += n;
            n = num_chs_in_str(cp + 1, len - 1, 'H');
            doHex += n;
            res += n;
            n = num_chs_in_str(cp + 1, len - 1, 'N');
            noAddr += n;
            res += n;
            n = num_chs_in_str(cp + 1, len - 1, 'V');
            doVersion += n;
            res += n;
            n = num_chs_in_str(cp + 1, len - 1, '?');
            doHelp += n;
            res += n;
            if (0 == res) {
                fprintf(stderr, "No option recognized in str: %s\n", cp);
                usage();
                return 1;
            }
        } else if (0 == strcmp("-?", argv[k]))
            ++doHelp;
        else if (*argv[k] == '-') {
            fprintf(stderr, "unknown switch: %s\n", argv[k]);
            usage();
            return 1;
        } else {
            hasFilename = 1;
            break;
        }
    }
    if (doVersion) {
        printf("%s\n", version_str);
        return 0;
    }
    if (doHelp) {
        usage();
        return 0;
    }

    /* Make sure num to fetch is integral multiple of bytes_per_line */
    if (0 != (num % bytes_per_line))
        num = (num / bytes_per_line) * bytes_per_line;

    if (hasFilename) {
        for ( ; k < argc; k++)
        {
            inFile = open(argv[k], O_RDONLY);
            if (inFile < 0) {
                fprintf(stderr, "Couldn't open file: %s\n", argv[k]);
                ret = 1;
            } else {
                sg_set_binary_mode(inFile);
                start = 0;
                if (! doHex)
                    printf("ASCII hex dump of file: %s\n", argv[k]);
                while ((res = read(inFile, buff, num)) > 0) {
                    if (doHex)
                        dStrHexOnly(buff, res, start, noAddr);
                    else
                        dStrHex(buff, res, start, noAddr);
                    start += (long)res;
                }
            }
            close(inFile);
        }
    } else {
        sg_set_binary_mode(inFile);
        while ((res = read(inFile, buff, num)) > 0) {
            if (doHex)
                dStrHexOnly(buff, res, start, noAddr);
            else
                dStrHex(buff, res, start, noAddr);
            start += (long)res;
        }
    }
    return ret;
}
Пример #2
0
int
main(int argc, char * argv[])
{
    bool verbose_given = false;
    bool version_given = false;
    int skip = 0;
    int seek = 0;
    int ibs = 0;
    int obs = 0;
    char str[STR_SZ];
    char * key;
    char * buf;
    char inf[INOUTF_SZ];
    char outf[INOUTF_SZ];
    int res, k, n, keylen;
    int in_num_sect = 0;
    int out_num_sect = 0;
    int num_threads = DEF_NUM_THREADS;
    int gen = 0;
    int do_time = 0;
    int in_sect_sz, out_sect_sz, first_xfer, qstate, req_index, seek_skip;
    int blocks, stop_after_write, terminate;
    char ebuff[EBUFF_SZ];
    Rq_elem * rep;
    struct timeval start_tm, end_tm;

    memset(&rcoll, 0, sizeof(Rq_coll));
    rcoll.bpt = DEF_BLOCKS_PER_TRANSFER;
    rcoll.in_type = FT_OTHER;
    rcoll.out_type = FT_OTHER;
    inf[0] = '\0';
    outf[0] = '\0';

    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';
        keylen = strlen(key);
        if (strcmp(key,"if") == 0)
            strncpy(inf, buf, INOUTF_SZ);
        else if (strcmp(key,"of") == 0)
            strncpy(outf, buf, INOUTF_SZ);
        else if (0 == strcmp(key,"ibs"))
            ibs = sg_get_num(buf);
        else if (0 == strcmp(key,"obs"))
            obs = sg_get_num(buf);
        else if (0 == strcmp(key,"bs"))
            rcoll.bs = sg_get_num(buf);
        else if (0 == strcmp(key,"bpt"))
            rcoll.bpt = sg_get_num(buf);
        else if (0 == strcmp(key,"skip"))
            skip = sg_get_num(buf);
        else if (0 == strcmp(key,"seek"))
            seek = sg_get_num(buf);
        else if (0 == strcmp(key,"count"))
            dd_count = sg_get_num(buf);
        else if (0 == strcmp(key,"dio"))
            rcoll.dio = sg_get_num(buf);
        else if (0 == strcmp(key,"thr"))
            num_threads = sg_get_num(buf);
        else if (0 == strcmp(key,"coe"))
            rcoll.coe = sg_get_num(buf);
        else if (0 == strcmp(key,"gen"))
            gen = sg_get_num(buf);
        else if ((0 == strncmp(key,"deb", 3)) || (0 == strncmp(key,"verb", 4)))
            rcoll.debug = sg_get_num(buf);
        else if (0 == strcmp(key,"time"))
            do_time = sg_get_num(buf);
        else if ((keylen > 1) && ('-' == key[0]) && ('-' != key[1])) {
            res = 0;
            n = num_chs_in_str(key + 1, keylen - 1, 'h');
            if (n > 0) {
                usage();
                return 0;
            }
            n = num_chs_in_str(key + 1, keylen - 1, 'v');
            if (n > 0)
                verbose_given = true;
            rcoll.debug += n;
            res += n;
            n = num_chs_in_str(key + 1, keylen - 1, 'V');
            if (n > 0)
                version_given = true;
            res += n;
            if (res < (keylen - 1)) {
                fprintf(stderr, "Unrecognised short option in '%s', try "
                        "'--help'\n", key);
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strncmp(key, "--help", 6)) {
            usage();
            return 0;
        } else if (0 == strncmp(key, "--verb", 6)) {
            verbose_given = true;
            ++rcoll.debug;
        } else if (0 == strncmp(key, "--vers", 6))
            version_given = true;
        else {
            fprintf(stderr, "Unrecognized argument '%s'\n", key);
            usage();
            return 1;
        }
    }
#ifdef DEBUG
    fprintf(stderr, "In DEBUG mode, ");
    if (verbose_given && version_given) {
        fprintf(stderr, "but override: '-vV' given, zero verbose and "
                "continue\n");
        verbose_given = false;
        version_given = false;
        rcoll.debug = 0;
    } else if (! verbose_given) {
        fprintf(stderr, "set '-vv'\n");
        rcoll.debug = 2;
    } else
        fprintf(stderr, "keep verbose=%d\n", rcoll.debug);
#else
    if (verbose_given && version_given)
        fprintf(stderr, "Not in DEBUG mode, so '-vV' has no special action\n");
#endif
    if (version_given) {
        fprintf(stderr, "sgq_dd for sg version 3 driver: %s\n",
                version_str);
            return 0;
        return 0;
    }

    if (argc < 2) {
        usage();
        return 1;
    }
    if (rcoll.bs <= 0) {
        rcoll.bs = DEF_BLOCK_SIZE;
        fprintf(stderr, "Assume default 'bs' (block size) of %d bytes\n",
                rcoll.bs);
    }
    if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) {
        fprintf(stderr, "If 'ibs' or 'obs' given must be same as 'bs'\n");
        usage();
        return 1;
    }
    if ((skip < 0) || (seek < 0)) {
        fprintf(stderr, "skip and seek cannot be negative\n");
        return 1;
    }
    if ((num_threads < 1) || (num_threads > MAX_NUM_THREADS)) {
        fprintf(stderr, "too few or too many threads requested\n");
        usage();
        return 1;
    }
    if (rcoll.debug)
        fprintf(stderr, "sgq_dd: if=%s skip=%d of=%s seek=%d count=%d\n",
               inf, skip, outf, seek, dd_count);
    install_handler (SIGINT, interrupt_handler);
    install_handler (SIGQUIT, interrupt_handler);
    install_handler (SIGPIPE, interrupt_handler);
    install_handler (SIGUSR1, siginfo_handler);

    rcoll.infd = STDIN_FILENO;
    rcoll.outfd = STDOUT_FILENO;
    if (inf[0] && ('-' != inf[0])) {
        rcoll.in_type = dd_filetype(inf);

        if (FT_SG == rcoll.in_type) {
            if ((rcoll.infd = open(inf, O_RDWR)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                         "sgq_dd: could not open %s for sg reading", inf);
                perror(ebuff);
                return 1;
            }
        }
        if (FT_SG != rcoll.in_type) {
            if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                         "sgq_dd: could not open %s for reading", inf);
                perror(ebuff);
                return 1;
            }
            else if (skip > 0) {
                loff_t offset = skip;

                offset *= rcoll.bs;       /* could exceed 32 here! */
                if (lseek(rcoll.infd, offset, SEEK_SET) < 0) {
                    snprintf(ebuff, EBUFF_SZ,
                "sgq_dd: couldn't skip to required position on %s", inf);
                    perror(ebuff);
                    return 1;
                }
            }
        }
    }
    if (outf[0] && ('-' != outf[0])) {
        rcoll.out_type = dd_filetype(outf);

        if (FT_SG == rcoll.out_type) {
            if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                        "sgq_dd: could not open %s for sg writing", outf);
                perror(ebuff);
                return 1;
            }
        }
        else {
            if (FT_OTHER == rcoll.out_type) {
                if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
                    snprintf(ebuff, EBUFF_SZ,
                            "sgq_dd: could not open %s for writing", outf);
                    perror(ebuff);
                    return 1;
                }
            }
            else {
                if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
                    snprintf(ebuff, EBUFF_SZ,
                            "sgq_dd: could not open %s for raw writing", outf);
                    perror(ebuff);
                    return 1;
                }
            }
            if (seek > 0) {
                loff_t offset = seek;

                offset *= rcoll.bs;       /* could exceed 32 bits here! */
                if (lseek(rcoll.outfd, offset, SEEK_SET) < 0) {
                    snprintf(ebuff, EBUFF_SZ,
                "sgq_dd: couldn't seek to required position on %s", outf);
                    perror(ebuff);
                    return 1;
                }
            }
        }
    }
    if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
        fprintf(stderr, "Disallow both if and of to be stdin and stdout\n");
        return 1;
    }
    if ((FT_OTHER == rcoll.in_type) && (FT_OTHER == rcoll.out_type) && !gen) {
        fprintf(stderr, "Either 'if' or 'of' must be a sg or raw device\n");
        return 1;
    }
    if (0 == dd_count)
        return 0;
    else if (dd_count < 0) {
        if (FT_SG == rcoll.in_type) {
            res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
            if (2 == res) {
                fprintf(stderr, "Unit attention, media changed(in), repeat\n");
                res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
            }
            if (0 != res) {
                fprintf(stderr, "Unable to read capacity on %s\n", inf);
                in_num_sect = -1;
            }
            else {
                if (in_num_sect > skip)
                    in_num_sect -= skip;
            }
        }
        if (FT_SG == rcoll.out_type) {
            res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
            if (2 == res) {
                fprintf(stderr, "Unit attention, media changed(out), "
                        "repeat\n");
                res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
            }
            if (0 != res) {
                fprintf(stderr, "Unable to read capacity on %s\n", outf);
                out_num_sect = -1;
            }
            else {
                if (out_num_sect > seek)
                    out_num_sect -= seek;
            }
        }
        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 (rcoll.debug > 1)
        fprintf(stderr, "Start of loop, count=%d, in_num_sect=%d, "
                "out_num_sect=%d\n", dd_count, in_num_sect, out_num_sect);
    if (dd_count <= 0) {
        fprintf(stderr, "Couldn't calculate count, please give one\n");
        return 1;
    }

    rcoll.in_count = dd_count;
    rcoll.in_done_count = dd_count;
    rcoll.skip = skip;
    rcoll.in_blk = skip;
    rcoll.out_count = dd_count;
    rcoll.out_done_count = dd_count;
    rcoll.seek = seek;
    rcoll.out_blk = seek;

    if ((FT_SG == rcoll.in_type) || (FT_SG == rcoll.out_type))
        rcoll.num_rq_elems = num_threads;
    else
        rcoll.num_rq_elems = 1;
    if (prepare_rq_elems(&rcoll, inf, outf)) {
        fprintf(stderr, "Setup failure, perhaps no memory\n");
        return 1;
    }

    first_xfer = 1;
    stop_after_write = 0;
    terminate = 0;
    seek_skip =  rcoll.seek - rcoll.skip;
    if (do_time) {
        start_tm.tv_sec = 0;
        start_tm.tv_usec = 0;
        gettimeofday(&start_tm, NULL);
    }
    while (rcoll.out_done_count > 0) { /* >>>>>>>>> main loop */
        req_index = -1;
        qstate = decider(&rcoll, first_xfer, &req_index);
        rep = (req_index < 0) ? NULL : (rcoll.req_arr + req_index);
        switch (qstate) {
        case QS_IDLE:
            if ((NULL == rep) || (rcoll.in_count <= 0)) {
                /* usleep(1000); */
                /* do_poll(&rcoll, 10, NULL); */
                /* do_poll(&rcoll, 0, NULL); */
                break;
            }
            if (rcoll.debug > 8)
                fprintf(stderr, "    sgq_dd: non-sleeping QS_IDLE state, "
                                "req_index=%d\n", req_index);
            if (first_xfer >= 2)
                first_xfer = 0;
            else if (1 == first_xfer)
                ++first_xfer;
            if (stop_after_write) {
                terminate = 1;
                break;
            }
            blocks = (rcoll.in_count > rcoll.bpt) ? rcoll.bpt : rcoll.in_count;
            rep->wr = 0;
            rep->blk = rcoll.in_blk;
            rep->num_blks = blocks;
            rcoll.in_blk += blocks;
            rcoll.in_count -= blocks;

            if (FT_SG == rcoll.in_type) {
                res = sg_start_io(rep);
                if (0 != res) {
                    if (1 == res)
                        fprintf(stderr, "Out of memory starting sg io\n");
                    terminate = 1;
                }
            }
            else {
                res = normal_in_operation(&rcoll, rep, blocks);
                if (res < 0)
                    terminate = 1;
                else if (res > 0)
                    stop_after_write = 1;
            }
            break;
        case QS_IN_FINISHED:
            if (rcoll.debug > 8)
                fprintf(stderr, "    sgq_dd: state is QS_IN_FINISHED, "
                                "req_index=%d\n", req_index);
            if ((rep->blk + seek_skip) != rcoll.out_blk) {
                /* if write would be out of sequence then wait */
                if (rcoll.debug > 4)
                    fprintf(stderr, "    sgq_dd: QS_IN_FINISHED, "
                            "out of sequence\n");
                usleep(200);
                break;
            }
            rep->wr = 1;
            rep->blk = rcoll.out_blk;
            blocks = rep->num_blks;
            rcoll.out_blk += blocks;
            rcoll.out_count -= blocks;

            if (FT_SG == rcoll.out_type) {
                res = sg_start_io(rep);
                if (0 != res) {
                    if (1 == res)
                        fprintf(stderr, "Out of memory starting sg io\n");
                    terminate = 1;
                }
            }
            else {
                if (normal_out_operation(&rcoll, rep, blocks) < 0)
                    terminate = 1;
            }
            break;
        case QS_IN_POLL:
            if (rcoll.debug > 8)
                fprintf(stderr, "    sgq_dd: state is QS_IN_POLL, "
                                "req_index=%d\n", req_index);
            res = sg_fin_in_operation(&rcoll, rep);
            if (res < 0)
                terminate = 1;
            else if (res > 1) {
                if (first_xfer) {
                    /* only retry on first xfer */
                    if (0 != sg_start_io(rep))
                        terminate = 1;
                }
                else
                    terminate = 1;
            }
            break;
        case QS_OUT_POLL:
            if (rcoll.debug > 8)
                fprintf(stderr, "    sgq_dd: state is QS_OUT_POLL, "
                                "req_index=%d\n", req_index);
            res = sg_fin_out_operation(&rcoll, rep);
            if (res < 0)
                terminate = 1;
            else if (res > 1) {
                if (first_xfer) {
                    /* only retry on first xfer */
                    if (0 != sg_start_io(rep))
                        terminate = 1;
                }
                else
                    terminate = 1;
            }
            break;
        default:
            if (rcoll.debug > 8)
                fprintf(stderr, "    sgq_dd: state is ?????\n");
            terminate = 1;
            break;
        }
        if (terminate)
            break;
    } /* >>>>>>>>>>>>> end of main loop */

    if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
        struct timeval res_tm;
        double a, b;

        gettimeofday(&end_tm, NULL);
        res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
        res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
        if (res_tm.tv_usec < 0) {
            --res_tm.tv_sec;
            res_tm.tv_usec += 1000000;
        }
        a = res_tm.tv_sec;
        a += (0.000001 * res_tm.tv_usec);
        b = (double)rcoll.bs * (dd_count - rcoll.out_done_count);
        printf("time to transfer data was %d.%06d secs",
               (int)res_tm.tv_sec, (int)res_tm.tv_usec);
        if ((a > 0.00001) && (b > 511))
            printf(", %.2f MB/sec\n", b / (a * 1000000.0));
        else
            printf("\n");
    }

    if (STDIN_FILENO != rcoll.infd)
        close(rcoll.infd);
    if (STDOUT_FILENO != rcoll.outfd)
        close(rcoll.outfd);
    res = 0;
    if (0 != rcoll.out_count) {
        fprintf(stderr, ">>>> Some error occurred,\n");
        res = 2;
    }
    print_stats();
    if (rcoll.dio_incomplete) {
        int fd;
        char c;

        fprintf(stderr, ">> Direct IO requested but incomplete %d times\n",
                rcoll.dio_incomplete);
        if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) {
            if (1 == read(fd, &c, 1)) {
                if ('0' == c)
                    fprintf(stderr, ">>> %s set to '0' but should be set "
                            "to '1' for direct IO\n", proc_allow_dio);
            }
            close(fd);
        }
    }
    if (rcoll.sum_of_resids)
        fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
               rcoll.sum_of_resids);
    return res;
}