aboutsummaryrefslogtreecommitdiff
path: root/archive
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2007-06-27 03:26:00 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2007-06-27 03:26:00 +0000
commit543a9ec553506a206d3191503ed6a24ac7721101 (patch)
tree3b2b9a102e67f38a89a5a54c21e5d125cb1c8d3a /archive
parent71e6e2d40657e63b9c20dc68f5e307639ef19c21 (diff)
downloadsg3_utils-543a9ec553506a206d3191503ed6a24ac7721101.tar.gz
Load sg3_utils-1.22 into trunk/.
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@71 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'archive')
-rw-r--r--archive/Makefile74
-rw-r--r--archive/README40
-rw-r--r--archive/isosize.838
-rw-r--r--archive/isosize.c189
-rw-r--r--archive/llseek.h14
-rw-r--r--archive/scsi_devfs_scan.842
-rw-r--r--archive/scsi_devfs_scan.c358
-rw-r--r--archive/sg3_utils.spec113234
-rw-r--r--archive/sg_bus_xfer.c194
-rw-r--r--archive/sg_dd2048.c586
-rw-r--r--archive/sg_dd512.c586
-rw-r--r--archive/sg_dd_old.c612
-rw-r--r--archive/sg_debug.c71
-rw-r--r--archive/sg_hold.c144
l---------archive/sg_io_linux.h1
l---------archive/sg_lib.h1
l---------archive/sg_linux_inc.h1
-rw-r--r--archive/sg_poll.c351
-rw-r--r--archive/sg_simple0.c93
-rw-r--r--archive/sgq_dd.c1151
-rw-r--r--archive/sgq_dd.c.orig1139
-rw-r--r--archive/sgq_old_dd.c838
-rw-r--r--archive/sgs_dd.c893
23 files changed, 6 insertions, 7644 deletions
diff --git a/archive/Makefile b/archive/Makefile
deleted file mode 100644
index a2848016..00000000
--- a/archive/Makefile
+++ /dev/null
@@ -1,74 +0,0 @@
-SHELL = /bin/sh
-
-INSTDIR=/usr/local/bin
-MANDIR=/usr/local/man
-
-CC = gcc
-LD = gcc
-
-EXECS = sgq_dd sg_poll sg_bus_xfer sg_hold sg_debug isosize scsi_devfs_scan
-
-COMMON = isosize
-
-MAN_PGS = isosize.8
-MAN_PREF = man8
-
-CFLAGS = -g -O2 -W -Wall -D_REENTRANT
-# CFLAGS = -g -O2 -Wall -pedantic -std=c99 -D_REENTRANT
-
-LDFLAGS =
-
-all: $(EXECS)
-
-common: $(COMMON)
-
-depend dep:
- for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \
- done > .depend
-
-clean:
- /bin/rm -f *.o $(EXECS) core .depend
-
-sg_poll: sg_poll.o ../sg_lib.o ../sg_io_linux.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-sgq_dd: sgq_dd.o ../sg_lib.o ../sg_io_linux.o ../llseek.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-sg_bus_xfer: sg_bus_xfer.o ../sg_lib.o ../sg_io_linux.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-sg_hold: sg_hold.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-isosize: isosize.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-scsi_devfs_scan: scsi_devfs_scan.o ../sg_lib.o ../sg_io_linux.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-sg_debug: sg_debug.o
- $(LD) -o $@ $(LDFLAGS) $^
-
-install: $(EXECS) $(COMMON)
- install -d $(INSTDIR)
- for name in $^; \
- do install -s -o root -g root -m 755 $$name $(INSTDIR); \
- done
- for mp in $(MAN_PGS); \
- do install -o root -g root -m 644 $$mp $(MANDIR)/$(MAN_PREF); \
- gzip -9f $(MANDIR)/$(MAN_PREF)/$$mp; \
- done
-
-uninstall:
- dists="$(EXECS)"; \
- for name in $$dists; do \
- rm -f $(INSTDIR)/$$name; \
- done
- for mp in $(MAN_PGS); do \
- rm -f $(MANDIR)/$(MAN_PREF)/$$mp.gz; \
- done
-
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
diff --git a/archive/README b/archive/README
index 9732d3f9..5763cac0 100644
--- a/archive/README
+++ b/archive/README
@@ -1,35 +1,7 @@
-This archive directory contains programs the use the Linux SCSI
-subsystem and typically use the SCSI generic interface (sg) as
-well.
+In order to save source code space, the files is this directory have
+been removed (apart from the rescan-scsi-bus.sh script). See the
+sg3_utils-1.22 source tarball for the most recent version that
+included this source.
-The programs in this directory are fully functional but have been
-"retired" from the main sg3_utils directory most likely because
-their functionality is done in another (perhaps better) way.
-
-The last time I checked these programs compiled and built and
-didn't depend on too many other things (see the Makefile in the
-parent directory for ideas).
-
-Since I actively use some of these programs for testing, a Makefile has
-been set up which builds:
- - sgq_dd [a dd variant the uses a dispatch loop rather than
- POSIX threads (as does sgp_dd)]
- - sg_hold holds a sg device open and periodically sends a TEST
- UNIT READY command to the device
- - sg_poll [internal testing]
- - isosize available in util-linux-2.10s and later
-
-The sg_lib.h and llseek.h headers have simply been copied from the parent
-directory.
-
-The very useful rescan-scsi-bus.sh script from Kurt Garloff
-<kurt at garloff dot de> is included in this directory.
-
-A test program called sg_bus_xfer.c exercises a patch that adds a
-SG_FLAG_BUS_ADDR capability. This allows a bus address (e.g. PCI
-video card's frame buffer) to be passed through to a SCSI adapter
-to side step various buffer copies. See:
-http://www.torque.net/sg/mem2disk.html
-
-Doug Gilbert
-3rd September 2004
+Douglas Gilbert
+10th October 2006
diff --git a/archive/isosize.8 b/archive/isosize.8
deleted file mode 100644
index f9fb4180..00000000
--- a/archive/isosize.8
+++ /dev/null
@@ -1,38 +0,0 @@
-.TH ISOSIZE "8" "December 2000" "sg3_utils-0.92" SG_UTILS
-.SH NAME
-isosize \- outputs the length of a iso9660 file system
-.SH SYNOPSIS
-.B isosize
-[\fI-x\fR] [\fI-d <num>\fR] \fI<iso9660_image_file>\fR
-.SH DESCRIPTION
-.\" Add any additional description here
-.PP
-This command outputs the length of an iso9660 file system that
-is contained in the given file. That file may be a normal file or
-a block device (e.g. /dev/hdd or /dev/sr0). In the absence of
-any switches (or errors) it will output the size of the iso9660
-file system in bytes. This can now be a large number (> > 4 GB).
-.TP
--x
-output in humanly readable form the block count and the block
-size. Output uses the term "sectors" for "blocks".
-.TP
--d <num>
-only has affect when "-x" is not given. The number output (if no errors)
-is the iso9660 file size in bytes divided by <num>. So if <num> is
-the block size then the output number will be the block count.
-.PP
-The size of the file (or block device) holding a iso9660 file
-system can be marginally larger than the actual size of the
-iso9660 file system. One reason for this is that cd writers
-are allowed to add "run out" sectors at the end of a iso9660
-image.
-.SH AUTHOR
-Written by Andries Brouwer
-.SH "REPORTING BUGS"
-Report bugs to <Andries.Brouwer at cwi dot nl>.
-.SH COPYRIGHT
-Copyright \(co 2000 Andries Brouwer
-.br
-This software is distributed under the GPL version 2. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/archive/isosize.c b/archive/isosize.c
deleted file mode 100644
index d570afa4..00000000
--- a/archive/isosize.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * isosize : use iso9660 header info to find size of associated
- * iso9660 file system
- *
- * Copyright (C) 2000 Andries Brouwer
- * 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.
- *
- * isosize.c - Andries Brouwer, 000608
- *
- * Synopsis:
- * isosize [-x] [-d <num>] <filename>
- * where "-x" gives length in sectors and sector size while
- * without this argument the size is given in bytes
- * without "-x" gives length in bytes unless "-d <num>" is
- * given. In the latter case the length in bytes divided
- * by <num> is given
- *
- * Version 2.03 2000/12/21
- * - add "-d <num>" option and use long long to fix things > 2 GB
- * Version 2.02 2000/10/11
- * - error messages on IO failures [D. Gilbert]
- *
- */
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-#define ISODCL(from, to) (to - from + 1)
-
-int xflag;
-
-int
-isonum_721 (unsigned char * p) {
- return ((p[0] & 0xff)
- | ((p[1] & 0xff) << 8));
-}
-
-int
-isonum_722 (unsigned char * p) {
- return ((p[1] & 0xff)
- | ((p[0] & 0xff) << 8));
-}
-
-int
-isonum_723 (unsigned char * p) {
- int le = isonum_721 (p);
- int be = isonum_722 (p+2);
- if (xflag && le != be)
- fprintf(stderr, "723error: le=%d be=%d\n", le, be);
- return (le);
-}
-
-int
-isonum_731 (unsigned char * p) {
- return ((p[0] & 0xff)
- | ((p[1] & 0xff) << 8)
- | ((p[2] & 0xff) << 16)
- | ((p[3] & 0xff) << 24));
-}
-
-int
-isonum_732 (unsigned char * p) {
- return ((p[3] & 0xff)
- | ((p[2] & 0xff) << 8)
- | ((p[1] & 0xff) << 16)
- | ((p[0] & 0xff) << 24));
-}
-
-
-int
-isonum_733 (unsigned char * p) {
- int le = isonum_731 (p);
- int be = isonum_732 (p+4);
- if (xflag && le != be)
- fprintf(stderr, "733error: le=%d be=%d\n", le, be);
- return (le);
-}
-
-struct iso_primary_descriptor {
- unsigned char type [ISODCL ( 1, 1)]; /* 711 */
- unsigned char id [ISODCL ( 2, 6)];
- unsigned char version [ISODCL ( 7, 7)]; /* 711 */
- unsigned char unused1 [ISODCL ( 8, 8)];
- unsigned char system_id [ISODCL ( 9, 40)]; /* auchars */
- unsigned char volume_id [ISODCL ( 41, 72)]; /* duchars */
- unsigned char unused2 [ISODCL ( 73, 80)];
- unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
- unsigned char unused3 [ISODCL ( 89, 120)];
- unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */
- unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
- unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */
- unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */
- unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */
- unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
- unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */
- unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
- unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
- unsigned char volume_set_id [ISODCL (191, 318)]; /* duchars */
- unsigned char publisher_id [ISODCL (319, 446)]; /* achars */
- unsigned char preparer_id [ISODCL (447, 574)]; /* achars */
- unsigned char application_id [ISODCL (575, 702)]; /* achars */
- unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
- unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
- unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
- unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
- unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
- unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
- unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
- unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */
- unsigned char unused4 [ISODCL (883, 883)];
- unsigned char application_data [ISODCL (884, 1395)];
- unsigned char unused5 [ISODCL (1396, 2048)];
-};
-
-int main(int argc, char * argv[]) {
- struct iso_primary_descriptor ipd;
- int fd, nsecs, ssize, j, m;
- int divisor = 0;
- const char * filenamep = NULL;
-
- for (j = 1; j < argc; ++j) {
- if (0 == strncmp("-d", argv[j], 2)) {
- if (strlen(argv[j]) > 2)
- m = 2;
- else {
- ++j;
- if (j >= argc) {
- filenamep = NULL;
- break;
- }
- m = 0;
- }
- if (1 != sscanf(argv[j] + m, "%d", &divisor)) {
- fprintf(stderr, "Couldn't decode number after '-d' switch\n");
- filenamep = NULL;
- break;
- }
- }
- else if (0 == strcmp("-x", argv[j]))
- xflag = 1;
- else if (*argv[j] == '-') {
- fprintf(stderr, "Unrecognized switch: %s\n", argv[j]);
- filenamep = NULL;
- break;
- }
- else
- filenamep = argv[j];
- }
-
- if(filenamep == NULL) {
- fprintf(stderr, "Usage: isosize [-x] [-d <num>] iso9660-image\n");
- return 1;
- }
-
- if ((fd = open(filenamep,O_RDONLY)) < 0) {
- fprintf(stderr, "failed to open: %s", filenamep);
- perror(", error");
- return 1;
- }
- if (lseek(fd, 16 << 11, 0) == (off_t)-1) {
- perror("lseek error");
- return 1;
- }
- if (read(fd, &ipd, sizeof(ipd)) < 0) {
- perror("read error");
- return 1;
- }
-
- nsecs = isonum_733(ipd.volume_space_size);
- ssize = isonum_723(ipd.logical_block_size); /* nowadays always 2048 */
-
- if (xflag)
- printf ("sector count: %d, sector size: %d\n", nsecs, ssize);
- else {
- long long product = nsecs;
-
- if (0 == divisor)
- printf ("%lld\n", product * ssize);
- else if (divisor == ssize)
- printf ("%d\n", nsecs);
- else
- printf ("%lld\n", (product * ssize) / divisor);
- }
- return 0;
-}
diff --git a/archive/llseek.h b/archive/llseek.h
deleted file mode 100644
index 2f6aef0f..00000000
--- a/archive/llseek.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef LLSEEK_H
-#define LLSEEK_H
-
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long llse_loff_t;
-#else
-typedef long llse_loff_t;
-#endif
-
-extern llse_loff_t llse_llseek(unsigned int fd,
- llse_loff_t offset,
- unsigned int origin);
-
-#endif
diff --git a/archive/scsi_devfs_scan.8 b/archive/scsi_devfs_scan.8
deleted file mode 100644
index c371b24c..00000000
--- a/archive/scsi_devfs_scan.8
+++ /dev/null
@@ -1,42 +0,0 @@
-.TH SG_DEVFS_SCAN "8" "April 2003" "sg3_utils-1.03" SG3_UTILS
-.SH NAME
-sg_devfs_scan \- Scan SCSI devices within a devfs tree
-.SH SYNOPSIS
-.B sg_devfs_scan
-[\fI-d <dir>\fR]
-[\fI-i\fR]
-[\fI-ide\fR]
-[\fI-l [-x]\fR]
-[\fI-q\fR]
-<\fIgeneric device\fR>
-.SH DESCRIPTION
-.\" Add any additional description here
-.PP
-scsi_devfs_scan is a utility for doing a directory scan on a system
-running devfs to identify SCSI (and optionally IDE) devices. Various
-information (including an INQUIRY) can be listed for each found device.
-.TP
--d <dir>
-location of devfs [default: /dev ]
-.TP
--i
-show INQUIRY data for each SCSI device
-.TP
--ide
-show scan of IDE devices after SCSI ones
-.TP
--l
-show device file names in leaf directory
-.TP
--x
-add (major,minor) information to '-l'
-.TP
--q
-just output host, bus, target, lun numbers
-.SH AUTHORS
-Written by D. Gilbert
-.SH COPYRIGHT
-Copyright \(co 2001 Douglas Gilbert
-.br
-This software is distributed under the GPL version 2. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/archive/scsi_devfs_scan.c b/archive/scsi_devfs_scan.c
deleted file mode 100644
index 6cd526a0..00000000
--- a/archive/scsi_devfs_scan.c
+++ /dev/null
@@ -1,358 +0,0 @@
-#define _XOPEN_SOURCE 500
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <unistd.h>
-#include "sg_lib.h"
-#include "sg_io_linux.h"
-
-/* Code for scanning for SCSI devices within a Linux device pseudo file
- system.
- * Copyright (C) 2001 D. Gilbert
- * 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 scans the /dev directory structure looking for the
- devfs "primary" scsi (and optionally IDE) device names.
-
- Version 0.13 20030430
-*/
-
-void usage()
-{
- printf("Usage: 'scsi_devfs_scan [-d <dir>] [-i] [-ide] [-l [-x]] "
- "[-q]'\n");
- printf(" where: -d <dir> location of devfs [default: /dev ]\n");
- printf(" -i show INQUIRY data for each SCSI device\n");
- printf(" -ide show scan of IDE devices after SCSI devices\n");
- printf(" -l show device file names in leaf directory\n");
- printf(" -q just output host, bus, target, lun numbers\n");
- printf(" -x add (major,minor) information to '-l'\n");
-}
-
-#define NAME_LEN_MAX 256
-#define LEVELS 4
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
-#define INQUIRY_CMD 0x12
-#define INQUIRY_CMDLEN 6
-
-static const char * level_arr[LEVELS] = {"host", "bus", "target", "lun"};
-
-static int do_ide = 0;
-static int do_inq = 0;
-static int do_leaf = 0;
-static int do_extra = 0;
-static int do_quiet = 0;
-static int checked_sg = 0;
-
-static void ddStrHex(const char* str, int len)
-{
- const char* p = str;
- unsigned char c;
- char buff[82];
- int a = 0;
- const int bpstart = 5;
- const int cpstart = 60;
- int cpos = cpstart;
- int bpos = bpstart;
- int i, k;
-
- if (len <= 0) return;
- memset(buff,' ',80);
- buff[80]='\0';
- k = sprintf(buff + 1, "%.2x", a);
- buff[k + 1] = ' ';
- if (bpos >= ((bpstart + (9 * 3))))
- bpos++;
-
- for(i = 0; i < len; i++)
- {
- c = *p++;
- bpos += 3;
- if (bpos == (bpstart + (9 * 3)))
- bpos++;
- sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
- buff[bpos + 2] = ' ';
- if ((c < ' ') || (c >= 0x7f))
- c='.';
- buff[cpos++] = c;
- if (cpos > (cpstart+15))
- {
- printf("%s\n", buff);
- bpos = bpstart;
- cpos = cpstart;
- a += 16;
- memset(buff,' ',80);
- k = sprintf(buff + 1, "%.2x", a);
- buff[k + 1] = ' ';
- }
- }
- if (cpos > cpstart)
- {
- printf("%s\n", buff);
- }
-}
-
-static int do_inquiry(int sg_fd, void * resp, int mx_resp_len)
-{
- int res;
- unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- inqCmdBlk[4] = (unsigned char)mx_resp_len;
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_TO_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (inquiry) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_LIB_CAT_CLEAN:
- case SG_LIB_CAT_RECOVERED:
- return 0;
- default:
- sg_chk_n_print3("Failed INQUIRY", &io_hdr, 1);
- return -1;
- }
-}
-
-void leaf_dir(const char * lf, unsigned int * larr)
-{
- char name[NAME_LEN_MAX * 2];
- int res;
-
- if (do_quiet) {
- printf("%u\t%u\t%u\t%u\n", larr[0], larr[1], larr[2], larr[3]);
- return;
- }
- printf("%u\t%u\t%u\t%u\t%s\n", larr[0], larr[1], larr[2], larr[3], lf);
- if (do_leaf) {
- struct dirent * de_entry;
- struct dirent * de_result;
- DIR * sdir;
- int outpos;
-
- if (NULL == (sdir = opendir(lf))) {
- fprintf(stderr, "leaf_dir: opendir of %s: failed\n", lf);
- return;
- }
- de_entry = (struct dirent *)malloc(sizeof(struct dirent) +
- NAME_LEN_MAX);
- if (NULL == de_entry)
- return;
- res = 0;
- printf("\t");
- outpos = 8;
- while (1) {
- res = readdir_r(sdir, de_entry, &de_result);
- if (0 != res) {
- fprintf(stderr, "leaf_dir: readdir_r of %s: %s\n",
- lf, strerror(res));
- res = -2;
- break;
- }
- if (de_result == NULL)
- break;
- strncpy(name, de_entry->d_name, NAME_LEN_MAX * 2);
- if ((0 == strcmp("..", name)) ||(0 == strcmp(".", name)))
- continue;
- if (do_extra) {
- struct stat st;
- char devname[NAME_LEN_MAX * 2];
-
- strncpy(devname, lf, NAME_LEN_MAX * 2);
- strcat(devname, "/");
- strcat(devname, name);
- if (stat(devname, &st) < 0)
- return;
- if (S_ISCHR(st.st_mode)) {
- strcat(name, "(c ");
- sprintf(name + strlen(name), "%d %d)", major(st.st_rdev),
- minor(st.st_rdev));
- }
- else if (S_ISBLK(st.st_mode)) {
- strcat(name, "(b ");
- sprintf(name + strlen(name), "%d %d)", major(st.st_rdev),
- minor(st.st_rdev));
- }
- }
- res = strlen(name);
- if ((outpos + res + 2) > 80) {
- printf("\n\t");
- outpos = 8;
- }
- printf("%s ", name);
- outpos += res + 2;
- }
- printf("\n");
- }
- if (do_inq) {
- int sg_fd;
- char buff[64];
-
- memset(buff, 0, sizeof(buff));
- strncpy(name, lf, NAME_LEN_MAX * 2);
- strcat(name, "/generic");
- if ((sg_fd = open(name, O_RDONLY)) < 0) {
- if (! checked_sg) {
- checked_sg = 1;
- if ((sg_fd = open("/dev/sg0", O_RDONLY)) >= 0)
- close(sg_fd); /* try and get sg module loaded */
- sg_fd = open(name, O_RDONLY);
- }
- if (sg_fd < 0) {
- printf("Unable to open sg device: %s, %s\n", name,
- strerror(errno));
- return;
- }
- }
- if (0 != do_inquiry(sg_fd, buff, 64))
- return;
- close(sg_fd);
- ddStrHex(buff, 64);
- }
-}
-
-/* Return 0 -> ok, -1 -> opendir() error, -2 -> readdir_r error,
- -3 -> malloc error */
-int hbtl_scan(const char * path, int level, unsigned int *larr)
-{
- struct dirent * de_entry;
- struct dirent * de_result;
- char new_path[NAME_LEN_MAX * 2];
- DIR * sdir;
- int res;
- size_t level_slen;
-
- level_slen = strlen(level_arr[level]);
- if (NULL == (sdir = opendir(path))) {
- fprintf(stderr, "hbtl_scan: opendir of %s: failed\n", path);
- return -1;
- }
- de_entry = (struct dirent *)malloc(sizeof(struct dirent) + NAME_LEN_MAX);
- if (NULL == de_entry)
- return -3;
- res = 0;
- while (1) {
- res = readdir_r(sdir, de_entry, &de_result);
- if (0 != res) {
- fprintf(stderr, "hbtl_scan: readdir_r of %s: %s\n",
- path, strerror(res));
- res = -2;
- break;
- }
- if (de_result == NULL)
- break;
- if (0 == strncmp(level_arr[level], de_entry->d_name, level_slen)) {
- if (1 != sscanf(de_entry->d_name + level_slen, "%u", larr + level))
- larr[level] = UINT_MAX;
- strncpy(new_path, path, NAME_LEN_MAX * 2);
- strcat(new_path, "/");
- strcat(new_path, de_entry->d_name);
- if ((level + 1) < LEVELS) {
- res = hbtl_scan(new_path, level + 1, larr);
- if (res < 0)
- break;
- }
- else
- leaf_dir(new_path, larr);
- }
- }
- free(de_entry);
- closedir(sdir);
- return res;
-}
-
-#define D_ROOT_SZ 512
-
-
-int main(int argc, char * argv[])
-{
- int k, res;
- char ds_root[D_ROOT_SZ];
- char di_root[D_ROOT_SZ];
- unsigned int larr[LEVELS];
- struct stat st;
-
- strncpy(ds_root, "/dev", D_ROOT_SZ);
- for (k = 1; k < argc; ++k) {
- if (0 == strcmp("-ide", argv[k]))
- do_ide = 1;
- else if (0 == strcmp("-i", argv[k]))
- do_inq = 1;
- else if (0 == strcmp("-l", argv[k]))
- do_leaf = 1;
- else if (0 == strcmp("-x", argv[k]))
- do_extra = 1;
- else if (0 == strcmp("-q", argv[k]))
- do_quiet = 1;
- else if (0 == strncmp("-d", argv[k], 2)) {
- if (strlen(argv[k]) > 2)
- strncpy(ds_root, argv[k] + 2, D_ROOT_SZ);
- else if (++k < argc)
- strncpy(ds_root, argv[k], D_ROOT_SZ);
- }
- else if ((0 == strcmp("-?", argv[k])) ||
- (0 == strncmp("-h", argv[k], 2))) {
- printf("Scan SCSI devices within a devfs tree\n\n");
- usage();
- return 1;
- }
- else if (*argv[k] == '-') {
- printf("Unknown switch: %s\n", argv[k]);
- usage();
- return 1;
- }
- else if (*argv[k] != '-') {
- printf("Unknown argument\n");
- usage();
- return 1;
- }
- }
- strncpy(di_root, ds_root, D_ROOT_SZ);
- strcat(di_root, "/.devfsd");
- if (stat(di_root, &st) < 0)
- printf("Didn't find %s so perhaps devfs is not present,"
- " continuing ...\n", di_root);
- strncpy(di_root, ds_root, D_ROOT_SZ);
- strcat(ds_root, "/scsi");
- strcat(di_root, "/ide");
-
- if (do_ide)
- printf("SCSI scan:\n");
- res = hbtl_scan(ds_root, 0, larr);
- if (res < 0)
- printf("main: scsi hbtl_scan res=%d\n", res);
- do_inq = 0; /* won't try SCSI INQUIRY on IDE devices */
- if (do_ide) {
- printf("\nIDE scan:\n");
- res = hbtl_scan(di_root, 0, larr);
- if (res < 0)
- printf("main: ide hbtl_scan res=%d\n", res);
- }
- return 0;
-}
diff --git a/archive/sg3_utils.spec113 b/archive/sg3_utils.spec113
deleted file mode 100644
index 3dfc4873..00000000
--- a/archive/sg3_utils.spec113
+++ /dev/null
@@ -1,234 +0,0 @@
-Summary: Utilities for SCSI devices in Linux
-Name: sg3_utils
-Version: 1.13
-Release: 1
-Packager: Douglas Gilbert <dgilbert at interlog dot com>
-License: GPL/FreeBSD
-Group: Utilities/System
-Source: ftp://www.torque.net/sg/p/sg3_utils-%{version}.tgz
-Url: http://www.torque.net/sg/u_index.html
-Provides: sg_utils
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root/
-
-%description
-Collection of Linux utilities for devices that use the SCSI command set.
-Includes utilities to copy data based on "dd" syntax and semantics (called
-sg_dd, sgp_dd and sgm_dd); check INQUIRY data and VPD pages (sg_inq); check
-mode and log pages (sginfo, sg_modes and sg_logs); spin up and down
-disks (sg_start); do self tests (sg_senddiag); and various other functions.
-See the README, CHANGELOG and COVERAGE files. Requires the linux kernel 2.4
-series or later. In the 2.4 series SCSI generic device names (e.g. /dev/sg0)
-must be used. In the 2.6 series other device names may be used as
-well (e.g. /dev/sda).
-
-Warning: Some of these tools access the internals of your system and their
-incorrect usage may render your system inoperable.
-
-Authors:
---------
- Doug Gilbert <dgilbert at interlog dot com>
- See CREDITS file
-
-%package devel
-Summary: Files needed for developing applications using the SCSI command set
-Group: Development/Libraries
-Requires: %{name} = %{version}-%{release}
-
-%description devel
-sg3_utils-devel contains a static library (libsgutils.a) and header files
-to support using the SCSI command set on devices in Linux.
-
-%prep
-%setup
-
-%build
-make LIBDIR=/usr/lib
-
-%install
-if [ "$RPM_BUILD_ROOT" != "/" ]; then
- rm -rf $RPM_BUILD_ROOT
-fi
-make install INSTDIR=$RPM_BUILD_ROOT/usr/bin MANDIR=$RPM_BUILD_ROOT/usr/share/man LIBDIR=$RPM_BUILD_ROOT/usr/lib INCLUDEDIR=$RPM_BUILD_ROOT/usr/include
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-%attr(-,root,root) %doc CREDITS README README.sg_start
-%attr(-,root,root) %doc CHANGELOG INSTALL COVERAGE
-%attr(755,root,root) %{_bindir}/sg_dd
-%attr(755,root,root) %{_bindir}/sg_inq
-%attr(755,root,root) %{_bindir}/sg_scan
-%attr(755,root,root) %{_bindir}/sg_rbuf
-%attr(755,root,root) %{_bindir}/sginfo
-%attr(755,root,root) %{_bindir}/sg_readcap
-%attr(755,root,root) %{_bindir}/sgp_dd
-%attr(755,root,root) %{_bindir}/sg_map
-%attr(755,root,root) %{_bindir}/sg_turs
-%attr(755,root,root) %{_bindir}/sg_test_rwbuf
-%attr(755,root,root) %{_bindir}/sg_start
-%attr(755,root,root) %{_bindir}/sgm_dd
-%attr(755,root,root) %{_bindir}/sg_read
-%attr(755,root,root) %{_bindir}/sg_reset
-%attr(755,root,root) %{_bindir}/sg_modes
-%attr(755,root,root) %{_bindir}/sg_logs
-%attr(755,root,root) %{_bindir}/sg_senddiag
-%attr(755,root,root) %{_bindir}/sg_opcodes
-%attr(755,root,root) %{_bindir}/sg_persist
-%attr(755,root,root) %{_bindir}/sg_write_long
-%attr(755,root,root) %{_bindir}/sg_read_long
-%attr(755,root,root) %{_bindir}/sg_requests
-%attr(755,root,root) %{_bindir}/sg_ses
-%attr(755,root,root) %{_bindir}/sg_verify
-%attr(755,root,root) %{_bindir}/sg_emc_trespass
-%attr(755,root,root) %{_bindir}/sg_luns
-%attr(755,root,root) %{_bindir}/sg_sync
-%attr(755,root,root) %{_bindir}/sg_prevent
-%attr(755,root,root) %{_bindir}/sg_get_config
-%attr(755,root,root) %{_bindir}/sg_wr_mode
-%attr(755,root,root) %{_bindir}/sg_rtpg
-%attr(755,root,root) %{_bindir}/sg_reassign
-%attr(755,root,root) %{_bindir}/sg_format
-%attr(755,root,root) %{_libdir}/libsgutils.so
-%attr(755,root,root) %{_libdir}/libsgutils.so.1
-%attr(755,root,root) %{_libdir}/libsgutils.so.1.0.0
-# Mandrake compresses man pages with bzip2, RedHat with gzip
-%attr(-,root,root) %doc %{_mandir}/man8/sg_dd.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sgp_dd.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sgm_dd.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_read.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_map.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_scan.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_rbuf.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sginfo.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_readcap.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_turs.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_inq.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_test_rwbuf.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_start.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_reset.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_modes.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_logs.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_senddiag.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_opcodes.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_persist.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_write_long.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_read_long.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_requests.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_ses.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_verify.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_emc_trespass.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_luns.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_sync.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_prevent.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_get_config.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_wr_mode.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_rtpg.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_reassign.8*
-%attr(-,root,root) %doc %{_mandir}/man8/sg_format.8*
-
-%files devel
-%defattr(-,root,root)
-%attr(644,root,root) %{_includedir}/scsi/sg_lib.h
-%attr(644,root,root) %{_includedir}/scsi/sg_cmds.h
-%attr(755,root,root) %{_libdir}/libsgutils.la
-%attr(644,root,root) %{_libdir}/libsgutils.a
-
-
-%changelog
-* Sun Mar 13 2005 - dgilbert at interlog dot com
-- add sg_format, sg_dd extensions
- * sg3_utils-1.13
-
-* Fri Jan 21 2005 - dgilbert at interlog dot com
-- add sg_wr_mode, sg_rtpg + sg_reassign; sginfo sas tweaks
- * sg3_utils-1.12
-
-* Fri Nov 26 2004 - dgilbert at interlog dot com
-- add sg_sync, sg_prevent and sg_get_config; fix sg_requests
- * sg3_utils-1.11
-
-* Sat Oct 30 2004 - dgilbert at interlog dot com
-- fix read capacity (10+16), add sg_luns
- * sg3_utils-1.10
-
-* Thu Oct 21 2004 - dgilbert at interlog dot com
-- sg_requests, sg_ses, sg_verify, libsgutils(sg_lib.c+sg_cmds.c), devel rpm
- * sg3_utils-1.09
-
-* Tue Aug 31 2004 - dgilbert at interlog dot com
-- 'register+move' in sg_persist, sg_opcodes sorts, sg_write_long
- * sg3_utils-1.08
-
-* Thu Jul 08 2004 - dgilbert at interlog dot com
-- add '-fHead' to sginfo, '-i' for sg_inq, new sg_opcodes + sg_persist
- * sg3_utils-1.07
-
-* Mon Apr 26 2004 - dgilbert at interlog dot com
-- sg3_utils.spec for mandrake; more sginfo work, sg_scan, sg_logs
- * sg3_utils-1.06
-
-* Wed Nov 12 2003 - dgilbert at interlog dot com
-- sg_readcap: sizes; sg_logs: double fetch; sg_map 256 sg devices; sginfo
- * sg3_utils-1.05
-
-* Tue May 13 2003 - dgilbert at interlog dot com
-- default sg_turs '-n=' to 1, sg_logs gets '-t' for temperature, CREDITS
- * sg3_utils-1.04
-
-* Wed Apr 02 2003 - dgilbert at interlog dot com
-- 6 byte CDBs for sg_modes, sg_start on block devs, sg_senddiag, man pages
- * sg3_utils-1.03
-
-* Wed Jan 01 2003 - dgilbert at interlog dot com
-- interwork with block SG_IO, fix in sginfo, '-t' for sg_turs
- * sg3_utils-1.02
-
-* Wed Aug 14 2002 - dgilbert at interlog dot com
-- raw switch in sg_inq
- * sg3_utils-1.01
-
-* Sun Jul 28 2002 - dgilbert at interlog dot com
-- decode sg_logs pages, add dio to sgm_dd, drop "gen=1" arg, "of=/dev/null"
- * sg3_utils-1.00
-
-* Sun Mar 17 2002 - dgilbert at interlog dot com
-- add sg_modes+sg_logs for sense pages, expand sg_inq, add fua+sync to sg_dd++
- * sg3_utils-0.99
-
-* Sat Feb 16 2002 - dgilbert at interlog dot com
-- resurrect sg_reset; snprintf cleanup, time,gen+cdbsz args to sg_dd++
- * sg3_utils-0.98
-
-* Sun Dec 23 2001 - dgilbert at interlog dot com
-- move isosize to archive directory; now found in util-linux-2.10s and later
- * sg3_utils-0.97
-
-* Fri Dec 21 2001 - dgilbert at interlog dot com
-- add sgm_dd, sg_read, sg_simple4 and sg_simple16 [add mmap-ed IO support]
- * sg3_utils-0.96
-
-* Sun Sep 15 2001 - dgilbert at interlog dot com
-- sg_map can do inquiry; sg_dd, sgp_dd + sgq_dd dio help
- * sg3_utils-0.95
-
-* Sun Apr 19 2001 - dgilbert at interlog dot com
-- add sg_start, improve sginfo and sg_map [Kurt Garloff]
- * sg3_utils-0.94
-
-* Sun Mar 5 2001 - dgilbert at interlog dot com
-- add scsi_devfs_scan, add sg_include.h, 'coe' more general in sgp_dd
- * sg3_utils-0.93
-
-* Tue Jan 16 2001 - dgilbert at interlog dot com
-- clean sg_err.h include dependencies, bug fixes, Makefile in archive directory
- * sg3_utils-0.92
-
-* Mon Dec 21 2000 - dgilbert at interlog dot com
-- signals for sg_dd, man pages and additions for sg_rbuf and isosize
- * sg3_utils-0.91
-
-* Mon Dec 11 2000 - dgilbert at interlog dot com
-- Initial creation of package, containing
- * sg3_utils-0.90
diff --git a/archive/sg_bus_xfer.c b/archive/sg_bus_xfer.c
deleted file mode 100644
index eada35fd..00000000
--- a/archive/sg_bus_xfer.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "sg_lib.h"
-#include "sg_io_linux.h"
-
-/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
- device driver.
-* Copyright (C) 2001 D. Gilbert
-* 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 tests the SG_FLAG_BUS_ADDR capability.
- It is for moving data to and from fixed memory addresses (e.g. memory
- mapped io used by video frame buffers) directly to a SCSI device via
- the sg driver. The given address is passed straight through by sg to the
- scsi adapter driver. The adapter typically does a "virtual to bus"
- address transformation and gives the new address to its DMA engine.
- Large amounts of data (in physically contiguous memory) can be moved
- (quickly) in a single SCSI command.
-
- This will probably only work on i386 architecture with PCI cards that
- memory map their IO area (e.g. video frame buffer). On i386 the
- "virt_to_bus" transformation involves subtracting 0xC0000000 from the
- given address. So from the addresses seen in the lspci command,
- subtracting 0x40000000 would be an appropriate correction (due to
- 32 bit wrap around).
-
- The SG_FLAG_BUS_ADDR logic is not in normal sg drivers, you need a
- patch, see the sg web site.
-
- Version 0.11 (20010210)
-*/
-
-#ifndef SG_FLAG_BUS_ADDR
-#define SG_FLAG_BUS_ADDR 0x10
-#endif
-
-
-#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */
-
-#define SGP_READ10 0x28
-#define SGP_WRITE10 0x2a
-
-/* #define SG_DEBUG */
-
-
-int main(int argc, char * argv[])
-{
- int sg_fd, res, j, m;
- unsigned int k, num;
- unsigned char rwCmdBlk[S_RW_LEN];
- unsigned char sense_buffer[32];
- int do_wr = -1; /* 1 -> write, 0 -> read */
- unsigned long addr = ULONG_MAX;
- int bs = 512;
- int skip = -1;
- int count = -1;
- char * file_name = 0;
- sg_io_hdr_t io_hdr;
-
- for (j = 1; j < argc; ++j) {
- if (0 == strncmp("-a=", argv[j], 3)) {
- m = 3;
- num = sscanf(argv[j] + m, "%lx", &addr);
- if (1 != num) {
- printf("Couldn't decode number after '-a=' switch\n");
- file_name = 0;
- break;
- }
- }
- else if (0 == strncmp("-bs=", argv[j], 4)) {
- m = 4;
- bs = sg_get_num(argv[j] + m);
- if (-1 == bs) {
- printf("Couldn't decode number after '-bs=' switch\n");
- file_name = 0;
- break;
- }
- }
- else if (0 == strncmp("-skip=", argv[j], 6)) {
- m = 6;
- skip = sg_get_num(argv[j] + m);
- if (-1 == skip) {
- printf("Couldn't decode number after '-skip=' switch\n");
- file_name = 0;
- break;
- }
- }
- else if (0 == strncmp("-count=", argv[j], 7)) {
- m = 7;
- count = sg_get_num(argv[j] + m);
- if (-1 == count) {
- printf("Couldn't decode number after '-count=' switch\n");
- file_name = 0;
- break;
- }
- }
- else if (0 == strcmp("-r", argv[j]))
- do_wr = 0;
- else if (0 == strcmp("-w", argv[j]))
- do_wr = 1;
- else if (*argv[j] == '-') {
- printf("Unrecognized switch: %s\n", argv[j]);
- file_name = 0;
- break;
- }
- else
- file_name = argv[j];
- }
- if ((0 == file_name) || (count < 0) || (do_wr < 0) || (addr == ULONG_MAX)
- || (skip < 0)) {
- printf("Probabably missing parameter\n\n");
- printf(
- "Usage: 'sg_bus_xfer -r|w -a=hex_num [-bs=num] -skip=num"
- " <sg_device>'\n");
- printf(" where: -r|w read from (or write to) sg device\n");
- printf(" -a=hex_num memory address (virtual ?)\n");
- printf(" -bs=num blocks size in bytes (default 512)\n");
- printf(" -skip=num num is blocks to skip/seek on sg dev\n");
- printf(" -count=num num of blocks to xfer\n");
- printf("\n BEWARE you could do damage with this command "
- "(needs root access)\n");
- printf("\n bs, skip and count may take k,K,m,M etc multipliers\n");
- return 1;
- }
-
- sg_fd = open(file_name, O_RDWR);
- if (sg_fd < 0) {
- perror("sg_bus_xfer: open error");
- return 1;
- }
- /* Don't worry, being very careful not to write to a none-sg file ... */
- res = ioctl(sg_fd, SG_GET_VERSION_NUM, &k);
- if ((res < 0) || (k < 30000)) {
- printf("sg_bus_xfer: not a sg device, or driver prior to 3.x\n");
- return 1;
- }
-
- memset(rwCmdBlk, 0, S_RW_LEN);
- rwCmdBlk[0] = do_wr ? SGP_WRITE10 : SGP_READ10;
- rwCmdBlk[2] = (unsigned char)((skip >> 24) & 0xFF);
- rwCmdBlk[3] = (unsigned char)((skip >> 16) & 0xFF);
- rwCmdBlk[4] = (unsigned char)((skip >> 8) & 0xFF);
- rwCmdBlk[5] = (unsigned char)(skip & 0xFF);
- rwCmdBlk[6] = (unsigned char)((count >> 16) & 0xff);
- rwCmdBlk[7] = (unsigned char)((count >> 8) & 0xff);
- rwCmdBlk[8] = (unsigned char)(count & 0xff);
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rwCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = do_wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = bs * count;
- // io_hdr.dxferp = malloc(1024 * 1024); /* <<<<<<<<<<<<<<<< */
- io_hdr.dxferp = (void *)addr;
- io_hdr.cmdp = rwCmdBlk;
- io_hdr.flags = SG_FLAG_BUS_ADDR;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 10000; /* 10000 millisecs == 10 seconds */
-
- printf(" dxferp=%p len=%d\n", io_hdr.dxferp, bs * count);
-#ifdef SG_DEBUG
- sg_print_command(rwCmdBlk);
- printf(" dxferp=%p len=%d\n", io_hdr.dxferp, bs * count);
- return 0;
-#endif
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("sg_bus_xfer: SG_IO failed");
- return 1;
- }
-
- /* now for the error processing */
- switch (sg_err_category3(&io_hdr)) {
- case SG_LIB_CAT_CLEAN:
- break;
- case SG_LIB_CAT_RECOVERED:
- printf("Recovered error, continuing\n");
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("SG_IO error", &io_hdr, 1);
- return 1;
- }
- return 0;
-}
diff --git a/archive/sg_dd2048.c b/archive/sg_dd2048.c
deleted file mode 100644
index ea9bf415..00000000
--- a/archive/sg_dd2048.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 2048 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 2048
-
-#define BLOCKS_PER_WBUFF 32 /* 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_dd2048 [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n"
- " [count=<n>] [tq=<n>] {2048 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_dd2048: 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_dd2048: SCSI_IOCTL_TAGGED error");
- t = BLOCK_SIZE * BLOCKS_PER_WBUFF;
- res = ioctl(infd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror("sg_dd2048: SG_SET_RESERVED_SIZE error");
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- printf("sg_dd2048: sg driver prior to 3.x.y\n");
- return 1;
- }
- }
- }
- if (! in_is_sg) {
- if ((infd = open(inf, O_RDONLY)) < 0) {
- sprintf(ebuff, "sg_dd2048: 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_dd2048: 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_dd2048: SCSI_IOCTL_TAGGED(o) error");
- t = BLOCK_SIZE * BLOCKS_PER_WBUFF;
- res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror("sg_dd2048: SG_SET_RESERVED_SIZE error");
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- printf("sg_dd2048: 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_dd2048: 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_dd2048: 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_dd2048: 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_ddd2048: 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;
-}
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;
-}
diff --git a/archive/sg_dd_old.c b/archive/sg_dd_old.c
deleted file mode 100644
index 83dc6451..00000000
--- a/archive/sg_dd_old.c
+++ /dev/null
@@ -1,612 +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"
-
-/* A utility program for 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. A block size
- ('bs') is assumed to be 512 if not given. This program complains if
- 'ibs' or 'obs' are given with some other value.
- If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is
- not given or 'of=-' then stdout assumed. The multipliers "c, b, k, m"
- are recognized on numeric arguments.
-
- A non-standard argument "bpt" (blocks per transfer) is added to control
- the maximum number of blocks in each transfer. The default value is 128.
- For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
- in this case) are transferred to or from the sg device in a single SCSI
- command.
-
- This version should compile with Linux sg drivers with version numbers
- >= 30000 .
-
- Version 3.992 20000823
-*/
-
-#define DEF_BLOCK_SIZE 512
-#define DEF_BLOCKS_PER_TRANSFER 128
-
-// #define SG_DEBUG
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define READ_CAP_REPLY_LEN 8
-#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */
-
-static int sum_of_resids = 0;
-
-
-void usage()
-{
- printf("Usage: "
- "sg_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n"
- " [bs=<num>] [bpt=<num>] [count=<n>]"
- " [dio=<n>]\n"
- " either 'if' or 'of' must be a scsi generic device\n"
- " 'bpt' is blocks_per_transfer (default is 128)\n"
- " 'dio' is direct IO, 1->attempt, 0->indirect IO (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[READ_CAP_REPLY_LEN];
- 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];
-#ifdef SG_DEBUG
- printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz);
-#endif
- 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,
- int bs, int * diop)
-{
- 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 = bs * 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;
- if (diop && *diop)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
-
- 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;
- }
- if (diop && *diop &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- *diop = 0; /* flag that dio not done (completely) */
- sum_of_resids += io_hdr.resid;
-#if SG_DEBUG
- printf("duration=%u ms\n", io_hdr.duration);
-#endif
- 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,
- int bs, int * diop)
-{
- 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 = bs * 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;
- if (diop && *diop)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
-
- 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;
- }
- if (diop && *diop &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- *diop = 0; /* flag that dio not done (completely) */
- return 0;
-}
-
-
-int main(int argc, char * argv[])
-{
- int skip = 0;
- int seek = 0;
- int bs = 0;
- int ibs = 0;
- int obs = 0;
- int bpt = DEF_BLOCKS_PER_TRANSFER;
- 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 dio = 0;
- int dio_incomplete = 0;
- int res, k, t, buf_sz, dio_tmp;
- 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"))
- ibs = sg_get_num(buf);
- else if (0 == strcmp(key,"obs"))
- obs = sg_get_num(buf);
- else if (0 == strcmp(key,"bs"))
- bs = sg_get_num(buf);
- else if (0 == strcmp(key,"bpt"))
- 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"))
- count = sg_get_num(buf);
- else if (0 == strcmp(key,"dio"))
- dio = sg_get_num(buf);
- else {
- printf("Unrecognized argument '%s'\n", key);
- usage();
- return 1;
- }
- }
- if (bs <= 0) {
- bs = DEF_BLOCK_SIZE;
- printf("Assume default 'bs' (block size) of %d bytes\n", bs);
- }
- if ((ibs && (ibs != bs)) || (obs && (obs != bs))) {
- printf("If 'ibs' or 'obs' given must be same as 'bs'\n");
- usage();
- return 1;
- }
- if ((skip < 0) || (seek < 0)) {
- printf("skip and seek cannot be negative\n");
- return 1;
- }
-#ifdef SG_DEBUG
- printf("sg_dd: 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;
- t = bs * bpt;
- res = ioctl(infd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror("sg_dd: SG_SET_RESERVED_SIZE error");
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- printf("sg_dd: sg driver prior to 3.x.y\n");
- return 1;
- }
- }
- }
- if (! in_is_sg) {
- if ((infd = open(inf, O_RDONLY)) < 0) {
- sprintf(ebuff, "sg_dd: could not open %s for reading", inf);
- perror(ebuff);
- return 1;
- }
- else if (skip > 0) {
- off_t offset = skip;
-
- offset *= bs; /* could overflow here! */
- if (lseek(infd, offset, SEEK_SET) < 0) {
- sprintf(ebuff,
- "sg_dd: 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;
- t = bs * bpt;
- res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror("sg_dd: SG_SET_RESERVED_SIZE error");
- res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- printf("sg_dd: 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_dd: could not open %s for writing", outf);
- perror(ebuff);
- return 1;
- }
- else if (seek > 0) {
- off_t offset = seek;
-
- offset *= bs; /* could overflow here! */
- if (lseek(outfd, offset, SEEK_SET) < 0) {
- sprintf(ebuff,
- "sg_dd: 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 = bs;
- else if (in_sect_sz > bs)
- in_num_sect *= (in_sect_sz / bs);
- else if (in_sect_sz < bs)
- in_num_sect /= (bs / 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;
- }
- }
-#ifdef SG_DEBUG
- printf("Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- count, in_num_sect, out_num_sect);
-#endif
- 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(bs * bpt);
- if (0 == wrkBuff) {
- printf("Not enough user memory\n");
- return 1;
- }
- wrkPos = wrkBuff;
-
- blocks_per = bpt;
-#ifdef SG_DEBUG
- printf("Start of loop, count=%d, blocks_per=%d\n", count, blocks_per);
-#endif
- while (count) {
- blocks = (count > blocks_per) ? blocks_per : count;
- if (in_is_sg) {
- dio_tmp = dio;
- res = sg_read(infd, wrkBuff, blocks, skip, bs, &dio_tmp);
- 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 + bs - 1) / bs;
- blocks = blocks_per;
- printf("Reducing read to %d blocks per loop\n", blocks_per);
- res = sg_read(infd, wrkBuff, blocks, skip, bs, &dio_tmp);
- }
- else if (2 == res) {
- printf("Unit attention, media changed, try again (r)\n");
- res = sg_read(infd, wrkBuff, blocks, skip, bs, &dio_tmp);
- }
- if (0 != res) {
- printf("sg_read failed, skip=%d\n", skip);
- break;
- }
- else {
- in_full += blocks;
- if (dio && (0 == dio_tmp))
- dio_incomplete++;
- }
- }
- else {
- while (((res = read(infd, wrkPos, blocks * bs)) < 0) &&
- (EINTR == errno))
- ;
- if (res < 0) {
- sprintf(ebuff, "sg_dd: reading, skip=%d ", skip);
- perror(ebuff);
- break;
- }
- else if (res < blocks * bs) {
- count = 0;
- blocks = res / bs;
- if ((res % bs) > 0) {
- blocks++;
- in_partial++;
- }
- }
- in_full += blocks;
- }
-
- if (out_is_sg) {
- dio_tmp = dio;
- res = sg_write(outfd, wrkBuff, blocks, seek, bs, &dio_tmp);
- 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 + bs - 1) / bs;
- blocks = blocks_per;
- printf("Reducing write to %d blocks per loop\n", blocks);
- res = sg_write(outfd, wrkBuff, blocks, seek, bs, &dio_tmp);
- }
- else if (2 == res) {
- printf("Unit attention, media changed, try again (w)\n");
- res = sg_write(outfd, wrkBuff, blocks, seek, bs, &dio_tmp);
- }
- else if (0 != res) {
- printf("sg_write failed, seek=%d\n", seek);
- break;
- }
- else {
- out_full += blocks;
- if (dio && (0 == dio_tmp))
- dio_incomplete++;
- }
- }
- else {
- while (((res = write(outfd, wrkPos, blocks * bs)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- sprintf(ebuff, "sg_ddd512: writing, seek=%d ", seek);
- perror(ebuff);
- break;
- }
- else if (res < blocks * bs) {
- printf("output file probably full, seek=%d ", seek);
- blocks = res / bs;
- out_full += blocks;
- if ((res % bs) > 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);
- if (dio_incomplete)
- printf(">> Direct IO requested but incomplete %d times\n",
- dio_incomplete);
- if (sum_of_resids)
- printf(">> Non-zero sum of residual counts=%d\n", sum_of_resids);
- return 0;
-}
diff --git a/archive/sg_debug.c b/archive/sg_debug.c
deleted file mode 100644
index c29b87b3..00000000
--- a/archive/sg_debug.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <sys/ioctl.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
-* 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 outputs debug information to the console/log for _all_
- active sg devices.
-
- Version 3.55 (20020115)
-*/
-
-#define EBUFF_SZ 256
-
-
-int main(int argc, char * argv[])
-{
- int fd, res, debug, t;
- char ebuff[EBUFF_SZ];
-
- if ((argc != 2) || ('-' == *argv[1])) {
- printf("Usage: sg_debug <sg_device>\n");
- return 1;
- }
- fd = open(argv[1], O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- if (EBUSY == errno)
- printf("Failed trying to open %s because it is busy\n", argv[1]);
- else {
- snprintf(ebuff, EBUFF_SZ, "sg_debug: Error trying to open %s ",
- argv[1]);
- perror(ebuff);
- }
- return 1;
- }
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res >= 0) || (t >= 30000)) {
- printf("System is using sg version 3 driver. Hence the user can");
- printf(" execute:\n 'cat /proc/scsi/sg/debug' themselves. ");
- printf("Here is an example:\n");
- system("cat /proc/scsi/sg/debug");
- return 0;
- }
- debug = 10;
- res = ioctl(fd, SG_SET_DEBUG, &debug);
- if (res < 0) {
- perror("sg_debug: ioctl error on SG_SET_DEBUG");
- return 1;
- }
-
- res = close(fd);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "sg_debug: trying to close %s ", argv[1]);
- perror(ebuff);
- return 1;
- }
- return 0;
-}
diff --git a/archive/sg_hold.c b/archive/sg_hold.c
deleted file mode 100644
index 01c73d35..00000000
--- a/archive/sg_hold.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "sg_linux_inc.h"
-
-/* This is a program that periodically executes a TEST UNIT READY
- SCSI command using the SCSI generic (sg) driver.
-
-* Copyright (C) 2001 D. Gilbert
-* 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.
-
- Invocation: sg_hold [-t<secs>] [-d] <sg_device>
-
- Version 1.00 (20010312)
-
-6 byte TEST UNIT READY command:
-[0x00][ |lu][res ][res ][res ][res ]
-
-*/
-#define TUR_CMD_LEN 6
-
-
-int main(int argc, char * argv[])
-{
- int sg_fd, k, j, res;
- unsigned char turCmdBlk [TUR_CMD_LEN] =
- {0x00, 0, 0, 0, 0, 0};
- sg_io_hdr_t io_hdr;
- char * file_name = 0;
- char ebuff[128];
- unsigned char sense_buffer[32];
- int sleep_period = 1;
- int debug = 0;
- size_t len;
-
- for (k = 1; k < argc; ++k) {
- if (0 == memcmp("-t", argv[k], 2)) {
- len = strlen(argv[k]);
- if (len > 2)
- res = sscanf(argv[k] + 2, "%d", &sleep_period);
- else if (++k < argc)
- res = sscanf(argv[k], "%d", &sleep_period);
- else
- res = 0;
- if ((1 != res) || (sleep_period < 1)) {
- file_name = 0;
- printf("Bad '-t' argument\n");
- break;
- }
- }
- else if (0 == memcmp("-d", argv[k], 2))
- debug = 1;
- else if (*argv[k] == '-') {
- printf("Unrecognized switch: %s\n", argv[k]);
- file_name = 0;
- break;
- }
- else if (0 == file_name)
- file_name = argv[k];
- else {
- printf("too many arguments\n");
- file_name = 0;
- break;
- }
- }
- if (0 == file_name) {
- printf("Usage: 'sg_hold [-t<secs>] [-d] <sg_device>'\n");
- printf(" where: -t<secs> time in seconds between TURs "
- "(default: 1 sec)\n");
- printf(" -d output message with each TUR\n");
- return 1;
- }
-
- if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
- sprintf(ebuff, "sg_hold: error opening file: %s", file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf("sg_hold: %s doesn't seem to be an new sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
-
- for (j = 1; ; ++j) {
- /* Prepare TEST UNIT READY command */
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(turCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.cmdp = turCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
- io_hdr.pack_id = j; /* marching pack_id starting at 1 */
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("sg_hold: Test Unit Ready SG_IO ioctl error");
- close(sg_fd);
- return 1;
- }
-
- /* now for the error processing */
- if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
- if (io_hdr.sb_len_wr > 0) {
- printf("TEST UNIT READY sense data: ");
- for (k = 0; k < io_hdr.sb_len_wr; ++k) {
- if ((k > 0) && (0 == (k % 10)))
- printf("\n ");
- printf("0x%02x ", sense_buffer[k]);
- }
- printf("\n");
- }
- else if (io_hdr.masked_status)
- printf("TEST UNIT READY SCSI status=0x%x\n", io_hdr.status);
- else if (io_hdr.host_status)
- printf("TEST UNIT READY host_status=0x%x\n",
- io_hdr.host_status);
- else if (io_hdr.driver_status)
- printf("TEST UNIT READY driver_status=0x%x\n",
- io_hdr.driver_status);
- else
- printf("TEST UNIT READY unexpected error\n");
- printf("Test Unit Ready failed so unit may _not_ be ready!\n");
- }
- else if (debug)
- printf("Test Unit Ready successful so unit is ready!\n");
-
- sleep(sleep_period);
- }
- close(sg_fd);
- return 0;
-}
diff --git a/archive/sg_io_linux.h b/archive/sg_io_linux.h
deleted file mode 120000
index 6c9c2ba9..00000000
--- a/archive/sg_io_linux.h
+++ /dev/null
@@ -1 +0,0 @@
-../sg_io_linux.h \ No newline at end of file
diff --git a/archive/sg_lib.h b/archive/sg_lib.h
deleted file mode 120000
index f6ce0761..00000000
--- a/archive/sg_lib.h
+++ /dev/null
@@ -1 +0,0 @@
-../sg_lib.h \ No newline at end of file
diff --git a/archive/sg_linux_inc.h b/archive/sg_linux_inc.h
deleted file mode 120000
index 55808134..00000000
--- a/archive/sg_linux_inc.h
+++ /dev/null
@@ -1 +0,0 @@
-../sg_linux_inc.h \ No newline at end of file
diff --git a/archive/sg_poll.c b/archive/sg_poll.c
deleted file mode 100644
index e6fb28f8..00000000
--- a/archive/sg_poll.c
+++ /dev/null
@@ -1,351 +0,0 @@
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/poll.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#include "sg_lib.h"
-#include "sg_io_linux.h"
-
-/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
- device driver.
-* Copyright (C) 1999-2001 D. Gilbert
-* 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 tests out asynchronous parts of the 'sg' device driver.
- It only uses the SCSI read command on the 'sg' device.
- This program performs unbalanced, non-polling "write-write-read"
- sequences. Asynchronous notification is turned on and signals are
- counted. Due to the imbalance, when the close() is executed there
- are several packets still to be read() [some of which may not yet
- be awaiting a read()]. This tests how the device driver cleans up
- after an unexpected close().
- If the "-deb" flag is given then outputs state to console/log
- (for all active sg devices).
-
- Version 0.76 20010112
-*/
-
-
-/*
-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 ]
-*/
-
-#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
- /* union semun is defined by including <sys/sem.h> */
-#else
- /* according to X/OPEN we have to define it ourselves */
-union semun {
- int val; /* value for SETVAL */
- struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
- unsigned short int *array; /* array for GETALL, SETALL */
- struct seminfo *__buf; /* buffer for IPC_INFO */
-};
-#endif
-
-#ifdef O_ASYNC
-#define MY_ASYNC O_ASYNC
-#else
-#define MY_ASYNC FASYNC
-#endif
-
-
-// #define SG_DEBUG
-
-#define OFF sizeof(struct sg_header)
-// #define NUM_SECTORS 7777
-// #define NUM_SECTORS 577
-// #define NUM_SECTORS 97
-#define NUM_SECTORS 150
-#define BLOCK_SIZE 2048
-
-volatile int hand_count = 0;
-volatile int signo = 0;
-volatile int poll_res = 0;
-volatile short revents = 0;
-volatile int sg_fd = 0;
-int semset_id = 0;
-
-int do_poll()
-{
- struct pollfd a_pollfd = {0, POLLIN | POLLOUT, 0};
-
- a_pollfd.fd = sg_fd;
- if ((poll_res = poll(&a_pollfd, 1, 0)) < 0) {
- perror("poll error");
- return 0;
- }
- revents = a_pollfd.revents;
- return (a_pollfd.revents & POLLIN) ? 1 : 0;
-}
-
-void sg_sa_handler(int sig, siginfo_t *si, void * data)
-{
- signo = sig;
- if (SIGRTMIN != sig)
- fprintf(stderr, "Unexpected signal, signum=%d\n", sig);
- if (sg_fd != si->si_fd)
- fprintf(stderr, "Unexpected fd, fd=%d\n", si->si_fd);
- ++hand_count;
- if (do_poll()) {
- struct sembuf a_sembuf;
-
- a_sembuf.sem_num = 0;
- a_sembuf.sem_op = 1;
- a_sembuf.sem_flg = 0;
- if (semop(semset_id, &a_sembuf, 1) < 0)
- perror("semop(sh) error");
- }
-}
-
-int main(int argc, char * argv[])
-{
- int flags;
- int res;
- int k;
- unsigned char rdCmdBlk [10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- unsigned char * rdBuff = malloc(OFF + sizeof(rdCmdBlk) +
- (BLOCK_SIZE * NUM_SECTORS));
- unsigned char * rdBuff2 = malloc(OFF + sizeof(rdCmdBlk) +
- (BLOCK_SIZE * NUM_SECTORS));
- int rdInLen = OFF + sizeof(rdCmdBlk);
- int rdOutLen;
- unsigned char * rdCmd = rdBuff + OFF;
- unsigned char * rdCmd2 = rdBuff + OFF;
- struct sg_header * rsghp = (struct sg_header *)rdBuff;
- struct sg_header * rsghp2 = (struct sg_header *)rdBuff2;
- int sectorNo = 10000;
- int sectorNo2;
- int numSectors = NUM_SECTORS;
- const int times = 3;
- struct sigaction s_action;
- union semun a_semun;
- struct sembuf a_sembuf;
- struct sg_scsi_id sg_id;
- char ebuff[256];
- int deb = 0;
- char * file_name = 0;
-
- for (k = 1; k < argc; ++k) {
- if (0 == memcmp("-deb", argv[k], 4))
- deb = 10;
- else if (*argv[k] != '-')
- file_name = argv[k];
- }
- if (0 == file_name) {
-printf("Usage: 'sg_poll [-deb] <generic_device>' eg: sg_poll /dev/sg0\n");
- return 1;
- }
-
- semset_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
- if (-1 == semset_id) {
- perror("semget error");
- return 1;
- }
- a_semun.val = 0;
- res = semctl(semset_id, 0, SETVAL, a_semun);
- if (-1 == res) {
- perror("semctl(val) error");
- return 1;
- }
-
-
- sg_fd = open(file_name, O_RDWR | O_NONBLOCK);
- if (sg_fd < 0) {
- sprintf(ebuff, "sg_poll: open error on %s", file_name);
- perror(ebuff);
- return 1;
- }
- res = ioctl(sg_fd, SG_GET_SCSI_ID, &sg_id);
- if (res < 0) {
- /* perror("ioctl on generic device, error"); */
- printf("sg_poll: %s not a scsi generic device\n", file_name);
- return 1;
- }
- printf("scsi%d, channel=%d, device=%d, lun=%d, scsi_type=%d\n",
- sg_id.host_no, sg_id.channel, sg_id.scsi_id, sg_id.lun,
- sg_id.scsi_type);
-
-#ifdef SG_DEBUG
- ioctl(sg_fd, SG_SET_DEBUG, &deb);
-#endif
- res = ioctl(sg_fd, SG_GET_COMMAND_Q, &k);
- if (res < 0) {
- perror("SG_GET_COMMAND_Q ioctl error");
- return 1;
- }
- if (0 == k) {
- k = 1;
- res = ioctl(sg_fd, SG_SET_COMMAND_Q, &k);
- if (res < 0) {
- perror("SG_SET_COMMAND_Q ioctl error");
- return 1;
- }
- }
-
- s_action.sa_flags = SA_SIGINFO;
- s_action.sa_sigaction = sg_sa_handler;
- sigemptyset(&s_action.sa_mask);
- res = sigaction(SIGRTMIN, &s_action, NULL);
- if (res == -1) {
- perror("sg_poll: sigaction error");
- return 1;
- }
- res = fcntl(sg_fd, F_SETOWN, getpid());
- if (res == -1) {
- perror("sg_poll: fcntl(setown) error");
- return 1;
- }
- flags = fcntl(sg_fd, F_GETFL);
- res = fcntl(sg_fd, F_SETFL, flags | MY_ASYNC);
- if (res == -1) {
- perror("sg_poll: fcntl(setfl) error");
- return 1;
- }
- fcntl(sg_fd, F_SETSIG, SIGRTMIN);
-
- do_poll();
- printf("pre-loop check, poll_res=%d, revents=%d\n", poll_res, (int)revents);
-
-
- for (k = 0; k < times; ++k, sectorNo += numSectors) {
-
- rdOutLen = OFF + (BLOCK_SIZE * numSectors);
- rsghp->pack_len = 999; /* don't care */
- rsghp->pack_id = k;
- rsghp->reply_len = rdOutLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
- memcpy(rdBuff + OFF, rdCmdBlk, sizeof(rdCmdBlk));
- rdCmd[3] = (unsigned char)((sectorNo >> 16) & 0xFF);
- rdCmd[4] = (unsigned char)((sectorNo >> 8) & 0xFF);
- rdCmd[5] = (unsigned char)(sectorNo & 0xFF);
- rdCmd[7] = (unsigned char)((numSectors >> 8) & 0xff);
- rdCmd[8] = (unsigned char)(numSectors & 0xff);
-
- res = write(sg_fd, rdBuff, rdInLen);
- if (res < 0) {
- perror("sg_poll: write (rd) error");
- return 1;
- }
- if (res < rdInLen) {
- printf("sg_poll: wrote less (rd), ask=%d, got=%d", rdInLen, res);
- return 1;
- }
-
- rsghp2->pack_len = 888; /* don't care */
- rsghp2->pack_id = k + 100;
- rsghp2->reply_len = rdOutLen;
- rsghp2->twelve_byte = 0;
- rsghp2->result = 0;
- memcpy(rdBuff2 + OFF, rdCmdBlk, sizeof(rdCmdBlk));
- sectorNo2 = sectorNo + 6666;
- rdCmd2[3] = (unsigned char)((sectorNo2 >> 16) & 0xFF);
- rdCmd2[4] = (unsigned char)((sectorNo2 >> 8) & 0xFF);
- rdCmd2[5] = (unsigned char)(sectorNo2 & 0xFF);
- rdCmd2[7] = (unsigned char)((numSectors >> 8) & 0xff);
- rdCmd2[8] = (unsigned char)(numSectors & 0xff);
-
-#if 1
- res = write(sg_fd, rdBuff2, rdInLen);
- if (res < 0) {
- perror("sg_poll: write2 (rd) error");
- return 1;
- }
- if (res < rdInLen) {
- printf("sg_poll: wrote less (rd), ask=%d, got=%d", rdInLen, res);
- return 1;
- }
-#endif
-
- do_poll();
- printf("pre-write pause, k=%d, "
- "hand_count=%d, signo=%d, poll_res=%d, revents=%d\n",
- k, hand_count, signo, poll_res, (int)revents);
-#ifdef SG_DEBUG
- ioctl(sg_fd, SG_SET_DEBUG, &deb);
-#endif
- system("cat /proc/scsi/sg/debug");
-
- a_sembuf.sem_num = 0;
- a_sembuf.sem_op = -1;
- a_sembuf.sem_flg = 0;
- while (semop(semset_id, &a_sembuf, 1) < 0) {
- if (EINTR != errno) {
- perror("semop(main) error");
- return 0;
- }
- }
- /* pause(); */
-
- printf("post-write pause, k=%d, "
- "hand_count=%d, signo=%d, poll_res=%d, revents=%d\n",
- k, hand_count, signo, poll_res, (int)revents);
-#ifdef SG_DEBUG
- ioctl(sg_fd, SG_SET_DEBUG, &deb);
-#endif
-
- res = read(sg_fd, rdBuff, rdOutLen);
- if (res < 0) {
- perror("sg_poll: read (rd) error");
- return 1;
- }
- if (res < rdOutLen) {
- printf("sg_poll: read less (rd), ask=%d, got=%d", rdOutLen, res);
- return 1;
- }
- sg_chk_n_print("after read(rd)", rsghp->target_status,
- rsghp->host_status, rsghp->driver_status,
- rsghp->sense_buffer, SG_MAX_SENSE, 1);
-
- }
- printf("\treq_len=%d, dma_count=%d\n", rsghp->reply_len, rsghp->pack_len);
-
-#ifdef SG_DEBUG
- ioctl(sg_fd, SG_SET_DEBUG, &deb);
-#endif
- res = close(sg_fd);
- if (res < 0) {
- perror("sg_poll: close error");
- return 1;
- }
-
- if (deb > 0) {
- sg_fd = open(file_name, O_RDONLY);
- if (sg_fd < 0) {
- sprintf(ebuff, "sg_poll: open (2) error on %s", file_name);
- perror(ebuff);
- return 1;
- }
- res = ioctl(sg_fd, SG_SET_DEBUG, &deb);
- if (res < 0) {
- perror("ioctl (2) error");
- return 1;
- }
- res = close(sg_fd);
- if (res < 0) {
- perror("sg_poll: close (2) error");
- return 1;
- }
- }
-
- return 0;
-}
diff --git a/archive/sg_simple0.c b/archive/sg_simple0.c
deleted file mode 100644
index 7e1d8db7..00000000
--- a/archive/sg_simple0.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <scsi/sg.h> /* take care: fetches glibc's /usr/include/scsi/sg.h */
-
-/* This is a simple program executing a SCSI INQUIRY command using the
- sg_io_hdr interface of the SCSI generic (sg) driver.
-
-* Copyright (C) 2001 D. Gilbert
-* This program is free software. Version 1.00 (20011204)
-*/
-
-#define INQ_REPLY_LEN 96
-#define INQ_CMD_CODE 0x12
-#define INQ_CMD_LEN 6
-
-int main(int argc, char * argv[])
-{
- int sg_fd, k;
- unsigned char inqCmdBlk[INQ_CMD_LEN] =
- {INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0};
-/* This is a "standard" SCSI INQUIRY command. It is standard because the
- * CMDDT and EVPD bits (in the second byte) are zero. All SCSI targets
- * should respond promptly to a standard INQUIRY */
- unsigned char inqBuff[INQ_REPLY_LEN];
- unsigned char sense_buffer[32];
- sg_io_hdr_t io_hdr;
-
- if (2 != argc) {
- printf("Usage: 'sg_simple0 <sg_device>'\n");
- return 1;
- }
- if ((sg_fd = open(argv[1], O_RDONLY)) < 0) {
- perror("error opening given file name");
- return 1;
- }
- /* It is prudent to check we have a sg device by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf("%s is not an sg device, or old sg driver\n", argv[1]);
- return 1;
- }
- /* Prepare INQUIRY command */
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- /* io_hdr.iovec_count = 0; */ /* memset takes care of this */
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = INQ_REPLY_LEN;
- io_hdr.dxferp = inqBuff;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
- /* io_hdr.flags = 0; */ /* take defaults: indirect IO, etc */
- /* io_hdr.pack_id = 0; */
- /* io_hdr.usr_ptr = NULL; */
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("sg_simple0: Inquiry SG_IO ioctl error");
- return 1;
- }
-
- /* now for the error processing */
- if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
- if (io_hdr.sb_len_wr > 0) {
- printf("INQUIRY sense data: ");
- for (k = 0; k < io_hdr.sb_len_wr; ++k) {
- if ((k > 0) && (0 == (k % 10)))
- printf("\n ");
- printf("0x%02x ", sense_buffer[k]);
- }
- printf("\n");
- }
- if (io_hdr.masked_status)
- printf("INQUIRY SCSI status=0x%x\n", io_hdr.status);
- if (io_hdr.host_status)
- printf("INQUIRY host_status=0x%x\n", io_hdr.host_status);
- if (io_hdr.driver_status)
- printf("INQUIRY driver_status=0x%x\n", io_hdr.driver_status);
- }
- else { /* assume INQUIRY response is present */
- char * p = (char *)inqBuff;
- printf("Some of the INQUIRY command's response:\n");
- printf(" %.8s %.16s %.4s\n", p + 8, p + 16, p + 32);
- printf("INQUIRY duration=%u millisecs, resid=%d\n",
- io_hdr.duration, io_hdr.resid);
- }
- close(sg_fd);
- return 0;
-}
diff --git a/archive/sgq_dd.c b/archive/sgq_dd.c
deleted file mode 100644
index 52de5184..00000000
--- a/archive/sgq_dd.c
+++ /dev/null
@@ -1,1151 +0,0 @@
-#define _XOPEN_SOURCE 500
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <sys/poll.h>
-#include <linux/major.h>
-#include <sys/time.h>
-typedef unsigned char u_char; /* horrible, for scsi.h */
-#include "sg_lib.h"
-#include "sg_io_linux.h"
-#include "llseek.h"
-
-/* A utility program for the Linux OS SCSI generic ("sg") device driver.
-* Copyright (C) 1999-2002 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 or a raw
- device. A block size ('bs') is assumed to be 512 if not given. This
- program complains if 'ibs' or 'obs' are given with some other value
- than 'bs'. If 'if' is not given or 'if=-' then stdin is assumed. If
- 'of' is not given or 'of=-' then stdout assumed. Multipliers:
- 'c','C' *1 'b','B' *512 'k' *1024 'K' *1000
- 'm' *(1024^2) 'M' *(1000^2) 'g' *(1024^3) 'G' *(1000^3)
-
- A non-standard argument "bpt" (blocks per transfer) is added to control
- the maximum number of blocks in each transfer. The default value is 128.
- For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
- in this case) are transferred to or from the sg device in a single SCSI
- command.
-
- This version should compile with Linux sg drivers with version numbers
- >= 30000 . This version uses posix threads.
-
-*/
-
-static char * version_str = "0.55 20020509";
-
-#define DEF_BLOCK_SIZE 512
-#define DEF_BLOCKS_PER_TRANSFER 128
-
-/* #define SG_DEBUG */
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
-#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */
-
-#define SGP_READ10 0x28
-#define SGP_WRITE10 0x2a
-#define DEF_NUM_THREADS 4 /* actually degree of concurrency */
-#define MAX_NUM_THREADS 32
-
-#ifndef RAW_MAJOR
-#define RAW_MAJOR 255 /*unlikey value */
-#endif
-
-#define FT_OTHER 0 /* filetype other than sg or raw device */
-#define FT_SG 1 /* filetype is sg char device */
-#define FT_RAW 2 /* filetype is raw char device */
-
-#define QS_IDLE 0 /* ready to start a copy cycle */
-#define QS_IN_STARTED 1 /* commenced read */
-#define QS_IN_FINISHED 2 /* finished read, ready for write */
-#define QS_OUT_STARTED 3 /* commenced write */
-
-#define QS_IN_POLL 11
-#define QS_OUT_POLL 12
-
-#define STR_SZ 1024
-#define INOUTF_SZ 512
-#define EBUFF_SZ 512
-
-
-struct request_element;
-
-typedef struct request_collection
-{ /* one instance visible to all threads */
- int infd;
- int skip;
- int in_type;
- int in_scsi_type;
- int in_blk; /* next block address to read */
- int in_count; /* blocks remaining for next read */
- int in_done_count; /* count of completed in blocks */
- int in_partial;
- int outfd;
- int seek;
- int out_type;
- int out_scsi_type;
- int out_blk; /* next block address to write */
- int out_count; /* blocks remaining for next write */
- int out_done_count; /* count of completed out blocks */
- int out_partial;
- int bs;
- int bpt;
- int dio;
- int dio_incomplete;
- int sum_of_resids;
- int coe;
- int debug;
- int num_rq_elems;
- struct request_element * req_arr;
-} Rq_coll;
-
-typedef struct request_element
-{ /* one instance per worker thread */
- int qstate; /* "QS" state */
- int infd;
- int outfd;
- int wr;
- int blk;
- int num_blks;
- unsigned char * buffp;
- unsigned char * alloc_bp;
- sg_io_hdr_t io_hdr;
- unsigned char cmd[S_RW_LEN];
- unsigned char sb[SENSE_BUFF_LEN];
- int bs;
- int dio;
- int dio_incomplete;
- int resid;
- int in_scsi_type;
- int out_scsi_type;
- int debug;
-} Rq_elem;
-
-static Rq_coll rcoll;
-static struct pollfd in_pollfd_arr[MAX_NUM_THREADS];
-static struct pollfd out_pollfd_arr[MAX_NUM_THREADS];
-static int dd_count = -1;
-
-static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
-
-int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep);
-int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep);
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-int sg_start_io(Rq_elem * rep);
-int sg_finish_io(int wr, Rq_elem * rep);
-
-
-static void install_handler (int sig_num, void (*sig_handler) (int sig))
-{
- struct sigaction sigact;
- sigaction (sig_num, NULL, &sigact);
- if (sigact.sa_handler != SIG_IGN)
- {
- sigact.sa_handler = sig_handler;
- sigemptyset (&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction (sig_num, &sigact, NULL);
- }
-}
-
-void print_stats()
-{
- int infull, outfull;
-
- if (0 != rcoll.out_count)
- fprintf(stderr, " remaining block count=%d\n", rcoll.out_count);
- infull = dd_count - rcoll.in_done_count - rcoll.in_partial;
- fprintf(stderr, "%d+%d records in\n", infull, rcoll.in_partial);
- outfull = dd_count - rcoll.out_done_count - rcoll.out_partial;
- fprintf(stderr, "%d+%d records out\n", outfull, rcoll.out_partial);
-}
-
-static void interrupt_handler(int sig)
-{
- struct sigaction sigact;
-
- sigact.sa_handler = SIG_DFL;
- sigemptyset (&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction (sig, &sigact, NULL);
- fprintf(stderr, "Interrupted by signal,");
- print_stats ();
- kill (getpid (), sig);
-}
-
-static void siginfo_handler(int sig)
-{
- fprintf(stderr, "Progress report, continuing ...\n");
- print_stats ();
-}
-
-int dd_filetype(const char * filename)
-{
- struct stat st;
-
- if (stat(filename, &st) < 0)
- return FT_OTHER;
- if (S_ISCHR(st.st_mode)) {
- if (RAW_MAJOR == major(st.st_rdev))
- return FT_RAW;
- else if (SCSI_GENERIC_MAJOR == major(st.st_rdev))
- return FT_SG;
- }
- return FT_OTHER;
-}
-
-void usage()
-{
- fprintf(stderr, "Usage: "
- "sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>] "
- "[bs=<num>]\n"
- " [bpt=<num>] [count=<n>] [dio=0|1] [thr=<n>] "
- "[coe=0|1] [gen=<n>]\n"
- " [time=0|1] [deb=<n>] [--version]\n"
- " usually either 'if' or 'of' is a sg or raw device\n"
- " 'bpt' is blocks_per_transfer (default is 128)\n"
- " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"
- " 'thr' is number of queues, must be > 0, default 4, max 32\n");
- fprintf(stderr, " 'coe' continue on sg error, 0->exit (def), "
- "1->zero + continue\n"
- " 'time' 0->no timing(def), 1->time plus calculate throughput\n"
- " 'gen' 0-> 1 file is special(def), 1-> any files allowed\n"
- " 'deb' is debug, 0->none (def), > 0->varying degrees of debug\n");
-}
-
-/* Returns -1 for error, 0 for nothing found, QS_IN_POLL or QS_OUT_POLL */
-int do_poll(Rq_coll * clp, int timeout, int * req_indexp)
-{
- int k, res;
-
- if (FT_SG == clp->out_type) {
- while (((res = poll(out_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- perror("poll error on output fds");
- return -1;
- }
- else if (res > 0) {
- for (k = 0; k < clp->num_rq_elems; ++k) {
- if (out_pollfd_arr[k].revents & POLLIN) {
- if (req_indexp)
- *req_indexp = k;
- return QS_OUT_POLL;
- }
- }
- }
- }
- if (FT_SG == clp->in_type) {
- while (((res = poll(in_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- perror("poll error on input fds");
- return -1;
- }
- else if (res > 0) {
- for (k = 0; k < clp->num_rq_elems; ++k) {
- if (in_pollfd_arr[k].revents & POLLIN) {
- if (req_indexp)
- *req_indexp = k;
- return QS_IN_POLL;
- }
- }
- }
- }
- return 0;
-}
-
-
-/* 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, 1);
- 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];
-#ifdef SG_DEBUG
- fprintf(stderr, "number of sectors=%d, sector size=%d\n",
- *num_sect, *sect_sz);
-#endif
- return 0;
-}
-
-/* 0 -> ok, 1 -> short read, -1 -> error */
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
- int stop_after_write = 0;
-
- rep->qstate = QS_IN_STARTED;
- if (rep->debug > 8)
- fprintf(stderr, "normal_in_operation: start blk=%d num_blks=%d\n",
- rep->blk, rep->num_blks);
- while (((res = read(rep->infd, rep->buffp,
- blocks * rep->bs)) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- fprintf(stderr, "sgq_dd: reading, in_blk=%d, errno=%d\n", rep->blk,
- errno);
- return -1;
- }
- if (res < blocks * rep->bs) {
- int o_blocks = blocks;
- stop_after_write = 1;
- blocks = res / rep->bs;
- if ((res % rep->bs) > 0) {
- blocks++;
- clp->in_partial++;
- }
- /* Reverse out + re-apply blocks on clp */
- clp->in_blk -= o_blocks;
- clp->in_count += o_blocks;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- }
- clp->in_done_count -= blocks;
- rep->qstate = QS_IN_FINISHED;
- return stop_after_write;
-}
-
-/* 0 -> ok, -1 -> error */
-int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
-
- rep->qstate = QS_OUT_STARTED;
- if (rep->debug > 8)
- fprintf(stderr, "normal_out_operation: start blk=%d num_blks=%d\n",
- rep->blk, rep->num_blks);
- while (((res = write(rep->outfd, rep->buffp,
- rep->num_blks * rep->bs)) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- fprintf(stderr, "sgq_dd: output, out_blk=%d, errno=%d\n", rep->blk,
- errno);
- return -1;
- }
- if (res < blocks * rep->bs) {
- blocks = res / rep->bs;
- if ((res % rep->bs) > 0) {
- blocks++;
- clp->out_partial++;
- }
- rep->num_blks = blocks;
- }
- clp->out_done_count -= blocks;
- rep->qstate = QS_IDLE;
- return 0;
-}
-
-/* Returns 1 for retryable, 0 for ok, -ve for error */
-int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
-
- rep->qstate = QS_IN_FINISHED;
- res = sg_finish_io(rep->wr, rep);
- if (res < 0) {
- if (clp->coe) {
- memset(rep->buffp, 0, rep->num_blks * rep->bs);
- fprintf(stderr, ">> substituted zeros for in blk=%d for "
- "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
- res = 0;
- }
- else {
- fprintf(stderr, "error finishing sg in command\n");
- return res;
- }
- }
- if (0 == res) { /* looks good, going to return */
- if (rep->dio_incomplete || rep->resid) {
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- }
- clp->in_done_count -= rep->num_blks;
- }
- return res;
-}
-
-/* Returns 1 for retryable, 0 for ok, -ve for error */
-int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
-
- rep->qstate = QS_IDLE;
- res = sg_finish_io(rep->wr, rep);
- if (res < 0) {
- if (clp->coe) {
- fprintf(stderr, ">> ignored error for out blk=%d for "
- "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
- res = 0;
- }
- else {
- fprintf(stderr, "error finishing sg out command\n");
- return res;
- }
- }
- if (0 == res) {
- if (rep->dio_incomplete || rep->resid) {
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- }
- clp->out_done_count -= rep->num_blks;
- }
- return res;
-}
-
-int sg_start_io(Rq_elem * rep)
-{
- sg_io_hdr_t * hp = &rep->io_hdr;
- int res;
-
- rep->qstate = rep->wr ? QS_OUT_STARTED : QS_IN_STARTED;
- memset(rep->cmd, 0, sizeof(rep->cmd));
- rep->cmd[0] = rep->wr ? SGP_WRITE10 : SGP_READ10;
- rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF);
- rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF);
- rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF);
- rep->cmd[5] = (unsigned char)(rep->blk & 0xFF);
- rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff);
- rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff);
- memset(hp, 0, sizeof(sg_io_hdr_t));
- hp->interface_id = 'S';
- hp->cmd_len = sizeof(rep->cmd);
- hp->cmdp = rep->cmd;
- hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- hp->dxfer_len = rep->bs * rep->num_blks;
- hp->dxferp = rep->buffp;
- hp->mx_sb_len = sizeof(rep->sb);
- hp->sbp = rep->sb;
- hp->timeout = DEF_TIMEOUT;
- hp->usr_ptr = rep;
- hp->pack_id = rep->blk;
- if (rep->dio)
- hp->flags |= SG_FLAG_DIRECT_IO;
- if (rep->debug > 8) {
- fprintf(stderr, "sg_start_io: SCSI %s, blk=%d num_blks=%d\n",
- rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks);
- sg_print_command(hp->cmdp);
- fprintf(stderr, " len=%d, dxfrp=%p, cmd_len=%d\n",
- hp->dxfer_len, hp->dxferp, hp->cmd_len);
- }
-
- while (((res = write(rep->wr ? rep->outfd : rep->infd, hp,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- return res;
- }
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
-int sg_finish_io(int wr, Rq_elem * rep)
-{
- int res;
- sg_io_hdr_t io_hdr;
- sg_io_hdr_t * hp;
-#if 0
- static int testing = 0; /* thread dubious! */
-#endif
-
- memset(&io_hdr, 0 , sizeof(sg_io_hdr_t));
- /* FORCE_PACK_ID active set only read packet with matching pack_id */
- io_hdr.interface_id = 'S';
- io_hdr.dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- io_hdr.pack_id = rep->blk;
-
- while (((res = read(wr ? rep->outfd : rep->infd, &io_hdr,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- perror("finishing io on sg device, error");
- return -1;
- }
- if (rep != (Rq_elem *)io_hdr.usr_ptr) {
- fprintf(stderr,
- "sg_finish_io: bad usr_ptr, request-response mismatch\n");
- exit(1);
- }
- memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t));
- hp = &rep->io_hdr;
-
- switch (sg_err_category3(hp)) {
- case SG_LIB_CAT_CLEAN:
- break;
- case SG_LIB_CAT_RECOVERED:
- fprintf(stderr, "Recovered error on block=%d, num=%d\n",
- rep->blk, rep->num_blks);
- break;
- case SG_LIB_CAT_UNIT_ATTENTION:
- return 1;
- default:
- {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "%s blk=%d",
- rep->wr ? "writing": "reading", rep->blk);
- sg_chk_n_print3(ebuff, hp, 1);
- return -1;
- }
- }
-#if 0
- if (0 == (++testing % 100)) return -1;
-#endif
- if (rep->dio &&
- ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- rep->dio_incomplete = 1; /* count dios done as indirect IO */
- else
- rep->dio_incomplete = 0;
- rep->resid = hp->resid;
- if (rep->debug > 8)
- fprintf(stderr, "sg_finish_io: completed %s, blk=%d\n",
- wr ? "WRITE" : "READ", rep->blk);
- return 0;
-}
-
-/* Returns scsi_type or -1 for error */
-int sg_prepare(int fd, int sz)
-{
- int res, t;
- struct sg_scsi_id info;
-
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- fprintf(stderr, "sgq_dd: sg driver prior to 3.x.y\n");
- return -1;
- }
- res = ioctl(fd, SG_SET_RESERVED_SIZE, &sz);
- if (res < 0)
- perror("sgq_dd: SG_SET_RESERVED_SIZE error");
-#if 0
- t = 1;
- res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
- if (res < 0)
- perror("sgq_dd: SG_SET_FORCE_PACK_ID error");
-#endif
- res = ioctl(fd, SG_GET_SCSI_ID, &info);
- if (res < 0) {
- perror("sgq_dd: SG_SET_SCSI_ID error");
- return -1;
- }
- else
- return info.scsi_type;
-}
-
-/* Return 0 for ok, anything else for errors */
-int prepare_rq_elems(Rq_coll * clp, const char * inf, const char * outf)
-{
- int k;
- Rq_elem * rep;
- size_t psz;
- char ebuff[EBUFF_SZ];
- int sz = clp->bpt * clp->bs;
- int scsi_type;
-
- clp->req_arr = malloc(sizeof(Rq_elem) * clp->num_rq_elems);
- if (NULL == clp->req_arr)
- return 1;
- for (k = 0; k < clp->num_rq_elems; ++k) {
- rep = &clp->req_arr[k];
- memset(rep, 0, sizeof(Rq_elem));
- psz = getpagesize();
- if (NULL == (rep->alloc_bp = malloc(sz + psz)))
- return 1;
- rep->buffp = (unsigned char *)
- (((unsigned long)rep->alloc_bp + psz - 1) & (~(psz - 1)));
- rep->qstate = QS_IDLE;
- rep->bs = clp->bs;
- rep->dio = clp->dio;
- rep->debug = clp->debug;
- rep->out_scsi_type = clp->out_scsi_type;
- if (FT_SG == clp->in_type) {
- if (0 == k)
- rep->infd = clp->infd;
- else {
- if ((rep->infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg reading", inf);
- perror(ebuff);
- return 1;
- }
- }
- in_pollfd_arr[k].fd = rep->infd;
- in_pollfd_arr[k].events = POLLIN;
- if ((scsi_type = sg_prepare(rep->infd, sz)) < 0)
- return 1;
- if (0 == k)
- clp->in_scsi_type = scsi_type;
- rep->in_scsi_type = clp->in_scsi_type;
- }
- else
- rep->infd = clp->infd;
-
- if (FT_SG == clp->out_type) {
- if (0 == k)
- rep->outfd = clp->outfd;
- else {
- if ((rep->outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg writing", outf);
- perror(ebuff);
- return 1;
- }
- }
- out_pollfd_arr[k].fd = rep->outfd;
- out_pollfd_arr[k].events = POLLIN;
- if ((scsi_type = sg_prepare(rep->outfd, sz)) < 0)
- return 1;
- if (0 == k)
- clp->out_scsi_type = scsi_type;
- rep->out_scsi_type = clp->out_scsi_type;
- }
- else
- rep->outfd = clp->outfd;
- }
- return 0;
-}
-
-/* Returns a "QS" code and req index, or QS_IDLE and position of first idle
- (-1 if no idle position). Returns -1 on poll error. */
-int decider(Rq_coll * clp, int first_xfer, int * req_indexp)
-{
- int k, res;
- Rq_elem * rep;
- int first_idle_index = -1;
- int lowest_blk_index = -1;
- int times;
- int try_poll = 0;
- int lowest_blk = INT_MAX;
-
- times = first_xfer ? 1 : clp->num_rq_elems;
- for (k = 0; k < times; ++k) {
- rep = &clp->req_arr[k];
- if ((QS_IN_STARTED == rep->qstate) ||
- (QS_OUT_STARTED == rep->qstate))
- try_poll = 1;
- else if ((QS_IN_FINISHED == rep->qstate) && (rep->blk < lowest_blk)) {
- lowest_blk = rep->blk;
- lowest_blk_index = k;
- }
- else if ((QS_IDLE == rep->qstate) && (first_idle_index < 0))
- first_idle_index = k;
- }
- if (try_poll) {
- res = do_poll(clp, 0, req_indexp);
- if (0 != res)
- return res;
- }
-
- if (lowest_blk_index >= 0) {
- if (req_indexp)
- *req_indexp = lowest_blk_index;
- return QS_IN_FINISHED;
- }
-#if 0
- if (try_poll) {
- res = do_poll(clp, 2, req_indexp);
- if (0 != res)
- return res;
- }
-#endif
- if (req_indexp)
- *req_indexp = first_idle_index;
- return QS_IDLE;
-}
-
-
-int main(int argc, char * argv[])
-{
- 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;
- 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';
- if (argc < 2) {
- usage();
- return 1;
- }
-
- 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 (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))
- rcoll.debug = sg_get_num(buf);
- else if (0 == strcmp(key,"time"))
- do_time = sg_get_num(buf);
- else if (0 == strncmp(key, "--vers", 6)) {
- fprintf(stderr, "sgq_dd for sg version 3 driver: %s\n",
- version_str);
- return 0;
- }
- else {
- fprintf(stderr, "Unrecognized argument '%s'\n", key);
- 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) {
- llse_loff_t offset = skip;
-
- offset *= rcoll.bs; /* could exceed 32 here! */
- if (llse_llseek(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) {
- llse_loff_t offset = seek;
-
- offset *= rcoll.bs; /* could exceed 32 bits here! */
- if (llse_llseek(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");
- 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;
-}
diff --git a/archive/sgq_dd.c.orig b/archive/sgq_dd.c.orig
deleted file mode 100644
index c55280ea..00000000
--- a/archive/sgq_dd.c.orig
+++ /dev/null
@@ -1,1139 +0,0 @@
-#define _XOPEN_SOURCE 500
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <sys/poll.h>
-#include <linux/major.h>
-#include <sys/time.h>
-typedef unsigned char u_char; /* horrible, for scsi.h */
-#include "sg_lib.h"
-#include "sg_linux_inc.h"
-#include "llseek.h"
-
-/* A utility program for the Linux OS SCSI generic ("sg") device driver.
-* Copyright (C) 1999-2002 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 or a raw
- device. A block size ('bs') is assumed to be 512 if not given. This
- program complains if 'ibs' or 'obs' are given with some other value
- than 'bs'. If 'if' is not given or 'if=-' then stdin is assumed. If
- 'of' is not given or 'of=-' then stdout assumed. Multipliers:
- 'c','C' *1 'b','B' *512 'k' *1024 'K' *1000
- 'm' *(1024^2) 'M' *(1000^2) 'g' *(1024^3) 'G' *(1000^3)
-
- A non-standard argument "bpt" (blocks per transfer) is added to control
- the maximum number of blocks in each transfer. The default value is 128.
- For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
- in this case) are transferred to or from the sg device in a single SCSI
- command.
-
- This version should compile with Linux sg drivers with version numbers
- >= 30000 . This version uses posix threads.
-
-*/
-
-static char * version_str = "0.54 20020223";
-
-#define DEF_BLOCK_SIZE 512
-#define DEF_BLOCKS_PER_TRANSFER 128
-
-/* #define SG_DEBUG */
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
-#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */
-
-#define SGP_READ10 0x28
-#define SGP_WRITE10 0x2a
-#define DEF_NUM_THREADS 4 /* actually degree of concurrency */
-#define MAX_NUM_THREADS 32
-
-#ifndef RAW_MAJOR
-#define RAW_MAJOR 255 /*unlikey value */
-#endif
-
-#define FT_OTHER 0 /* filetype other than sg or raw device */
-#define FT_SG 1 /* filetype is sg char device */
-#define FT_RAW 2 /* filetype is raw char device */
-
-#define QS_IDLE 0 /* ready to start a copy cycle */
-#define QS_IN_STARTED 1 /* commenced read */
-#define QS_IN_FINISHED 2 /* finished read, ready for write */
-#define QS_OUT_STARTED 3 /* commenced write */
-
-#define QS_IN_POLL 11
-#define QS_OUT_POLL 12
-
-#define STR_SZ 1024
-#define INOUTF_SZ 512
-#define EBUFF_SZ 512
-
-
-struct request_element;
-
-typedef struct request_collection
-{ /* one instance visible to all threads */
- int infd;
- int skip;
- int in_type;
- int in_scsi_type;
- int in_blk; /* next block address to read */
- int in_count; /* blocks remaining for next read */
- int in_done_count; /* count of completed in blocks */
- int in_partial;
- int outfd;
- int seek;
- int out_type;
- int out_scsi_type;
- int out_blk; /* next block address to write */
- int out_count; /* blocks remaining for next write */
- int out_done_count; /* count of completed out blocks */
- int out_partial;
- int bs;
- int bpt;
- int dio;
- int dio_incomplete;
- int sum_of_resids;
- int coe;
- int debug;
- int num_rq_elems;
- struct request_element * req_arr;
-} Rq_coll;
-
-typedef struct request_element
-{ /* one instance per worker thread */
- int qstate; /* "QS" state */
- int infd;
- int outfd;
- int wr;
- int blk;
- int num_blks;
- unsigned char * buffp;
- unsigned char * alloc_bp;
- sg_io_hdr_t io_hdr;
- unsigned char cmd[S_RW_LEN];
- unsigned char sb[SENSE_BUFF_LEN];
- int bs;
- int dio;
- int dio_incomplete;
- int resid;
- int in_scsi_type;
- int out_scsi_type;
- int debug;
-} Rq_elem;
-
-static Rq_coll rcoll;
-static struct pollfd in_pollfd_arr[MAX_NUM_THREADS];
-static struct pollfd out_pollfd_arr[MAX_NUM_THREADS];
-static int dd_count = -1;
-
-static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
-
-int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep);
-int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep);
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-int sg_start_io(Rq_elem * rep);
-int sg_finish_io(int wr, Rq_elem * rep);
-
-
-static void install_handler (int sig_num, void (*sig_handler) (int sig))
-{
- struct sigaction sigact;
- sigaction (sig_num, NULL, &sigact);
- if (sigact.sa_handler != SIG_IGN)
- {
- sigact.sa_handler = sig_handler;
- sigemptyset (&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction (sig_num, &sigact, NULL);
- }
-}
-
-void print_stats()
-{
- int infull, outfull;
-
- if (0 != rcoll.out_count)
- fprintf(stderr, " remaining block count=%d\n", rcoll.out_count);
- infull = dd_count - rcoll.in_done_count - rcoll.in_partial;
- fprintf(stderr, "%d+%d records in\n", infull, rcoll.in_partial);
- outfull = dd_count - rcoll.out_done_count - rcoll.out_partial;
- fprintf(stderr, "%d+%d records out\n", outfull, rcoll.out_partial);
-}
-
-static void interrupt_handler(int sig)
-{
- struct sigaction sigact;
-
- sigact.sa_handler = SIG_DFL;
- sigemptyset (&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigaction (sig, &sigact, NULL);
- fprintf(stderr, "Interrupted by signal,");
- print_stats ();
- kill (getpid (), sig);
-}
-
-static void siginfo_handler(int sig)
-{
- fprintf(stderr, "Progress report, continuing ...\n");
- print_stats ();
-}
-
-int dd_filetype(const char * filename)
-{
- struct stat st;
-
- if (stat(filename, &st) < 0)
- return FT_OTHER;
- if (S_ISCHR(st.st_mode)) {
- if (RAW_MAJOR == major(st.st_rdev))
- return FT_RAW;
- else if (SCSI_GENERIC_MAJOR == major(st.st_rdev))
- return FT_SG;
- }
- return FT_OTHER;
-}
-
-void usage()
-{
- fprintf(stderr, "Usage: "
- "sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>] "
- "[bs=<num>]\n"
- " [bpt=<num>] [count=<n>] [dio=<n>] [thr=<n>] "
- "[coe=<n>] [gen=<n>]\n"
- " [dio=<n>] [thr=<n>] [coe=<n>] [gen=<n>] "
- "[deb=<n>] [--version]\n"
- " usually either 'if' or 'of' is a sg or raw device\n"
- " 'bpt' is blocks_per_transfer (default is 128)\n"
- " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"
- " 'thr' is number of queues, must be > 0, default 4, max 32\n");
- fprintf(stderr, " 'coe' continue on sg error, 0->exit (def), "
- "1->zero + continue\n"
- " 'gen' 0-> 1 file is special(def), 1-> any files allowed\n"
- " 'deb' is debug, 0->none (def), > 0->varying degrees of debug\n");
-}
-
-/* Returns -1 for error, 0 for nothing found, QS_IN_POLL or QS_OUT_POLL */
-int do_poll(Rq_coll * clp, int timeout, int * req_indexp)
-{
- int k, res;
-
- if (FT_SG == clp->out_type) {
- while (((res = poll(out_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- perror("poll error on output fds");
- return -1;
- }
- else if (res > 0) {
- for (k = 0; k < clp->num_rq_elems; ++k) {
- if (out_pollfd_arr[k].revents & POLLIN) {
- if (req_indexp)
- *req_indexp = k;
- return QS_OUT_POLL;
- }
- }
- }
- }
- if (FT_SG == clp->in_type) {
- while (((res = poll(in_pollfd_arr, clp->num_rq_elems, timeout)) < 0)
- && (EINTR == errno))
- ;
- if (res < 0) {
- perror("poll error on input fds");
- return -1;
- }
- else if (res > 0) {
- for (k = 0; k < clp->num_rq_elems; ++k) {
- if (in_pollfd_arr[k].revents & POLLIN) {
- if (req_indexp)
- *req_indexp = k;
- return QS_IN_POLL;
- }
- }
- }
- }
- return 0;
-}
-
-
-/* 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_ERR_CAT_MEDIA_CHANGED == res)
- return 2; /* probably have another go ... */
- else if (SG_ERR_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];
-#ifdef SG_DEBUG
- fprintf(stderr, "number of sectors=%d, sector size=%d\n",
- *num_sect, *sect_sz);
-#endif
- return 0;
-}
-
-/* 0 -> ok, 1 -> short read, -1 -> error */
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
- int stop_after_write = 0;
-
- rep->qstate = QS_IN_STARTED;
- if (rep->debug > 8)
- fprintf(stderr, "normal_in_operation: start blk=%d num_blks=%d\n",
- rep->blk, rep->num_blks);
- while (((res = read(rep->infd, rep->buffp,
- blocks * rep->bs)) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- fprintf(stderr, "sgq_dd: reading, in_blk=%d, errno=%d\n", rep->blk,
- errno);
- return -1;
- }
- if (res < blocks * rep->bs) {
- int o_blocks = blocks;
- stop_after_write = 1;
- blocks = res / rep->bs;
- if ((res % rep->bs) > 0) {
- blocks++;
- clp->in_partial++;
- }
- /* Reverse out + re-apply blocks on clp */
- clp->in_blk -= o_blocks;
- clp->in_count += o_blocks;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- }
- clp->in_done_count -= blocks;
- rep->qstate = QS_IN_FINISHED;
- return stop_after_write;
-}
-
-/* 0 -> ok, -1 -> error */
-int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
-
- rep->qstate = QS_OUT_STARTED;
- if (rep->debug > 8)
- fprintf(stderr, "normal_out_operation: start blk=%d num_blks=%d\n",
- rep->blk, rep->num_blks);
- while (((res = write(rep->outfd, rep->buffp,
- rep->num_blks * rep->bs)) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- fprintf(stderr, "sgq_dd: output, out_blk=%d, errno=%d\n", rep->blk,
- errno);
- return -1;
- }
- if (res < blocks * rep->bs) {
- blocks = res / rep->bs;
- if ((res % rep->bs) > 0) {
- blocks++;
- clp->out_partial++;
- }
- rep->num_blks = blocks;
- }
- clp->out_done_count -= blocks;
- rep->qstate = QS_IDLE;
- return 0;
-}
-
-/* Returns 1 for retryable, 0 for ok, -ve for error */
-int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
-
- rep->qstate = QS_IN_FINISHED;
- res = sg_finish_io(rep->wr, rep);
- if (res < 0) {
- if (clp->coe) {
- memset(rep->buffp, 0, rep->num_blks * rep->bs);
- fprintf(stderr, ">> substituted zeros for in blk=%d for "
- "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
- res = 0;
- }
- else {
- fprintf(stderr, "error finishing sg in command\n");
- return res;
- }
- }
- if (0 == res) { /* looks good, going to return */
- if (rep->dio_incomplete || rep->resid) {
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- }
- clp->in_done_count -= rep->num_blks;
- }
- return res;
-}
-
-/* Returns 1 for retryable, 0 for ok, -ve for error */
-int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
-
- rep->qstate = QS_IDLE;
- res = sg_finish_io(rep->wr, rep);
- if (res < 0) {
- if (clp->coe) {
- fprintf(stderr, ">> ignored error for out blk=%d for "
- "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
- res = 0;
- }
- else {
- fprintf(stderr, "error finishing sg out command\n");
- return res;
- }
- }
- if (0 == res) {
- if (rep->dio_incomplete || rep->resid) {
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- }
- clp->out_done_count -= rep->num_blks;
- }
- return res;
-}
-
-int sg_start_io(Rq_elem * rep)
-{
- sg_io_hdr_t * hp = &rep->io_hdr;
- int res;
-
- rep->qstate = rep->wr ? QS_OUT_STARTED : QS_IN_STARTED;
- memset(rep->cmd, 0, sizeof(rep->cmd));
- rep->cmd[0] = rep->wr ? SGP_WRITE10 : SGP_READ10;
- rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF);
- rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF);
- rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF);
- rep->cmd[5] = (unsigned char)(rep->blk & 0xFF);
- rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff);
- rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff);
- memset(hp, 0, sizeof(sg_io_hdr_t));
- hp->interface_id = 'S';
- hp->cmd_len = sizeof(rep->cmd);
- hp->cmdp = rep->cmd;
- hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- hp->dxfer_len = rep->bs * rep->num_blks;
- hp->dxferp = rep->buffp;
- hp->mx_sb_len = sizeof(rep->sb);
- hp->sbp = rep->sb;
- hp->timeout = DEF_TIMEOUT;
- hp->usr_ptr = rep;
- hp->pack_id = rep->blk;
- if (rep->dio)
- hp->flags |= SG_FLAG_DIRECT_IO;
- if (rep->debug > 8) {
- fprintf(stderr, "sg_start_io: SCSI %s, blk=%d num_blks=%d\n",
- rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks);
- sg_print_command(hp->cmdp);
- fprintf(stderr, "dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n",
- hp->dxfer_direction, hp->dxfer_len, hp->dxferp, hp->cmd_len);
- }
-
- while (((res = write(rep->wr ? rep->outfd : rep->infd, hp,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- return res;
- }
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
-int sg_finish_io(int wr, Rq_elem * rep)
-{
- int res;
- sg_io_hdr_t io_hdr;
- sg_io_hdr_t * hp;
-#if 0
- static int testing = 0; /* thread dubious! */
-#endif
-
- memset(&io_hdr, 0 , sizeof(sg_io_hdr_t));
- /* FORCE_PACK_ID active set only read packet with matching pack_id */
- io_hdr.interface_id = 'S';
- io_hdr.dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- io_hdr.pack_id = rep->blk;
-
- while (((res = read(wr ? rep->outfd : rep->infd, &io_hdr,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- perror("finishing io on sg device, error");
- return -1;
- }
- if (rep != (Rq_elem *)io_hdr.usr_ptr) {
- fprintf(stderr,
- "sg_finish_io: bad usr_ptr, request-response mismatch\n");
- exit(1);
- }
- memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t));
- hp = &rep->io_hdr;
-
- switch (sg_err_category3(hp)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr, "Recovered error on block=%d, num=%d\n",
- rep->blk, rep->num_blks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 1;
- default:
- {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "%s blk=%d",
- rep->wr ? "writing": "reading", rep->blk);
- sg_chk_n_print3(ebuff, hp);
- return -1;
- }
- }
-#if 0
- if (0 == (++testing % 100)) return -1;
-#endif
- if (rep->dio &&
- ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- rep->dio_incomplete = 1; /* count dios done as indirect IO */
- else
- rep->dio_incomplete = 0;
- rep->resid = hp->resid;
- if (rep->debug > 8)
- fprintf(stderr, "sg_finish_io: completed %s\n", wr ? "WRITE" : "READ");
- return 0;
-}
-
-/* Returns scsi_type or -1 for error */
-int sg_prepare(int fd, int sz)
-{
- int res, t;
- struct sg_scsi_id info;
-
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- fprintf(stderr, "sgq_dd: sg driver prior to 3.x.y\n");
- return -1;
- }
- res = ioctl(fd, SG_SET_RESERVED_SIZE, &sz);
- if (res < 0)
- perror("sgq_dd: SG_SET_RESERVED_SIZE error");
-#if 0
- t = 1;
- res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
- if (res < 0)
- perror("sgq_dd: SG_SET_FORCE_PACK_ID error");
-#endif
- res = ioctl(fd, SG_GET_SCSI_ID, &info);
- if (res < 0) {
- perror("sgq_dd: SG_SET_SCSI_ID error");
- return -1;
- }
- else
- return info.scsi_type;
-}
-
-/* Return 0 for ok, anything else for errors */
-int prepare_rq_elems(Rq_coll * clp, const char * inf, const char * outf)
-{
- int k;
- Rq_elem * rep;
- size_t psz;
- char ebuff[EBUFF_SZ];
- int sz = clp->bpt * clp->bs;
- int scsi_type;
-
- clp->req_arr = malloc(sizeof(Rq_elem) * clp->num_rq_elems);
- if (NULL == clp->req_arr)
- return 1;
- for (k = 0; k < clp->num_rq_elems; ++k) {
- rep = &clp->req_arr[k];
- memset(rep, 0, sizeof(Rq_elem));
- psz = getpagesize();
- if (NULL == (rep->alloc_bp = malloc(sz + psz)))
- return 1;
- rep->buffp = (unsigned char *)
- (((unsigned long)rep->alloc_bp + psz - 1) & (~(psz - 1)));
- rep->qstate = QS_IDLE;
- rep->bs = clp->bs;
- rep->dio = clp->dio;
- rep->debug = clp->debug;
- rep->out_scsi_type = clp->out_scsi_type;
- if (FT_SG == clp->in_type) {
- if (0 == k)
- rep->infd = clp->infd;
- else {
- if ((rep->infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg reading", inf);
- perror(ebuff);
- return 1;
- }
- }
- in_pollfd_arr[k].fd = rep->infd;
- in_pollfd_arr[k].events = POLLIN;
- if ((scsi_type = sg_prepare(rep->infd, sz)) < 0)
- return 1;
- if (0 == k)
- clp->in_scsi_type = scsi_type;
- rep->in_scsi_type = clp->in_scsi_type;
- }
- else
- rep->infd = clp->infd;
-
- if (FT_SG == clp->out_type) {
- if (0 == k)
- rep->outfd = clp->outfd;
- else {
- if ((rep->outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgq_dd: could not open %s for sg writing", outf);
- perror(ebuff);
- return 1;
- }
- }
- out_pollfd_arr[k].fd = rep->outfd;
- out_pollfd_arr[k].events = POLLIN;
- if ((scsi_type = sg_prepare(rep->outfd, sz)) < 0)
- return 1;
- if (0 == k)
- clp->out_scsi_type = scsi_type;
- rep->out_scsi_type = clp->out_scsi_type;
- }
- else
- rep->outfd = clp->outfd;
- }
- return 0;
-}
-
-/* Returns a "QS" code and req index, or QS_IDLE and position of first idle
- (-1 if no idle position). Returns -1 on poll error. */
-int decider(Rq_coll * clp, int first_xfer, int * req_indexp)
-{
- int k, res;
- Rq_elem * rep;
- int first_idle_index = -1;
- int lowest_blk_index = -1;
- int times;
- int try_poll = 0;
- int lowest_blk = INT_MAX;
-
- times = first_xfer ? 1 : clp->num_rq_elems;
- for (k = 0; k < times; ++k) {
- rep = &clp->req_arr[k];
- if ((QS_IN_STARTED == rep->qstate) ||
- (QS_OUT_STARTED == rep->qstate))
- try_poll = 1;
- else if ((QS_IN_FINISHED == rep->qstate) && (rep->blk < lowest_blk)) {
- lowest_blk = rep->blk;
- lowest_blk_index = k;
- }
- else if ((QS_IDLE == rep->qstate) && (first_idle_index < 0))
- first_idle_index = k;
- }
- if (try_poll) {
- res = do_poll(clp, 0, req_indexp);
- if (0 != res)
- return res;
- }
-
- if (lowest_blk_index >= 0) {
- if (req_indexp)
- *req_indexp = lowest_blk_index;
- return QS_IN_FINISHED;
- }
- if (req_indexp)
- *req_indexp = first_idle_index;
- return QS_IDLE;
-}
-
-
-int main(int argc, char * argv[])
-{
- 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;
- 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';
- if (argc < 2) {
- usage();
- return 1;
- }
-
- 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 (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))
- rcoll.debug = sg_get_num(buf);
- else if (0 == strcmp(key,"time"))
- do_time = sg_get_num(buf);
- else if (0 == strncmp(key, "--vers", 6)) {
- fprintf(stderr, "sgq_dd for sg version 3 driver: %s\n",
- version_str);
- return 0;
- }
- else {
- fprintf(stderr, "Unrecognized argument '%s'\n", key);
- 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) {
- llse_loff_t offset = skip;
-
- offset *= rcoll.bs; /* could exceed 32 here! */
- if (llse_llseek(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) {
- llse_loff_t offset = seek;
-
- offset *= rcoll.bs; /* could exceed 32 bits here! */
- if (llse_llseek(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");
- 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);
- 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 */
- usleep(1000);
- 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;
-}
diff --git a/archive/sgq_old_dd.c b/archive/sgq_old_dd.c
deleted file mode 100644
index 66c149b3..00000000
--- a/archive/sgq_old_dd.c
+++ /dev/null
@@ -1,838 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <poll.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "sg_lib.h"
-#include "sg_linux_inc.h"
-
-/* A utility program for 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. A block size
- ('bs') is assumed to be 512 if not given. This program complains if
- 'ibs' or 'obs' are given with some other value than 'bs'.
- 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.
-
- A non-standard argument "bpt" (blocks per transfer) is added to control
- the maximum number of blocks in each transfer. The default value is 128.
- For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
- in this case) are transferred to or from the sg device in a single SCSI
- command.
-
- This version should compile with Linux sg drivers with version numbers
- >= 30000 . This version uses usleep() for a delay loop.
-
- Version 3.982 20000827
-*/
-
-#define DEF_BLOCK_SIZE 512
-#define DEF_BLOCKS_PER_TRANSFER 128
-
-/* #define SG_DEBUG */
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */
-#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */
-#define RCAP_REPLY_LEN 8
-#define SGQ_MAX_RD_AHEAD 4
-#define SGQ_MAX_WR_AHEAD 4
-#define SGQ_NUM_ELEMS (SGQ_MAX_RD_AHEAD+ SGQ_MAX_WR_AHEAD + 1)
-
-#define SGQ_FREE 0
-#define SGQ_IO_STARTED 1
-#define SGQ_IO_FINISHED 2
-#define SGQ_IO_ERR 3
-#define SGQ_IO_WAIT 4
-
-#define SGQ_CAN_DO_NOTHING 0 /* only temporarily in use */
-#define SGQ_CAN_READ 1
-#define SGQ_CAN_WRITE 2
-#define SGQ_TIMEOUT 4
-
-typedef struct request_element
-{
- struct request_element * nextp;
- int state;
- int wr;
- int blk;
- int num_blks;
- unsigned char * buffp;
- unsigned char * alloc_bp;
- sg_io_hdr_t io_hdr;
- unsigned char cmd[S_RW_LEN];
- unsigned char sb[SENSE_BUFF_LEN];
- int result;
- int stop_after_wr;
-} Rq_elem;
-
-typedef struct request_collection
-{
- int infd;
- int in_is_sg;
- int in_blk; /* next block address to read */
- int in_count; /* blocks remaining for next read */
- int in_done_count; /* count of completed in blocks */
- int in_partial;
- int outfd;
- int out_is_sg;
- int lowest_seek;
- int out_blk; /* next block address to write */
- int out_count; /* blocks remaining for next write */
- int out_done_count; /* count of completed out blocks */
- int out_partial;
- int bs;
- int bpt;
- int dio;
- int dio_incomplete;
- int sum_of_resids;
- int debug;
- Rq_elem * rd_posp;
- Rq_elem * wr_posp;
- Rq_elem elem[SGQ_NUM_ELEMS];
-} Rq_coll;
-
-
-void usage()
-{
- printf("Usage: "
- "sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n"
- " [bs=<num>] [bpt=<num>] [count=<n>]"
- " [dio=<n>] [deb=<n>]\n"
- " either 'if' or 'of' must be a scsi generic device\n"
- " 'bpt' is blocks_per_transfer (default is 128)\n"
- " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"
- " 'deb' is debug, 1->output some, 0->no debug (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 = RCAP_REPLY_LEN;
- 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];
-#ifdef SG_DEBUG
- printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz);
-#endif
- return 0;
-}
-
-/* -ve -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM) */
-int sg_start_io(Rq_coll * clp, Rq_elem * rep)
-{
- sg_io_hdr_t * hp = &rep->io_hdr;
- int res;
-#if 0
- static int testing = 0;
-#endif
-
- memset(rep->cmd, 0, sizeof(rep->cmd));
- rep->cmd[0] = rep->wr ? 0x2a : 0x28;
- rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF);
- rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF);
- rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF);
- rep->cmd[5] = (unsigned char)(rep->blk & 0xFF);
- rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff);
- rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff);
- memset(hp, 0, sizeof(sg_io_hdr_t));
- hp->interface_id = 'S';
- hp->cmd_len = sizeof(rep->cmd);
- hp->cmdp = rep->cmd;
- hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- hp->dxfer_len = clp->bs * rep->num_blks;
- hp->dxferp = rep->buffp;
- hp->mx_sb_len = sizeof(rep->sb);
- hp->sbp = rep->sb;
- hp->timeout = DEF_TIMEOUT;
- hp->usr_ptr = rep;
- hp->pack_id = rep->blk;
- if (clp->dio)
- hp->flags |= SG_FLAG_DIRECT_IO;
-#ifdef SG_DEBUG
- printf("sg_start_io: SCSI %s, blk=%d num_blks=%d\n",
- rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks);
- sg_print_command(hp->cmdp);
- printf("dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n", hp->dxfer_direction,
- hp->dxfer_len, hp->dxferp, hp->cmd_len);
-#endif
-
-#if 0
- testing++;
- if (0 == (testing % 10)) {
- rep->state = SGQ_IO_WAIT; /* busy so wait */
- return 0;
- }
-#endif
-
- while (((res = write(rep->wr ? clp->outfd : clp->infd, hp,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- if ((EDOM == errno) || (EAGAIN == errno)) {
- rep->state = SGQ_IO_WAIT; /* busy so wait */
- return 0;
- }
- perror("starting io on sg device, error");
- rep->state = SGQ_IO_ERR;
- return res;
- }
- rep->state = SGQ_IO_STARTED;
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
-int sg_finish_io(Rq_coll * clp, int wr, Rq_elem ** repp)
-{
- int res;
- sg_io_hdr_t io_hdr;
- sg_io_hdr_t * hp;
- Rq_elem * rep;
-
- memset(&io_hdr, 0 , sizeof(sg_io_hdr_t));
- while (((res = read(wr ? clp->outfd : clp->infd, &io_hdr,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- rep = (Rq_elem *)io_hdr.usr_ptr;
- if (res < 0) {
- perror("finishing io on sg device, error");
- rep->state = SGQ_IO_ERR;
- return -1;
- }
- if (! (rep && (SGQ_IO_STARTED == rep->state))) {
- printf("sg_finish_io: bad usr_ptr\n");
- rep->state = SGQ_IO_ERR;
- return -1;
- }
- memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t));
- hp = &rep->io_hdr;
- if (repp)
- *repp = rep;
-
- switch (sg_err_category3(hp)) {
- case SG_LIB_CAT_CLEAN:
- break;
- case SG_LIB_CAT_RECOVERED:
- printf("Recovered error on block=%d, num=%d\n",
- rep->blk, rep->num_blks);
- break;
- case SG_LIB_CAT_UNIT_ATTENTION:
- return 1;
- default:
- sg_chk_n_print3(rep->wr ? "writing": "reading", hp);
- rep->state = SGQ_IO_ERR;
- return -1;
- }
- if (clp->dio &&
- ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- ++clp->dio_incomplete; /* count dios done as indirect IO */
- clp->sum_of_resids += hp->resid;
- rep->state = SGQ_IO_FINISHED;
-#ifdef SG_DEBUG
- printf("sg_finish_io: %s ", wr ? "writing" : "reading");
- printf(" SGQ_IO_FINISHED elem idx=%d\n", rep - clp->elem);
-#endif
- return 0;
-}
-
-int sz_reserve(int fd, int bs, int bpt)
-{
- int res, t;
-
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- printf("sgq_dd: sg driver prior to 3.x.y\n");
- return 1;
- }
- res = 0;
- t = bs * bpt;
- res = ioctl(fd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror("sgq_dd: SG_SET_RESERVED_SIZE error");
- return 0;
-}
-
-void init_elems(Rq_coll * clp)
-{
- Rq_elem * rep;
- int k;
- int off = 0;
- int sz = clp->bpt * clp->bs;
-
- if (clp->dio) {
- off = getpagesize();
- sz += off;
- }
- clp->wr_posp = &clp->elem[0]; /* making ring buffer */
- clp->rd_posp = clp->wr_posp;
- for (k = 0; k < SGQ_NUM_ELEMS - 1; ++k)
- clp->elem[k].nextp = &clp->elem[k + 1];
- clp->elem[SGQ_NUM_ELEMS - 1].nextp = &clp->elem[0];
- for (k = 0; k < SGQ_NUM_ELEMS; ++k) {
- rep = &clp->elem[k];
- rep->state = SGQ_FREE;
- if (NULL == (rep->alloc_bp = malloc(sz))) {
- printf("out of memory creating user buffers\n");
- exit(1);
- }
- else
- rep->buffp = rep->alloc_bp + off;
- }
-}
-
-int start_read(Rq_coll * clp)
-{
- int blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count;
- Rq_elem * rep = clp->rd_posp;
- int buf_sz, res;
- char ebuff[256];
-
-#ifdef SG_DEBUG
- printf("start_read, elem idx=%d\n", rep - clp->elem);
-#endif
- rep->wr = 0;
- rep->blk = clp->in_blk;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- if (clp->in_is_sg) {
- res = sg_start_io(clp, rep);
- if (1 == res) { /* ENOMEM, find what's available+try that */
- if ((res = ioctl(clp->infd, SG_GET_RESERVED_SIZE, &buf_sz)) < 0) {
- perror("RESERVED_SIZE ioctls failed");
- return res;
- }
- clp->bpt = (buf_sz + clp->bs - 1) / clp->bs;
- printf("Reducing blocks per transfer to %d\n", clp->bpt);
- if (clp->bpt < 1)
- return -ENOMEM;
- res = sg_start_io(clp, rep);
- if (1 == res)
- res = -ENOMEM;
- }
- else if (res < 0) {
- printf("sgq_dd inputting from sg failed, blk=%d\n", rep->blk);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- }
- else {
- rep->state = SGQ_IO_STARTED;
- while (((res = read(clp->infd, rep->buffp, blocks * clp->bs)) < 0) &&
- (EINTR == errno))
- ;
- if (res < 0) {
- sprintf(ebuff, "sgq_dd: reading, in_blk=%d ", rep->blk);
- perror(ebuff);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- if (res < blocks * clp->bs) {
- int o_blocks = blocks;
- rep->stop_after_wr = 1;
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->in_partial++;
- }
- /* Reverse out + re-apply blocks on clp */
- clp->in_blk -= o_blocks;
- clp->in_count += o_blocks;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- }
- clp->in_done_count -= blocks;
- rep->state = SGQ_IO_FINISHED;
- }
- clp->rd_posp = rep->nextp;
- return blocks;
-}
-
-int start_write(Rq_coll * clp)
-{
- Rq_elem * rep = clp->wr_posp;
- int res, blocks;
- char ebuff[256];
-
- while ((0 != rep->wr) || (SGQ_IO_FINISHED != rep->state)) {
- rep = rep->nextp;
- if (rep == clp->rd_posp)
- return -1;
- }
-#ifdef SG_DEBUG
- printf("start_write, elem idx=%d\n", rep - clp->elem);
-#endif
- rep->wr = 1;
- blocks = rep->num_blks;
- rep->blk = clp->out_blk;
- clp->out_blk += blocks;
- clp->out_count -= blocks;
- if (clp->out_is_sg) {
- res = sg_start_io(clp, rep);
- if (1 == res) /* ENOMEM, give up */
- return -ENOMEM;
- else if (res < 0) {
- printf("sgq_dd output to sg failed, blk=%d\n", rep->blk);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- }
- else {
- rep->state = SGQ_IO_STARTED;
- while (((res = write(clp->outfd, rep->buffp,
- rep->num_blks * clp->bs)) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- sprintf(ebuff, "sgq_dd: output, out_blk=%d ", rep->blk);
- perror(ebuff);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->out_partial++;
- }
- rep->num_blks = blocks;
- }
- rep->state = SGQ_IO_FINISHED;
- }
- return blocks;
-}
-
-int do_poll(int fd)
-{
- struct pollfd a_pollfd = {0, POLLIN | POLLOUT, 0};
-
- a_pollfd.fd = fd;
- if (poll(&a_pollfd, 1, 0) < 0) {
- perror("poll error");
- return 0;
- }
- /* printf("do_poll: revents=0x%x\n", (int)a_pollfd.revents); */
- return (a_pollfd.revents & POLLIN) ? 1 : 0;
-}
-
-int can_read_write(Rq_coll * clp)
-{
- Rq_elem * rep = NULL;
- int res = 0;
- int reading = 0;
- int writing = 0;
- int writeable = 0;
- int rd_waiting = 0;
- int wr_waiting = 0;
- int sg_finished = 0;
-
- /* if write completion pending, then complete it + start read */
- if (clp->out_is_sg) {
- while ((res = do_poll(clp->outfd))) {
- if (res < 0)
- return res;
- res = sg_finish_io(clp, 1, &rep);
- if (res < 0)
- return res;
- else if (1 == res) {
- res = sg_start_io(clp, rep);
- if (0 != res)
- return -1; /* give up if any problems with retry */
- }
- else
- sg_finished++;
- }
- while ((rep = clp->wr_posp) && (SGQ_IO_FINISHED == rep->state) &&
- (1 == rep->wr) && (rep != clp->rd_posp)) {
- rep->state = SGQ_FREE;
- clp->out_done_count -= rep->num_blks;
- clp->wr_posp = rep->nextp;
- if (rep->stop_after_wr)
- return -1;
- }
- }
- else if ((rep = clp->wr_posp) && (1 == rep->wr) &&
- (SGQ_IO_FINISHED == rep->state)) {
- rep->state = SGQ_FREE;
- clp->out_done_count -= rep->num_blks;
- clp->wr_posp = rep->nextp;
- if (rep->stop_after_wr)
- return -1;
- }
-
- /* if read completion pending, then complete it + start maybe write */
- if (clp->in_is_sg) {
- while ((res = do_poll(clp->infd))) {
- if (res < 0)
- return res;
- res = sg_finish_io(clp, 0, &rep);
- if (res < 0)
- return res;
- if (1 == res) {
- res = sg_start_io(clp, rep);
- if (0 != res)
- return -1; /* give up if any problems with retry */
- }
- else {
- sg_finished++;
- clp->in_done_count -= rep->num_blks;
- }
- }
- }
-
- for (rep = clp->wr_posp, res = 1;
- rep != clp->rd_posp; rep = rep->nextp) {
- if (SGQ_IO_STARTED == rep->state) {
- if (rep->wr)
- ++writing;
- else {
- res = 0;
- ++reading;
- }
- }
- else if ((0 == rep->wr) && (SGQ_IO_FINISHED == rep->state)) {
- if (res)
- writeable = 1;
- }
- else if (SGQ_IO_WAIT == rep->state) {
- res = 0;
- if (rep->wr)
- ++wr_waiting;
- else
- ++rd_waiting;
- }
- else
- res = 0;
- }
- if (clp->debug) {
- if ((clp->debug >= 9) || wr_waiting || rd_waiting)
- printf("%d/%d (nwb/nrb): read=%d/%d (do/wt) "
- "write=%d/%d (do/wt) writeable=%d sg_fin=%d\n",
- clp->out_blk, clp->in_blk, reading, rd_waiting,
- writing, wr_waiting, writeable, sg_finished);
- }
- if (writeable && (writing < SGQ_MAX_WR_AHEAD) && (clp->out_count > 0))
- return SGQ_CAN_WRITE;
- if ((reading < SGQ_MAX_RD_AHEAD) && (clp->in_count > 0) &&
- (0 == rd_waiting) && (clp->rd_posp->nextp != clp->wr_posp))
- return SGQ_CAN_READ;
-
- if (clp->out_done_count <= 0)
- return SGQ_CAN_DO_NOTHING;
-
- usleep(3000); /* hang about for 10 milliseconds */
- /* Now check the _whole_ buffer for pending requests */
- for (rep = clp->rd_posp->nextp; rep != clp->rd_posp; rep = rep->nextp) {
- if (SGQ_IO_WAIT == rep->state) {
- res = sg_start_io(clp, rep);
- if (res < 0)
- return res;
- if (res > 0)
- return -1;
- break;
- }
- }
- return SGQ_CAN_DO_NOTHING;
-}
-
-
-int main(int argc, char * argv[])
-{
- int skip = 0;
- int seek = 0;
- int ibs = 0;
- int obs = 0;
- int count = -1;
- char str[512];
- char * key;
- char * buf;
- char inf[512];
- char outf[512];
- int res, k;
- int in_num_sect = 0;
- int out_num_sect = 0;
- int in_sect_sz, out_sect_sz, crw;
- char ebuff[256];
- Rq_coll rcoll;
-
- memset(&rcoll, 0, sizeof(Rq_coll));
- rcoll.bpt = DEF_BLOCKS_PER_TRANSFER;
- 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"))
- 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"))
- count = sg_get_num(buf);
- else if (0 == strcmp(key,"dio"))
- rcoll.dio = sg_get_num(buf);
- else if (0 == strcmp(key,"deb"))
- rcoll.debug = sg_get_num(buf);
- else {
- printf("Unrecognized argument '%s'\n", key);
- usage();
- return 1;
- }
- }
- if (rcoll.bs <= 0) {
- rcoll.bs = DEF_BLOCK_SIZE;
- printf("Assume default 'bs' (block size) of %d bytes\n", rcoll.bs);
- }
- if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) {
- printf("If 'ibs' or 'obs' given must be same as 'bs'\n");
- usage();
- return 1;
- }
- if ((skip < 0) || (seek < 0)) {
- printf("skip and seek cannot be negative\n");
- return 1;
- }
-#ifdef SG_DEBUG
- printf("sgq_dd: if=%s skip=%d of=%s seek=%d count=%d\n",
- inf, skip, outf, seek, count);
-#endif
- rcoll.infd = STDIN_FILENO;
- rcoll.outfd = STDOUT_FILENO;
- if (inf[0] && ('-' != inf[0])) {
- if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
- sprintf(ebuff, "sgq_dd: could not open %s for reading", inf);
- perror(ebuff);
- return 1;
- }
- if (ioctl(rcoll.infd, SG_GET_TIMEOUT, 0) < 0) {
- rcoll.in_is_sg = 0;
- if (skip > 0) {
- off_t offset = skip;
-
- offset *= rcoll.bs; /* could overflow here! */
- if (lseek(rcoll.infd, offset, SEEK_SET) < 0) {
- sprintf(ebuff,
- "sgq_dd: couldn't skip to required position on %s", inf);
- perror(ebuff);
- return 1;
- }
- }
- }
- else { /* looks like sg device so close then re-open it RW */
- close(rcoll.infd);
- if ((rcoll.infd = open(inf, O_RDWR | O_NONBLOCK)) < 0) {
- printf("If %s is a sg device, need read+write permissions,"
- " even to read it!\n", inf);
- return 1;
- }
- rcoll.in_is_sg = 1;
- if (sz_reserve(rcoll.infd, rcoll.bs, rcoll.bpt))
- return 1;
- }
- }
- if (outf[0] && ('-' != outf[0])) {
- if ((rcoll.outfd = open(outf, O_RDWR | O_NONBLOCK)) >= 0) {
- if (ioctl(rcoll.outfd, SG_GET_TIMEOUT, 0) < 0) {
- /* not a scsi generic device so now try and open RDONLY */
- close(rcoll.outfd);
- }
- else {
- rcoll.out_is_sg = 1;
- if (sz_reserve(rcoll.outfd, rcoll.bs, rcoll.bpt))
- return 1;
- }
- }
- if (! rcoll.out_is_sg) {
- if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
- sprintf(ebuff,
- "sgq_dd: could not open %s for writing", outf);
- perror(ebuff);
- return 1;
- }
- else if (seek > 0) {
- off_t offset = seek;
-
- offset *= rcoll.bs; /* could overflow here! */
- if (lseek(rcoll.outfd, offset, SEEK_SET) < 0) {
- sprintf(ebuff,
- "sgq_dd: couldn't seek to required position on %s", outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
- printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n");
- return 1;
- }
- if (! (rcoll.in_is_sg || rcoll.out_is_sg)) {
- printf("Either 'if' or 'of' must be a scsi generic device\n");
- return 1;
- }
- if (0 == count)
- return 0;
- else if (count < 0) {
- if (rcoll.in_is_sg) {
- res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
- if (2 == res) {
- printf("Unit attention, media changed(in), try again\n");
- res = read_capacity(rcoll.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 (in_num_sect > skip)
- in_num_sect -= skip;
- }
- }
- if (rcoll.out_is_sg) {
- res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
- if (2 == res) {
- printf("Unit attention, media changed(out), try again\n");
- res = read_capacity(rcoll.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;
- }
- }
-#ifdef SG_DEBUG
- printf("Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- count, in_num_sect, out_num_sect);
-#endif
- 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;
- }
-
-#ifdef SG_DEBUG
- printf("Start of loop, count=%d, bpt=%d\n", count, rcoll.bpt);
-#endif
-
- rcoll.in_count = count;
- rcoll.in_done_count = count;
- rcoll.in_blk = skip;
- rcoll.out_count = count;
- rcoll.out_done_count = count;
- rcoll.out_blk = seek;
- init_elems(&rcoll);
-
-/* vvvvvvvvvvvvvvvvv Main Loop vvvvvvvvvvvvvvvvvvvvvvvv */
- while (rcoll.out_done_count > 0) {
- crw = can_read_write(&rcoll);
- if (crw < 0)
- break;
- if (SGQ_CAN_READ & crw) {
- res = start_read(&rcoll);
- if (res <= 0) {
- printf("start_read: res=%d\n", res);
- break;
- }
- }
- if (SGQ_CAN_WRITE & crw) {
- res = start_write(&rcoll);
- if (res <= 0) {
- printf("start_write: res=%d\n", res);
- break;
- }
- }
- }
-
- if (STDIN_FILENO != rcoll.infd)
- close(rcoll.infd);
- if (STDOUT_FILENO != rcoll.outfd)
- close(rcoll.outfd);
- if (0 != rcoll.out_count) {
- printf("Some error occurred, remaining blocks=%d\n", rcoll.out_count);
- return 1;
- }
- printf("%d+%d records in\n", count - rcoll.in_done_count,
- rcoll.in_partial);
- printf("%d+%d records out\n", count - rcoll.out_done_count,
- rcoll.out_partial);
- if (rcoll.dio_incomplete)
- printf(">> Direct IO requested but incomplete %d times\n",
- rcoll.dio_incomplete);
- if (rcoll.sum_of_resids)
- printf(">> Non-zero sum of residual counts=%d\n",
- rcoll.sum_of_resids);
- return 0;
-}
diff --git a/archive/sgs_dd.c b/archive/sgs_dd.c
deleted file mode 100644
index fa34d7b1..00000000
--- a/archive/sgs_dd.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/* We need F_SETSIG, (signal redirect), so following define */
-#define _GNU_SOURCE 1
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <poll.h>
-#include <signal.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 the 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. A block size
- ('bs') is assumed to be 512 if not given. This program complains if
- 'ibs' or 'obs' are given with some other value than 'bs'.
- 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.
-
- A non-standard argument "bpt" (blocks per transfer) is added to control
- the maximum number of blocks in each transfer. The default value is 128.
- For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
- in this case) are transferred to or from the sg device in a single SCSI
- command.
-
- 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 . Also this version tries to use real time signals.
-
- Version 3.99 20020126
-
-
-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 DEF_BLOCK_SIZE 512
-#define DEF_BLOCKS_PER_TRANSFER 128
-
-/* #define SG_DEBUG */
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */
-#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */
-#define SGQ_MAX_RD_AHEAD 4
-#define SGQ_MAX_WR_AHEAD 4
-#define SGQ_NUM_ELEMS (SGQ_MAX_RD_AHEAD+ SGQ_MAX_WR_AHEAD + 1)
-
-#define SGQ_FREE 0
-#define SGQ_IO_STARTED 1
-#define SGQ_IO_FINISHED 2
-#define SGQ_IO_ERR 3
-#define SGQ_IO_WAIT 4
-
-#define SGQ_CAN_DO_NOTHING 0 /* only temporarily in use */
-#define SGQ_CAN_READ 1
-#define SGQ_CAN_WRITE 2
-#define SGQ_TIMEOUT 4
-
-
-#define STR_SZ 1024
-#define INOUTF_SZ 512
-#define EBUFF_SZ 512
-
-
-typedef struct request_element
-{
- struct request_element * nextp;
- int state;
- int wr;
- int blk;
- int num_blks;
- unsigned char * buffp;
- sg_io_hdr_t io_hdr;
- unsigned char cmd[S_RW_LEN];
- unsigned char sb[SENSE_BUFF_LEN];
- int result;
- int stop_after_wr;
-} Rq_elem;
-
-typedef struct request_collection
-{
- int infd;
- int in_is_sg;
- int in_blk; /* most recent read */
- int in_count; /* most recent read */
- int in_done_count; /* count of completed in blocks */
- int in_partial;
- int outfd;
- int out_is_sg;
- int lowest_seek;
- int out_blk; /* most recent write */
- int out_count; /* most recent write */
- int out_done_count; /* count of completed out blocks */
- int out_partial;
- int bs;
- int bpt;
- int dio;
- int dio_incomplete;
- int sum_of_resids;
- int debug;
- sigset_t blocked_sigs;
- int sigs_waiting;
- Rq_elem * rd_posp;
- Rq_elem * wr_posp;
- Rq_elem elem[SGQ_NUM_ELEMS];
-} Rq_coll;
-
-
-void usage()
-{
- printf("Usage: "
- "sgs_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n"
- " [bs=<num>] [bpt=<num>] [count=<n>]"
- " [dio=<n>] [deb=<n>]\n"
- " either 'if' or 'of' must be a scsi generic device\n"
- " 'bpt' is blocks_per_transfer (default is 128)\n"
- " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"
- " 'deb' is debug, 1->output some, 0->no debug (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];
-#ifdef SG_DEBUG
- printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz);
-#endif
- return 0;
-}
-
-/* -ve -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM) */
-int sg_start_io(Rq_coll * clp, Rq_elem * rep)
-{
- sg_io_hdr_t * hp = &rep->io_hdr;
- int res;
-
- memset(rep->cmd, 0, sizeof(rep->cmd));
- rep->cmd[0] = rep->wr ? 0x2a : 0x28;
- rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF);
- rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF);
- rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF);
- rep->cmd[5] = (unsigned char)(rep->blk & 0xFF);
- rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff);
- rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff);
- memset(hp, 0, sizeof(sg_io_hdr_t));
- hp->interface_id = 'S';
- hp->cmd_len = sizeof(rep->cmd);
- hp->cmdp = rep->cmd;
- hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- hp->dxfer_len = clp->bs * rep->num_blks;
- hp->dxferp = rep->buffp;
- hp->mx_sb_len = sizeof(rep->sb);
- hp->sbp = rep->sb;
- hp->timeout = DEF_TIMEOUT;
- hp->usr_ptr = rep;
- hp->pack_id = rep->blk;
- if (clp->dio)
- hp->flags |= SG_FLAG_DIRECT_IO;
-#ifdef SG_DEBUG
- printf("sg_start_io: SCSI %s, blk=%d num_blks=%d\n",
- rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks);
- sg_print_command(hp->cmdp);
- printf("dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n", hp->dxfer_direction,
- hp->dxfer_len, hp->dxferp, hp->cmd_len);
-#endif
-
- while (((res = write(rep->wr ? clp->outfd : clp->infd, hp,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- if (ENOMEM == errno)
- return 1;
- if ((EDOM == errno) || (EAGAIN == errno)) {
- rep->state = SGQ_IO_WAIT; /* busy so wait */
- return 0;
- }
- perror("starting io on sg device, error");
- rep->state = SGQ_IO_ERR;
- return res;
- }
- rep->state = SGQ_IO_STARTED;
- clp->sigs_waiting++;
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
-int sg_finish_io(Rq_coll * clp, int wr, Rq_elem ** repp)
-{
- int res;
- sg_io_hdr_t io_hdr;
- sg_io_hdr_t * hp;
- Rq_elem * rep;
-
- memset(&io_hdr, 0 , sizeof(sg_io_hdr_t));
- while (((res = read(wr ? clp->outfd : clp->infd, &io_hdr,
- sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno))
- ;
- rep = (Rq_elem *)io_hdr.usr_ptr;
- if (res < 0) {
- perror("finishing io on sg device, error");
- rep->state = SGQ_IO_ERR;
- return -1;
- }
- if (! (rep && (SGQ_IO_STARTED == rep->state))) {
- printf("sg_finish_io: bad usr_ptr\n");
- rep->state = SGQ_IO_ERR;
- return -1;
- }
- memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t));
- hp = &rep->io_hdr;
- if (repp)
- *repp = rep;
-
- switch (sg_err_category3(hp)) {
- case SG_LIB_CAT_CLEAN:
- break;
- case SG_LIB_CAT_RECOVERED:
- printf("Recovered error on block=%d, num=%d\n",
- rep->blk, rep->num_blks);
- break;
- case SG_LIB_CAT_UNIT_ATTENTION:
- return 1;
- default:
- sg_chk_n_print3(rep->wr ? "writing": "reading", hp);
- rep->state = SGQ_IO_ERR;
- return -1;
- }
- if (clp->dio &&
- ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
- ++clp->dio_incomplete; /* count dios done as indirect IO */
- clp->sum_of_resids += hp->resid;
- rep->state = SGQ_IO_FINISHED;
-#ifdef SG_DEBUG
- printf("sg_finish_io: %s ", wr ? "writing" : "reading");
- printf(" SGQ_IO_FINISHED elem idx=%d\n", rep - clp->elem);
-#endif
- return 0;
-}
-
-int sz_reserve(int fd, int bs, int bpt)
-{
- int res, t, flags;
-
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- printf("sgs_dd: sg driver prior to 3.x.y\n");
- return 1;
- }
- res = 0;
- t = bs * bpt;
- res = ioctl(fd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror("sgs_dd: SG_SET_RESERVED_SIZE error");
- if (-1 == fcntl(fd, F_SETOWN, getpid())) {
- perror("fcntl(,F_SETOWN,)");
- return 1;
- }
- flags = fcntl(fd, F_GETFL, 0);
- if (-1 == fcntl(fd, F_SETFL, flags | O_ASYNC)) {
- perror("fcntl(,F_SETFL,)");
- return 1;
- }
- fcntl(fd, F_SETSIG, SIGRTMIN + 1);
- return 0;
-}
-
-void init_elems(Rq_coll * clp)
-{
- Rq_elem * rep;
- int k;
-
- clp->wr_posp = &clp->elem[0]; /* making ring buffer */
- clp->rd_posp = clp->wr_posp;
- for (k = 0; k < SGQ_NUM_ELEMS - 1; ++k)
- clp->elem[k].nextp = &clp->elem[k + 1];
- clp->elem[SGQ_NUM_ELEMS - 1].nextp = &clp->elem[0];
- for (k = 0; k < SGQ_NUM_ELEMS; ++k) {
- rep = &clp->elem[k];
- rep->state = SGQ_FREE;
- if (NULL == (rep->buffp = malloc(clp->bpt * clp->bs)))
- printf("out of memory creating user buffers\n");
- }
-}
-
-int start_read(Rq_coll * clp)
-{
- int blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count;
- Rq_elem * rep = clp->rd_posp;
- int buf_sz, res;
- char ebuff[EBUFF_SZ];
-
-#ifdef SG_DEBUG
- printf("start_read, elem idx=%d\n", rep - clp->elem);
-#endif
- rep->wr = 0;
- rep->blk = clp->in_blk;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- if (clp->in_is_sg) {
- res = sg_start_io(clp, rep);
- if (1 == res) { /* ENOMEM, find what's available+try that */
- if ((res = ioctl(clp->infd, SG_GET_RESERVED_SIZE, &buf_sz)) < 0) {
- perror("RESERVED_SIZE ioctls failed");
- return res;
- }
- clp->bpt = (buf_sz + clp->bs - 1) / clp->bs;
- printf("Reducing blocks per transfer to %d\n", clp->bpt);
- if (clp->bpt < 1)
- return -ENOMEM;
- res = sg_start_io(clp, rep);
- if (1 == res)
- res = -ENOMEM;
- }
- else if (res < 0) {
- printf("sgs_dd inputting from sg failed, blk=%d\n", rep->blk);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- }
- else {
- rep->state = SGQ_IO_STARTED;
- while (((res = read(clp->infd, rep->buffp, blocks * clp->bs)) < 0) &&
- (EINTR == errno))
- ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "sgs_dd: reading, in_blk=%d ", rep->blk);
- perror(ebuff);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- if (res < blocks * clp->bs) {
- int o_blocks = blocks;
- rep->stop_after_wr = 1;
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->in_partial++;
- }
- /* Reverse out + re-apply blocks on clp */
- clp->in_blk -= o_blocks;
- clp->in_count += o_blocks;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
- }
- clp->in_done_count -= blocks;
- rep->state = SGQ_IO_FINISHED;
- }
- clp->rd_posp = rep->nextp;
- return blocks;
-}
-
-int start_write(Rq_coll * clp)
-{
- Rq_elem * rep = clp->wr_posp;
- int res, blocks;
- char ebuff[EBUFF_SZ];
-
- while ((0 != rep->wr) || (SGQ_IO_FINISHED != rep->state)) {
- rep = rep->nextp;
- if (rep == clp->rd_posp)
- return -1;
- }
-#ifdef SG_DEBUG
- printf("start_write, elem idx=%d\n", rep - clp->elem);
-#endif
- rep->wr = 1;
- blocks = rep->num_blks;
- rep->blk = clp->out_blk;
- clp->out_blk += blocks;
- clp->out_count -= blocks;
- if (clp->out_is_sg) {
- res = sg_start_io(clp, rep);
- if (1 == res) /* ENOMEM, give up */
- return -ENOMEM;
- else if (res < 0) {
- printf("sgs_dd output to sg failed, blk=%d\n", rep->blk);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- }
- else {
- rep->state = SGQ_IO_STARTED;
- while (((res = write(clp->outfd, rep->buffp,
- rep->num_blks * clp->bs)) < 0) && (EINTR == errno))
- ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "sgs_dd: output, out_blk=%d ", rep->blk);
- perror(ebuff);
- rep->state = SGQ_IO_ERR;
- return res;
- }
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->out_partial++;
- }
- rep->num_blks = blocks;
- }
- rep->state = SGQ_IO_FINISHED;
- }
- return blocks;
-}
-
-int do_poll(Rq_coll * clp, int fd)
-{
- struct pollfd a_pollfd = {0, POLLIN | POLLOUT, 0};
- siginfo_t info;
-
- a_pollfd.fd = fd;
- if (poll(&a_pollfd, 1, 0) < 0) {
- perror("poll error");
- return 0;
- }
- /* printf("do_poll: revents=0x%x\n", (int)a_pollfd.revents); */
- if (a_pollfd.revents & POLLIN) {
- if (clp->sigs_waiting) {
- while (sigwaitinfo(&clp->blocked_sigs, &info) < 0) {
- if (EINTR != errno) {
- perror("sigwaitinfo"); /* consume signal */
- return -1;
- }
- }
- if ((SIGRTMIN + 1) == info.si_signo)
- clp->sigs_waiting--;
- if (SIGIO == info.si_signo) {
- printf("SIGIO received, continue\n");
- clp->sigs_waiting = 0;
- }
- else
- return -1;
- }
- return 1;
- }
- else
- return 0;
-}
-
-int can_read_write(Rq_coll * clp)
-{
- Rq_elem * rep = NULL;
- int res = 0;
- int reading = 0;
- int writing = 0;
- int writeable = 0;
- int rd_waiting = 0;
- int wr_waiting = 0;
- int sg_finished = 0;
- siginfo_t info;
-
- /* if write completion pending, then complete it + start read */
- if (clp->out_is_sg) {
- while ((res = do_poll(clp, clp->outfd))) {
- if (res < 0)
- return res;
- res = sg_finish_io(clp, 1, &rep);
- if (res < 0)
- return res;
- else if (1 == res) {
- res = sg_start_io(clp, rep);
- if (0 != res)
- return -1; /* give up if any problems with retry */
- }
- else
- sg_finished++;
- }
- while ((rep = clp->wr_posp) && (SGQ_IO_FINISHED == rep->state) &&
- (1 == rep->wr) && (rep != clp->rd_posp)) {
- rep->state = SGQ_FREE;
- clp->out_done_count -= rep->num_blks;
- clp->wr_posp = rep->nextp;
- if (rep->stop_after_wr)
- return -1;
- }
- }
- else if ((rep = clp->wr_posp) && (1 == rep->wr) &&
- (SGQ_IO_FINISHED == rep->state)) {
- rep->state = SGQ_FREE;
- clp->out_done_count -= rep->num_blks;
- clp->wr_posp = rep->nextp;
- if (rep->stop_after_wr)
- return -1;
- }
-
- /* if read completion pending, then complete it + start maybe write */
- if (clp->in_is_sg) {
- while ((res = do_poll(clp, clp->infd))) {
- if (res < 0)
- return res;
- res = sg_finish_io(clp, 0, &rep);
- if (res < 0)
- return res;
- if (1 == res) {
- res = sg_start_io(clp, rep);
- if (0 != res)
- return -1; /* give up if any problems with retry */
- }
- else {
- sg_finished++;
- clp->in_done_count -= rep->num_blks;
- }
- }
- }
-
- for (rep = clp->wr_posp, res = 1;
- rep != clp->rd_posp; rep = rep->nextp) {
- if (SGQ_IO_STARTED == rep->state) {
- if (rep->wr)
- ++writing;
- else {
- res = 0;
- ++reading;
- }
- }
- else if ((0 == rep->wr) && (SGQ_IO_FINISHED == rep->state)) {
- if (res)
- writeable = 1;
- }
- else if (SGQ_IO_WAIT == rep->state) {
- res = 0;
- if (rep->wr)
- ++wr_waiting;
- else
- ++rd_waiting;
- }
- else
- res = 0;
- }
- if (clp->debug) {
- if ((clp->debug >= 9) || wr_waiting || rd_waiting)
- printf("%d/%d (nwb/nrb): read=%d/%d (do/wt) "
- "write=%d/%d (do/wt) writeable=%d sg_fin=%d\n",
- clp->out_blk, clp->in_blk, reading, rd_waiting,
- writing, wr_waiting, writeable, sg_finished);
- fflush(stdout);
- }
- if (writeable && (writing < SGQ_MAX_WR_AHEAD) && (clp->out_count > 0))
- return SGQ_CAN_WRITE;
- if ((reading < SGQ_MAX_RD_AHEAD) && (clp->in_count > 0) &&
- (0 == rd_waiting) && (clp->rd_posp->nextp != clp->wr_posp))
- return SGQ_CAN_READ;
-
- if (clp->out_done_count <= 0)
- return SGQ_CAN_DO_NOTHING;
-
- /* usleep(10000); */ /* hang about for 10 milliseconds */
- if (clp->sigs_waiting) {
- while (sigwaitinfo(&clp->blocked_sigs, &info) < 0) {
- if (EINTR != errno) {
- perror("sigwaitinfo"); /* consume signal */
- return -1;
- }
- }
- if ((SIGRTMIN + 1) != info.si_signo)
- return -1;
- clp->sigs_waiting--;
- }
- /* Now check the _whole_ buffer for pending requests */
- for (rep = clp->rd_posp->nextp; rep != clp->rd_posp; rep = rep->nextp) {
- if (SGQ_IO_WAIT == rep->state) {
- res = sg_start_io(clp, rep);
- if (res < 0)
- return res;
- if (res > 0)
- return -1;
- break;
- }
- }
- return SGQ_CAN_DO_NOTHING;
-}
-
-
-int main(int argc, char * argv[])
-{
- int skip = 0;
- int seek = 0;
- int ibs = 0;
- int obs = 0;
- int count = -1;
- char str[STR_SZ];
- char * key;
- char * buf;
- char inf[INOUTF_SZ];
- char outf[INOUTF_SZ];
- int res, k;
- int in_num_sect = 0;
- int out_num_sect = 0;
- int in_sect_sz, out_sect_sz, crw;
- char ebuff[EBUFF_SZ];
- Rq_coll rcoll;
-
- memset(&rcoll, 0, sizeof(Rq_coll));
- rcoll.bpt = DEF_BLOCKS_PER_TRANSFER;
- inf[0] = '\0';
- outf[0] = '\0';
- if (argc < 2) {
- usage();
- return 1;
- }
-
- for(k = 1; k < argc; k++) {
- if (argv[k]) {
- strncpy(str, argv[k], STR_SZ);
- str[STR_SZ - 1] = '\0';
- }
- else
- continue;
- for(key = str, buf = key; *buf && *buf != '=';)
- buf++;
- if (*buf)
- *buf++ = '\0';
- 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"))
- count = sg_get_num(buf);
- else if (0 == strcmp(key,"dio"))
- rcoll.dio = sg_get_num(buf);
- else if (0 == strcmp(key,"deb"))
- rcoll.debug = sg_get_num(buf);
- else {
- printf("Unrecognized argument '%s'\n", key);
- usage();
- return 1;
- }
- }
- if (rcoll.bs <= 0) {
- rcoll.bs = DEF_BLOCK_SIZE;
- printf("Assume default 'bs' (block size) of %d bytes\n", rcoll.bs);
- }
- if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) {
- printf("If 'ibs' or 'obs' given must be same as 'bs'\n");
- usage();
- return 1;
- }
- if ((skip < 0) || (seek < 0)) {
- printf("skip and seek cannot be negative\n");
- return 1;
- }
-#ifdef SG_DEBUG
- printf("sgs_dd: if=%s skip=%d of=%s seek=%d count=%d\n",
- inf, skip, outf, seek, count);
-#endif
- rcoll.infd = STDIN_FILENO;
- rcoll.outfd = STDOUT_FILENO;
- if (inf[0] && ('-' != inf[0])) {
- if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ, "sgs_dd: could not open %s for reading",
- inf);
- perror(ebuff);
- return 1;
- }
- if (ioctl(rcoll.infd, SG_GET_TIMEOUT, 0) < 0) {
- rcoll.in_is_sg = 0;
- if (skip > 0) {
- off_t offset = skip;
-
- offset *= rcoll.bs; /* could overflow here! */
- if (lseek(rcoll.infd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgs_dd: couldn't skip to required position on %s", inf);
- perror(ebuff);
- return 1;
- }
- }
- }
- else { /* looks like sg device so close then re-open it RW */
- close(rcoll.infd);
- if ((rcoll.infd = open(inf, O_RDWR | O_NONBLOCK)) < 0) {
- printf("If %s is a sg device, need read+write permissions,"
- " even to read it!\n", inf);
- return 1;
- }
- rcoll.in_is_sg = 1;
- if (sz_reserve(rcoll.infd, rcoll.bs, rcoll.bpt))
- return 1;
- }
- }
- if (outf[0] && ('-' != outf[0])) {
- if ((rcoll.outfd = open(outf, O_RDWR | O_NONBLOCK)) >= 0) {
- if (ioctl(rcoll.outfd, SG_GET_TIMEOUT, 0) < 0) {
- /* not a scsi generic device so now try and open RDONLY */
- close(rcoll.outfd);
- }
- else {
- rcoll.out_is_sg = 1;
- if (sz_reserve(rcoll.outfd, rcoll.bs, rcoll.bpt))
- return 1;
- }
- }
- if (! rcoll.out_is_sg) {
- if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgs_dd: could not open %s for writing", outf);
- perror(ebuff);
- return 1;
- }
- else if (seek > 0) {
- off_t offset = seek;
-
- offset *= rcoll.bs; /* could overflow here! */
- if (lseek(rcoll.outfd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sgs_dd: couldn't seek to required position on %s", outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
- printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n");
- return 1;
- }
- if (! (rcoll.in_is_sg || rcoll.out_is_sg)) {
- printf("Either 'if' or 'of' must be a scsi generic device\n");
- return 1;
- }
- if (0 == count)
- return 0;
- else if (count < 0) {
- if (rcoll.in_is_sg) {
- res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
- if (2 == res) {
- printf("Unit attention, media changed(in), try again\n");
- res = read_capacity(rcoll.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 (in_num_sect > skip)
- in_num_sect -= skip;
- }
- }
- if (rcoll.out_is_sg) {
- res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
- if (2 == res) {
- printf("Unit attention, media changed(out), try again\n");
- res = read_capacity(rcoll.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;
- }
- }
-#ifdef SG_DEBUG
- printf("Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- count, in_num_sect, out_num_sect);
-#endif
- 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;
- }
-
-#ifdef SG_DEBUG
- printf("Start of loop, count=%d, bpt=%d\n", count, rcoll.bpt);
-#endif
-
- sigemptyset(&rcoll.blocked_sigs);
- sigaddset(&rcoll.blocked_sigs, SIGRTMIN + 1);
- sigaddset(&rcoll.blocked_sigs, SIGINT);
- sigaddset(&rcoll.blocked_sigs, SIGIO);
- sigprocmask(SIG_BLOCK, &rcoll.blocked_sigs, 0);
- rcoll.in_count = count;
- rcoll.in_done_count = count;
- rcoll.in_blk = skip;
- rcoll.out_count = count;
- rcoll.out_done_count = count;
- rcoll.out_blk = seek;
- init_elems(&rcoll);
-
-/* vvvvvvvvvvvvvvvvv Main Loop vvvvvvvvvvvvvvvvvvvvvvvv */
- while (rcoll.out_done_count > 0) {
- crw = can_read_write(&rcoll);
- if (crw < 0)
- break;
- if (SGQ_CAN_READ & crw) {
- res = start_read(&rcoll);
- if (res <= 0) {
- printf("start_read: res=%d\n", res);
- break;
- }
- }
- if (SGQ_CAN_WRITE & crw) {
- res = start_write(&rcoll);
- if (res <= 0) {
- printf("start_write: res=%d\n", res);
- break;
- }
- }
- }
-
- if (STDIN_FILENO != rcoll.infd)
- close(rcoll.infd);
- if (STDOUT_FILENO != rcoll.outfd)
- close(rcoll.outfd);
- if (0 != rcoll.out_count) {
- printf("Some error occurred, remaining blocks=%d\n", rcoll.out_count);
- return 1;
- }
- printf("%d+%d records in\n", count - rcoll.in_done_count,
- rcoll.in_partial);
- printf("%d+%d records out\n", count - rcoll.out_done_count,
- rcoll.out_partial);
- if (rcoll.dio_incomplete)
- printf(">> Direct IO requested but incomplete %d times\n",
- rcoll.dio_incomplete);
- if (rcoll.sum_of_resids)
- printf(">> Non-zero sum of residual counts=%d\n",
- rcoll.sum_of_resids);
- return 0;
-}