diff options
Diffstat (limited to 'archive/sg_dd512.c')
-rw-r--r-- | archive/sg_dd512.c | 586 |
1 files changed, 0 insertions, 586 deletions
diff --git a/archive/sg_dd512.c b/archive/sg_dd512.c deleted file mode 100644 index 6291ef43..00000000 --- a/archive/sg_dd512.c +++ /dev/null @@ -1,586 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_linux_inc.h" - -/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 1999 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device. It assumes - a 'bs' (block size) of 512 and complains if 'bs' ('ibs' or 'obs') is - given with some other value. - If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is - not given of 'of=-' then stdout assumed. The multipliers "c, b, k, m" - are recognized on numeric arguments. - As an experiment added an argument "tq" to allow 'tagged queuing' to - be enabled (1), disabled(0) or left as is (-1) which is the default. - BEWARE: If the 'of' file is a 'sg' device (eg a disk) then it _will_ - be written to, potentially destroying its previous contents. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . - - Version 3.96 991208 - - -6 byte commands [READ: 0x08, WRITE: 0x0a]: -[cmd ][had|lu][midAdd][lowAdd][count ][flags ] -10 byte commands [EREAD: 0x28, EWRITE: 0x2a, READ_CAPACITY 0x25]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][ ][hiCnt ][lowCnt][flags ] -12 byte commands [LREAD: 0xd8, LWRITE: 0xda]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][hiCnt ][hmCnt ][lmCnt ][lowCnt] - ... [ ][flags ] -*/ - -#define BLOCK_SIZE 512 - -#define BLOCKS_PER_WBUFF 128 /* this implies 64 KByte working buffer */ - -// #define SG_DEBUG - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ - - -void usage() -{ - printf("Usage: " - "sg_dd512 [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n" - " [count=<n>] [tq=<n>] {512 byte 'bs' assumed}\n" - " either 'if' or 'of' must be a scsi generic device\n" - " 'tq' is tagged queuing, 1->enable, 0->disable, -1->leave(def)\n"); -} - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -/* printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz); */ - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_read(int sg_fd, unsigned char * buff, int blocks, int from_block) -{ - unsigned char rdCmd[10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - rdCmd[2] = (unsigned char)((from_block >> 24) & 0xFF); - rdCmd[3] = (unsigned char)((from_block >> 16) & 0xFF); - rdCmd[4] = (unsigned char)((from_block >> 8) & 0xFF); - rdCmd[5] = (unsigned char)(from_block & 0xFF); - rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - rdCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rdCmd); - io_hdr.cmdp = rdCmd; - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = BLOCK_SIZE * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = from_block; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("reading (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("reading (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while reading block=%d, num=%d\n", - from_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("reading", &io_hdr); - return -1; - } - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_write(int sg_fd, unsigned char * buff, int blocks, int to_block) -{ - unsigned char wrCmd[10] = {0x2a, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - wrCmd[2] = (unsigned char)((to_block >> 24) & 0xFF); - wrCmd[3] = (unsigned char)((to_block >> 16) & 0xFF); - wrCmd[4] = (unsigned char)((to_block >> 8) & 0xFF); - wrCmd[5] = (unsigned char)(to_block & 0xFF); - wrCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - wrCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(wrCmd); - io_hdr.cmdp = wrCmd; - io_hdr.dxfer_direction = SG_DXFER_TO_DEV; - io_hdr.dxfer_len = BLOCK_SIZE * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = to_block; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("writing (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("writing (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while writing block=%d, num=%d\n", - to_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("writing", &io_hdr); - return -1; - } - return 0; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int count = -1; - char str[512]; - char * key; - char * buf; - char inf[512]; - int in_is_sg = 0; - char outf[512]; - int out_is_sg = 0; - int bs_bad = 0; - int tq = -1; - int res, k, t, buf_sz; - int infd, outfd, blocks; - unsigned char * wrkBuff; - unsigned char * wrkPos; - int in_num_sect = 0; - int out_num_sect = 0; - int in_sect_sz, out_sect_sz; - int in_full = 0; - int in_partial = 0; - int out_full = 0; - int out_partial = 0; - char ebuff[256]; - int blocks_per; - - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strcpy(str, argv[k]); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strcpy(inf, buf); - else if (strcmp(key,"of") == 0) - strcpy(outf, buf); - else if (0 == strcmp(key,"ibs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"obs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"bs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - 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")) - count = sg_get_num(buf); - else if (0 == strcmp(key,"tq")) - tq = sg_get_num(buf); - else { - printf("Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (bs_bad) { - printf("If bs/ibs/obs given, must=%d\n", BLOCK_SIZE); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - printf("skip and seek cannot be negative\n"); - return 1; - } -#ifdef SG_DEBUG - printf("sg_dd512: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, count); -#endif - infd = STDIN_FILENO; - outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - if ((infd = open(inf, O_RDWR)) >= 0) { - if (ioctl(infd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(infd); - } - else { - in_is_sg = 1; - res = 0; - if (0 == tq) - res = ioctl(infd, SCSI_IOCTL_TAGGED_DISABLE, &t); - if (1 == tq) - res = ioctl(infd, SCSI_IOCTL_TAGGED_ENABLE, &t); - if (res < 0) - perror("sg_dd512: SCSI_IOCTL_TAGGED error"); - t = BLOCK_SIZE * BLOCKS_PER_WBUFF; - res = ioctl(infd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd512: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd512: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! in_is_sg) { - if ((infd = open(inf, O_RDONLY)) < 0) { - sprintf(ebuff, "sg_dd512: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - else if (skip > 0) { - off_t offset = skip; - - offset *= BLOCK_SIZE; /* could overflow here! */ - if (lseek(infd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd512: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - } - if (outf[0] && ('-' != outf[0])) { - if ((outfd = open(outf, O_RDWR)) >= 0) { - if (ioctl(outfd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(outfd); - } - else { - out_is_sg = 1; - res = 0; - if (0 == tq) - res = ioctl(outfd, SCSI_IOCTL_TAGGED_DISABLE, &t); - if (1 == tq) - res = ioctl(outfd, SCSI_IOCTL_TAGGED_ENABLE, &t); - if (res < 0) - perror("sg_dd512: SCSI_IOCTL_TAGGED(o) error"); - t = BLOCK_SIZE * BLOCKS_PER_WBUFF; - res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd512: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd512: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! out_is_sg) { - if ((outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - sprintf(ebuff, - "sg_dd512: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - else if (seek > 0) { - off_t offset = seek; - - offset *= BLOCK_SIZE; /* could overflow here! */ - if (lseek(outfd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd512: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) { - printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n"); - return 1; - } -#if 1 - if (! (in_is_sg || out_is_sg)) { - printf("Either 'if' or 'of' must be a scsi generic device\n"); - return 1; - } -#endif - if (0 == count) - return 0; - else if (count < 0) { - if (in_is_sg) { - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(in), try again\n"); - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { -#if 0 - if (0 == in_sect_sz) - in_sect_sz = BLOCK_SIZE; - else if (in_sect_sz > BLOCK_SIZE) - in_num_sect *= (in_sect_sz / BLOCK_SIZE); - else if (in_sect_sz < BLOCK_SIZE) - in_num_sect /= (BLOCK_SIZE / in_sect_sz); -#endif - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (out_is_sg) { - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(out), try again\n"); - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - printf("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) - count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - count = in_num_sect; - } - else - count = out_num_sect; - } - - wrkBuff= malloc(BLOCK_SIZE * BLOCKS_PER_WBUFF); - if (0 == wrkBuff) { - printf("Not enough user memory\n"); - return 1; - } - wrkPos = wrkBuff; - - blocks_per = BLOCKS_PER_WBUFF; - while (count) { - blocks = (count > blocks_per) ? blocks_per : count; - if (in_is_sg) { - res = sg_read(infd, wrkBuff, blocks, skip); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(infd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + BLOCK_SIZE - 1) / BLOCK_SIZE; - blocks = blocks_per; - printf("Reducing read to %d blocks per loop\n", blocks_per); - res = sg_read(infd, wrkBuff, blocks, skip); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (r)\n"); - res = sg_read(infd, wrkBuff, blocks, skip); - } - if (0 != res) { - printf("sg_read failed, skip=%d\n", skip); - break; - } - else - in_full += blocks; - } - else { - while (((res = read(infd, wrkPos, blocks * BLOCK_SIZE)) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_dd512: reading, skip=%d ", skip); - perror(ebuff); - break; - } - else if (res < blocks * BLOCK_SIZE) { - count = 0; - blocks = res / BLOCK_SIZE; - if ((res % BLOCK_SIZE) > 0) { - blocks++; - in_partial++; - } - } - in_full += blocks; - } - - if (out_is_sg) { - res = sg_write(outfd, wrkBuff, blocks, seek); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(outfd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + BLOCK_SIZE - 1) / BLOCK_SIZE; - blocks = blocks_per; - printf("Reducing write to %d blocks per loop\n", blocks); - res = sg_write(outfd, wrkBuff, blocks, seek); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (w)\n"); - res = sg_write(outfd, wrkBuff, blocks, seek); - } - else if (0 != res) { - printf("sg_write failed, seek=%d\n", seek); - break; - } - else - out_full += blocks; - } - else { - while (((res = write(outfd, wrkPos, blocks * BLOCK_SIZE)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_ddd512: writing, seek=%d ", seek); - perror(ebuff); - break; - } - else if (res < blocks * BLOCK_SIZE) { - printf("output file probably full, seek=%d ", seek); - blocks = res / BLOCK_SIZE; - out_full += blocks; - if ((res % BLOCK_SIZE) > 0) - out_partial++; - break; - } - else - out_full += blocks; - } - if (count > 0) - count -= blocks; - skip += blocks; - seek += blocks; - } - - free(wrkBuff); - if (STDIN_FILENO != infd) - close(infd); - if (STDOUT_FILENO != outfd) - close(outfd); - if (0 != count) { - printf("Some error occurred, count=%d\n", count); - return 1; - } - printf("%d+%d records in\n", in_full, in_partial); - printf("%d+%d records out\n", out_full, out_partial); - return 0; -} |