ddpt-0.94/0000755000175000017500000000000012320426231011370 5ustar douggdouggddpt-0.94/INSTALL0000644000175000017500000002245011130302611012415 0ustar douggdouggInstallation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 6. Often, you can also type `make uninstall' to remove the installed files again. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ddpt-0.94/config.guess0000755000175000017500000013036112234471250013721 0ustar douggdougg#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-06-10' # This file 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 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ddpt-0.94/install-sh0000755000175000017500000003325512234471250013411 0ustar douggdougg#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ddpt-0.94/missing0000755000175000017500000001533112234471250012777 0ustar douggdougg#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # 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 distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ddpt-0.94/lib/0000755000175000017500000000000012320426231012136 5ustar douggdouggddpt-0.94/lib/sg_pt_common.c0000644000175000017500000000062212207377272015004 0ustar douggdougg/* * Copyright (c) 2009-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #include "sg_pt.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif static const char * scsi_pt_version_str = "2.10 20130827"; const char * scsi_pt_version() { return scsi_pt_version_str; } ddpt-0.94/lib/sg_cmds_mmc.c0000644000175000017500000003002512176051475014572 0ustar douggdougg/* * Copyright (c) 2008-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_cmds_mmc.h" #include "sg_pt.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_PT_TIMEOUT 60 /* 60 seconds */ #define GET_CONFIG_CMD 0x46 #define GET_CONFIG_CMD_LEN 10 #define GET_PERFORMANCE_CMD 0xac #define GET_PERFORMANCE_CMD_LEN 12 #define SET_CD_SPEED_CMD 0xbb #define SET_CD_SPEED_CMDLEN 12 #define SET_STREAMING_CMD 0xb6 #define SET_STREAMING_CMDLEN 12 /* Invokes a SCSI SET CD SPEED command (MMC). * Return of 0 -> success, SG_LIB_CAT_INVALID_OP -> command not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed, int drv_write_speed, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char scsCmdBlk[SET_CD_SPEED_CMDLEN] = {SET_CD_SPEED_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; scsCmdBlk[1] |= (rot_control & 0x3); scsCmdBlk[2] = (drv_read_speed >> 8) & 0xff; scsCmdBlk[3] = drv_read_speed & 0xff; scsCmdBlk[4] = (drv_write_speed >> 8) & 0xff; scsCmdBlk[5] = drv_write_speed & 0xff; if (verbose) { fprintf(sg_warnings_strm, " set cd speed cdb: "); for (k = 0; k < SET_CD_SPEED_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", scsCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "set cd speed: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, scsCmdBlk, sizeof(scsCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "set cd speed", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI GET CONFIGURATION command (MMC-3,4,5). * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp, int mx_resp_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char gcCmdBlk[GET_CONFIG_CMD_LEN] = {GET_CONFIG_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if ((rt < 0) || (rt > 3)) { fprintf(sg_warnings_strm, "Bad rt value: %d\n", rt); return -1; } gcCmdBlk[1] = (rt & 0x3); if ((starting < 0) || (starting > 0xffff)) { fprintf(sg_warnings_strm, "Bad starting field number: 0x%x\n", starting); return -1; } gcCmdBlk[2] = (unsigned char)((starting >> 8) & 0xff); gcCmdBlk[3] = (unsigned char)(starting & 0xff); if ((mx_resp_len < 0) || (mx_resp_len > 0xffff)) { fprintf(sg_warnings_strm, "Bad mx_resp_len: 0x%x\n", starting); return -1; } gcCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff); gcCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff); if (verbose) { fprintf(sg_warnings_strm, " Get Configuration cdb: "); for (k = 0; k < GET_CONFIG_CMD_LEN; ++k) fprintf(sg_warnings_strm, "%02x ", gcCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "get configuration: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, gcCmdBlk, sizeof(gcCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "get configuration", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 3)) { unsigned char * ucp; int len; ucp = (unsigned char *)resp; len = (ucp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8) + ucp[3] + 4; if (len < 0) len = 0; len = (ret < len) ? ret : len; fprintf(sg_warnings_strm, " get configuration: response%s\n", (len > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (len > 256 ? 256 : len), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI GET PERFORMANCE command (MMC-3...6). * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_get_performance(int sg_fd, int data_type, unsigned int starting_lba, int max_num_desc, int ttype, void * resp, int mx_resp_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char gpCmdBlk[GET_PERFORMANCE_CMD_LEN] = {GET_PERFORMANCE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if ((data_type < 0) || (data_type > 0x1f)) { fprintf(sg_warnings_strm, "Bad data_type value: %d\n", data_type); return -1; } gpCmdBlk[1] = (data_type & 0x1f); gpCmdBlk[2] = (unsigned char)((starting_lba >> 24) & 0xff); gpCmdBlk[3] = (unsigned char)((starting_lba >> 16) & 0xff); gpCmdBlk[4] = (unsigned char)((starting_lba >> 8) & 0xff); gpCmdBlk[3] = (unsigned char)(starting_lba & 0xff); if ((max_num_desc < 0) || (max_num_desc > 0xffff)) { fprintf(sg_warnings_strm, "Bad max_num_desc: 0x%x\n", max_num_desc); return -1; } gpCmdBlk[8] = (unsigned char)((max_num_desc >> 8) & 0xff); gpCmdBlk[9] = (unsigned char)(max_num_desc & 0xff); if ((ttype < 0) || (ttype > 0xff)) { fprintf(sg_warnings_strm, "Bad type: 0x%x\n", ttype); return -1; } gpCmdBlk[10] = (unsigned char)ttype; if (verbose) { fprintf(sg_warnings_strm, " Get Performance cdb: "); for (k = 0; k < GET_PERFORMANCE_CMD_LEN; ++k) fprintf(sg_warnings_strm, "%02x ", gpCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "get performance: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, gpCmdBlk, sizeof(gpCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "get performance", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 3)) { unsigned char * ucp; int len; ucp = (unsigned char *)resp; len = (ucp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8) + ucp[3] + 4; if (len < 0) len = 0; len = (ret < len) ? ret : len; fprintf(sg_warnings_strm, " get performance:: response%s\n", (len > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (len > 256 ? 256 : len), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI SET STREAMING command (MMC). Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Set Streaming not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_NOT_READY -> device not ready, * -1 -> other failure */ int sg_ll_set_streaming(int sg_fd, int type, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char ssCmdBlk[SET_STREAMING_CMDLEN] = {SET_STREAMING_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; ssCmdBlk[8] = type; ssCmdBlk[9] = (param_len >> 8) & 0xff; ssCmdBlk[10] = param_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " set streaming cdb: "); for (k = 0; k < SET_STREAMING_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", ssCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " set streaming " "parameter list:\n"); dStrHexErr((const char *)paramp, param_len, -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "set streaming: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, ssCmdBlk, sizeof(ssCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "set streaming", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } ddpt-0.94/lib/sg_lib.c0000644000175000017500000020673612316660506013571 0ustar douggdougg/* * Copyright (c) 1999-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* NOTICE: * On 5th October 2004 (v1.00) this file name was changed from sg_err.c * to sg_lib.c and the previous GPL was changed to a FreeBSD license. * The intention is to maintain this file and the related sg_lib.h file * as open source and encourage their unencumbered use. * * CONTRIBUTIONS: * This file started out as a copy of SCSI opcodes, sense keys and * additional sense codes (ASC/ASCQ) kept in the Linux SCSI subsystem * in the kernel source file: drivers/scsi/constant.c . That file * bore this notice: "Copyright (C) 1993, 1994, 1995 Eric Youngdale" * and a GPL notice. * * Much of the data in this file is derived from SCSI draft standards * found at http://www.t10.org with the "SCSI Primary Commands-4" (SPC-4) * being the central point of reference. * * Contributions: * sense key specific field decoding [Trent Piepho 20031116] * */ #include #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include "sg_lib.h" #include "sg_lib_data.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif /* sg_lib_version_str (and datestamp) defined in sg_lib_data.c file */ #define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d /* corresponding ASC is 0 */ FILE * sg_warnings_strm = NULL; /* would like to default to stderr */ /* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of * functions. Returns number number of chars placed in cp excluding the * trailing null char. So for cp_max_len > 0 the return value is always * < cp_max_len; for cp_max_len <= 1 the return value is 0 and no chars * are written to cp. Note this means that when cp_max_len = 1, this * function assumes that cp[0] is the null character and does nothing * (and returns 0). */ static int my_snprintf(char * cp, int cp_max_len, const char * fmt, ...) { va_list args; int n; if (cp_max_len < 2) return 0; va_start(args, fmt); n = vsnprintf(cp, cp_max_len, fmt, args); va_end(args); return (n < cp_max_len) ? n : (cp_max_len - 1); } /* Searches 'arr' for match on 'value' then 'peri_type'. If matches 'value' but not 'peri_type' then yields first 'value' match entry. Last element of 'arr' has NULL 'name'. If no match returns NULL. */ static const struct sg_lib_value_name_t * get_value_name(const struct sg_lib_value_name_t * arr, int value, int peri_type) { const struct sg_lib_value_name_t * vp = arr; const struct sg_lib_value_name_t * holdp; for (; vp->name; ++vp) { if (value == vp->value) { if (peri_type == vp->peri_dev_type) return vp; holdp = vp; while ((vp + 1)->name && (value == (vp + 1)->value)) { ++vp; if (peri_type == vp->peri_dev_type) return vp; } return holdp; } } return NULL; } void sg_set_warnings_strm(FILE * warnings_strm) { sg_warnings_strm = warnings_strm; } #define CMD_NAME_LEN 128 void sg_print_command(const unsigned char * command) { int k, sz; char buff[CMD_NAME_LEN]; sg_get_command_name(command, 0, CMD_NAME_LEN, buff); buff[CMD_NAME_LEN - 1] = '\0'; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "%s [", buff); if (SG_VARIABLE_LENGTH_CMD == command[0]) sz = command[7] + 8; else sz = sg_get_command_size(command[0]); for (k = 0; k < sz; ++k) fprintf(sg_warnings_strm, "%02x ", command[k]); fprintf(sg_warnings_strm, "]\n"); } void sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff) { const char * ccp; if ((NULL == buff) || (buff_len < 1)) return; else if (1 == buff_len) { buff[0] = '\0'; return; } scsi_status &= 0x7e; /* sanitize as much as possible */ switch (scsi_status) { case 0: ccp = "Good"; break; case 0x2: ccp = "Check Condition"; break; case 0x4: ccp = "Condition Met"; break; case 0x8: ccp = "Busy"; break; case 0x10: ccp = "Intermediate (obsolete)"; break; case 0x14: ccp = "Intermediate-Condition Met (obs)"; break; case 0x18: ccp = "Reservation Conflict"; break; case 0x22: ccp = "Command Terminated (obsolete)"; break; case 0x28: ccp = "Task set Full"; break; case 0x30: ccp = "ACA Active"; break; case 0x40: ccp = "Task Aborted"; break; default: ccp = "Unknown status"; break; } my_snprintf(buff, buff_len, "%s", ccp); } void sg_print_scsi_status(int scsi_status) { char buff[128]; sg_get_scsi_status_str(scsi_status, sizeof(buff) - 1, buff); buff[sizeof(buff) - 1] = '\0'; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "%s ", buff); } int sg_get_sense_key(const unsigned char * sensep, int sense_len) { if ((NULL == sensep) || (sense_len < 2)) return -1; switch (sensep[0] & 0x7f) { case 0x70: case 0x71: return (sense_len < 3) ? -1 : (sensep[2] & 0xf); case 0x72: case 0x73: return sensep[1] & 0xf; default: return -1; } } char * sg_get_sense_key_str(int sense_key, int buff_len, char * buff) { if (1 == buff_len) { buff[0] = '\0'; return buff; } if ((sense_key >= 0) && (sense_key < 16)) my_snprintf(buff, buff_len, "%s", sg_lib_sense_key_desc[sense_key]); else my_snprintf(buff, buff_len, "invalid value: 0x%x", sense_key); return buff; } char * sg_get_asc_ascq_str(int asc, int ascq, int buff_len, char * buff) { int k, num, rlen; int found = 0; struct sg_lib_asc_ascq_t * eip; struct sg_lib_asc_ascq_range_t * ei2p; if (1 == buff_len) { buff[0] = '\0'; return buff; } for (k = 0; sg_lib_asc_ascq_range[k].text; ++k) { ei2p = &sg_lib_asc_ascq_range[k]; if ((ei2p->asc == asc) && (ascq >= ei2p->ascq_min) && (ascq <= ei2p->ascq_max)) { found = 1; num = my_snprintf(buff, buff_len, "Additional sense: "); rlen = buff_len - num; num += my_snprintf(buff + num, ((rlen > 0) ? rlen : 0), ei2p->text, ascq); } } if (found) return buff; for (k = 0; sg_lib_asc_ascq[k].text; ++k) { eip = &sg_lib_asc_ascq[k]; if (eip->asc == asc && eip->ascq == ascq) { found = 1; my_snprintf(buff, buff_len, "Additional sense: %s", eip->text); } } if (! found) { if (asc >= 0x80) my_snprintf(buff, buff_len, "vendor specific ASC=%02x, " "ASCQ=%02x (hex)", asc, ascq); else if (ascq >= 0x80) my_snprintf(buff, buff_len, "ASC=%02x, vendor specific " "qualification ASCQ=%02x (hex)", asc, ascq); else my_snprintf(buff, buff_len, "ASC=%02x, ASCQ=%02x (hex)", asc, ascq); } return buff; } const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len, int desc_type) { int add_sb_len, add_d_len, desc_len, k; const unsigned char * descp; if ((sense_len < 8) || (0 == (add_sb_len = sensep[7]))) return NULL; if ((sensep[0] < 0x72) || (sensep[0] > 0x73)) return NULL; add_sb_len = (add_sb_len < (sense_len - 8)) ? add_sb_len : (sense_len - 8); descp = &sensep[8]; for (desc_len = 0, k = 0; k < add_sb_len; k += desc_len) { descp += desc_len; add_d_len = (k < (add_sb_len - 1)) ? descp[1]: -1; desc_len = add_d_len + 2; if (descp[0] == desc_type) return descp; if (add_d_len < 0) /* short descriptor ?? */ break; } return NULL; } int sg_get_sense_info_fld(const unsigned char * sensep, int sb_len, uint64_t * info_outp) { int j; const unsigned char * ucp; uint64_t ull; if (info_outp) *info_outp = 0; if (sb_len < 7) return 0; switch (sensep[0] & 0x7f) { case 0x70: case 0x71: if (info_outp) *info_outp = ((unsigned int)sensep[3] << 24) + (sensep[4] << 16) + (sensep[5] << 8) + sensep[6]; return (sensep[0] & 0x80) ? 1 : 0; case 0x72: case 0x73: ucp = sg_scsi_sense_desc_find(sensep, sb_len, 0 /* info desc */); if (ucp && (0xa == ucp[1])) { ull = 0; for (j = 0; j < 8; ++j) { if (j > 0) ull <<= 8; ull |= ucp[4 + j]; } if (info_outp) *info_outp = ull; return !!(ucp[2] & 0x80); /* since spc3r23 should be set */ } else return 0; default: return 0; } } int sg_get_sense_filemark_eom_ili(const unsigned char * sensep, int sb_len, int * filemark_p, int * eom_p, int * ili_p) { const unsigned char * ucp; if (sb_len < 7) return 0; switch (sensep[0] & 0x7f) { case 0x70: case 0x71: if (sensep[2] & 0xe0) { if (filemark_p) *filemark_p = !!(sensep[2] & 0x80); if (eom_p) *eom_p = !!(sensep[2] & 0x40); if (ili_p) *ili_p = !!(sensep[2] & 0x20); return 1; } else return 0; case 0x72: case 0x73: /* Look for stream commands sense data descriptor */ ucp = sg_scsi_sense_desc_find(sensep, sb_len, 4); if (ucp && (ucp[1] >= 2)) { if (ucp[3] & 0xe0) { if (filemark_p) *filemark_p = !!(ucp[3] & 0x80); if (eom_p) *eom_p = !!(ucp[3] & 0x40); if (ili_p) *ili_p = !!(ucp[3] & 0x20); return 1; } } return 0; default: return 0; } } /* Returns 1 if SKSV is set and sense key is NO_SENSE or NOT_READY. Also * returns 1 if progress indication sense data descriptor found. Places * progress field from sense data where progress_outp points. If progress * field is not available returns 0 and *progress_outp is unaltered. Handles * both fixed and descriptor sense formats. * Hint: if 1 is returned *progress_outp may be multiplied by 100 then * divided by 65536 to get the percentage completion. */ int sg_get_sense_progress_fld(const unsigned char * sensep, int sb_len, int * progress_outp) { const unsigned char * ucp; int sk, sk_pr; if (sb_len < 7) return 0; switch (sensep[0] & 0x7f) { case 0x70: case 0x71: sk = (sensep[2] & 0xf); if ((sb_len < 18) || ((SPC_SK_NO_SENSE != sk) && (SPC_SK_NOT_READY != sk))) return 0; if (sensep[15] & 0x80) { /* SKSV bit set */ if (progress_outp) *progress_outp = (sensep[16] << 8) + sensep[17]; return 1; } else return 0; case 0x72: case 0x73: /* sense key specific progress (0x2) or progress descriptor (0xa) */ sk = (sensep[1] & 0xf); sk_pr = (SPC_SK_NO_SENSE == sk) || (SPC_SK_NOT_READY == sk); if (sk_pr && ((ucp = sg_scsi_sense_desc_find(sensep, sb_len, 2))) && (0x6 == ucp[1]) && (0x80 & ucp[4])) { if (progress_outp) *progress_outp = (ucp[5] << 8) + ucp[6]; return 1; } else if (((ucp = sg_scsi_sense_desc_find(sensep, sb_len, 0xa))) && ((0x6 == ucp[1]))) { if (progress_outp) *progress_outp = (ucp[6] << 8) + ucp[7]; return 1; } else return 0; default: return 0; } } char * sg_get_pdt_str(int pdt, int buff_len, char * buff) { if ((pdt < 0) || (pdt > 31)) my_snprintf(buff, buff_len, "bad pdt"); else my_snprintf(buff, buff_len, "%s", sg_lib_pdt_strs[pdt]); return buff; } char * sg_get_trans_proto_str(int tpi, int buff_len, char * buff) { if ((tpi < 0) || (tpi > 15)) my_snprintf(buff, buff_len, "bad tpi"); else my_snprintf(buff, buff_len, "%s", sg_lib_transport_proto_strs[tpi]); return buff; } #define TPGS_STATE_OPTIMIZED 0x0 #define TPGS_STATE_NONOPTIMIZED 0x1 #define TPGS_STATE_STANDBY 0x2 #define TPGS_STATE_UNAVAILABLE 0x3 #define TPGS_STATE_OFFLINE 0xe #define TPGS_STATE_TRANSITIONING 0xf static int decode_tpgs_state(int st, char * b, int blen) { switch (st) { case TPGS_STATE_OPTIMIZED: return my_snprintf(b, blen, "active/optimized"); case TPGS_STATE_NONOPTIMIZED: return my_snprintf(b, blen, "active/non optimized"); case TPGS_STATE_STANDBY: return my_snprintf(b, blen, "standby"); case TPGS_STATE_UNAVAILABLE: return my_snprintf(b, blen, "unavailable"); case TPGS_STATE_OFFLINE: return my_snprintf(b, blen, "offline"); case TPGS_STATE_TRANSITIONING: return my_snprintf(b, blen, "transitioning between states"); default: return my_snprintf(b, blen, "unknown: 0x%x", st); } } static int uds_referral_descriptor_str(char * b, int blen, const unsigned char * dp, int alen) { int n = 0; int dlen = alen - 2; int k, j, g, f, tpgd; const unsigned char * tp; uint64_t ull; char c[40]; n += my_snprintf(b + n, blen - n, " Not all referrals: %d\n", !!(dp[2] & 0x1)); dp += 4; for (k = 0, f = 1; (k + 4) < dlen; k += g, dp += g, ++f) { tpgd = dp[3]; g = (tpgd * 4) + 20; n += my_snprintf(b + n, blen - n, " Descriptor %d\n", f); if ((k + g) > dlen) { n += my_snprintf(b + n, blen - n, " truncated descriptor, " "stop\n"); return n; } ull = 0; for (j = 0; j < 8; ++j) { if (j > 0) ull <<= 8; ull |= dp[4 + j]; } n += my_snprintf(b + n, blen - n, " first uds LBA: 0x%" PRIx64 "\n", ull); ull = 0; for (j = 0; j < 8; ++j) { if (j > 0) ull <<= 8; ull |= dp[12 + j]; } n += my_snprintf(b + n, blen - n, " last uds LBA: 0x%" PRIx64 "\n", ull); for (j = 0; j < tpgd; ++j) { tp = dp + 20 + (j * 4); decode_tpgs_state(tp[0] & 0xf, c, sizeof(c)); n += my_snprintf(b + n, blen - n, " tpg: %d state: %s\n", (tp[2] << 8) + tp[3], c); } } return n; } static const char * sdata_src[] = { "unknown", "Extended Copy command source device", "Extended Copy command destination device", }; /* Decode descriptor format sense descriptors (assumes sense buffer is * in descriptor format) */ static void sg_get_sense_descriptors_str(const unsigned char * sense_buffer, int sb_len, int blen, char * b) { int add_sb_len, add_d_len, desc_len, k, j, sense_key, processed; int n, progress, pr, rem; const unsigned char * descp; const char * dtsp = " >> descriptor too short"; if ((NULL == b) || (blen <= 0)) return; b[0] = '\0'; if ((sb_len < 8) || (0 == (add_sb_len = sense_buffer[7]))) return; add_sb_len = (add_sb_len < (sb_len - 8)) ? add_sb_len : (sb_len - 8); sense_key = (sense_buffer[1] & 0xf); for (descp = (sense_buffer + 8), k = 0, n = 0; (k < add_sb_len) && (n < blen); k += desc_len, descp += desc_len) { add_d_len = (k < (add_sb_len - 1)) ? descp[1] : -1; if ((k + add_d_len + 2) > add_sb_len) add_d_len = add_sb_len - k - 2; desc_len = add_d_len + 2; n += my_snprintf(b + n, blen - n, " Descriptor type: "); processed = 1; switch (descp[0]) { case 0: n += my_snprintf(b + n, blen - n, "Information\n"); if ((add_d_len >= 10) && (0x80 & descp[2])) { n += my_snprintf(b + n, blen - n, " 0x"); for (j = 0; j < 8; ++j) n += my_snprintf(b + n, blen - n, "%02x", descp[4 + j]); n += my_snprintf(b + n, blen - n, "\n"); } else { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; } break; case 1: n += my_snprintf(b + n, blen - n, "Command specific\n"); if (add_d_len >= 10) { n += my_snprintf(b + n, blen - n, " 0x"); for (j = 0; j < 8; ++j) n += my_snprintf(b + n, blen - n, "%02x", descp[4 + j]); n += my_snprintf(b + n, blen - n, "\n"); } else { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; } break; case 2: n += my_snprintf(b + n, blen - n, "Sense key specific:"); switch (sense_key) { case SPC_SK_ILLEGAL_REQUEST: n += my_snprintf(b + n, blen - n, " Field pointer\n"); if (add_d_len < 6) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } n += my_snprintf(b + n, blen - n, " Error in %s byte %d", (descp[4] & 0x40) ? "Command" : "Data", (descp[5] << 8) | descp[6]); if (descp[4] & 0x08) { n += my_snprintf(b + n, blen - n, " bit %d\n", descp[4] & 0x07); } else n += my_snprintf(b + n, blen - n, "\n"); break; case SPC_SK_HARDWARE_ERROR: case SPC_SK_MEDIUM_ERROR: case SPC_SK_RECOVERED_ERROR: n += my_snprintf(b + n, blen - n, " Actual retry count\n"); if (add_d_len < 6) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } n += my_snprintf(b + n, blen - n," 0x%02x%02x\n", descp[5], descp[6]); break; case SPC_SK_NO_SENSE: case SPC_SK_NOT_READY: n += my_snprintf(b + n, blen - n, " Progress indication: "); if (add_d_len < 6) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } progress = (descp[5] << 8) + descp[6]; pr = (progress * 100) / 65536; rem = ((progress * 100) % 65536) / 656; n += my_snprintf(b + n, blen - n, "%d.%02d%%\n", pr, rem); break; case SPC_SK_COPY_ABORTED: n += my_snprintf(b + n, blen - n, " Segment pointer\n"); if (add_d_len < 6) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } n += my_snprintf(b + n, blen - n, " Relative to start of %s, " "byte %d", (descp[4] & 0x20) ? "segment descriptor" : "parameter list", (descp[5] << 8) | descp[6]); if (descp[4] & 0x08) n += my_snprintf(b + n, blen - n, " bit %d\n", descp[4] & 0x07); else n += my_snprintf(b + n, blen - n, "\n"); break; case SPC_SK_UNIT_ATTENTION: n += my_snprintf(b + n, blen - n, " Unit attention condition " "queue: "); n += my_snprintf(b + n, blen - n, "overflow flag is %d\n", !!(descp[4] & 0x1)); break; default: n += my_snprintf(b + n, blen - n, " Sense_key: 0x%x " "unexpected\n", sense_key); processed = 0; break; } break; case 3: n += my_snprintf(b + n, blen - n, "Field replaceable unit\n"); if (add_d_len >= 2) n += my_snprintf(b + n, blen - n, " code=0x%x\n", descp[3]); else { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; } break; case 4: n += my_snprintf(b + n, blen - n, "Stream commands\n"); if (add_d_len >= 2) { if (descp[3] & 0x80) n += my_snprintf(b + n, blen - n, " FILEMARK"); if (descp[3] & 0x40) n += my_snprintf(b + n, blen - n, " End Of Medium " "(EOM)"); if (descp[3] & 0x20) n += my_snprintf(b + n, blen - n, " Incorrect Length " "Indicator (ILI)"); n += my_snprintf(b + n, blen - n, "\n"); } else { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; } break; case 5: n += my_snprintf(b + n, blen - n, "Block commands\n"); if (add_d_len >= 2) n += my_snprintf(b + n, blen - n, " Incorrect Length " "Indicator (ILI) %s\n", (descp[3] & 0x20) ? "set" : "clear"); else { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; } break; case 6: n += my_snprintf(b + n, blen - n, "OSD object identification\n"); processed = 0; break; case 7: n += my_snprintf(b + n, blen - n, "OSD response integrity check " "value\n"); processed = 0; break; case 8: n += my_snprintf(b + n, blen - n, "OSD attribute " "identification\n"); processed = 0; break; case 9: /* this is defined in SAT (and SAT-2) */ n += my_snprintf(b + n, blen - n, "ATA Status Return\n"); if (add_d_len >= 12) { int extend, sector_count; extend = descp[2] & 1; sector_count = descp[5] + (extend ? (descp[4] << 8) : 0); n += my_snprintf(b + n, blen - n, " extend=%d error=0x%x " " sector_count=0x%x\n", extend, descp[3], sector_count); if (extend) n += my_snprintf(b + n, blen - n, " " "lba=0x%02x%02x%02x%02x%02x%02x\n", descp[10], descp[8], descp[6], descp[11], descp[9], descp[7]); else n += my_snprintf(b + n, blen - n, " " "lba=0x%02x%02x%02x\n", descp[11], descp[9], descp[7]); n += my_snprintf(b + n, blen - n, " device=0x%x " "status=0x%x\n", descp[12], descp[13]); } else { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; } break; case 0xa: /* Added in SPC-4 rev 17, became 'Another ...' in rev 34 */ n += my_snprintf(b + n, blen - n, "Another progress " "indication\n"); if (add_d_len < 6) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } progress = (descp[6] << 8) + descp[7]; pr = (progress * 100) / 65536; rem = ((progress * 100) % 65536) / 656; n += my_snprintf(b + n, blen - n, " %d.02%d%%", pr, rem); n += my_snprintf(b + n, blen - n, " [sense_key=0x%x " "asc,ascq=0x%x,0x%x]\n", descp[2], descp[3], descp[4]); break; case 0xb: /* Added in SPC-4 rev 23, defined in SBC-3 rev 22 */ n += my_snprintf(b + n, blen - n, "User data segment referral\n"); if (add_d_len < 2) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } n += uds_referral_descriptor_str(b + n, blen - n, descp, add_d_len); break; case 0xc: /* Added in SPC-4 rev 28 */ n += my_snprintf(b + n, blen - n, "Forwarded sense data\n"); if (add_d_len < 2) { n += my_snprintf(b + n, blen - n, "%s\n", dtsp); processed = 0; break; } n += my_snprintf(b + n, blen - n, " FSDT: %s\n", (descp[2] & 0x80) ? "set" : "clear"); j = descp[2] & 0xf; if (j < 3) n += my_snprintf(b + n, blen - n, " Sense data source: " "%s\n", sdata_src[j]); else n += my_snprintf(b + n, blen - n, " Sense data source: " "reserved [%d]\n", j); { char c[200]; sg_get_scsi_status_str(descp[3], sizeof(c) - 1, c); c[sizeof(c) - 1] = '\0'; n += my_snprintf(b + n, blen - n, " Forwarded status: " "%s\n", c); if (add_d_len > 2) { /* recursing; hope not to get carried away */ n += my_snprintf(b + n, blen - n, " vvvvvvvvvvvvvvvv\n"); sg_get_sense_str(NULL, descp + 4, add_d_len - 2, 0, sizeof(c), c); n += my_snprintf(b + n, blen - n, "%s", c); n += my_snprintf(b + n, blen - n, " ^^^^^^^^^^^^^^^^\n"); } } break; default: if (descp[0] >= 0x80) n += my_snprintf(b + n, blen - n, "Vendor specific [0x%x]\n", descp[0]); else n += my_snprintf(b + n, blen - n, "Unknown [0x%x]\n", descp[0]); processed = 0; break; } if (! processed) { if (add_d_len > 0) { n += my_snprintf(b + n, blen - n, " "); for (j = 0; j < add_d_len; ++j) { if ((j > 0) && (0 == (j % 24))) n += my_snprintf(b + n, blen - n, "\n "); n += my_snprintf(b + n, blen - n, "%02x ", descp[j + 2]); } n += my_snprintf(b + n, blen - n, "\n"); } } if (add_d_len < 0) n += my_snprintf(b + n, blen - n, " short descriptor\n"); } } /* Decode SAT ATA PASS-THROUGH fixed format sense */ static void sg_get_sense_sat_pt_fixed_str(const unsigned char * sp, int slen, int blen, char * b) { int n = 0; if (slen) { ; } /* unused, suppress warning */ if (blen < 1) return; if (SPC_SK_RECOVERED_ERROR != (0xf & sp[2])) n += my_snprintf(b + n, blen - n, " >> expected Sense key: " "Recovered Error ??\n"); n += my_snprintf(b + n, blen - n, " error=0x%x, status=0x%x, " "device=0x%x, sector_count(7:0)=0x%x%c\n", sp[3], sp[4], sp[5], sp[6], ((0x40 & sp[8]) ? '+' : ' ')); n += my_snprintf(b + n, blen - n, " extend=%d, log_index=0x%x, " "lba_high,mid,low(7:0)=0x%x,0x%x,0x%x%c\n", (!!(0x80 & sp[8])), (0xf & sp[8]), sp[9], sp[10], sp[11], ((0x20 & sp[8]) ? '+' : ' ')); } /* Fetch sense information */ void sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer, int sb_len, int raw_sinfo, int buff_len, char * buff) { int len, valid, progress, n, r, pr, rem, blen; unsigned int info; int descriptor_format = 0; int sdat_ovfl = 0; const char * ebp = NULL; char error_buff[64]; char b[256]; struct sg_scsi_sense_hdr ssh; if ((NULL == buff) || (buff_len <= 0)) return; else if (1 == buff_len) { buff[0] = '\0'; return; } blen = sizeof(b); n = 0; if (sb_len < 1) { my_snprintf(buff, buff_len, "sense buffer empty\n"); return; } if (leadin) n += my_snprintf(buff + n, buff_len - n, "%s: ", leadin); len = sb_len; if (sg_scsi_normalize_sense(sense_buffer, sb_len, &ssh)) { switch (ssh.response_code) { case 0x70: /* fixed, current */ ebp = "Fixed format, current"; len = (sb_len > 7) ? (sense_buffer[7] + 8) : sb_len; len = (len > sb_len) ? sb_len : len; sdat_ovfl = (len > 2) ? !!(sense_buffer[2] & 0x10) : 0; break; case 0x71: /* fixed, deferred */ /* error related to a previous command */ ebp = "Fixed format, <<>>"; len = (sb_len > 7) ? (sense_buffer[7] + 8) : sb_len; len = (len > sb_len) ? sb_len : len; sdat_ovfl = (len > 2) ? !!(sense_buffer[2] & 0x10) : 0; break; case 0x72: /* descriptor, current */ descriptor_format = 1; ebp = "Descriptor format, current"; sdat_ovfl = (sb_len > 4) ? !!(sense_buffer[4] & 0x80) : 0; break; case 0x73: /* descriptor, deferred */ descriptor_format = 1; ebp = "Descriptor format, <<>>"; sdat_ovfl = (sb_len > 4) ? !!(sense_buffer[4] & 0x80) : 0; break; case 0x0: ebp = "Response code: 0x0 (?)"; break; default: my_snprintf(error_buff, sizeof(error_buff), "Unknown response code: 0x%x", ssh.response_code); ebp = error_buff; break; } n += my_snprintf(buff + n, buff_len - n, " %s; Sense key: %s\n ", ebp, sg_lib_sense_key_desc[ssh.sense_key]); if (sdat_ovfl) n += my_snprintf(buff + n, buff_len - n, "<<>>\n"); if (descriptor_format) { n += my_snprintf(buff + n, buff_len - n, "%s\n", sg_get_asc_ascq_str(ssh.asc, ssh.ascq, sizeof(b), b)); sg_get_sense_descriptors_str(sense_buffer, len, buff_len - n, buff + n); n = strlen(buff); } else if ((len > 12) && (0 == ssh.asc) && (ASCQ_ATA_PT_INFO_AVAILABLE == ssh.ascq)) { /* SAT ATA PASS-THROUGH fixed format */ n += my_snprintf(buff + n, buff_len - n, "%s\n", sg_get_asc_ascq_str(ssh.asc, ssh.ascq, sizeof(b), b)); sg_get_sense_sat_pt_fixed_str(sense_buffer, len, buff_len - n, buff + n); n = strlen(buff); } else if (len > 2) { /* fixed format */ if (len > 12) n += my_snprintf(buff + n, buff_len - n, "%s\n", sg_get_asc_ascq_str(ssh.asc, ssh.ascq, sizeof(b), b)); r = 0; valid = sense_buffer[0] & 0x80; if (len > 6) { info = (unsigned int)((sense_buffer[3] << 24) | (sense_buffer[4] << 16) | (sense_buffer[5] << 8) | sense_buffer[6]); if (valid) r += my_snprintf(b + r, blen - r, " Info fld=0x%x [%u] ", info, info); else if (info > 0) r += my_snprintf(b + r, blen - r, " Valid=0, Info " "fld=0x%x [%u] ", info, info); } else info = 0; if (sense_buffer[2] & 0xe0) { if (sense_buffer[2] & 0x80) r += my_snprintf(b + r, blen - r, " FMK"); /* current command has read a filemark */ if (sense_buffer[2] & 0x40) r += my_snprintf(b + r, blen - r, " EOM"); /* end-of-medium condition exists */ if (sense_buffer[2] & 0x20) r += my_snprintf(b + r, blen - r, " ILI"); /* incorrect block length requested */ r += my_snprintf(b + r, blen - r, "\n"); } else if (valid || (info > 0)) r += my_snprintf(b + r, blen - r, "\n"); if ((len >= 14) && sense_buffer[14]) r += my_snprintf(b + r, blen - r, " Field replaceable unit " "code: %d\n", sense_buffer[14]); if ((len >= 18) && (sense_buffer[15] & 0x80)) { /* sense key specific decoding */ switch (ssh.sense_key) { case SPC_SK_ILLEGAL_REQUEST: r += my_snprintf(b + r, blen - r, " Sense Key Specific: " "Error in %s byte %d", ((sense_buffer[15] & 0x40) ? "Command" : "Data"), (sense_buffer[16] << 8) | sense_buffer[17]); if (sense_buffer[15] & 0x08) r += my_snprintf(b + r, blen - r, " bit %d\n", sense_buffer[15] & 0x07); else r += my_snprintf(b + r, blen - r, "\n"); break; case SPC_SK_NO_SENSE: case SPC_SK_NOT_READY: progress = (sense_buffer[16] << 8) + sense_buffer[17]; pr = (progress * 100) / 65536; rem = ((progress * 100) % 65536) / 656; r += my_snprintf(b + r, blen - r, " Progress " "indication: %d.%02d%%\n", pr, rem); break; case SPC_SK_HARDWARE_ERROR: case SPC_SK_MEDIUM_ERROR: case SPC_SK_RECOVERED_ERROR: r += my_snprintf(b + r, blen - r, " Actual retry count: " "0x%02x%02x\n", sense_buffer[16], sense_buffer[17]); break; case SPC_SK_COPY_ABORTED: r += my_snprintf(b + r, blen - r, " Segment pointer: "); r += my_snprintf(b + r, blen - r, "Relative to start of " "%s, byte %d", ((sense_buffer[15] & 0x20) ? "segment descriptor" : "parameter list"), ((sense_buffer[16] << 8) + sense_buffer[17])); if (sense_buffer[15] & 0x08) r += my_snprintf(b + r, blen - r, " bit %d\n", sense_buffer[15] & 0x07); else r += my_snprintf(b + r, blen - r, "\n"); break; case SPC_SK_UNIT_ATTENTION: r += my_snprintf(b + r, blen - r, " Unit attention " "condition queue: "); r += my_snprintf(b + r, blen - r, "overflow flag is %d\n", !!(sense_buffer[15] & 0x1)); break; default: r += my_snprintf(b + r, blen - r, " Sense_key: 0x%x " "unexpected\n", ssh.sense_key); break; } } if (r > 0) n += my_snprintf(buff + n, buff_len - n, "%s", b); } else n += my_snprintf(buff + n, buff_len - n, " fixed descriptor " "length too short, len=%d\n", len); } else { /* non-extended SCSI-1 sense data ?? */ if (sb_len < 4) { n += my_snprintf(buff + n, buff_len - n, "sense buffer too short " "(4 byte minimum)\n"); return; } r = 0; r += my_snprintf(b + r, blen - r, "Probably uninitialized data.\n " "Try to view as SCSI-1 non-extended sense:\n"); r += my_snprintf(b + r, blen - r, " AdValid=%d Error class=%d " "Error code=%d\n", !!(sense_buffer[0] & 0x80), ((sense_buffer[0] >> 4) & 0x7), (sense_buffer[0] & 0xf)); if (sense_buffer[0] & 0x80) r += my_snprintf(b + r, blen - r, " lba=0x%x\n", ((sense_buffer[1] & 0x1f) << 16) + (sense_buffer[2] << 8) + sense_buffer[3]); n += my_snprintf(buff + n, buff_len - n, "%s\n", b); len = sb_len; if (len > 32) len = 32; /* trim in case there is a lot of rubbish */ } if (raw_sinfo) { n += my_snprintf(buff + n, buff_len - n, " Raw sense data (in hex):" "\n"); if (n >= (buff_len - 1)) return; dStrHexStr((const char *)sense_buffer, len, " ", 0, buff_len - n, buff + n); } } /* Print sense information */ void sg_print_sense(const char * leadin, const unsigned char * sense_buffer, int sb_len, int raw_sinfo) { char b[2048]; sg_get_sense_str(leadin, sense_buffer, sb_len, raw_sinfo, sizeof(b), b); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "%s", b); } /* See description in sg_lib.h header file */ int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len, struct sg_scsi_sense_hdr * sshp) { if (sshp) memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr)); if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0]))) return 0; if (sshp) { sshp->response_code = (0x7f & sensep[0]); if (sshp->response_code >= 0x72) { /* descriptor format */ if (sb_len > 1) sshp->sense_key = (0xf & sensep[1]); if (sb_len > 2) sshp->asc = sensep[2]; if (sb_len > 3) sshp->ascq = sensep[3]; if (sb_len > 7) sshp->additional_length = sensep[7]; } else { /* fixed format */ if (sb_len > 2) sshp->sense_key = (0xf & sensep[2]); if (sb_len > 7) { sb_len = (sb_len < (sensep[7] + 8)) ? sb_len : (sensep[7] + 8); if (sb_len > 12) sshp->asc = sensep[12]; if (sb_len > 13) sshp->ascq = sensep[13]; } } } return 1; } /* Returns a SG_LIB_CAT_* value. If cannot decode sense_buffer or a less * common sense key then return SG_LIB_CAT_SENSE .*/ int sg_err_category_sense(const unsigned char * sense_buffer, int sb_len) { struct sg_scsi_sense_hdr ssh; if ((sense_buffer && (sb_len > 2)) && (sg_scsi_normalize_sense(sense_buffer, sb_len, &ssh))) { switch (ssh.sense_key) { /* 0 to 0x1f */ case SPC_SK_NO_SENSE: return SG_LIB_CAT_NO_SENSE; case SPC_SK_RECOVERED_ERROR: return SG_LIB_CAT_RECOVERED; case SPC_SK_NOT_READY: return SG_LIB_CAT_NOT_READY; case SPC_SK_MEDIUM_ERROR: case SPC_SK_HARDWARE_ERROR: case SPC_SK_BLANK_CHECK: return SG_LIB_CAT_MEDIUM_HARD; case SPC_SK_UNIT_ATTENTION: return SG_LIB_CAT_UNIT_ATTENTION; /* used to return SG_LIB_CAT_MEDIA_CHANGED when ssh.asc==0x28 */ case SPC_SK_ILLEGAL_REQUEST: if ((0x20 == ssh.asc) && (0x0 == ssh.ascq)) return SG_LIB_CAT_INVALID_OP; else return SG_LIB_CAT_ILLEGAL_REQ; break; case SPC_SK_ABORTED_COMMAND: return SG_LIB_CAT_ABORTED_COMMAND; case SPC_SK_MISCOMPARE: return SG_LIB_CAT_MISCOMPARE; case SPC_SK_DATA_PROTECT: case SPC_SK_COMPLETED: case SPC_SK_COPY_ABORTED: case SPC_SK_VOLUME_OVERFLOW: return SG_LIB_CAT_SENSE; default: ; /* reserved and vendor specific sense keys fall through */ } } return SG_LIB_CAT_SENSE; } /* Beware: gives wrong answer for variable length command (opcode=0x7f) */ int sg_get_command_size(unsigned char opcode) { switch ((opcode >> 5) & 0x7) { case 0: return 6; case 1: case 2: case 6: case 7: return 10; case 3: case 5: return 12; break; case 4: return 16; default: return 10; } } void sg_get_command_name(const unsigned char * cmdp, int peri_type, int buff_len, char * buff) { int service_action; if ((NULL == buff) || (buff_len < 1)) return; else if (1 == buff_len) { buff[0] = '\0'; return; } if (NULL == cmdp) { my_snprintf(buff, buff_len, "%s", " command pointer"); return; } service_action = (SG_VARIABLE_LENGTH_CMD == cmdp[0]) ? ((cmdp[8] << 8) | cmdp[9]) : (cmdp[1] & 0x1f); sg_get_opcode_sa_name(cmdp[0], service_action, peri_type, buff_len, buff); } void sg_get_opcode_sa_name(unsigned char cmd_byte0, int service_action, int peri_type, int buff_len, char * buff) { const struct sg_lib_value_name_t * vnp; if ((NULL == buff) || (buff_len < 1)) return; else if (1 == buff_len) { buff[0] = '\0'; return; } switch ((int)cmd_byte0) { case SG_VARIABLE_LENGTH_CMD: vnp = get_value_name(sg_lib_variable_length_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Variable length service action=0x%x", service_action); break; case SG_MAINTENANCE_IN: vnp = get_value_name(sg_lib_maint_in_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Maintenance in service action=0x%x", service_action); break; case SG_MAINTENANCE_OUT: vnp = get_value_name(sg_lib_maint_out_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Maintenance out service action=0x%x", service_action); break; case SG_SERVICE_ACTION_IN_12: vnp = get_value_name(sg_lib_serv_in12_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Service action in(12)=0x%x", service_action); break; case SG_SERVICE_ACTION_OUT_12: vnp = get_value_name(sg_lib_serv_out12_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Service action out(12)=0x%x", service_action); break; case SG_SERVICE_ACTION_IN_16: vnp = get_value_name(sg_lib_serv_in16_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Service action in(16)=0x%x", service_action); break; case SG_SERVICE_ACTION_OUT_16: vnp = get_value_name(sg_lib_serv_out16_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Service action out(16)=0x%x", service_action); break; case SG_PERSISTENT_RESERVE_IN: vnp = get_value_name(sg_lib_pr_in_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Persistent reserve in, service " "action=0x%x", service_action); break; case SG_PERSISTENT_RESERVE_OUT: vnp = get_value_name(sg_lib_pr_out_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Persistent reserve out, service " "action=0x%x", service_action); break; case SG_EXTENDED_COPY: /* 'Extended copy' was renamed 'Third party copy out' in spc4r34 */ vnp = get_value_name(sg_lib_xcopy_sa_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Third party copy out, service " "action=0x%x", service_action); break; case SG_RECEIVE_COPY: /* 'Receive copy results' was renamed 'Third party copy in' in * spc4r34 */ vnp = get_value_name(sg_lib_rec_copy_sa_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Third party copy in, service " "action=0x%x", service_action); break; case SG_READ_BUFFER: /* spc4r34 requested treating mode as service action */ vnp = get_value_name(sg_lib_read_buff_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "Read buffer (%s)\n", vnp->name); else my_snprintf(buff, buff_len, "Read buffer, mode=0x%x", service_action); break; case SG_WRITE_BUFFER: /* spc4r34 requested treating mode as service action */ vnp = get_value_name(sg_lib_write_buff_arr, service_action, peri_type); if (vnp) my_snprintf(buff, buff_len, "Write buffer (%s)\n", vnp->name); else my_snprintf(buff, buff_len, "Write buffer, mode=0x%x", service_action); break; default: sg_get_opcode_name(cmd_byte0, peri_type, buff_len, buff); break; } } void sg_get_opcode_name(unsigned char cmd_byte0, int peri_type, int buff_len, char * buff) { const struct sg_lib_value_name_t * vnp; int grp; if ((NULL == buff) || (buff_len < 1)) return; else if (1 == buff_len) { buff[0] = '\0'; return; } if (SG_VARIABLE_LENGTH_CMD == cmd_byte0) { my_snprintf(buff, buff_len, "%s", "Variable length"); return; } grp = (cmd_byte0 >> 5) & 0x7; switch (grp) { case 0: case 1: case 2: case 4: case 5: vnp = get_value_name(sg_lib_normal_opcodes, cmd_byte0, peri_type); if (vnp) my_snprintf(buff, buff_len, "%s", vnp->name); else my_snprintf(buff, buff_len, "Opcode=0x%x", (int)cmd_byte0); break; case 3: my_snprintf(buff, buff_len, "Reserved [0x%x]", (int)cmd_byte0); break; case 6: case 7: my_snprintf(buff, buff_len, "Vendor specific [0x%x]", (int)cmd_byte0); break; default: my_snprintf(buff, buff_len, "Opcode=0x%x", (int)cmd_byte0); break; } } /* Iterates to next designation descriptor in the device identification * VPD page. The 'initial_desig_desc' should point to start of first * descriptor with 'page_len' being the number of valid bytes in that * and following descriptors. To start, 'off' should point to a negative * value, thereafter it should point to the value yielded by the previous * call. If 0 returned then 'initial_desig_desc + *off' should be a valid * descriptor; returns -1 if normal end condition and -2 for an abnormal * termination. Matches association, designator_type and/or code_set when * any of those values are greater than or equal to zero. */ int sg_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len, int * off, int m_assoc, int m_desig_type, int m_code_set) { const unsigned char * ucp; int k, c_set, assoc, desig_type; for (k = *off, ucp = initial_desig_desc ; (k + 3) < page_len; ) { k = (k < 0) ? 0 : (k + ucp[k + 3] + 4); if ((k + 4) > page_len) break; c_set = (ucp[k] & 0xf); if ((m_code_set >= 0) && (m_code_set != c_set)) continue; assoc = ((ucp[k + 1] >> 4) & 0x3); if ((m_assoc >= 0) && (m_assoc != assoc)) continue; desig_type = (ucp[k + 1] & 0xf); if ((m_desig_type >= 0) && (m_desig_type != desig_type)) continue; *off = k; return 0; } return (k == page_len) ? -1 : -2; } /* safe_strerror() contributed by Clayton Weaver * Allows for situation in which strerror() is given a wild value (or the * C library is incomplete) and returns NULL. Still not thread safe. */ static char safe_errbuf[64] = {'u', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'n', 'o', ':', ' ', 0}; char * safe_strerror(int errnum) { size_t len; char * errstr; if (errnum < 0) errnum = -errnum; errstr = strerror(errnum); if (NULL == errstr) { len = strlen(safe_errbuf); my_snprintf(safe_errbuf + len, sizeof(safe_errbuf) - len, "%i", errnum); return safe_errbuf; } return errstr; } /* Note the ASCII-hex output goes to stdout. [Most other output from functions * in this file go to sg_warnings_strm (default stderr).] * 'no_ascii' allows for 3 output types: * > 0 each line has address then up to 16 ASCII-hex bytes * = 0 in addition, the bytes are listed in ASCII to the right * < 0 only the ASCII-hex bytes are listed (i.e. without address) */ static void dStrHexFp(const char* str, int len, int no_ascii, FILE * fp) { const char * p = str; const char * formatstr; unsigned char c; char buff[82]; int a = 0; int bpstart = 5; const int cpstart = 60; int cpos = cpstart; int bpos = bpstart; int i, k, blen; if (len <= 0) return; blen = (int)sizeof(buff); formatstr = (0 == no_ascii) ? "%.76s\n" : "%.48s\n"; memset(buff, ' ', 80); buff[80] = '\0'; if (no_ascii < 0) { bpstart = 0; bpos = bpstart; for (k = 0; k < len; k++) { c = *p++; if (0 != (k % 16)) bpos += 3; if (bpos == (bpstart + (8 * 3))) bpos++; my_snprintf(&buff[bpos], blen - bpos, "%.2x", (int)(unsigned char)c); buff[bpos + 2] = ' '; if ((k > 0) && (0 == ((k + 1) % 16))) { fprintf(fp, formatstr, buff); bpos = bpstart; memset(buff, ' ', 80); } } if (bpos > bpstart) { buff[bpos + 2] = '\0'; fprintf(fp, "%s\n", buff); } return; } /* no_ascii>=0, start each line with address (offset) */ k = my_snprintf(buff + 1, blen - 1, "%.2x", a); buff[k + 1] = ' '; for (i = 0; i < len; i++) { c = *p++; bpos += 3; if (bpos == (bpstart + (9 * 3))) bpos++; my_snprintf(&buff[bpos], blen - bpos, "%.2x", (int)(unsigned char)c); buff[bpos + 2] = ' '; if (no_ascii) buff[cpos++] = ' '; else { if ((c < ' ') || (c >= 0x7f)) c = '.'; buff[cpos++] = c; } if (cpos > (cpstart + 15)) { fprintf(fp, formatstr, buff); bpos = bpstart; cpos = cpstart; a += 16; memset(buff, ' ', 80); k = my_snprintf(buff + 1, blen - 1, "%.2x", a); buff[k + 1] = ' '; } } if (cpos > cpstart) { buff[cpos] = '\0'; fprintf(fp, "%s\n", buff); } } void dStrHex(const char* str, int len, int no_ascii) { dStrHexFp(str, len, no_ascii, stdout); } void dStrHexErr(const char* str, int len, int no_ascii) { dStrHexFp(str, len, no_ascii, (sg_warnings_strm ? sg_warnings_strm : stderr)); } /* Read 'len' bytes from 'str' and output as ASCII-Hex bytes (space * separated) to 'b' not to exceed 'b_len' characters. Each line * starts with 'leadin' (NULL for no leadin) and there are 16 bytes * per line with an extra space between the 8th and 9th bytes. 'format' * is unused (currently), set to 0 . */ void dStrHexStr(const char* str, int len, const char * leadin, int format, int b_len, char * b) { const char * p = str; unsigned char c; char buff[122]; int bpstart, bpos, k, n; if (len <= 0) return; if (0 != format) { ; /* do nothing different for now */ } if (leadin) { bpstart = strlen(leadin); /* Cap leadin at 60 characters */ if (bpstart > 60) bpstart = 60; } else bpstart = 0; bpos = bpstart; n = 0; memset(buff, ' ', 120); buff[120] = '\0'; if (bpstart > 0) memcpy(buff, leadin, bpstart); for (k = 0; k < len; k++) { c = *p++; if (bpos == (bpstart + (8 * 3))) bpos++; my_snprintf(&buff[bpos], (int)sizeof(buff) - bpos, "%.2x", (int)(unsigned char)c); buff[bpos + 2] = ' '; if ((k > 0) && (0 == ((k + 1) % 16))) { n += my_snprintf(b + n, b_len - n, "%.*s\n", bpstart + 48, buff); if (n >= (b_len - 1)) return; bpos = bpstart; memset(buff, ' ', 120); if (bpstart > 0) memcpy(buff, leadin, bpstart); } else bpos += 3; } if (bpos > bpstart) n += my_snprintf(b + n, b_len - n, "%.*s\n", bpstart + 48, buff); return; } /* Returns 1 when executed on big endian machine; else returns 0. * Useful for displaying ATA identify words (which need swapping on a * big endian machine). */ int sg_is_big_endian() { union u_t { unsigned short s; unsigned char c[sizeof(unsigned short)]; } u; u.s = 0x0102; return (u.c[0] == 0x01); /* The lowest address contains the most significant byte */ } static unsigned short swapb_ushort(unsigned short u) { unsigned short r; r = (u >> 8) & 0xff; r |= ((u & 0xff) << 8); return r; } /* Note the ASCII-hex output goes to stdout. [Most other output from functions * in this file go to sg_warnings_strm (default stderr).] * 'no_ascii' allows for 3 output types: * > 0 each line has address then up to 8 ASCII-hex 16 bit words * = 0 in addition, the ASCI bytes pairs are listed to the right * = -1 only the ASCII-hex words are listed (i.e. without address) * = -2 only the ASCII-hex words, formatted for "hdparm --Istdin" * < -2 same as -1 * If 'swapb' non-zero then bytes in each word swapped. Needs to be set * for ATA IDENTIFY DEVICE response on big-endian machines. */ void dWordHex(const unsigned short* words, int num, int no_ascii, int swapb) { const unsigned short * p = words; unsigned short c; char buff[82]; unsigned char upp, low; int a = 0; const int bpstart = 3; const int cpstart = 52; int cpos = cpstart; int bpos = bpstart; int i, k, blen; if (num <= 0) return; blen = (int)sizeof(buff); memset(buff, ' ', 80); buff[80] = '\0'; if (no_ascii < 0) { for (k = 0; k < num; k++) { c = *p++; if (swapb) c = swapb_ushort(c); bpos += 5; my_snprintf(&buff[bpos], blen - bpos, "%.4x", (unsigned int)c); buff[bpos + 4] = ' '; if ((k > 0) && (0 == ((k + 1) % 8))) { if (-2 == no_ascii) printf("%.39s\n", buff +8); else printf("%.47s\n", buff); bpos = bpstart; memset(buff, ' ', 80); } } if (bpos > bpstart) { if (-2 == no_ascii) printf("%.39s\n", buff +8); else printf("%.47s\n", buff); } return; } /* no_ascii>=0, start each line with address (offset) */ k = my_snprintf(buff + 1, blen - 1, "%.2x", a); buff[k + 1] = ' '; for (i = 0; i < num; i++) { c = *p++; if (swapb) c = swapb_ushort(c); bpos += 5; my_snprintf(&buff[bpos], blen - bpos, "%.4x", (unsigned int)c); buff[bpos + 4] = ' '; if (no_ascii) { buff[cpos++] = ' '; buff[cpos++] = ' '; buff[cpos++] = ' '; } else { upp = (c >> 8) & 0xff; low = c & 0xff; if ((upp < 0x20) || (upp >= 0x7f)) upp = '.'; buff[cpos++] = upp; if ((low < 0x20) || (low >= 0x7f)) low = '.'; buff[cpos++] = low; buff[cpos++] = ' '; } if (cpos > (cpstart + 23)) { printf("%.76s\n", buff); bpos = bpstart; cpos = cpstart; a += 8; memset(buff, ' ', 80); k = my_snprintf(buff + 1, blen - 1, "%.2x", a); buff[k + 1] = ' '; } } if (cpos > cpstart) printf("%.76s\n", buff); } /* If the number in 'buf' can be decoded or the multiplier is unknown * then -1 is returned. Accepts a hex prefix (0x or 0X) or a decimal * multiplier suffix (as per GNU's dd (since 2002: SI and IEC 60027-2)). * Main (SI) multipliers supported: K, M, G. Ignore leading spaces and * tabs; accept comma, space, tab and hash as terminator. */ int sg_get_num(const char * buf) { int res, num, n, len; unsigned int unum; char * cp; const char * b; char c = 'c'; char c2, c3; char lb[16]; if ((NULL == buf) || ('\0' == buf[0])) return -1; len = strlen(buf); n = strspn(buf, " \t"); if (n > 0) { if (n == len) return -1; buf += n; len -=n; } /* following hack to keep C++ happy */ cp = strpbrk((char *)buf, " \t,#"); if (cp) { len = cp - buf; n = (int)sizeof(lb) - 1; len = (len < n) ? len : n; memcpy(lb, buf, len); lb[len] = '\0'; b = lb; } else b = buf; if (('0' == b[0]) && (('x' == b[1]) || ('X' == b[1]))) { res = sscanf(b + 2, "%x", &unum); num = unum; } else if ('H' == toupper((int)b[len - 1])) { res = sscanf(b, "%x", &unum); num = unum; } else res = sscanf(b, "%d%c%c%c", &num, &c, &c2, &c3); if (res < 1) return -1LL; else if (1 == res) return num; else { if (res > 2) c2 = toupper((int)c2); if (res > 3) c3 = toupper((int)c3); switch (toupper((int)c)) { case 'C': return num; case 'W': return num * 2; case 'B': return num * 512; case 'K': if (2 == res) return num * 1024; if (('B' == c2) || ('D' == c2)) return num * 1000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1024; return -1; case 'M': if (2 == res) return num * 1048576; if (('B' == c2) || ('D' == c2)) return num * 1000000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1048576; return -1; case 'G': if (2 == res) return num * 1073741824; if (('B' == c2) || ('D' == c2)) return num * 1000000000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1073741824; return -1; case 'X': cp = (char *)strchr(b, 'x'); if (NULL == cp) cp = (char *)strchr(b, 'X'); if (cp) { n = sg_get_num(cp + 1); if (-1 != n) return num * n; } return -1; default: if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "unrecognized multiplier\n"); return -1; } } } /* If the number in 'buf' can not be decoded then -1 is returned. Accepts a * hex prefix (0x or 0X) or a 'h' (or 'H') suffix; otherwise decimal is * assumed. Does not accept multipliers. Accept a comma (","), a whitespace * or newline as terminator. */ int sg_get_num_nomult(const char * buf) { int res, len, num; unsigned int unum; char * commap; if ((NULL == buf) || ('\0' == buf[0])) return -1; len = strlen(buf); commap = (char *)strchr(buf + 1, ','); if (('0' == buf[0]) && (('x' == buf[1]) || ('X' == buf[1]))) { res = sscanf(buf + 2, "%x", &unum); num = unum; } else if (commap && ('H' == toupper((int)*(commap - 1)))) { res = sscanf(buf, "%x", &unum); num = unum; } else if ((NULL == commap) && ('H' == toupper((int)buf[len - 1]))) { res = sscanf(buf, "%x", &unum); num = unum; } else res = sscanf(buf, "%d", &num); if (1 == res) return num; else return -1; } /* If the number in 'buf' can be decoded or the multiplier is unknown * then -1LL is returned. Accepts a hex prefix (0x or 0X) or a decimal * multiplier suffix (as per GNU's dd (since 2002: SI and IEC 60027-2)). * Main (SI) multipliers supported: K, M, G, T, P. Ignore leading spaces * and tabs; accept comma, space, tab and hash as terminator. */ int64_t sg_get_llnum(const char * buf) { int res, len, n; int64_t num, ll; uint64_t unum; char * cp; const char * b; char c = 'c'; char c2, c3; char lb[32]; if ((NULL == buf) || ('\0' == buf[0])) return -1LL; len = strlen(buf); n = strspn(buf, " \t"); if (n > 0) { if (n == len) return -1LL; buf += n; len -=n; } /* following hack to keep C++ happy */ cp = strpbrk((char *)buf, " \t,#"); if (cp) { len = cp - buf; n = (int)sizeof(lb) - 1; len = (len < n) ? len : n; memcpy(lb, buf, len); lb[len] = '\0'; b = lb; } else b = buf; if (('0' == b[0]) && (('x' == b[1]) || ('X' == b[1]))) { res = sscanf(b + 2, "%" SCNx64 "", &unum); num = unum; } else if ('H' == toupper((int)b[len - 1])) { res = sscanf(b, "%" SCNx64 "", &unum); num = unum; } else res = sscanf(b, "%" SCNd64 "%c%c%c", &num, &c, &c2, &c3); if (res < 1) return -1LL; else if (1 == res) return num; else { if (res > 2) c2 = toupper((int)c2); if (res > 3) c3 = toupper((int)c3); switch (toupper((int)c)) { case 'C': return num; case 'W': return num * 2; case 'B': return num * 512; case 'K': if (2 == res) return num * 1024; if (('B' == c2) || ('D' == c2)) return num * 1000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1024; return -1LL; case 'M': if (2 == res) return num * 1048576; if (('B' == c2) || ('D' == c2)) return num * 1000000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1048576; return -1LL; case 'G': if (2 == res) return num * 1073741824; if (('B' == c2) || ('D' == c2)) return num * 1000000000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1073741824; return -1LL; case 'T': if (2 == res) return num * 1099511627776LL; if (('B' == c2) || ('D' == c2)) return num * 1000000000000LL; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1099511627776LL; return -1LL; case 'P': if (2 == res) return num * 1099511627776LL * 1024; if (('B' == c2) || ('D' == c2)) return num * 1000000000000LL * 1000; if (('I' == c2) && (4 == res) && ('B' == c3)) return num * 1099511627776LL * 1024; return -1LL; case 'X': cp = (char *)strchr(b, 'x'); if (NULL == cp) cp = (char *)strchr(b, 'X'); if (cp) { ll = sg_get_llnum(cp + 1); if (-1LL != ll) return num * ll; } return -1LL; default: if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "unrecognized multiplier\n"); return -1LL; } } } /* Extract character sequence from ATA words as in the model string * in a IDENTIFY DEVICE response. Returns number of characters * written to 'ochars' before 0 character is found or 'num' words * are processed. */ int sg_ata_get_chars(const unsigned short * word_arr, int start_word, int num_words, int is_big_endian, char * ochars) { int k; unsigned short s; char a, b; char * op = ochars; for (k = start_word; k < (start_word + num_words); ++k) { s = word_arr[k]; if (is_big_endian) { a = s & 0xff; b = (s >> 8) & 0xff; } else { a = (s >> 8) & 0xff; b = s & 0xff; } if (a == 0) break; *op++ = a; if (b == 0) break; *op++ = b; } return op - ochars; } const char * sg_lib_version() { return sg_lib_version_str; } #ifdef SG_LIB_MINGW /* Non Unix OSes distinguish between text and binary files. Set text mode on fd. Does nothing in Unix. Returns negative number on failure. */ #include #include int sg_set_text_mode(int fd) { return setmode(fd, O_TEXT); } /* Set binary mode on fd. Does nothing in Unix. Returns negative number on failure. */ int sg_set_binary_mode(int fd) { return setmode(fd, O_BINARY); } #else /* For Unix the following functions are dummies. */ int sg_set_text_mode(int fd) { return fd; /* fd should be >= 0 */ } int sg_set_binary_mode(int fd) { return fd; } #endif ddpt-0.94/lib/Makefile.am0000644000175000017500000000221212254763724014210 0ustar douggdougglibsgutils2_la_SOURCES = \ sg_lib.c \ sg_lib_data.c \ sg_cmds_basic.c \ sg_cmds_basic2.c \ sg_cmds_extra.c \ sg_cmds_mmc.c \ sg_pt_common.c if OS_LINUX libsgutils2_la_SOURCES += \ sg_pt_linux.c \ sg_io_linux.c endif if OS_WIN32_MINGW libsgutils2_la_SOURCES += sg_pt_win32.c endif if OS_WIN32_CYGWIN libsgutils2_la_SOURCES += sg_pt_win32.c endif if OS_FREEBSD libsgutils2_la_SOURCES += sg_pt_freebsd.c endif if OS_SOLARIS libsgutils2_la_SOURCES += sg_pt_solaris.c endif if OS_OSF libsgutils2_la_SOURCES += sg_pt_osf1.c endif # For C++/clang testing ## CC = g++ ## CC = g++ ## CC = clang ## CC = clang++ # -std= can be c99, c11, gnu11, etc. Default is gnu89 (gnu90 is the same) AM_CFLAGS = -I ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W # AM_CFLAGS = -I ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c11 # AM_CFLAGS = -I ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c++11 lib_LTLIBRARIES = libsgutils2.la libsgutils2_la_LDFLAGS = -version-info 2:0:0 libsgutils2_la_LIBADD = @GETOPT_O_FILES@ @os_libs@ libsgutils2_la_DEPENDENCIES = @GETOPT_O_FILES@ ddpt-0.94/lib/sg_cmds_basic.c0000644000175000017500000005010312305171513015064 0ustar douggdougg/* * Copyright (c) 1999-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* * CONTENTS * Some SCSI commands are executed in many contexts and hence began * to appear in several sg3_utils utilities. This files centralizes * some of the low level command execution code. In most cases the * interpretation of the command response is left to the each * utility. */ #include #include #include #include #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_pt.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif static const char * version_str = "1.66 20140222"; #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define EBUFF_SZ 256 #define DEF_PT_TIMEOUT 60 /* 60 seconds */ #define START_PT_TIMEOUT 120 /* 120 seconds == 2 minutes */ #define LONG_PT_TIMEOUT 7200 /* 7,200 seconds == 120 minutes */ #define INQUIRY_CMD 0x12 #define INQUIRY_CMDLEN 6 #define REQUEST_SENSE_CMD 0x3 #define REQUEST_SENSE_CMDLEN 6 #define REPORT_LUNS_CMD 0xa0 #define REPORT_LUNS_CMDLEN 12 #define TUR_CMD 0x0 #define TUR_CMDLEN 6 #define INQUIRY_RESP_INITIAL_LEN 36 const char * sg_cmds_version() { return version_str; } /* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. */ int sg_cmds_open_device(const char * device_name, int read_only, int verbose) { return scsi_pt_open_device(device_name, read_only, verbose); } /* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. */ int sg_cmds_open_flags(const char * device_name, int flags, int verbose) { return scsi_pt_open_flags(device_name, flags, verbose); } /* Returns 0 if successful. If error in Unix returns negated errno. */ int sg_cmds_close_device(int device_fd) { return scsi_pt_close_device(device_fd); } static int sg_cmds_process_helper(const char * leadin, int mx_di_len, int resid, const unsigned char * sbp, int slen, int noisy, int verbose, int * o_sense_cat) { int scat, got; int n = 0; int check_data_in = 0; char b[512]; scat = sg_err_category_sense(sbp, slen); switch (scat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: case SG_LIB_CAT_NO_SENSE: n = 0; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_MEDIUM_HARD: ++check_data_in; /* drop through */ case SG_LIB_CAT_UNIT_ATTENTION: default: n = noisy; break; } if (verbose || n) { sg_get_sense_str(leadin, sbp, slen, (verbose > 1), sizeof(b), b); fprintf(sg_warnings_strm, "%s", b); if ((mx_di_len > 0) && (resid > 0)) { got = mx_di_len - resid; if ((verbose > 2) || check_data_in || (got > 0)) fprintf(sg_warnings_strm, " pass-through requested %d " "bytes (data-in) but got %d bytes\n", mx_di_len, got); } } if (o_sense_cat) *o_sense_cat = scat; return -2; } /* This is a helper function used by sg_cmds_* implementations after the * call to the pass-through. pt_res is returned from do_scsi_pt(). If valid * sense data is found it is decoded and output to sg_warnings_strm (def: * stderr); depending on the 'noisy' and 'verbose' settings. Returns -2 for * sense data (may not be fatal), -1 for failed, 0, or a positive number. If * 'mx_di_len > 0' then asks pass-through for resid and returns * (mx_di_len - resid); otherwise returns 0. So for data-in it should return * the actual number of bytes received. For data-out (to device) or no data * call with 'mx_di_len' set to 0 or less. If -2 returned then sense category * output via 'o_sense_cat' pointer (if not NULL). Note that several sense * categories also have data in bytes received; -2 is still returned. */ int sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, int pt_res, int mx_di_len, const unsigned char * sbp, int noisy, int verbose, int * o_sense_cat) { int got, cat, duration, slen, resid, resp_code; char b[1024]; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (NULL == leadin) leadin = ""; if (pt_res < 0) { if (noisy || verbose) fprintf(sg_warnings_strm, "%s: pass through os error: %s\n", leadin, safe_strerror(-pt_res)); return -1; } else if (SCSI_PT_DO_BAD_PARAMS == pt_res) { fprintf(sg_warnings_strm, "%s: bad pass through setup\n", leadin); return -1; } else if (SCSI_PT_DO_TIMEOUT == pt_res) { fprintf(sg_warnings_strm, "%s: pass through timeout\n", leadin); return -1; } if ((verbose > 2) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0)) fprintf(sg_warnings_strm, " duration=%d ms\n", duration); resid = (mx_di_len > 0) ? get_scsi_pt_resid(ptvp) : 0; slen = get_scsi_pt_sense_len(ptvp); switch ((cat = get_scsi_pt_result_category(ptvp))) { case SCSI_PT_RESULT_GOOD: if (slen > 7) { resp_code = sbp[0] & 0x7f; /* SBC referrals can have status=GOOD and sense_key=COMPLETED */ if (resp_code >= 0x70) { if (resp_code < 0x72) { if (SPC_SK_NO_SENSE != (0xf & sbp[2])) sg_err_category_sense(sbp, slen); } else if (resp_code < 0x74) { if (SPC_SK_NO_SENSE != (0xf & sbp[1])) sg_err_category_sense(sbp, slen); } } } if (mx_di_len > 0) { got = mx_di_len - resid; if ((verbose > 1) && (resid > 0)) fprintf(sg_warnings_strm, " %s: pass-through requested " "%d bytes (data-in) but got %d bytes\n", leadin, mx_di_len, got); return got; } else return 0; case SCSI_PT_RESULT_STATUS: /* other than GOOD and CHECK CONDITION */ if (verbose || noisy) { sg_get_scsi_status_str(get_scsi_pt_status_response(ptvp), sizeof(b), b); fprintf(sg_warnings_strm, "%s: scsi status: %s\n", leadin, b); } return -1; case SCSI_PT_RESULT_SENSE: return sg_cmds_process_helper(leadin, mx_di_len, resid, sbp, slen, noisy, verbose, o_sense_cat); case SCSI_PT_RESULT_TRANSPORT_ERR: if (verbose || noisy) { get_scsi_pt_transport_err_str(ptvp, sizeof(b), b); fprintf(sg_warnings_strm, "%s: transport: %s\n", leadin, b); } if ((SAM_STAT_CHECK_CONDITION == get_scsi_pt_status_response(ptvp)) && (slen > 0)) return sg_cmds_process_helper(leadin, mx_di_len, resid, sbp, slen, noisy, verbose, o_sense_cat); else return -1; case SCSI_PT_RESULT_OS_ERR: if (verbose || noisy) { get_scsi_pt_os_err_str(ptvp, sizeof(b), b); fprintf(sg_warnings_strm, "%s: os: %s\n", leadin, b); } return -1; default: fprintf(sg_warnings_strm, "%s: unknown pass through result " "category (%d)\n", leadin, cat); return -1; } } /* Invokes a SCSI INQUIRY command and yields the response * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_MALFORMED -> bad response, -1 -> other errors */ int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp, int mx_resp_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; unsigned char * up; struct sg_pt_base * ptvp; if (cmddt) inqCmdBlk[1] |= 2; if (evpd) inqCmdBlk[1] |= 1; inqCmdBlk[2] = (unsigned char)pg_op; /* 16 bit allocation length (was 8) is a recent SPC-3 addition */ inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); inqCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " inquiry cdb: "); for (k = 0; k < INQUIRY_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", inqCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } if (resp && (mx_resp_len > 0)) { up = (unsigned char *)resp; up[0] = 0x7f; /* defensive prefill */ if (mx_resp_len > 4) up[4] = 0; } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "inquiry: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, inqCmdBlk, sizeof(inqCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "inquiry", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); destruct_scsi_pt_obj(ptvp); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else if (ret < 4) { if (verbose) fprintf(sg_warnings_strm, "inquiry: got too few " "bytes (%d)\n", ret); ret = SG_LIB_CAT_MALFORMED; } else ret = 0; return ret; } /* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response. * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_MALFORMED -> bad response, -1 -> other errors */ int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; unsigned char inq_resp[INQUIRY_RESP_INITIAL_LEN]; struct sg_pt_base * ptvp; if (inq_data) { memset(inq_data, 0, sizeof(* inq_data)); inq_data->peripheral_qualifier = 0x3; inq_data->peripheral_type = 0x1f; } inqCmdBlk[4] = (unsigned char)sizeof(inq_resp); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " inquiry cdb: "); for (k = 0; k < INQUIRY_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", inqCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } memset(inq_resp, 0, sizeof(inq_resp)); inq_resp[0] = 0x7f; /* defensive prefill */ ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "inquiry: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, inqCmdBlk, sizeof(inqCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, inq_resp, sizeof(inq_resp)); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "inquiry", res, sizeof(inq_resp), sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else if (ret < 4) { if (verbose) fprintf(sg_warnings_strm, "inquiry: got too few " "bytes (%d)\n", ret); ret = SG_LIB_CAT_MALFORMED; } else ret = 0; if (0 == ret) { inq_data->peripheral_qualifier = (inq_resp[0] >> 5) & 0x7; inq_data->peripheral_type = inq_resp[0] & 0x1f; inq_data->rmb = (inq_resp[1] & 0x80) ? 1 : 0; inq_data->version = inq_resp[2]; inq_data->byte_3 = inq_resp[3]; inq_data->byte_5 = inq_resp[5]; inq_data->byte_6 = inq_resp[6]; inq_data->byte_7 = inq_resp[7]; memcpy(inq_data->vendor, inq_resp + 8, 8); memcpy(inq_data->product, inq_resp + 16, 16); memcpy(inq_data->revision, inq_resp + 32, 4); } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI TEST UNIT READY command. * 'pack_id' is just for diagnostics, safe to set to 0. * Looks for progress indicator if 'progress' non-NULL; * if found writes value [0..65535] else write -1. * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> * device not ready, -1 -> other failure */ int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char turCmdBlk[TUR_CMDLEN] = {TUR_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " test unit ready cdb: "); for (k = 0; k < TUR_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", turCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "test unit ready: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, turCmdBlk, sizeof(turCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_packet_id(ptvp, pack_id); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "test unit ready", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { if (progress) { int slen = get_scsi_pt_sense_len(ptvp); if (! sg_get_sense_progress_fld(sense_b, slen, progress)) *progress = -1; } switch (sense_cat) { case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI TEST UNIT READY command. * 'pack_id' is just for diagnostics, safe to set to 0. * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> * device not ready, -1 -> other failure */ int sg_ll_test_unit_ready(int sg_fd, int pack_id, int noisy, int verbose) { return sg_ll_test_unit_ready_progress(sg_fd, pack_id, NULL, noisy, verbose); } /* Invokes a SCSI REQUEST SENSE command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Request Sense not supported??, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other failure */ int sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len, int noisy, int verbose) { int k, ret, res, sense_cat; unsigned char rsCmdBlk[REQUEST_SENSE_CMDLEN] = {REQUEST_SENSE_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (desc) rsCmdBlk[1] |= 0x1; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (mx_resp_len > 0xff) { fprintf(sg_warnings_strm, "mx_resp_len cannot exceed 255\n"); return -1; } rsCmdBlk[4] = mx_resp_len & 0xff; if (verbose) { fprintf(sg_warnings_strm, " Request Sense cmd: "); for (k = 0; k < REQUEST_SENSE_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rsCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "request sense: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rsCmdBlk, sizeof(rsCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "request sense", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_NOT_READY: /* shouldn't happen ?? */ default: ret = -1; break; } } else { if ((mx_resp_len >= 8) && (ret < 8)) { if (verbose) fprintf(sg_warnings_strm, " request sense: got %d " "bytes in response, too short\n", ret); ret = -1; } else ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI REPORT LUNS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Luns not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ int sg_ll_report_luns(int sg_fd, int select_report, void * resp, int mx_resp_len, int noisy, int verbose) { int k, ret, res, sense_cat; unsigned char rlCmdBlk[REPORT_LUNS_CMDLEN] = {REPORT_LUNS_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; rlCmdBlk[2] = select_report & 0xff; rlCmdBlk[6] = (mx_resp_len >> 24) & 0xff; rlCmdBlk[7] = (mx_resp_len >> 16) & 0xff; rlCmdBlk[8] = (mx_resp_len >> 8) & 0xff; rlCmdBlk[9] = mx_resp_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " report luns cdb: "); for (k = 0; k < REPORT_LUNS_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rlCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "report luns: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rlCmdBlk, sizeof(rlCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "report luns", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: case SG_LIB_CAT_NOT_READY: /* shouldn't happen ?? */ ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } ddpt-0.94/lib/Makefile.in0000644000175000017500000005367512253616765014245 0ustar douggdougg# Makefile.in generated by automake 1.13.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @OS_LINUX_TRUE@am__append_1 = \ @OS_LINUX_TRUE@ sg_pt_linux.c \ @OS_LINUX_TRUE@ sg_io_linux.c @OS_WIN32_MINGW_TRUE@am__append_2 = sg_pt_win32.c @OS_WIN32_CYGWIN_TRUE@am__append_3 = sg_pt_win32.c @OS_FREEBSD_TRUE@am__append_4 = sg_pt_freebsd.c @OS_SOLARIS_TRUE@am__append_5 = sg_pt_solaris.c @OS_OSF_TRUE@am__append_6 = sg_pt_osf1.c subdir = lib DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__libsgutils2_la_SOURCES_DIST = sg_lib.c sg_lib_data.c \ sg_cmds_basic.c sg_cmds_basic2.c sg_cmds_extra.c sg_cmds_mmc.c \ sg_pt_common.c sg_pt_linux.c sg_io_linux.c sg_pt_win32.c \ sg_pt_freebsd.c sg_pt_solaris.c sg_pt_osf1.c @OS_LINUX_TRUE@am__objects_1 = sg_pt_linux.lo sg_io_linux.lo @OS_WIN32_MINGW_TRUE@am__objects_2 = sg_pt_win32.lo @OS_WIN32_CYGWIN_TRUE@am__objects_3 = sg_pt_win32.lo @OS_FREEBSD_TRUE@am__objects_4 = sg_pt_freebsd.lo @OS_SOLARIS_TRUE@am__objects_5 = sg_pt_solaris.lo @OS_OSF_TRUE@am__objects_6 = sg_pt_osf1.lo am_libsgutils2_la_OBJECTS = sg_lib.lo sg_lib_data.lo sg_cmds_basic.lo \ sg_cmds_basic2.lo sg_cmds_extra.lo sg_cmds_mmc.lo \ sg_pt_common.lo $(am__objects_1) $(am__objects_2) \ $(am__objects_3) $(am__objects_4) $(am__objects_5) \ $(am__objects_6) libsgutils2_la_OBJECTS = $(am_libsgutils2_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libsgutils2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsgutils2_la_LDFLAGS) $(LDFLAGS) -o \ $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libsgutils2_la_SOURCES) DIST_SOURCES = $(am__libsgutils2_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETOPT_O_FILES = @GETOPT_O_FILES@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ libsgutils2_la_SOURCES = sg_lib.c sg_lib_data.c sg_cmds_basic.c \ sg_cmds_basic2.c sg_cmds_extra.c sg_cmds_mmc.c sg_pt_common.c \ $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) # For C++/clang testing # -std= can be c99, c11, gnu11, etc. Default is gnu89 (gnu90 is the same) AM_CFLAGS = -I ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W # AM_CFLAGS = -I ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c11 # AM_CFLAGS = -I ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c++11 lib_LTLIBRARIES = libsgutils2.la libsgutils2_la_LDFLAGS = -version-info 2:0:0 libsgutils2_la_LIBADD = @GETOPT_O_FILES@ @os_libs@ libsgutils2_la_DEPENDENCIES = @GETOPT_O_FILES@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libsgutils2.la: $(libsgutils2_la_OBJECTS) $(libsgutils2_la_DEPENDENCIES) $(EXTRA_libsgutils2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsgutils2_la_LINK) -rpath $(libdir) $(libsgutils2_la_OBJECTS) $(libsgutils2_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_basic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_basic2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_extra.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_mmc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_io_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib_data.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_freebsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_osf1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_solaris.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_win32.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ddpt-0.94/lib/sg_io_linux.c0000644000175000017500000001672112024633456014642 0ustar douggdougg/* * Copyright (c) 1999-2012 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #include #include #include // need to include the file in the build when sg_scan is built for Win32. // Hence the following guard ... // #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef SG_LIB_LINUX #include "sg_io_linux.h" /* Version 1.04 20120914 */ void sg_print_masked_status(int masked_status) { int scsi_status = (masked_status << 1) & 0x7e; sg_print_scsi_status(scsi_status); } static const char * linux_host_bytes[] = { "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE", "DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE", "DID_NEXUS_FAILURE", }; #define LINUX_HOST_BYTES_SZ \ (int)(sizeof(linux_host_bytes) / sizeof(linux_host_bytes[0])) void sg_print_host_status(int host_status) { if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "Host_status=0x%02x ", host_status); if ((host_status < 0) || (host_status >= LINUX_HOST_BYTES_SZ)) fprintf(sg_warnings_strm, "is invalid "); else fprintf(sg_warnings_strm, "[%s] ", linux_host_bytes[host_status]); } static const char * linux_driver_bytes[] = { "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE" }; #define LINUX_DRIVER_BYTES_SZ \ (int)(sizeof(linux_driver_bytes) / sizeof(linux_driver_bytes[0])) static const char * linux_driver_suggests[] = { "SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", "UNKNOWN","UNKNOWN","UNKNOWN", "SUGGEST_SENSE" }; #define LINUX_DRIVER_SUGGESTS_SZ \ (int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0])) void sg_print_driver_status(int driver_status) { int driv, sugg; const char * driv_cp = "invalid"; const char * sugg_cp = "invalid"; driv = driver_status & SG_LIB_DRIVER_MASK; if (driv < LINUX_DRIVER_BYTES_SZ) driv_cp = linux_driver_bytes[driv]; sugg = (driver_status & SG_LIB_SUGGEST_MASK) >> 4; if (sugg < LINUX_DRIVER_SUGGESTS_SZ) sugg_cp = linux_driver_suggests[sugg]; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "Driver_status=0x%02x", driver_status); fprintf(sg_warnings_strm, " [%s, %s] ", driv_cp, sugg_cp); } /* Returns 1 if no errors found and thus nothing printed; otherwise prints error/warning (prefix by 'leadin') and returns 0. */ static int sg_linux_sense_print(const char * leadin, int scsi_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len, int raw_sinfo) { int done_leadin = 0; int done_sense = 0; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; scsi_status &= 0x7e; /*sanity */ if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status)) return 1; /* No problems */ if (0 != scsi_status) { if (leadin) fprintf(sg_warnings_strm, "%s: ", leadin); done_leadin = 1; fprintf(sg_warnings_strm, "SCSI status: "); sg_print_scsi_status(scsi_status); fprintf(sg_warnings_strm, "\n"); if (sense_buffer && ((scsi_status == SAM_STAT_CHECK_CONDITION) || (scsi_status == SAM_STAT_COMMAND_TERMINATED))) { /* SAM_STAT_COMMAND_TERMINATED is obsolete */ sg_print_sense(0, sense_buffer, sb_len, raw_sinfo); done_sense = 1; } } if (0 != host_status) { if (leadin && (! done_leadin)) fprintf(sg_warnings_strm, "%s: ", leadin); if (done_leadin) fprintf(sg_warnings_strm, "plus...: "); else done_leadin = 1; sg_print_host_status(host_status); fprintf(sg_warnings_strm, "\n"); } if (0 != driver_status) { if (done_sense && (SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status))) return 0; if (leadin && (! done_leadin)) fprintf(sg_warnings_strm, "%s: ", leadin); if (done_leadin) fprintf(sg_warnings_strm, "plus...: "); else done_leadin = 1; sg_print_driver_status(driver_status); fprintf(sg_warnings_strm, "\n"); if (sense_buffer && (! done_sense) && (SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status))) sg_print_sense(0, sense_buffer, sb_len, raw_sinfo); } return 0; } #ifdef SG_IO int sg_normalize_sense(const struct sg_io_hdr * hp, struct sg_scsi_sense_hdr * sshp) { if ((NULL == hp) || (0 == hp->sb_len_wr)) { if (sshp) memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr)); return 0; } return sg_scsi_normalize_sense(hp->sbp, hp->sb_len_wr, sshp); } /* Returns 1 if no errors found and thus nothing printed; otherwise returns 0. */ int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp, int raw_sinfo) { return sg_linux_sense_print(leadin, hp->status, hp->host_status, hp->driver_status, hp->sbp, hp->sb_len_wr, raw_sinfo); } #endif /* Returns 1 if no errors found and thus nothing printed; otherwise returns 0. */ int sg_chk_n_print(const char * leadin, int masked_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len, int raw_sinfo) { int scsi_status = (masked_status << 1) & 0x7e; return sg_linux_sense_print(leadin, scsi_status, host_status, driver_status, sense_buffer, sb_len, raw_sinfo); } #ifdef SG_IO int sg_err_category3(struct sg_io_hdr * hp) { return sg_err_category_new(hp->status, hp->host_status, hp->driver_status, hp->sbp, hp->sb_len_wr); } #endif int sg_err_category(int masked_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len) { int scsi_status = (masked_status << 1) & 0x7e; return sg_err_category_new(scsi_status, host_status, driver_status, sense_buffer, sb_len); } int sg_err_category_new(int scsi_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len) { int masked_driver_status = (SG_LIB_DRIVER_MASK & driver_status); scsi_status &= 0x7e; if ((0 == scsi_status) && (0 == host_status) && (0 == masked_driver_status)) return SG_LIB_CAT_CLEAN; if ((SAM_STAT_CHECK_CONDITION == scsi_status) || (SAM_STAT_COMMAND_TERMINATED == scsi_status) || (SG_LIB_DRIVER_SENSE == masked_driver_status)) return sg_err_category_sense(sense_buffer, sb_len); if (0 != host_status) { if ((SG_LIB_DID_NO_CONNECT == host_status) || (SG_LIB_DID_BUS_BUSY == host_status) || (SG_LIB_DID_TIME_OUT == host_status)) return SG_LIB_CAT_TIMEOUT; } if (SG_LIB_DRIVER_TIMEOUT == masked_driver_status) return SG_LIB_CAT_TIMEOUT; return SG_LIB_CAT_OTHER; } #endif ddpt-0.94/lib/sg_lib_data.c0000644000175000017500000016617712316660506014566 0ustar douggdougg/* * Copyright (c) 2007-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #include "sg_lib.h" #include "sg_lib_data.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif const char * sg_lib_version_str = "1.96 20140401"; /* spc4r36s, sbc4r01 */ #ifdef SG_SCSI_STRINGS struct sg_lib_value_name_t sg_lib_normal_opcodes[] = { {0, 0, "Test Unit Ready"}, {0x1, 0, "Rezero Unit"}, {0x1, PDT_TAPE, "Rewind"}, {0x3, 0, "Request Sense"}, {0x4, 0, "Format Unit"}, {0x4, PDT_TAPE, "Format medium"}, {0x4, PDT_PRINTER, "Format"}, {0x5, 0, "Read Block Limits"}, {0x7, 0, "Reassign Blocks"}, {0x7, PDT_MCHANGER, "Initialize element status"}, {0x8, 0, "Read(6)"}, /* obsolete in sbc3r30 */ {0x8, PDT_PROCESSOR, "Receive"}, {0xa, 0, "Write(6)"}, /* obsolete in sbc3r30 */ {0xa, PDT_PRINTER, "Print"}, {0xa, PDT_PROCESSOR, "Send"}, {0xb, 0, "Seek(6)"}, {0xb, PDT_TAPE, "Set capacity"}, {0xb, PDT_PRINTER, "Slew and print"}, {0xf, 0, "Read reverse(6)"}, {0x10, 0, "Write filemarks(6)"}, {0x10, PDT_PRINTER, "Synchronize buffer"}, {0x11, 0, "Space(6)"}, {0x12, 0, "Inquiry"}, {0x13, 0, "Verify(6)"}, /* SSC */ {0x14, 0, "Recover buffered data"}, {0x15, 0, "Mode select(6)"}, /* SBC-3 r31 recommends Mode select(10) */ {0x16, 0, "Reserve(6)"}, /* obsolete in SPC-4 r11 */ {0x16, PDT_MCHANGER, "Reserve element(6)"}, {0x17, 0, "Release(6)"}, /* obsolete in SPC-4 r11 */ {0x17, PDT_MCHANGER, "Release element(6)"}, {0x18, 0, "Copy"}, /* obsolete in SPC-4 r11 */ {0x19, 0, "Erase(6)"}, {0x1a, 0, "Mode sense(6)"}, /* SBC-3 r31 recommends Mode sense(10) */ {0x1b, 0, "Start stop unit"}, {0x1b, PDT_TAPE, "Load unload"}, {0x1b, PDT_ADC, "Load unload"}, {0x1b, PDT_PRINTER, "Stop print"}, {0x1c, 0, "Receive diagnostic results"}, {0x1d, 0, "Send diagnostic"}, {0x1e, 0, "Prevent allow medium removal"}, {0x23, 0, "Read Format capacities"}, {0x24, 0, "Set window"}, {0x25, 0, "Read capacity(10)"}, /* SBC-3 r31 recommends Read capacity(16) */ {0x25, PDT_OCRW, "Read card capacity"}, {0x28, 0, "Read(10)"}, /* SBC-3 r31 recommends Read(16) */ {0x29, 0, "Read generation"}, {0x2a, 0, "Write(10)"}, /* SBC-3 r31 recommends Write(16) */ {0x2b, 0, "Seek(10)"}, {0x2b, PDT_TAPE, "Locate(10)"}, {0x2b, PDT_MCHANGER, "Position to element"}, {0x2c, 0, "Erase(10)"}, {0x2d, 0, "Read updated block"}, {0x2e, 0, "Write and verify(10)"}, /* SBC-3 r31 recommends Write and verify(16) */ {0x2f, 0, "Verify(10)"}, /* SBC-3 r31 recommends Verify(16) */ {0x30, 0, "Search data high(10)"}, {0x31, 0, "Search data equal(10)"}, {0x32, 0, "Search data low(10)"}, {0x33, 0, "Set limits(10)"}, {0x34, 0, "Pre-fetch(10)"}, /* SBC-3 r31 recommends Pre-fetch(16) */ {0x34, PDT_TAPE, "Read position"}, {0x35, 0, "Synchronize cache(10)"}, /* SBC-3 r31 recommends Synchronize cache(16) */ {0x36, 0, "Lock unlock cache(10)"}, {0x37, 0, "Read defect data(10)"}, /* SBC-3 r31 recommends Read defect data(12) */ {0x37, PDT_MCHANGER, "Initialize element status with range"}, {0x38, 0, "Medium scan"}, {0x39, 0, "Compare"}, /* obsolete in SPC-4 r11 */ {0x3a, 0, "Copy and verify"}, /* obsolete in SPC-4 r11 */ {0x3b, 0, "Write buffer"}, {0x3c, 0, "Read buffer"}, {0x3d, 0, "Update block"}, {0x3e, 0, "Read long(10)"}, /* SBC-3 r31 recommends Read long(16) */ {0x3f, 0, "Write long(10)"}, /* SBC-3 r31 recommends Write long(16) */ {0x40, 0, "Change definition"}, /* obsolete in SPC-4 r11 */ {0x41, 0, "Write same(10)"}, /* SBC-3 r31 recommends Write same(16) */ {0x42, 0, "Unmap"}, /* added SPC-4 rev 18 */ {0x42, PDT_MMC, "Read sub-channel"}, {0x43, PDT_MMC, "Read TOC/PMA/ATIP"}, {0x44, 0, "Report density support"}, {0x45, PDT_MMC, "Play audio(10)"}, {0x46, PDT_MMC, "Get configuration"}, {0x47, PDT_MMC, "Play audio msf"}, {0x48, 0, "Sanitize"}, {0x4a, PDT_MMC, "Get event status notification"}, {0x4b, PDT_MMC, "Pause/resume"}, {0x4c, 0, "Log select"}, {0x4d, 0, "Log sense"}, {0x4e, 0, "Stop play/scan"}, {0x50, 0, "Xdwrite(10)"}, /* obsolete in SBC-3 r31 */ {0x51, 0, "Xpwrite(10)"}, {0x51, PDT_MMC, "Read disk information"}, {0x52, 0, "Xdread(10)"}, /* obsolete in SBC-3 r31 */ {0x52, PDT_MMC, "Read track information"}, {0x53, 0, "Reserve track"}, {0x54, 0, "Send OPC information"}, {0x55, 0, "Mode select(10)"}, {0x56, 0, "Reserve(10)"}, /* obsolete in SPC-4 r11 */ {0x56, PDT_MCHANGER, "Reserve element(10)"}, {0x57, 0, "Release(10)"}, /* obsolete in SPC-4 r11 */ {0x57, PDT_MCHANGER, "Release element(10)"}, {0x58, 0, "Repair track"}, {0x5a, 0, "Mode sense(10)"}, {0x5b, 0, "Close track/session"}, {0x5c, 0, "Read buffer capacity"}, {0x5d, 0, "Send cue sheet"}, {0x5e, 0, "Persistent reserve in"}, {0x5f, 0, "Persistent reserve out"}, {0x7e, 0, "Extended cdb (XCBD)"}, /* added in SPC-4 r12 */ {0x80, 0, "Xdwrite extended(16)"}, {0x80, PDT_TAPE, "Write filemarks(16)"}, {0x81, 0, "Rebuild(16)"}, {0x81, PDT_TAPE, "Read reverse(16)"}, {0x82, 0, "Regenerate(16)"}, {0x83, 0, "Third party copy out"}, /* Extended copy, before spc4r34 */ /* Following was "Receive copy results", before spc4r34 */ {0x84, 0, "Third party copy in"}, {0x85, 0, "ATA pass-through(16)"}, /* was 0x98 in spc3 rev21c */ {0x86, 0, "Access control in"}, {0x87, 0, "Access control out"}, {0x88, 0, "Read(16)"}, {0x89, 0, "Compare and write"}, {0x8a, 0, "Write(16)"}, {0x8b, 0, "Orwrite(16)"}, {0x8c, 0, "Read attribute"}, {0x8d, 0, "Write attribute"}, {0x8e, 0, "Write and verify(16)"}, {0x8f, 0, "Verify(16)"}, {0x90, 0, "Pre-fetch(16)"}, {0x91, 0, "Synchronize cache(16)"}, {0x91, PDT_TAPE, "Space(16)"}, {0x92, 0, "Lock unlock cache(16)"}, {0x92, PDT_TAPE, "Locate(16)"}, {0x93, 0, "Write same(16)"}, {0x93, PDT_TAPE, "Erase(16)"}, {0x9d, 0, "Service action bidirectional"}, /* added spc4r35 */ {0x9e, 0, "Service action in(16)"}, {0x9f, 0, "Service action out(16)"}, {0xa0, 0, "Report luns"}, {0xa1, 0, "ATA pass-through(12)"}, {0xa1, PDT_MMC, "Blank"}, {0xa2, 0, "Security protocol in"}, {0xa3, 0, "Maintenance in"}, {0xa3, PDT_MMC, "Send key"}, {0xa4, 0, "Maintenance out"}, {0xa4, PDT_MMC, "Report key"}, {0xa5, 0, "Move medium"}, {0xa5, PDT_MMC, "Play audio(12)"}, {0xa6, 0, "Exchange medium"}, {0xa6, PDT_MMC, "Load/unload medium"}, {0xa7, 0, "Move medium attached"}, {0xa7, PDT_MMC, "Set read ahead"}, {0xa8, 0, "Read(12)"}, /* SBC-3 r31 recommends Read(16) */ {0xa9, 0, "Service action out(12)"}, {0xaa, 0, "Write(12)"}, /* SBC-3 r31 recommends Write(16) */ {0xab, 0, "Service action in(12)"}, {0xac, 0, "erase(12)"}, {0xac, PDT_MMC, "Get performance"}, {0xad, PDT_MMC, "Read DVD/BD structure"}, {0xae, 0, "Write and verify(12)"}, /* SBC-3 r31 recommends Write and verify(16) */ {0xaf, 0, "Verify(12)"}, /* SBC-3 r31 recommends Verify(16) */ {0xb0, 0, "Search data high(12)"}, {0xb1, 0, "Search data equal(12)"}, {0xb1, PDT_MCHANGER, "Open/close import/export element"}, {0xb2, 0, "Search data low(12)"}, {0xb3, 0, "Set limits(12)"}, {0xb4, 0, "Read element status attached"}, {0xb5, 0, "Security protocol out"}, {0xb5, PDT_MCHANGER, "Request volume element address"}, {0xb6, 0, "Send volume tag"}, {0xb6, PDT_MMC, "Set streaming"}, {0xb7, 0, "Read defect data(12)"}, {0xb8, 0, "Read element status"}, {0xb9, 0, "Read CD msf"}, {0xba, 0, "Redundancy group in"}, {0xba, PDT_MMC, "Scan"}, {0xbb, 0, "Redundancy group out"}, {0xbb, PDT_MMC, "Set CD speed"}, {0xbc, 0, "Spare in"}, {0xbd, 0, "Spare out"}, {0xbd, PDT_MMC, "Mechanism status"}, {0xbe, 0, "Volume set in"}, {0xbe, PDT_MMC, "Read CD"}, {0xbf, 0, "Volume set out"}, {0xbf, PDT_MMC, "Send DVD/BD structure"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_read_buff_arr[] = { /* opcode 0x3c */ {0x0, 0, "combined header and data [or multiple modes]"}, {0x2, 0, "data"}, {0x3, 0, "descriptor"}, {0xa, 0, "read data from echo buffer"}, {0xb, 0, "echo buffer descriptor"}, {0x1a, 0, "enable expander comms protocol and echo buffer"}, {0x1c, 0, "error history"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_write_buff_arr[] = { /* opcode 0x3b */ {0x0, 0, "combined header and data [or multiple modes]"}, {0x2, 0, "data"}, {0x4, 0, "download microcode and activate"}, {0x5, 0, "download microcode, save, and activate"}, {0x6, 0, "download microcode with offsets and activate"}, {0x7, 0, "download microcode with offsets, save, and activate"}, {0xa, 0, "write data to echo buffer"}, {0xd, 0, "download microcode with offsets, select activation events, " " save and defer activate"}, {0xe, 0, "download microcode with offsets, save and defer activate"}, {0xf, 0, "activate deferred microcode"}, {0x1a, 0, "enable expander comms protocol and echo buffer"}, {0x1b, 0, "disable expander comms protocol"}, {0x1c, 0, "download application client error history"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_maint_in_arr[] = { /* opcode 0xa3 */ {0x5, 0, "Report identifying information"}, /* was "Report device identifier" prior to spc4r07 */ {0xa, 0, "Report target port groups"}, {0xb, 0, "Report aliases"}, {0xc, 0, "Report supported operation codes"}, {0xd, 0, "Report supported task management functions"}, {0xe, 0, "Report priority"}, {0xf, 0, "Report timestamp"}, {0x10, 0, "Management protocol in"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_maint_out_arr[] = { /* opcode 0xa4 */ {0x6, 0, "Set identifying information"}, /* was "Set device identifier" prior to spc4r07 */ {0xa, 0, "Set target port groups"}, {0xb, 0, "Change aliases"}, {0xc, 0, "Remove I_T nexus"}, {0xe, 0, "Set priority"}, {0xf, 0, "Set timestamp"}, {0x10, 0, "Management protocol out"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_in12_arr[] = { /* opcode 0xab */ {0x1, 0, "Read media serial number"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_out12_arr[] = { /* opcode 0xa9 */ {0xff, 0, "Impossible command name"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = { /* opcode 0x9e */ {0x10, 0, "Read capacity(16)"}, {0x11, 0, "Read long(16)"}, {0x12, 0, "Get LBA status"}, {0x13, 0, "Report referrals"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_out16_arr[] = { /* opcode 0x9f */ {0x11, 0, "Write long(16)"}, {0x1f, PDT_ADC, "Notify data transfer device(16)"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_bidi_arr[] = { /* opcode 0x9d */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_pr_in_arr[] = { /* opcode 0x5e */ {0x0, 0, "Persistent reserve in, read keys"}, {0x1, 0, "Persistent reserve in, read reservation"}, {0x2, 0, "Persistent reserve in, report capabilities"}, {0x3, 0, "Persistent reserve in, read full status"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_pr_out_arr[] = { /* opcode 0x5f */ {0x0, 0, "Persistent reserve out, register"}, {0x1, 0, "Persistent reserve out, reserve"}, {0x2, 0, "Persistent reserve out, release"}, {0x3, 0, "Persistent reserve out, clear"}, {0x4, 0, "Persistent reserve out, preempt"}, {0x5, 0, "Persistent reserve out, preempt and abort"}, {0x6, 0, "Persistent reserve out, register and ignore existing key"}, {0x7, 0, "Persistent reserve out, register and move"}, {0x8, 0, "Persistent reserve out, replace lost reservation"}, {0xffff, 0, NULL}, }; /* 'Extended copy' was renamed 'Third party copy in' in spc4r34 */ /* LID1 is an abbreviation of List Identifier length of 1 byte */ struct sg_lib_value_name_t sg_lib_xcopy_sa_arr[] = { /* opcode 0x83 */ {0x0, 0, "Extended copy(LID1)"}, {0x1, 0, "Extended copy(LID4)"}, {0x10, 0, "Populate token"}, {0x11, 0, "Write using token"}, {0x1c, 0, "Copy operation abort"}, {0xffff, 0, NULL}, }; /* 'Receive copy results' was renamed 'Third party copy out' in spc4r34 */ /* LID4 is an abbreviation of List Identifier length of 4 bytes */ struct sg_lib_value_name_t sg_lib_rec_copy_sa_arr[] = { /* opcode 0x84 */ {0x0, 0, "Receive copy status(LID1)"}, {0x1, 0, "Receive copy data(LID1)"}, {0x3, 0, "Receive copy operating parameters"}, {0x4, 0, "Receive copy failure details(LID1)"}, {0x5, 0, "Receive copy status(LID4)"}, {0x6, 0, "Receive copy data(LID4)"}, {0x7, 0, "Receive ROD token information"}, {0x8, 0, "Report all ROD tokens"}, {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_variable_length_arr[] = { {0x1, 0, "Rebuild(32)"}, {0x2, 0, "Regenerate(32)"}, {0x3, 0, "Xdread(32)"}, /* obsolete in SBC-3 r31 */ {0x4, 0, "Xdwrite(32)"}, /* obsolete in SBC-3 r31 */ {0x5, 0, "Xdwrite extended(32)"}, {0x6, 0, "Xpwrite(32)"}, {0x7, 0, "Xdwriteread(32)"}, {0x8, 0, "Xdwrite extended(64)"}, {0x9, 0, "Read(32)"}, {0xa, 0, "Verify(32)"}, {0xb, 0, "Write(32)"}, {0xc, 0, "Write an verify(32)"}, {0xd, 0, "Write same(32)"}, {0xe, 0, "Orwrite(32)"}, /* added sbc3r25 */ {0x1800, 0, "Receive credential"}, {0x8801, 0, "Format OSD (osd)"}, {0x8802, 0, "Create (osd)"}, {0x8803, 0, "List (osd)"}, {0x8805, 0, "Read (osd)"}, {0x8806, 0, "Write (osd)"}, {0x8807, 0, "Append (osd)"}, {0x8808, 0, "Flush (osd)"}, {0x880a, 0, "Remove (osd)"}, {0x880b, 0, "Create partition (osd)"}, {0x880c, 0, "Remove partition (osd)"}, {0x880e, 0, "Get attributes (osd)"}, {0x880f, 0, "Set attributes (osd)"}, {0x8812, 0, "Create and write (osd)"}, {0x8815, 0, "Create collection (osd)"}, {0x8816, 0, "Remove collection (osd)"}, {0x8817, 0, "List collection (osd)"}, {0x8818, 0, "Set key (osd)"}, {0x8819, 0, "Set master key (osd)"}, {0x881a, 0, "Flush collection (osd)"}, {0x881b, 0, "Flush partition (osd)"}, {0x881c, 0, "Flush OSD (osd)"}, {0x8880, 0, "Object structure check (osd-2)"}, {0x8881, 0, "Format OSD (osd-2)"}, {0x8882, 0, "Create (osd-2)"}, {0x8883, 0, "List (osd-2)"}, {0x8884, 0, "Punch (osd-2)"}, {0x8885, 0, "Read (osd-2)"}, {0x8886, 0, "Write (osd-2)"}, {0x8887, 0, "Append (osd-2)"}, {0x8888, 0, "Flush (osd-2)"}, {0x8889, 0, "Clear (osd-2)"}, {0x888a, 0, "Remove (osd-2)"}, {0x888b, 0, "Create partition (osd-2)"}, {0x888c, 0, "Remove partition (osd-2)"}, {0x888e, 0, "Get attributes (osd-2)"}, {0x888f, 0, "Set attributes (osd-2)"}, {0x8892, 0, "Create and write (osd-2)"}, {0x8895, 0, "Create collection (osd-2)"}, {0x8896, 0, "Remove collection (osd-2)"}, {0x8897, 0, "List collection (osd-2)"}, {0x8898, 0, "Set key (osd-2)"}, {0x8899, 0, "Set master key (osd-2)"}, {0x889a, 0, "Flush collection (osd-2)"}, {0x889b, 0, "Flush partition (osd-2)"}, {0x889c, 0, "Flush OSD (osd-2)"}, {0x88a0, 0, "Query (osd-2)"}, {0x88a1, 0, "Remove member objects (osd-2)"}, {0x88a2, 0, "Get member attributes (osd-2)"}, {0x88a3, 0, "Set member attributes (osd-2)"}, {0x88b1, 0, "Read map (osd-2)"}, {0x8f7c, 0, "Perform SCSI command (osd-2)"}, {0x8f7d, 0, "Perform task management function (osd-2)"}, {0x8f7e, 0, "Perform SCSI command (osd)"}, {0x8f7f, 0, "Perform task management function (osd)"}, {0xffff, 0, NULL}, }; #else struct sg_lib_value_name_t sg_lib_normal_opcodes[] = { {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_read_buff_arr[] = { /* opcode 0x3c */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_write_buff_arr[] = { /* opcode 0x3b */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_maint_in_arr[] = { /* opcode 0xa3 */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_maint_out_arr[] = { /* opcode 0xa4 */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_in12_arr[] = { /* opcode 0xab */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_out12_arr[] = { /* opcode 0xa9 */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = { /* opcode 0x9e */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_out16_arr[] = { /* opcode 0x9f */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_serv_bidi_arr[] = { /* opcode 0x9d */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_pr_in_arr[] = { /* opcode 0x5e */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_pr_out_arr[] = { /* opcode 0x5f */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_xcopy_sa_arr[] = { /* opcode 0x83 */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_rec_copy_sa_arr[] = { /* opcode 0x84 */ {0xffff, 0, NULL}, }; struct sg_lib_value_name_t sg_lib_variable_length_arr[] = { {0xffff, 0, NULL}, }; #endif /* A conveniently formatted list of SCSI ASC/ASCQ codes and their * corresponding text can be found at: www.t10.org/lists/asc-num.txt * The following should match asc-num.txt dated 20140320 */ #ifdef SG_SCSI_STRINGS struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[] = { {0x40,0x01,0x7f,"Ram failure [0x%x]"}, {0x40,0x80,0xff,"Diagnostic failure on component [0x%x]"}, {0x41,0x01,0xff,"Data path failure [0x%x]"}, {0x42,0x01,0xff,"Power-on or self-test failure [0x%x]"}, {0x4d,0x00,0xff,"Tagged overlapped commands [0x%x]"}, {0x70,0x00,0xff,"Decompression exception short algorithm id of 0x%x"}, {0, 0, 0, NULL} }; struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] = { {0x00,0x00,"No additional sense information"}, {0x00,0x01,"Filemark detected"}, {0x00,0x02,"End-of-partition/medium detected"}, {0x00,0x03,"Setmark detected"}, {0x00,0x04,"Beginning-of-partition/medium detected"}, {0x00,0x05,"End-of-data detected"}, {0x00,0x06,"I/O process terminated"}, {0x00,0x07,"Programmable early warning detected"}, {0x00,0x11,"Audio play operation in progress"}, {0x00,0x12,"Audio play operation paused"}, {0x00,0x13,"Audio play operation successfully completed"}, {0x00,0x14,"Audio play operation stopped due to error"}, {0x00,0x15,"No current audio status to return"}, {0x00,0x16,"operation in progress"}, {0x00,0x17,"Cleaning requested"}, {0x00,0x18,"Erase operation in progress"}, {0x00,0x19,"Locate operation in progress"}, {0x00,0x1a,"Rewind operation in progress"}, {0x00,0x1b,"Set capacity operation in progress"}, {0x00,0x1c,"Verify operation in progress"}, {0x00,0x1d,"ATA pass through information available"}, {0x00,0x1e,"Conflicting SA creation request"}, {0x00,0x1f,"Logical unit transitioning to another power condition"}, {0x00,0x20,"Extended copy information available"}, {0x01,0x00,"No index/sector signal"}, {0x02,0x00,"No seek complete"}, {0x03,0x00,"Peripheral device write fault"}, {0x03,0x01,"No write current"}, {0x03,0x02,"Excessive write errors"}, {0x04,0x00,"Logical unit not ready, cause not reportable"}, {0x04,0x01,"Logical unit is in process of becoming ready"}, {0x04,0x02,"Logical unit not ready, " "initializing command required"}, {0x04,0x03,"Logical unit not ready, " "manual intervention required"}, {0x04,0x04,"Logical unit not ready, format in progress"}, {0x04,0x05,"Logical unit not ready, rebuild in progress"}, {0x04,0x06,"Logical unit not ready, recalculation in progress"}, {0x04,0x07,"Logical unit not ready, operation in progress"}, {0x04,0x08,"Logical unit not ready, long write in progress"}, {0x04,0x09,"Logical unit not ready, self-test in progress"}, {0x04,0x0a,"Logical unit " "not accessible, asymmetric access state transition"}, {0x04,0x0b,"Logical unit " "not accessible, target port in standby state"}, {0x04,0x0c,"Logical unit " "not accessible, target port in unavailable state"}, {0x04,0x0d,"Logical unit not ready, structure check required"}, {0x04,0x10,"Logical unit not ready, " "auxiliary memory not accessible"}, {0x04,0x11,"Logical unit not ready, " "notify (enable spinup) required"}, {0x04,0x12,"Logical unit not ready, offline"}, {0x04,0x13,"Logical unit not ready, SA creation in progress"}, {0x04,0x14,"Logical unit not ready, space allocation in progress"}, {0x04,0x15,"Logical unit not ready, robotics disabled"}, {0x04,0x16,"Logical unit not ready, configuration required"}, {0x04,0x17,"Logical unit not ready, calibration required"}, {0x04,0x18,"Logical unit not ready, a door is open"}, {0x04,0x19,"Logical unit not ready, operating in sequential mode"}, {0x04,0x1a,"Logical unit not ready, start stop unit command in progress"}, {0x04,0x1b,"Logical unit not ready, sanitize in progress"}, {0x04,0x1c,"Logical unit not ready, additional power use not yet " "granted"}, {0x04,0x1d,"Logical unit not ready, configuration in progress"}, {0x04,0x1e,"Logical unit not ready, microcode activation required"}, {0x04,0x1f,"Logical unit not ready, microcode download required"}, {0x04,0x20,"Logical unit not ready, logical unit reset required"}, {0x04,0x21,"Logical unit not ready, hard reset required"}, {0x04,0x22,"Logical unit not ready, power cycle required"}, {0x05,0x00,"Logical unit does not respond to selection"}, {0x06,0x00,"No reference position found"}, {0x07,0x00,"Multiple peripheral devices selected"}, {0x08,0x00,"Logical unit communication failure"}, {0x08,0x01,"Logical unit communication time-out"}, {0x08,0x02,"Logical unit communication parity error"}, {0x08,0x03,"Logical unit communication CRC error (Ultra-DMA/32)"}, {0x08,0x04,"Unreachable copy target"}, {0x09,0x00,"Track following error"}, {0x09,0x01,"Tracking servo failure"}, {0x09,0x02,"Focus servo failure"}, {0x09,0x03,"Spindle servo failure"}, {0x09,0x04,"Head select fault"}, {0x0A,0x00,"Error log overflow"}, {0x0B,0x00,"Warning"}, {0x0B,0x01,"Warning - specified temperature exceeded"}, {0x0B,0x02,"Warning - enclosure degraded"}, {0x0B,0x03,"Warning - background self-test failed"}, {0x0B,0x04,"Warning - background pre-scan detected medium error"}, {0x0B,0x05,"Warning - background medium scan detected medium error"}, {0x0B,0x06,"Warning - non-volatile cache now volatile"}, {0x0B,0x07,"Warning - degraded power to non-volatile cache"}, {0x0B,0x08,"Warning - power loss expected"}, {0x0B,0x09,"Warning - device statistics notification active"}, {0x0C,0x00,"Write error"}, {0x0C,0x01,"Write error - recovered with auto reallocation"}, {0x0C,0x02,"Write error - auto reallocation failed"}, {0x0C,0x03,"Write error - recommend reassignment"}, {0x0C,0x04,"Compression check miscompare error"}, {0x0C,0x05,"Data expansion occurred during compression"}, {0x0C,0x06,"Block not compressible"}, {0x0C,0x07,"Write error - recovery needed"}, {0x0C,0x08,"Write error - recovery failed"}, {0x0C,0x09,"Write error - loss of streaming"}, {0x0C,0x0A,"Write error - padding blocks added"}, {0x0C,0x0B,"Auxiliary memory write error"}, {0x0C,0x0C,"Write error - unexpected unsolicited data"}, {0x0C,0x0D,"Write error - not enough unsolicited data"}, {0x0C,0x0E,"Multiple write errors"}, {0x0C,0x0F,"Defects in error window"}, {0x0D,0x00,"Error detected by third party temporary initiator"}, {0x0D,0x01,"Third party device failure"}, {0x0D,0x02,"Copy target device not reachable"}, {0x0D,0x03,"Incorrect copy target device type"}, {0x0D,0x04,"Copy target device data underrun"}, {0x0D,0x05,"Copy target device data overrun"}, {0x0E,0x00,"Invalid information unit"}, {0x0E,0x01,"Information unit too short"}, {0x0E,0x02,"Information unit too long"}, {0x0E,0x03,"Invalid field in command information unit"}, {0x10,0x00,"Id CRC or ECC error"}, {0x10,0x01,"Logical block guard check failed"}, {0x10,0x02,"Logical block application tag check failed"}, {0x10,0x03,"Logical block reference tag check failed"}, {0x10,0x04,"Logical block protection error on recover buffered data"}, {0x10,0x05,"Logical block protection method error"}, {0x11,0x00,"Unrecovered read error"}, {0x11,0x01,"Read retries exhausted"}, {0x11,0x02,"Error too long to correct"}, {0x11,0x03,"Multiple read errors"}, {0x11,0x04,"Unrecovered read error - auto reallocate failed"}, {0x11,0x05,"L-EC uncorrectable error"}, {0x11,0x06,"CIRC unrecovered error"}, {0x11,0x07,"Data re-synchronization error"}, {0x11,0x08,"Incomplete block read"}, {0x11,0x09,"No gap found"}, {0x11,0x0A,"Miscorrected error"}, {0x11,0x0B,"Unrecovered read error - recommend reassignment"}, {0x11,0x0C,"Unrecovered read error - recommend rewrite the data"}, {0x11,0x0D,"De-compression CRC error"}, {0x11,0x0E,"Cannot decompress using declared algorithm"}, {0x11,0x0F,"Error reading UPC/EAN number"}, {0x11,0x10,"Error reading ISRC number"}, {0x11,0x11,"Read error - loss of streaming"}, {0x11,0x12,"Auxiliary memory read error"}, {0x11,0x13,"Read error - failed retransmission request"}, {0x11,0x14,"Read error - LBA marked bad by application client"}, {0x11,0x15,"Write after sanitize required"}, {0x12,0x00,"Address mark not found for id field"}, {0x13,0x00,"Address mark not found for data field"}, {0x14,0x00,"Recorded entity not found"}, {0x14,0x01,"Record not found"}, {0x14,0x02,"Filemark or setmark not found"}, {0x14,0x03,"End-of-data not found"}, {0x14,0x04,"Block sequence error"}, {0x14,0x05,"Record not found - recommend reassignment"}, {0x14,0x06,"Record not found - data auto-reallocated"}, {0x14,0x07,"Locate operation failure"}, {0x15,0x00,"Random positioning error"}, {0x15,0x01,"Mechanical positioning error"}, {0x15,0x02,"Positioning error detected by read of medium"}, {0x16,0x00,"Data synchronization mark error"}, {0x16,0x01,"Data sync error - data rewritten"}, {0x16,0x02,"Data sync error - recommend rewrite"}, {0x16,0x03,"Data sync error - data auto-reallocated"}, {0x16,0x04,"Data sync error - recommend reassignment"}, {0x17,0x00,"Recovered data with no error correction applied"}, {0x17,0x01,"Recovered data with retries"}, {0x17,0x02,"Recovered data with positive head offset"}, {0x17,0x03,"Recovered data with negative head offset"}, {0x17,0x04,"Recovered data with retries and/or circ applied"}, {0x17,0x05,"Recovered data using previous sector id"}, {0x17,0x06,"Recovered data without ECC - data auto-reallocated"}, {0x17,0x07,"Recovered data without ECC - recommend reassignment"}, {0x17,0x08,"Recovered data without ECC - recommend rewrite"}, {0x17,0x09,"Recovered data without ECC - data rewritten"}, {0x18,0x00,"Recovered data with error correction applied"}, {0x18,0x01,"Recovered data with error corr. & retries applied"}, {0x18,0x02,"Recovered data - data auto-reallocated"}, {0x18,0x03,"Recovered data with CIRC"}, {0x18,0x04,"Recovered data with L-EC"}, {0x18,0x05,"Recovered data - recommend reassignment"}, {0x18,0x06,"Recovered data - recommend rewrite"}, {0x18,0x07,"Recovered data with ECC - data rewritten"}, {0x18,0x08,"Recovered data with linking"}, {0x19,0x00,"Defect list error"}, {0x19,0x01,"Defect list not available"}, {0x19,0x02,"Defect list error in primary list"}, {0x19,0x03,"Defect list error in grown list"}, {0x1A,0x00,"Parameter list length error"}, {0x1B,0x00,"Synchronous data transfer error"}, {0x1C,0x00,"Defect list not found"}, {0x1C,0x01,"Primary defect list not found"}, {0x1C,0x02,"Grown defect list not found"}, {0x1D,0x00,"Miscompare during verify operation"}, {0x1D,0x01,"Miscompare verify of unmapped lba"}, {0x1E,0x00,"Recovered id with ECC correction"}, {0x1F,0x00,"Partial defect list transfer"}, {0x20,0x00,"Invalid command operation code"}, {0x20,0x01,"Access denied - initiator pending-enrolled"}, {0x20,0x02,"Access denied - no access rights"}, {0x20,0x03,"Access denied - invalid mgmt id key"}, {0x20,0x04,"Illegal command while in write capable state"}, {0x20,0x05,"Write type operation while in read capable state (obs)"}, {0x20,0x06,"Illegal command while in explicit address mode"}, {0x20,0x07,"Illegal command while in implicit address mode"}, {0x20,0x08,"Access denied - enrollment conflict"}, {0x20,0x09,"Access denied - invalid LU identifier"}, {0x20,0x0A,"Access denied - invalid proxy token"}, {0x20,0x0B,"Access denied - ACL LUN conflict"}, {0x20,0x0C,"Illegal command when not in append-only mode"}, {0x21,0x00,"Logical block address out of range"}, {0x21,0x01,"Invalid element address"}, {0x21,0x02,"Invalid address for write"}, {0x21,0x03,"Invalid write crossing layer jump"}, {0x22,0x00,"Illegal function (use 20 00, 24 00, or 26 00)"}, {0x23,0x00,"Invalid token operation, cause not reportable"}, {0x23,0x01,"Invalid token operation, unsupported token type"}, {0x23,0x02,"Invalid token operation, remote token usage not supported"}, {0x23,0x03,"invalid token operation, remote rod token creation not " "supported"}, {0x23,0x04,"Invalid token operation, token unknown"}, {0x23,0x05,"Invalid token operation, token corrupt"}, {0x23,0x06,"Invalid token operation, token revoked"}, {0x23,0x07,"Invalid token operation, token expired"}, {0x23,0x08,"Invalid token operation, token cancelled"}, {0x23,0x09,"Invalid token operation, token deleted"}, {0x23,0x0a,"Invalid token operation, invalid token length"}, {0x24,0x00,"Invalid field in cdb"}, {0x24,0x01,"CDB decryption error"}, {0x24,0x02,"Invalid cdb field while in explicit block model (obs)"}, {0x24,0x03,"Invalid cdb field while in implicit block model (obs)"}, {0x24,0x04,"Security audit value frozen"}, {0x24,0x05,"Security working key frozen"}, {0x24,0x06,"Nonce not unique"}, {0x24,0x07,"Nonce timestamp out of range"}, {0x24,0x08,"Invalid xcdb"}, {0x25,0x00,"Logical unit not supported"}, {0x26,0x00,"Invalid field in parameter list"}, {0x26,0x01,"Parameter not supported"}, {0x26,0x02,"Parameter value invalid"}, {0x26,0x03,"Threshold parameters not supported"}, {0x26,0x04,"Invalid release of persistent reservation"}, {0x26,0x05,"Data decryption error"}, {0x26,0x06,"Too many target descriptors"}, {0x26,0x07,"Unsupported target descriptor type code"}, {0x26,0x08,"Too many segment descriptors"}, {0x26,0x09,"Unsupported segment descriptor type code"}, {0x26,0x0A,"Unexpected inexact segment"}, {0x26,0x0B,"Inline data length exceeded"}, {0x26,0x0C,"Invalid operation for copy source or destination"}, {0x26,0x0D,"Copy segment granularity violation"}, {0x26,0x0E,"Invalid parameter while port is enabled"}, {0x26,0x0F,"Invalid data-out buffer integrity check value"}, {0x26,0x10,"Data decryption key fail limit reached"}, {0x26,0x11,"Incomplete key-associated data set"}, {0x26,0x12,"Vendor specific key reference not found"}, {0x27,0x00,"Write protected"}, {0x27,0x01,"Hardware write protected"}, {0x27,0x02,"Logical unit software write protected"}, {0x27,0x03,"Associated write protect"}, {0x27,0x04,"Persistent write protect"}, {0x27,0x05,"Permanent write protect"}, {0x27,0x06,"Conditional write protect"}, {0x27,0x07,"Space allocation failed write protect"}, {0x28,0x00,"Not ready to ready change, medium may have changed"}, {0x28,0x01,"Import or export element accessed"}, {0x28,0x02,"Format-layer may have changed"}, {0x28,0x03,"Import/export element accessed, medium changed"}, {0x29,0x00,"Power on, reset, or bus device reset occurred"}, {0x29,0x01,"Power on occurred"}, {0x29,0x02,"SCSI bus reset occurred"}, {0x29,0x03,"Bus device reset function occurred"}, {0x29,0x04,"Device internal reset"}, {0x29,0x05,"Transceiver mode changed to single-ended"}, {0x29,0x06,"Transceiver mode changed to lvd"}, {0x29,0x07,"I_T nexus loss occurred"}, {0x2A,0x00,"Parameters changed"}, {0x2A,0x01,"Mode parameters changed"}, {0x2A,0x02,"Log parameters changed"}, {0x2A,0x03,"Reservations preempted"}, {0x2A,0x04,"Reservations released"}, {0x2A,0x05,"Registrations preempted"}, {0x2A,0x06,"Asymmetric access state changed"}, {0x2A,0x07,"Implicit asymmetric access state transition failed"}, {0x2A,0x08,"Priority changed"}, {0x2A,0x09,"Capacity data has changed"}, {0x2A,0x0c, "Error recovery attributes have changed"}, {0x2A,0x0d, "Data encryption capabilities changed"}, {0x2A,0x10,"Timestamp changed"}, {0x2A,0x11,"Data encryption parameters changed by another i_t nexus"}, {0x2A,0x12,"Data encryption parameters changed by vendor specific event"}, {0x2A,0x13,"Data encryption key instance counter has changed"}, {0x2A,0x0a,"Error history i_t nexus cleared"}, {0x2A,0x0b,"Error history snapshot released"}, {0x2A,0x14,"SA creation capabilities data has changed"}, {0x2A,0x15,"Medium removal prevention preempted"}, {0x2B,0x00,"Copy cannot execute since host cannot disconnect"}, {0x2C,0x00,"Command sequence error"}, {0x2C,0x01,"Too many windows specified"}, {0x2C,0x02,"Invalid combination of windows specified"}, {0x2C,0x03,"Current program area is not empty"}, {0x2C,0x04,"Current program area is empty"}, {0x2C,0x05,"Illegal power condition request"}, {0x2C,0x06,"Persistent prevent conflict"}, {0x2C,0x07,"Previous busy status"}, {0x2C,0x08,"Previous task set full status"}, {0x2C,0x09,"Previous reservation conflict status"}, {0x2C,0x0A,"Partition or collection contains user objects"}, {0x2C,0x0B,"Not reserved"}, {0x2C,0x0C,"ORWRITE generation does not match"}, {0x2D,0x00,"Overwrite error on update in place"}, {0x2E,0x00,"Insufficient time for operation"}, {0x2E,0x01,"Command timeout before processing"}, {0x2E,0x02,"Command timeout during processing"}, {0x2E,0x03,"Command timeout during processing due to error recovery"}, {0x2F,0x00,"Commands cleared by another initiator"}, {0x2F,0x01,"Commands cleared by power loss notification"}, {0x2F,0x02,"Commands cleared by device server"}, {0x2F,0x03,"Some commands cleared by queuing layer event"}, {0x30,0x00,"Incompatible medium installed"}, {0x30,0x01,"Cannot read medium - unknown format"}, {0x30,0x02,"Cannot read medium - incompatible format"}, {0x30,0x03,"Cleaning cartridge installed"}, {0x30,0x04,"Cannot write medium - unknown format"}, {0x30,0x05,"Cannot write medium - incompatible format"}, {0x30,0x06,"Cannot format medium - incompatible medium"}, {0x30,0x07,"Cleaning failure"}, {0x30,0x08,"Cannot write - application code mismatch"}, {0x30,0x09,"Current session not fixated for append"}, {0x30,0x0A,"Cleaning request rejected"}, {0x30,0x0B,"Cleaning tape expired"}, {0x30,0x0C,"WORM medium - overwrite attempted"}, {0x30,0x0D,"WORM medium - integrity check"}, {0x30,0x10,"Medium not formatted"}, {0x30,0x11,"Incompatible volume type"}, {0x30,0x12,"Incompatible volume qualifier"}, {0x30,0x13,"Cleaning volume expired"}, {0x31,0x00,"Medium format corrupted"}, {0x31,0x01,"Format command failed"}, {0x31,0x02,"Zoned formatting failed due to spare linking"}, {0x31,0x03,"Sanitize command failed"}, {0x32,0x00,"No defect spare location available"}, {0x32,0x01,"Defect list update failure"}, {0x33,0x00,"Tape length error"}, {0x34,0x00,"Enclosure failure"}, {0x35,0x00,"Enclosure services failure"}, {0x35,0x01,"Unsupported enclosure function"}, {0x35,0x02,"Enclosure services unavailable"}, {0x35,0x03,"Enclosure services transfer failure"}, {0x35,0x04,"Enclosure services transfer refused"}, {0x35,0x05,"Enclosure services checksum error"}, {0x36,0x00,"Ribbon, ink, or toner failure"}, {0x37,0x00,"Rounded parameter"}, {0x38,0x00,"Event status notification"}, {0x38,0x02,"Esn - power management class event"}, {0x38,0x04,"Esn - media class event"}, {0x38,0x06,"Esn - device busy class event"}, {0x38,0x07,"Thin provisioning soft threshold reached"}, {0x39,0x00,"Saving parameters not supported"}, {0x3A,0x00,"Medium not present"}, {0x3A,0x01,"Medium not present - tray closed"}, {0x3A,0x02,"Medium not present - tray open"}, {0x3A,0x03,"Medium not present - loadable"}, {0x3A,0x04,"Medium not present - medium auxiliary memory accessible"}, {0x3B,0x00,"Sequential positioning error"}, {0x3B,0x01,"Tape position error at beginning-of-medium"}, {0x3B,0x02,"Tape position error at end-of-medium"}, {0x3B,0x03,"Tape or electronic vertical forms unit not ready"}, {0x3B,0x04,"Slew failure"}, {0x3B,0x05,"Paper jam"}, {0x3B,0x06,"Failed to sense top-of-form"}, {0x3B,0x07,"Failed to sense bottom-of-form"}, {0x3B,0x08,"Reposition error"}, {0x3B,0x09,"Read past end of medium"}, {0x3B,0x0A,"Read past beginning of medium"}, {0x3B,0x0B,"Position past end of medium"}, {0x3B,0x0C,"Position past beginning of medium"}, {0x3B,0x0D,"Medium destination element full"}, {0x3B,0x0E,"Medium source element empty"}, {0x3B,0x0F,"End of medium reached"}, {0x3B,0x11,"Medium magazine not accessible"}, {0x3B,0x12,"Medium magazine removed"}, {0x3B,0x13,"Medium magazine inserted"}, {0x3B,0x14,"Medium magazine locked"}, {0x3B,0x15,"Medium magazine unlocked"}, {0x3B,0x16,"Mechanical positioning or changer error"}, {0x3B,0x17,"Read past end of user object"}, {0x3B,0x18,"Element disabled"}, {0x3B,0x19,"Element enabled"}, {0x3B,0x1a,"Data transfer device removed"}, {0x3B,0x1b,"Data transfer device inserted"}, {0x3B,0x1c,"Too many logical objects on partition to support operation"}, {0x3D,0x00,"Invalid bits in identify message"}, {0x3E,0x00,"Logical unit has not self-configured yet"}, {0x3E,0x01,"Logical unit failure"}, {0x3E,0x02,"Timeout on logical unit"}, {0x3E,0x03,"Logical unit failed self-test"}, {0x3E,0x04,"Logical unit unable to update self-test log"}, {0x3F,0x00,"Target operating conditions have changed"}, {0x3F,0x01,"Microcode has been changed"}, {0x3F,0x02,"Changed operating definition"}, {0x3F,0x03,"Inquiry data has changed"}, {0x3F,0x04,"Component device attached"}, {0x3F,0x05,"Device identifier changed"}, {0x3F,0x06,"Redundancy group created or modified"}, {0x3F,0x07,"Redundancy group deleted"}, {0x3F,0x08,"Spare created or modified"}, {0x3F,0x09,"Spare deleted"}, {0x3F,0x0A,"Volume set created or modified"}, {0x3F,0x0B,"Volume set deleted"}, {0x3F,0x0C,"Volume set deassigned"}, {0x3F,0x0D,"Volume set reassigned"}, {0x3F,0x0E,"Reported luns data has changed"}, {0x3F,0x0F,"Echo buffer overwritten"}, {0x3F,0x10,"Medium loadable"}, {0x3F,0x11,"Medium auxiliary memory accessible"}, {0x3F,0x12,"iSCSI IP address added"}, {0x3F,0x13,"iSCSI IP address removed"}, {0x3F,0x14,"iSCSI IP address changed"}, {0x3F,0x15,"Inspect referrals sense descriptors"}, {0x3F,0x16,"Microcode has been changed without reset"}, /* * ASC 0x40, 0x41 and 0x42 overridden by "additional2" array entries * for ascq > 1. Preferred error message for this group is * "Diagnostic failure on component nn (80h-ffh)". */ {0x40,0x00,"Ram failure (should use 40 nn)"}, {0x41,0x00,"Data path failure (should use 40 nn)"}, {0x42,0x00,"Power-on or self-test failure (should use 40 nn)"}, {0x43,0x00,"Message error"}, {0x44,0x00,"Internal target failure"}, {0x44,0x01,"Persistent reservation information lost"}, {0x44,0x71,"ATA device failed Set Features"}, {0x45,0x00,"Select or reselect failure"}, {0x46,0x00,"Unsuccessful soft reset"}, {0x47,0x00,"SCSI parity error"}, {0x47,0x01,"Data phase CRC error detected"}, {0x47,0x02,"SCSI parity error detected during st data phase"}, {0x47,0x03,"Information unit iuCRC error detected"}, {0x47,0x04,"Asynchronous information protection error detected"}, {0x47,0x05,"Protocol service CRC error"}, {0x47,0x06,"Phy test function in progress"}, {0x47,0x7F,"Some commands cleared by iSCSI protocol event"}, {0x48,0x00,"Initiator detected error message received"}, {0x49,0x00,"Invalid message error"}, {0x4A,0x00,"Command phase error"}, {0x4B,0x00,"Data phase error"}, {0x4B,0x01,"Invalid target port transfer tag received"}, {0x4B,0x02,"Too much write data"}, {0x4B,0x03,"Ack/nak timeout"}, {0x4B,0x04,"Nak received"}, {0x4B,0x05,"Data offset error"}, {0x4B,0x06,"Initiator response timeout"}, {0x4B,0x07,"Connection lost"}, {0x4B,0x08,"Data-in buffer overflow - data buffer size"}, {0x4B,0x09,"Data-in buffer overflow - data buffer descriptor area"}, {0x4B,0x0A,"Data-in buffer error"}, {0x4B,0x0B,"Data-out buffer overflow - data buffer size"}, {0x4B,0x0C,"Data-out buffer overflow - data buffer descriptor area"}, {0x4B,0x0D,"Data-out buffer error"}, {0x4B,0x0E,"PCIe fabric error"}, {0x4B,0x0f,"PCIe completion timeout"}, {0x4B,0x10,"PCIe completer abort"}, {0x4B,0x11,"PCIe poisoned tlp received"}, {0x4B,0x12,"PCIe ecrc check failed"}, {0x4B,0x13,"PCIe unsupported request"}, {0x4B,0x14,"PCIe acs violation"}, {0x4B,0x15,"PCIe tlp prefix blocked"}, {0x4C,0x00,"Logical unit failed self-configuration"}, /* * ASC 0x4D overridden by an "additional2" array entry * so there is no need to have them here. */ /* {0x4D,0x00,"Tagged overlapped commands (nn = queue tag)"}, */ {0x4E,0x00,"Overlapped commands attempted"}, {0x50,0x00,"Write append error"}, {0x50,0x01,"Write append position error"}, {0x50,0x02,"Position error related to timing"}, {0x51,0x00,"Erase failure"}, {0x51,0x01,"Erase failure - incomplete erase operation detected"}, {0x52,0x00,"Cartridge fault"}, {0x53,0x00,"Media load or eject failed"}, {0x53,0x01,"Unload tape failure"}, {0x53,0x02,"Medium removal prevented"}, {0x53,0x03,"Medium removal prevented by data transfer element"}, {0x53,0x04,"Medium thread or unthread failure"}, {0x53,0x05,"Volume identifier invalid"}, {0x53,0x06,"Volume identifier missing"}, {0x53,0x07,"Duplicate volume identifier"}, {0x53,0x08,"Element status unknown"}, {0x53,0x09,"Data transfer device error - load failed"}, {0x53,0x0A,"Data transfer device error - unload failed"}, {0x53,0x0B,"Data transfer device error - unload missing"}, {0x53,0x0C,"Data transfer device error - eject failed"}, {0x53,0x0D,"Data transfer device error - library communication failed"}, {0x54,0x00,"SCSI to host system interface failure"}, {0x55,0x00,"System resource failure"}, {0x55,0x01,"System buffer full"}, {0x55,0x02,"Insufficient reservation resources"}, {0x55,0x03,"Insufficient resources"}, {0x55,0x04,"Insufficient registration resources"}, {0x55,0x05,"Insufficient access control resources"}, {0x55,0x06,"Auxiliary memory out of space"}, {0x55,0x07,"Quota error"}, {0x55,0x08,"Maximum number of supplemental decryption keys exceeded"}, {0x55,0x09,"Medium auxiliary memory not accessible"}, {0x55,0x0a,"Data currently unavailable"}, {0x55,0x0b,"Insufficient power for operation"}, {0x55,0x0c,"Insufficient resources to create rod"}, {0x55,0x0d,"Insufficient resources to create rod token"}, {0x57,0x00,"Unable to recover table-of-contents"}, {0x58,0x00,"Generation does not exist"}, {0x59,0x00,"Updated block read"}, {0x5A,0x00,"Operator request or state change input"}, {0x5A,0x01,"Operator medium removal request"}, {0x5A,0x02,"Operator selected write protect"}, {0x5A,0x03,"Operator selected write permit"}, {0x5B,0x00,"Log exception"}, {0x5B,0x01,"Threshold condition met"}, {0x5B,0x02,"Log counter at maximum"}, {0x5B,0x03,"Log list codes exhausted"}, {0x5C,0x00,"Rpl status change"}, {0x5C,0x01,"Spindles synchronized"}, {0x5C,0x02,"Spindles not synchronized"}, {0x5D,0x00,"Failure prediction threshold exceeded"}, {0x5D,0x01,"Media failure prediction threshold exceeded"}, {0x5D,0x02,"Logical unit failure prediction threshold exceeded"}, {0x5D,0x03,"spare area exhaustion prediction threshold exceeded"}, {0x5D,0x10,"Hardware impending failure general hard drive failure"}, {0x5D,0x11,"Hardware impending failure drive error rate too high" }, {0x5D,0x12,"Hardware impending failure data error rate too high" }, {0x5D,0x13,"Hardware impending failure seek error rate too high" }, {0x5D,0x14,"Hardware impending failure too many block reassigns"}, {0x5D,0x15,"Hardware impending failure access times too high" }, {0x5D,0x16,"Hardware impending failure start unit times too high" }, {0x5D,0x17,"Hardware impending failure channel parametrics"}, {0x5D,0x18,"Hardware impending failure controller detected"}, {0x5D,0x19,"Hardware impending failure throughput performance"}, {0x5D,0x1A,"Hardware impending failure seek time performance"}, {0x5D,0x1B,"Hardware impending failure spin-up retry count"}, {0x5D,0x1C,"Hardware impending failure drive calibration retry count"}, {0x5D,0x20,"Controller impending failure general hard drive failure"}, {0x5D,0x21,"Controller impending failure drive error rate too high" }, {0x5D,0x22,"Controller impending failure data error rate too high" }, {0x5D,0x23,"Controller impending failure seek error rate too high" }, {0x5D,0x24,"Controller impending failure too many block reassigns"}, {0x5D,0x25,"Controller impending failure access times too high" }, {0x5D,0x26,"Controller impending failure start unit times too high" }, {0x5D,0x27,"Controller impending failure channel parametrics"}, {0x5D,0x28,"Controller impending failure controller detected"}, {0x5D,0x29,"Controller impending failure throughput performance"}, {0x5D,0x2A,"Controller impending failure seek time performance"}, {0x5D,0x2B,"Controller impending failure spin-up retry count"}, {0x5D,0x2C,"Controller impending failure drive calibration retry count"}, {0x5D,0x30,"Data channel impending failure general hard drive failure"}, {0x5D,0x31,"Data channel impending failure drive error rate too high" }, {0x5D,0x32,"Data channel impending failure data error rate too high" }, {0x5D,0x33,"Data channel impending failure seek error rate too high" }, {0x5D,0x34,"Data channel impending failure too many block reassigns"}, {0x5D,0x35,"Data channel impending failure access times too high" }, {0x5D,0x36,"Data channel impending failure start unit times too high" }, {0x5D,0x37,"Data channel impending failure channel parametrics"}, {0x5D,0x38,"Data channel impending failure controller detected"}, {0x5D,0x39,"Data channel impending failure throughput performance"}, {0x5D,0x3A,"Data channel impending failure seek time performance"}, {0x5D,0x3B,"Data channel impending failure spin-up retry count"}, {0x5D,0x3C,"Data channel impending failure drive calibration retry count"}, {0x5D,0x40,"Servo impending failure general hard drive failure"}, {0x5D,0x41,"Servo impending failure drive error rate too high" }, {0x5D,0x42,"Servo impending failure data error rate too high" }, {0x5D,0x43,"Servo impending failure seek error rate too high" }, {0x5D,0x44,"Servo impending failure too many block reassigns"}, {0x5D,0x45,"Servo impending failure access times too high" }, {0x5D,0x46,"Servo impending failure start unit times too high" }, {0x5D,0x47,"Servo impending failure channel parametrics"}, {0x5D,0x48,"Servo impending failure controller detected"}, {0x5D,0x49,"Servo impending failure throughput performance"}, {0x5D,0x4A,"Servo impending failure seek time performance"}, {0x5D,0x4B,"Servo impending failure spin-up retry count"}, {0x5D,0x4C,"Servo impending failure drive calibration retry count"}, {0x5D,0x50,"Spindle impending failure general hard drive failure"}, {0x5D,0x51,"Spindle impending failure drive error rate too high" }, {0x5D,0x52,"Spindle impending failure data error rate too high" }, {0x5D,0x53,"Spindle impending failure seek error rate too high" }, {0x5D,0x54,"Spindle impending failure too many block reassigns"}, {0x5D,0x55,"Spindle impending failure access times too high" }, {0x5D,0x56,"Spindle impending failure start unit times too high" }, {0x5D,0x57,"Spindle impending failure channel parametrics"}, {0x5D,0x58,"Spindle impending failure controller detected"}, {0x5D,0x59,"Spindle impending failure throughput performance"}, {0x5D,0x5A,"Spindle impending failure seek time performance"}, {0x5D,0x5B,"Spindle impending failure spin-up retry count"}, {0x5D,0x5C,"Spindle impending failure drive calibration retry count"}, {0x5D,0x60,"Firmware impending failure general hard drive failure"}, {0x5D,0x61,"Firmware impending failure drive error rate too high" }, {0x5D,0x62,"Firmware impending failure data error rate too high" }, {0x5D,0x63,"Firmware impending failure seek error rate too high" }, {0x5D,0x64,"Firmware impending failure too many block reassigns"}, {0x5D,0x65,"Firmware impending failure access times too high" }, {0x5D,0x66,"Firmware impending failure start unit times too high" }, {0x5D,0x67,"Firmware impending failure channel parametrics"}, {0x5D,0x68,"Firmware impending failure controller detected"}, {0x5D,0x69,"Firmware impending failure throughput performance"}, {0x5D,0x6A,"Firmware impending failure seek time performance"}, {0x5D,0x6B,"Firmware impending failure spin-up retry count"}, {0x5D,0x6C,"Firmware impending failure drive calibration retry count"}, {0x5D,0xFF,"Failure prediction threshold exceeded (false)"}, {0x5E,0x00,"Low power condition on"}, {0x5E,0x01,"Idle condition activated by timer"}, {0x5E,0x02,"Standby condition activated by timer"}, {0x5E,0x03,"Idle condition activated by command"}, {0x5E,0x04,"Standby condition activated by command"}, {0x5E,0x05,"Idle_b condition activated by timer"}, {0x5E,0x06,"Idle_b condition activated by command"}, {0x5E,0x07,"Idle_c condition activated by timer"}, {0x5E,0x08,"Idle_c condition activated by command"}, {0x5E,0x09,"Standby_y condition activated by timer"}, {0x5E,0x0a,"Standby_y condition activated by command"}, {0x5E,0x41,"Power state change to active"}, {0x5E,0x42,"Power state change to idle"}, {0x5E,0x43,"Power state change to standby"}, {0x5E,0x45,"Power state change to sleep"}, {0x5E,0x47,"Power state change to device control"}, {0x60,0x00,"Lamp failure"}, {0x61,0x00,"Video acquisition error"}, {0x61,0x01,"Unable to acquire video"}, {0x61,0x02,"Out of focus"}, {0x62,0x00,"Scan head positioning error"}, {0x63,0x00,"End of user area encountered on this track"}, {0x63,0x01,"Packet does not fit in available space"}, {0x64,0x00,"Illegal mode for this track"}, {0x64,0x01,"Invalid packet size"}, {0x65,0x00,"Voltage fault"}, {0x66,0x00,"Automatic document feeder cover up"}, {0x66,0x01,"Automatic document feeder lift up"}, {0x66,0x02,"Document jam in automatic document feeder"}, {0x66,0x03,"Document miss feed automatic in document feeder"}, {0x67,0x00,"Configuration failure"}, {0x67,0x01,"Configuration of incapable logical units failed"}, {0x67,0x02,"Add logical unit failed"}, {0x67,0x03,"Modification of logical unit failed"}, {0x67,0x04,"Exchange of logical unit failed"}, {0x67,0x05,"Remove of logical unit failed"}, {0x67,0x06,"Attachment of logical unit failed"}, {0x67,0x07,"Creation of logical unit failed"}, {0x67,0x08,"Assign failure occurred"}, {0x67,0x09,"Multiply assigned logical unit"}, {0x67,0x0A,"Set target port groups command failed"}, {0x67,0x0B,"ATA device feature not enabled"}, {0x68,0x00,"Logical unit not configured"}, {0x68,0x01,"Subsidiary logical unit not configured"}, {0x69,0x00,"Data loss on logical unit"}, {0x69,0x01,"Multiple logical unit failures"}, {0x69,0x02,"Parity/data mismatch"}, {0x6A,0x00,"Informational, refer to log"}, {0x6B,0x00,"State change has occurred"}, {0x6B,0x01,"Redundancy level got better"}, {0x6B,0x02,"Redundancy level got worse"}, {0x6C,0x00,"Rebuild failure occurred"}, {0x6D,0x00,"Recalculate failure occurred"}, {0x6E,0x00,"Command to logical unit failed"}, {0x6F,0x00,"Copy protection key exchange failure - authentication " "failure"}, {0x6F,0x01,"Copy protection key exchange failure - key not present"}, {0x6F,0x02,"Copy protection key exchange failure - key not established"}, {0x6F,0x03,"Read of scrambled sector without authentication"}, {0x6F,0x04,"Media region code is mismatched to logical unit region"}, {0x6F,0x05,"Drive region must be permanent/region reset count error"}, {0x6F,0x06,"Insufficient block count for binding nonce recording"}, {0x6F,0x07,"Conflict in binding nonce recording"}, /* * ASC 0x70 overridden by an "additional2" array entry * so there is no need to have them here. */ /* {0x70,0x00,"Decompression exception short algorithm id of nn"}, */ {0x71,0x00,"Decompression exception long algorithm id"}, {0x72,0x00,"Session fixation error"}, {0x72,0x01,"Session fixation error writing lead-in"}, {0x72,0x02,"Session fixation error writing lead-out"}, {0x72,0x03,"Session fixation error - incomplete track in session"}, {0x72,0x04,"Empty or partially written reserved track"}, {0x72,0x05,"No more track reservations allowed"}, {0x72,0x06,"RMZ extension is not allowed"}, {0x72,0x07,"No more test zone extensions are allowed"}, {0x73,0x00,"CD control error"}, {0x73,0x01,"Power calibration area almost full"}, {0x73,0x02,"Power calibration area is full"}, {0x73,0x03,"Power calibration area error"}, {0x73,0x04,"Program memory area update failure"}, {0x73,0x05,"Program memory area is full"}, {0x73,0x06,"RMA/PMA is almost full"}, {0x73,0x10,"Current power calibration area almost full"}, {0x73,0x11,"Current power calibration area is full"}, {0x73,0x17,"RDZ is full"}, {0x74,0x00,"Security error"}, {0x74,0x01,"Unable to decrypt data"}, {0x74,0x02,"Unencrypted data encountered while decrypting"}, {0x74,0x03,"Incorrect data encryption key"}, {0x74,0x04,"Cryptographic integrity validation failed"}, {0x74,0x05,"Error decrypting data"}, {0x74,0x06,"Unknown signature verification key"}, {0x74,0x07,"Encryption parameters not useable"}, {0x74,0x08,"Digital signature validation failure"}, {0x74,0x09,"Encryption mode mismatch on read"}, {0x74,0x0a,"Encrypted block not raw read enabled"}, {0x74,0x0b,"Incorrect Encryption parameters"}, {0x74,0x0c,"Unable to decrypt parameter list"}, {0x74,0x0d,"Encryption algorithm disabled"}, {0x74,0x10,"SA creation parameter value invalid"}, {0x74,0x11,"SA creation parameter value rejected"}, {0x74,0x12,"Invalid SA usage"}, {0x74,0x21,"Data encryption configuration prevented"}, {0x74,0x30,"SA creation parameter not supported"}, {0x74,0x40,"Authentication failed"}, {0x74,0x61,"External data encryption key manager access error"}, {0x74,0x62,"External data encryption key manager error"}, {0x74,0x63,"External data encryption key not found"}, {0x74,0x64,"External data encryption request not authorized"}, {0x74,0x6e,"External data encryption control timeout"}, {0x74,0x6f,"External data encryption control error"}, {0x74,0x71,"Logical unit access not authorized"}, {0x74,0x79,"Security conflict in translated device"}, {0, 0, NULL} }; #else struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[] = { {0, 0, 0, NULL} }; struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] = { {0, 0, NULL} }; #endif /* SG_SCSI_STRINGS */ const char * sg_lib_sense_key_desc[] = { "No Sense", /* Filemark, ILI and/or EOM; progress indication (during FORMAT); power condition sensing (REQUEST SENSE) */ "Recovered Error", /* The last command completed successfully but used error correction */ "Not Ready", /* The addressed target is not ready */ "Medium Error", /* Data error detected on the medium */ "Hardware Error", /* Controller or device failure */ "Illegal Request", "Unit Attention", /* Removable medium was changed, or the target has been reset */ "Data Protect", /* Access to the data is blocked */ "Blank Check", /* Reached unexpected written or unwritten region of the medium */ "Vendor specific(9)", /* Vendor specific */ "Copy Aborted", /* COPY or COMPARE was aborted */ "Aborted Command", /* The target aborted the command */ "Equal", /* SEARCH DATA found data equal (obsolete) */ "Volume Overflow", /* Medium full with data to be written */ "Miscompare", /* Source data and data on the medium do not agree */ "Completed" /* may occur for successful cmd (spc4r23) */ }; const char * sg_lib_pdt_strs[] = { /* 0 */ "disk", "tape", "printer", "processor", /* often SAF-TE device, copy manager */ "write once optical disk", /* 5 */ "cd/dvd", "scanner", /* obsolete */ "optical memory device", "medium changer", "communications", /* obsolete */ /* 0xa */ "graphics [0xa]", /* obsolete */ "graphics [0xb]", /* obsolete */ "storage array controller", "enclosure services device", "simplified direct access device", "optical card reader/writer device", /* 0x10 */ "bridge controller commands", "object based storage", "automation/driver interface", "security manager device", "zoned block commands", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "well known logical unit", "no physical device on this lu", }; const char * sg_lib_transport_proto_strs[] = { "Fibre Channel Protocol for SCSI (FCP-4)", "SCSI Parallel Interface (SPI-5)", "Serial Storage Architecture SCSI-3 Protocol (SSA-S3P)", "Serial Bus Protocol for IEEE 1394 (SBP-3)", "SCSI RDMA Protocol (SRP)", "Internet SCSI (iSCSI)", "Serial Attached SCSI Protocol (SPL-3)", "Automation/Drive Interface Transport (ADT-2)", "AT Attachment Interface (ACS-2)", /* 0x8 */ "USB Attached SCSI (UAS-2)", "SCSI over PCI Express (SOP)", "Oxb", "Oxc", "Oxd", "Oxe", "No specific protocol" }; ddpt-0.94/lib/sg_pt_freebsd.c0000644000175000017500000003307712227056727015141 0ustar douggdougg/* * Copyright (c) 2005-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* sg_pt_freebsd version 1.12 20130919 */ #include #include #include #include #include #include #include #include #include #include // #include #include #include #include #include #include #include #include "sg_pt.h" #include "sg_lib.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #define FREEBSD_MAXDEV 64 #define FREEBSD_FDOFFSET 16; struct freebsd_dev_channel { char* devname; // the SCSI device name int unitnum; // the SCSI unit number struct cam_device* cam_dev; }; // Private table of open devices: guaranteed zero on startup since // part of static data. static struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV]; #define DEF_TIMEOUT 60000 /* 60,000 milliseconds (60 seconds) */ struct sg_pt_freebsd_scsi { struct cam_device* cam_dev; // copy held for error processing union ccb *ccb; unsigned char * cdb; int cdb_len; unsigned char * sense; int sense_len; unsigned char * dxferp; int dxfer_len; int dxfer_dir; int scsi_status; int resid; int sense_resid; int in_err; int os_err; int transport_err; }; struct sg_pt_base { struct sg_pt_freebsd_scsi impl; }; /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose) { int oflags = 0 /* O_NONBLOCK*/ ; oflags |= (read_only ? O_RDONLY : O_RDWR); return scsi_pt_open_flags(device_name, oflags, verbose); } /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. The 'flags' argument is ignored in FreeBSD. * Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags __attribute__ ((unused)), int verbose) { struct freebsd_dev_channel *fdchan; struct cam_device* cam_dev; int k; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; // Search table for a free entry for (k = 0; k < FREEBSD_MAXDEV; k++) if (! devicetable[k]) break; // If no free entry found, return error. We have max allowed number // of "file descriptors" already allocated. if (k == FREEBSD_MAXDEV) { if (verbose) fprintf(sg_warnings_strm, "too many open file descriptors " "(%d)\n", FREEBSD_MAXDEV); errno = EMFILE; return -1; } fdchan = (struct freebsd_dev_channel *) calloc(1,sizeof(struct freebsd_dev_channel)); if (fdchan == NULL) { // errno already set by call to calloc() return -1; } if (! (fdchan->devname = (char *)calloc(1, DEV_IDLEN+1))) return -1; if (cam_get_device(device_name, fdchan->devname, DEV_IDLEN, &(fdchan->unitnum)) == -1) { if (verbose) fprintf(sg_warnings_strm, "bad device name structure\n"); errno = EINVAL; return -1; } if (! (cam_dev = cam_open_spec_device(fdchan->devname, fdchan->unitnum, O_RDWR, NULL))) { if (verbose) fprintf(sg_warnings_strm, "cam_open_spec_device: %s\n", cam_errbuf); errno = EPERM; /* permissions or no CAM */ return -1; } fdchan->cam_dev = cam_dev; // return pointer to "file descriptor" table entry, properly offset. devicetable[k] = fdchan; return k + FREEBSD_FDOFFSET; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { struct freebsd_dev_channel *fdchan; int fd = device_fd - FREEBSD_FDOFFSET; if ((fd < 0) || (fd >= FREEBSD_MAXDEV)) { errno = ENODEV; return -1; } fdchan = devicetable[fd]; if (NULL == fdchan) { errno = ENODEV; return -1; } if (fdchan->devname) free(fdchan->devname); if (fdchan->cam_dev) cam_close_device(fdchan->cam_dev); free(fdchan); devicetable[fd] = NULL; return 0; } struct sg_pt_base * construct_scsi_pt_obj() { struct sg_pt_freebsd_scsi * ptp; ptp = (struct sg_pt_freebsd_scsi *) calloc(1, sizeof(struct sg_pt_freebsd_scsi)); if (ptp) { memset(ptp, 0, sizeof(struct sg_pt_freebsd_scsi)); ptp->dxfer_dir = CAM_DIR_NONE; } return (struct sg_pt_base *)ptp; } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp) { if (ptp->ccb) cam_freeccb(ptp->ccb); free(ptp); } } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp) { if (ptp->ccb) cam_freeccb(ptp->ccb); memset(ptp, 0, sizeof(struct sg_pt_freebsd_scsi)); ptp->dxfer_dir = CAM_DIR_NONE; } } void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, int cdb_len) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp->cdb) ++ptp->in_err; ptp->cdb = (unsigned char *)cdb; ptp->cdb_len = cdb_len; } void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, int max_sense_len) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp->sense) ++ptp->in_err; memset(sense, 0, max_sense_len); ptp->sense = sense; ptp->sense_len = max_sense_len; } /* Setup for data transfer from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, int dxfer_len) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp->dxferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->dxferp = dxferp; ptp->dxfer_len = dxfer_len; ptp->dxfer_dir = CAM_DIR_IN; } } /* Setup for data transfer toward device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, int dxfer_len) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp->dxferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->dxferp = (unsigned char *)dxferp; ptp->dxfer_len = dxfer_len; ptp->dxfer_dir = CAM_DIR_OUT; } } void set_scsi_pt_packet_id(struct sg_pt_base * vp __attribute__ ((unused)), int pack_id __attribute__ ((unused))) { } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag __attribute__ ((unused))) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; ++ptp->in_err; } void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code __attribute__ ((unused))) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; ++ptp->in_err; } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attrib __attribute__ ((unused)), int priority __attribute__ ((unused))) { struct sg_pt_freebsd_scsi * ptp = &vp->impl; ++ptp->in_err; } void set_scsi_pt_flags(struct sg_pt_base * objp, int flags) { if (objp) { ; } /* unused, suppress warning */ if (flags) { ; } /* unused, suppress warning */ } /* Executes SCSI command (or at least forwards it to lower layers). * Clears os_err field prior to active call (whose result may set it * again). */ int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { int fd = device_fd - FREEBSD_FDOFFSET; struct sg_pt_freebsd_scsi * ptp = &vp->impl; struct freebsd_dev_channel *fdchan; union ccb *ccb; int len, timout_ms; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; ptp->os_err = 0; if (ptp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused set_scsi_pt...\n"); return SCSI_PT_DO_BAD_PARAMS; } if (NULL == ptp->cdb) { if (verbose) fprintf(sg_warnings_strm, "No command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } if ((fd < 0) || (fd >= FREEBSD_MAXDEV)) { if (verbose) fprintf(sg_warnings_strm, "Bad file descriptor\n"); ptp->os_err = ENODEV; return -ptp->os_err; } fdchan = devicetable[fd]; if (NULL == fdchan) { if (verbose) fprintf(sg_warnings_strm, "File descriptor closed??\n"); ptp->os_err = ENODEV; return -ptp->os_err; } if (NULL == fdchan->cam_dev) { if (verbose) fprintf(sg_warnings_strm, "No open CAM device\n"); return SCSI_PT_DO_BAD_PARAMS; } if (NULL == ptp->ccb) { /* re-use if we have one already */ if (! (ccb = cam_getccb(fdchan->cam_dev))) { if (verbose) fprintf(sg_warnings_strm, "cam_getccb: failed\n"); ptp->os_err = ENOMEM; return -ptp->os_err; } ptp->ccb = ccb; } else ccb = ptp->ccb; // clear out structure, except for header that was filled in for us bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); timout_ms = (time_secs > 0) ? (time_secs * 1000) : DEF_TIMEOUT; cam_fill_csio(&ccb->csio, /* retries */ 1, /* cbfcnp */ NULL, /* flags */ ptp->dxfer_dir, /* tagaction */ MSG_SIMPLE_Q_TAG, /* dataptr */ ptp->dxferp, /* datalen */ ptp->dxfer_len, /* senselen */ ptp->sense_len, /* cdblen */ ptp->cdb_len, /* timeout (millisecs) */ timout_ms); memcpy(ccb->csio.cdb_io.cdb_bytes, ptp->cdb, ptp->cdb_len); if (cam_send_ccb(fdchan->cam_dev, ccb) < 0) { if (verbose) { warn("error sending SCSI ccb"); #if __FreeBSD_version > 500000 cam_error_print(fdchan->cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); #endif } cam_freeccb(ptp->ccb); ptp->ccb = NULL; ptp->os_err = EIO; return -ptp->os_err; } if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)) { ptp->scsi_status = ccb->csio.scsi_status; ptp->resid = ccb->csio.resid; ptp->sense_resid = ccb->csio.sense_resid; if ((SAM_STAT_CHECK_CONDITION == ptp->scsi_status) || (SAM_STAT_COMMAND_TERMINATED == ptp->scsi_status)) { if (ptp->sense_resid > ptp->sense_len) len = ptp->sense_len; /* crazy; ignore sense_resid */ else len = ptp->sense_len - ptp->sense_resid; if (len > 0) memcpy(ptp->sense, &(ccb->csio.sense_data), len); } } else ptp->transport_err = 1; ptp->cam_dev = fdchan->cam_dev; // for error processing return 0; } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp->os_err) return SCSI_PT_RESULT_OS_ERR; else if (ptp->transport_err) return SCSI_PT_RESULT_TRANSPORT_ERR; else if ((SAM_STAT_CHECK_CONDITION == ptp->scsi_status) || (SAM_STAT_COMMAND_TERMINATED == ptp->scsi_status)) return SCSI_PT_RESULT_SENSE; else if (ptp->scsi_status) return SCSI_PT_RESULT_STATUS; else return SCSI_PT_RESULT_GOOD; } int get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; return ptp->resid; } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; return ptp->scsi_status; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (ptp->sense_resid > ptp->sense_len) return ptp->sense_len; /* strange; ignore ptp->sense_resid */ else return ptp->sense_len - ptp->sense_resid; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused))) { // const struct sg_pt_freebsd_scsi * ptp = &vp->impl; return -1; } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; return ptp->transport_err; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; return ptp->os_err; } char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; if (0 == ptp->transport_err) { strncpy(b, "no transport error available", max_b_len); b[max_b_len - 1] = '\0'; return b; } #if __FreeBSD_version > 500000 if (ptp->cam_dev) cam_error_string(ptp->cam_dev, ptp->ccb, b, max_b_len, CAM_ESF_ALL, CAM_EPF_ALL); else { strncpy(b, "no transport error available", max_b_len); b[max_b_len - 1] = '\0'; } #else strncpy(b, "no transport error available", max_b_len); b[max_b_len - 1] = '\0'; #endif return b; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_freebsd_scsi * ptp = &vp->impl; const char * cp; cp = safe_strerror(ptp->os_err); strncpy(b, cp, max_b_len); if ((int)strlen(cp) >= max_b_len) b[max_b_len - 1] = '\0'; return b; } ddpt-0.94/lib/sg_pt_linux.c0000644000175000017500000006742612227056727014673 0ustar douggdougg/* * Copyright (c) 2005-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* sg_pt_linux version 1.20 20131014 */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "sg_pt.h" #include "sg_lib.h" #include "sg_linux_inc.h" #define DEF_TIMEOUT 60000 /* 60,000 millisecs (60 seconds) */ static const char * linux_host_bytes[] = { "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE" /* 0xd */, "DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE" /* 0x10 */, "DID_NEXUS_FAILURE (reservation conflict)", }; #define LINUX_HOST_BYTES_SZ \ (int)(sizeof(linux_host_bytes) / sizeof(linux_host_bytes[0])) static const char * linux_driver_bytes[] = { "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE" }; #define LINUX_DRIVER_BYTES_SZ \ (int)(sizeof(linux_driver_bytes) / sizeof(linux_driver_bytes[0])) static const char * linux_driver_suggests[] = { "SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", "UNKNOWN","UNKNOWN","UNKNOWN", "SUGGEST_SENSE" }; #define LINUX_DRIVER_SUGGESTS_SZ \ (int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0])) /* * These defines are for constants that should be visible in the * /usr/include/scsi directory (brought in by sg_linux_inc.h). * Redefined and aliased here to decouple this code from * sg_io_linux.h */ #ifndef DRIVER_MASK #define DRIVER_MASK 0x0f #endif #ifndef SUGGEST_MASK #define SUGGEST_MASK 0xf0 #endif #ifndef DRIVER_SENSE #define DRIVER_SENSE 0x08 #endif #define SG_LIB_DRIVER_MASK DRIVER_MASK #define SG_LIB_SUGGEST_MASK SUGGEST_MASK #define SG_LIB_DRIVER_SENSE DRIVER_SENSE // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #if defined(IGNORE_LINUX_BSG) || ! defined(HAVE_LINUX_BSG_H) /* * sg(v3) via SG_IO ioctl on a sg node or other node that accepts that ioctl. * Decision has been made at compile time because either: * a) no /usr/include/linux/bsg.h header file was found, or * b) the builder gave the '--enable-no-linux-bsg' option to ./configure */ struct sg_pt_linux_scsi { struct sg_io_hdr io_hdr; int in_err; int os_err; }; struct sg_pt_base { struct sg_pt_linux_scsi impl; }; /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose) { int oflags = O_NONBLOCK; oflags |= (read_only ? O_RDONLY : O_RDWR); return scsi_pt_open_flags(device_name, oflags, verbose); } /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed */ /* together. The 'flags' argument is advisory and may be ignored. */ /* Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags, int verbose) { int fd; if (verbose > 1) { if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "open %s with flags=0x%x\n", device_name, flags); } fd = open(device_name, flags); if (fd < 0) fd = -errno; return fd; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { int res; res = close(device_fd); if (res < 0) res = -errno; return res; } struct sg_pt_base * construct_scsi_pt_obj() { struct sg_pt_linux_scsi * ptp; ptp = (struct sg_pt_linux_scsi *) calloc(1, sizeof(struct sg_pt_linux_scsi)); if (ptp) { ptp->io_hdr.interface_id = 'S'; ptp->io_hdr.dxfer_direction = SG_DXFER_NONE; } return (struct sg_pt_base *)ptp; } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp) free(ptp); } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp) { memset(ptp, 0, sizeof(struct sg_pt_linux_scsi)); ptp->io_hdr.interface_id = 'S'; ptp->io_hdr.dxfer_direction = SG_DXFER_NONE; } } void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, int cdb_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.cmdp) ++ptp->in_err; ptp->io_hdr.cmdp = (unsigned char *)cdb; ptp->io_hdr.cmd_len = cdb_len; } void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, int max_sense_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.sbp) ++ptp->in_err; memset(sense, 0, max_sense_len); ptp->io_hdr.sbp = sense; ptp->io_hdr.mx_sb_len = max_sense_len; } /* Setup for data transfer from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, int dxfer_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.dxferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->io_hdr.dxferp = dxferp; ptp->io_hdr.dxfer_len = dxfer_len; ptp->io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; } } /* Setup for data transfer toward device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, int dxfer_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.dxferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->io_hdr.dxferp = (unsigned char *)dxferp; ptp->io_hdr.dxfer_len = dxfer_len; ptp->io_hdr.dxfer_direction = SG_DXFER_TO_DEV; } } void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id) { struct sg_pt_linux_scsi * ptp = &vp->impl; ptp->io_hdr.pack_id = pack_id; } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag) { struct sg_pt_linux_scsi * ptp = &vp->impl; ++ptp->in_err; if (tag) { ; } /* unused, suppress warning */ } /* Note that task management function codes are transport specific */ void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code) { struct sg_pt_linux_scsi * ptp = &vp->impl; ++ptp->in_err; if (tmf_code) { ; } /* unused, suppress warning */ } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority) { struct sg_pt_linux_scsi * ptp = &vp->impl; ++ptp->in_err; if (attribute) { ; } /* unused, suppress warning */ if (priority) { ; } /* unused, suppress warning */ } #ifndef SG_FLAG_Q_AT_TAIL #define SG_FLAG_Q_AT_TAIL 0x10 #endif #ifndef SG_FLAG_Q_AT_HEAD #define SG_FLAG_Q_AT_HEAD 0x20 #endif void set_scsi_pt_flags(struct sg_pt_base * vp, int flags) { struct sg_pt_linux_scsi * ptp = &vp->impl; /* default action of SG (v3) is QUEUE_AT_HEAD */ /* default action of block layer SG_IO ioctl is QUEUE_AT_TAIL */ if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags) { ptp->io_hdr.flags |= SG_FLAG_Q_AT_TAIL; ptp->io_hdr.flags &= ~SG_FLAG_Q_AT_HEAD; } if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) { ptp->io_hdr.flags |= SG_FLAG_Q_AT_HEAD; ptp->io_hdr.flags &= ~SG_FLAG_Q_AT_TAIL; } } /* Executes SCSI command (or at least forwards it to lower layers). * Clears os_err field prior to active call (whose result may set it * again). */ int do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; ptp->os_err = 0; if (ptp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused set_scsi_pt... " "functions\n"); return SCSI_PT_DO_BAD_PARAMS; } if (NULL == ptp->io_hdr.cmdp) { if (verbose) fprintf(sg_warnings_strm, "No SCSI command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } /* io_hdr.timeout is in milliseconds */ ptp->io_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) : DEF_TIMEOUT); if (ptp->io_hdr.sbp && (ptp->io_hdr.mx_sb_len > 0)) memset(ptp->io_hdr.sbp, 0, ptp->io_hdr.mx_sb_len); if (ioctl(fd, SG_IO, &ptp->io_hdr) < 0) { ptp->os_err = errno; if (verbose > 1) fprintf(sg_warnings_strm, "ioctl(SG_IO) failed: %s (errno=%d)\n", strerror(ptp->os_err), ptp->os_err); return -ptp->os_err; } return 0; } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; int dr_st = ptp->io_hdr.driver_status & SG_LIB_DRIVER_MASK; int scsi_st = ptp->io_hdr.status & 0x7e; if (ptp->os_err) return SCSI_PT_RESULT_OS_ERR; else if (ptp->io_hdr.host_status) return SCSI_PT_RESULT_TRANSPORT_ERR; else if (dr_st && (SG_LIB_DRIVER_SENSE != dr_st)) return SCSI_PT_RESULT_TRANSPORT_ERR; else if ((SG_LIB_DRIVER_SENSE == dr_st) || (SAM_STAT_CHECK_CONDITION == scsi_st) || (SAM_STAT_COMMAND_TERMINATED == scsi_st)) return SCSI_PT_RESULT_SENSE; else if (scsi_st) return SCSI_PT_RESULT_STATUS; else return SCSI_PT_RESULT_GOOD; } int get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.resid; } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.status; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.sb_len_wr; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.duration; } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return (ptp->io_hdr.host_status << 8) + ptp->io_hdr.driver_status; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->os_err; } /* Returns b which will contain a null char terminated string (if * max_b_len > 0). That string should decode Linux driver and host * status values. */ char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_linux_scsi * ptp = &vp->impl; int ds = ptp->io_hdr.driver_status; int hs = ptp->io_hdr.host_status; int n, m; char * cp = b; int driv, sugg; const char * driv_cp = "unknown"; const char * sugg_cp = "unknown"; if (max_b_len < 1) return b; m = max_b_len; n = 0; if (hs) { if ((hs < 0) || (hs >= LINUX_HOST_BYTES_SZ)) n = snprintf(cp, m, "Host_status=0x%02x is unknown\n", hs); else n = snprintf(cp, m, "Host_status=0x%02x [%s]\n", hs, linux_host_bytes[hs]); } m -= n; if (m < 1) { b[max_b_len - 1] = '\0'; return b; } cp += n; driv = ds & SG_LIB_DRIVER_MASK; if (driv < LINUX_DRIVER_BYTES_SZ) driv_cp = linux_driver_bytes[driv]; sugg = (ds & SG_LIB_SUGGEST_MASK) >> 4; if (sugg < LINUX_DRIVER_SUGGESTS_SZ) sugg_cp = linux_driver_suggests[sugg]; n = snprintf(cp, m, "Driver_status=0x%02x [%s, %s]\n", ds, driv_cp, sugg_cp); m -= n; if (m < 1) b[max_b_len - 1] = '\0'; return b; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_linux_scsi * ptp = &vp->impl; const char * cp; cp = safe_strerror(ptp->os_err); strncpy(b, cp, max_b_len); if ((int)strlen(cp) >= max_b_len) b[max_b_len - 1] = '\0'; return b; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #else /* allow for runtime selection of sg v3 or v4 (via bsg) */ // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /* * So bsg is an option. Thus we make a runtime decision. If all the following * are true we use sg v4 which is only currently supported on bsg device * nodes: * a) there is a bsg entry in the /proc/devices file * b) the device node given to scsi_pt_open() is a char device * c) the char major number of the device node given to scsi_pt_open() * matches the char major number of the bsg entry in /proc/devices * Otherwise the sg v3 interface is used. * * Note that in either case we prepare the data in a sg v4 structure. If * the runtime tests indicate that the v3 interface is needed then * do_scsi_pt_v3() transfers the input data into a v3 structure and * then the output data is transferred back into a sg v4 structure. * That implementation detail could change in the future. * * [20120806] Only use MAJOR() macro in kdev_t.h if that header file is * available and major() macro [N.B. lower case] is not available. */ #include #include #ifdef major #define SG_DEV_MAJOR major #else #ifdef HAVE_LINUX_KDEV_T_H #include #endif #define SG_DEV_MAJOR MAJOR /* MAJOR() macro faulty if > 255 minors */ #endif struct sg_pt_linux_scsi { struct sg_io_v4 io_hdr; /* use v4 header as it is more general */ int in_err; int os_err; unsigned char tmf_request[4]; }; struct sg_pt_base { struct sg_pt_linux_scsi impl; }; static int bsg_major_checked = 0; static int bsg_major = 0; static void find_bsg_major(int verbose) { const char * proc_devices = "/proc/devices"; FILE *fp; char a[128]; char b[128]; char * cp; int n; if (NULL == (fp = fopen(proc_devices, "r"))) { if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) fprintf(sg_warnings_strm, "fopen %s failed: %s\n", proc_devices, strerror(errno)); return; } while ((cp = fgets(b, sizeof(b), fp))) { if ((1 == sscanf(b, "%s", a)) && (0 == memcmp(a, "Character", 9))) break; } while (cp && (cp = fgets(b, sizeof(b), fp))) { if (2 == sscanf(b, "%d %s", &n, a)) { if (0 == strcmp("bsg", a)) { bsg_major = n; break; } } else break; } if (verbose > 3) { if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (cp) fprintf(sg_warnings_strm, "found bsg_major=%d\n", bsg_major); else fprintf(sg_warnings_strm, "found no bsg char device in %s\n", proc_devices); } fclose(fp); } /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose) { int oflags = O_NONBLOCK; oflags |= (read_only ? O_RDONLY : O_RDWR); return scsi_pt_open_flags(device_name, oflags, verbose); } /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed */ /* together. The 'flags' argument is advisory and may be ignored. */ /* Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags, int verbose) { int fd; if (! bsg_major_checked) { bsg_major_checked = 1; find_bsg_major(verbose); } if (verbose > 1) { if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; fprintf(sg_warnings_strm, "open %s with flags=0x%x\n", device_name, flags); } fd = open(device_name, flags); if (fd < 0) fd = -errno; return fd; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { int res; res = close(device_fd); if (res < 0) res = -errno; return res; } struct sg_pt_base * construct_scsi_pt_obj() { struct sg_pt_linux_scsi * ptp; ptp = (struct sg_pt_linux_scsi *) calloc(1, sizeof(struct sg_pt_linux_scsi)); if (ptp) { ptp->io_hdr.guard = 'Q'; #ifdef BSG_PROTOCOL_SCSI ptp->io_hdr.protocol = BSG_PROTOCOL_SCSI; #endif #ifdef BSG_SUB_PROTOCOL_SCSI_CMD ptp->io_hdr.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; #endif } return (struct sg_pt_base *)ptp; } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp) free(ptp); } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp) { memset(ptp, 0, sizeof(struct sg_pt_linux_scsi)); ptp->io_hdr.guard = 'Q'; #ifdef BSG_PROTOCOL_SCSI ptp->io_hdr.protocol = BSG_PROTOCOL_SCSI; #endif #ifdef BSG_SUB_PROTOCOL_SCSI_CMD ptp->io_hdr.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; #endif } } void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, int cdb_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.request) ++ptp->in_err; /* C99 has intptr_t instead of long */ ptp->io_hdr.request = (__u64)(long)cdb; ptp->io_hdr.request_len = cdb_len; } void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, int max_sense_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.response) ++ptp->in_err; memset(sense, 0, max_sense_len); ptp->io_hdr.response = (__u64)(long)sense; ptp->io_hdr.max_response_len = max_sense_len; } /* Setup for data transfer from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, int dxfer_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.din_xferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->io_hdr.din_xferp = (__u64)(long)dxferp; ptp->io_hdr.din_xfer_len = dxfer_len; } } /* Setup for data transfer toward device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, int dxfer_len) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (ptp->io_hdr.dout_xferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->io_hdr.dout_xferp = (__u64)(long)dxferp; ptp->io_hdr.dout_xfer_len = dxfer_len; } } void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id) { struct sg_pt_linux_scsi * ptp = &vp->impl; ptp->io_hdr.spare_in = pack_id; } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag) { struct sg_pt_linux_scsi * ptp = &vp->impl; ptp->io_hdr.request_tag = tag; } /* Note that task management function codes are transport specific */ void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code) { struct sg_pt_linux_scsi * ptp = &vp->impl; ptp->io_hdr.subprotocol = 1; /* SCSI task management function */ ptp->tmf_request[0] = (unsigned char)tmf_code; /* assume it fits */ ptp->io_hdr.request = (__u64)(long)(&(ptp->tmf_request[0])); ptp->io_hdr.request_len = 1; } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority) { struct sg_pt_linux_scsi * ptp = &vp->impl; ptp->io_hdr.request_attr = attribute; ptp->io_hdr.request_priority = priority; } #ifndef BSG_FLAG_Q_AT_TAIL #define BSG_FLAG_Q_AT_TAIL 0x10 #endif void set_scsi_pt_flags(struct sg_pt_base * vp, int flags) { struct sg_pt_linux_scsi * ptp = &vp->impl; /* default action of bsg (sg v4) is QUEUE_AT_HEAD */ if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags) ptp->io_hdr.flags |= BSG_FLAG_Q_AT_TAIL; if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_TAIL; } /* N.B. Returns din_resid and ignores dout_resid */ int get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.din_resid; } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.device_status; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.response_len; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.duration; } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->io_hdr.transport_status; } /* Returns b which will contain a null char terminated string (if * max_b_len > 0). Combined driver and transport (called "host" in Linux * kernel) statuses */ char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_linux_scsi * ptp = &vp->impl; int ds = ptp->io_hdr.driver_status; int hs = ptp->io_hdr.transport_status; int n, m; char * cp = b; int driv, sugg; const char * driv_cp = "invalid"; const char * sugg_cp = "invalid"; if (max_b_len < 1) return b; m = max_b_len; n = 0; if (hs) { if ((hs < 0) || (hs >= LINUX_HOST_BYTES_SZ)) n = snprintf(cp, m, "Host_status=0x%02x is invalid\n", hs); else n = snprintf(cp, m, "Host_status=0x%02x [%s]\n", hs, linux_host_bytes[hs]); } m -= n; if (m < 1) { b[max_b_len - 1] = '\0'; return b; } cp += n; driv = ds & SG_LIB_DRIVER_MASK; if (driv < LINUX_DRIVER_BYTES_SZ) driv_cp = linux_driver_bytes[driv]; sugg = (ds & SG_LIB_SUGGEST_MASK) >> 4; if (sugg < LINUX_DRIVER_SUGGESTS_SZ) sugg_cp = linux_driver_suggests[sugg]; n = snprintf(cp, m, "Driver_status=0x%02x [%s, %s]\n", ds, driv_cp, sugg_cp); m -= n; if (m < 1) b[max_b_len - 1] = '\0'; return b; } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; int dr_st = ptp->io_hdr.driver_status & SG_LIB_DRIVER_MASK; int scsi_st = ptp->io_hdr.device_status & 0x7e; if (ptp->os_err) return SCSI_PT_RESULT_OS_ERR; else if (ptp->io_hdr.transport_status) return SCSI_PT_RESULT_TRANSPORT_ERR; else if (dr_st && (SG_LIB_DRIVER_SENSE != dr_st)) return SCSI_PT_RESULT_TRANSPORT_ERR; else if ((SG_LIB_DRIVER_SENSE == dr_st) || (SAM_STAT_CHECK_CONDITION == scsi_st) || (SAM_STAT_COMMAND_TERMINATED == scsi_st)) return SCSI_PT_RESULT_SENSE; else if (scsi_st) return SCSI_PT_RESULT_STATUS; else return SCSI_PT_RESULT_GOOD; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { const struct sg_pt_linux_scsi * ptp = &vp->impl; return ptp->os_err; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_linux_scsi * ptp = &vp->impl; const char * cp; cp = safe_strerror(ptp->os_err); strncpy(b, cp, max_b_len); if ((int)strlen(cp) >= max_b_len) b[max_b_len - 1] = '\0'; return b; } /* Executes SCSI command using sg v3 interface */ static int do_scsi_pt_v3(struct sg_pt_linux_scsi * ptp, int fd, int time_secs, int verbose) { struct sg_io_hdr v3_hdr; memset(&v3_hdr, 0, sizeof(v3_hdr)); /* convert v4 to v3 header */ v3_hdr.interface_id = 'S'; v3_hdr.dxfer_direction = SG_DXFER_NONE; v3_hdr.cmdp = (unsigned char *)(long)ptp->io_hdr.request; v3_hdr.cmd_len = (unsigned char)ptp->io_hdr.request_len; if (ptp->io_hdr.din_xfer_len > 0) { if (ptp->io_hdr.dout_xfer_len > 0) { if (verbose) fprintf(sg_warnings_strm, "sgv3 doesn't support bidi\n"); return SCSI_PT_DO_BAD_PARAMS; } v3_hdr.dxferp = (void *)(long)ptp->io_hdr.din_xferp; v3_hdr.dxfer_len = (unsigned int)ptp->io_hdr.din_xfer_len; v3_hdr.dxfer_direction = SG_DXFER_FROM_DEV; } else if (ptp->io_hdr.dout_xfer_len > 0) { v3_hdr.dxferp = (void *)(long)ptp->io_hdr.dout_xferp; v3_hdr.dxfer_len = (unsigned int)ptp->io_hdr.dout_xfer_len; v3_hdr.dxfer_direction = SG_DXFER_TO_DEV; } if (ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 0)) { v3_hdr.sbp = (unsigned char *)(long)ptp->io_hdr.response; v3_hdr.mx_sb_len = (unsigned char)ptp->io_hdr.max_response_len; } v3_hdr.pack_id = (int)ptp->io_hdr.spare_in; if (NULL == v3_hdr.cmdp) { if (verbose) fprintf(sg_warnings_strm, "No SCSI command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } /* io_hdr.timeout is in milliseconds, if greater than zero */ v3_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) : DEF_TIMEOUT); /* Finally do the v3 SG_IO ioctl */ if (ioctl(fd, SG_IO, &v3_hdr) < 0) { ptp->os_err = errno; if (verbose > 1) fprintf(sg_warnings_strm, "ioctl(SG_IO v3) failed: %s " "(errno=%d)\n", strerror(ptp->os_err), ptp->os_err); return -ptp->os_err; } ptp->io_hdr.device_status = (__u32)v3_hdr.status; ptp->io_hdr.driver_status = (__u32)v3_hdr.driver_status; ptp->io_hdr.transport_status = (__u32)v3_hdr.host_status; ptp->io_hdr.response_len = (__u32)v3_hdr.sb_len_wr; ptp->io_hdr.duration = (__u32)v3_hdr.duration; ptp->io_hdr.din_resid = (__s32)v3_hdr.resid; /* v3_hdr.info not passed back since no mapping defined (yet) */ return 0; } /* Executes SCSI command (or at least forwards it to lower layers). * Clears os_err field prior to active call (whose result may set it * again). */ int do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose) { struct sg_pt_linux_scsi * ptp = &vp->impl; if (! bsg_major_checked) { bsg_major_checked = 1; find_bsg_major(verbose); } if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; ptp->os_err = 0; if (ptp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused set_scsi_pt... " "functions\n"); return SCSI_PT_DO_BAD_PARAMS; } if (bsg_major <= 0) return do_scsi_pt_v3(ptp, fd, time_secs, verbose); else { struct stat a_stat; if (fstat(fd, &a_stat) < 0) { ptp->os_err = errno; if (verbose > 1) fprintf(sg_warnings_strm, "fstat() failed: %s (errno=%d)\n", strerror(ptp->os_err), ptp->os_err); return -ptp->os_err; } if (! S_ISCHR(a_stat.st_mode) || (bsg_major != (int)SG_DEV_MAJOR(a_stat.st_rdev))) return do_scsi_pt_v3(ptp, fd, time_secs, verbose); } if (! ptp->io_hdr.request) { if (verbose) fprintf(sg_warnings_strm, "No SCSI command (cdb) given (v4)\n"); return SCSI_PT_DO_BAD_PARAMS; } /* io_hdr.timeout is in milliseconds */ ptp->io_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) : DEF_TIMEOUT); #if 0 /* sense buffer already zeroed */ if (ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 0)) { void * p; p = (void *)(long)ptp->io_hdr.response; memset(p, 0, ptp->io_hdr.max_response_len); } #endif if (ioctl(fd, SG_IO, &ptp->io_hdr) < 0) { ptp->os_err = errno; if (verbose > 1) fprintf(sg_warnings_strm, "ioctl(SG_IO v4) failed: %s " "(errno=%d)\n", strerror(ptp->os_err), ptp->os_err); return -ptp->os_err; } return 0; } #endif // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ddpt-0.94/lib/sg_pt_solaris.c0000644000175000017500000002146511351460102015160 0ustar douggdougg/* * Copyright (c) 2007-2010 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* sg_pt_solaris version 1.03 20100321 */ #include #include #include #include #include #include #include #include /* Solaris headers */ #include #include #include #include #include "sg_pt.h" #include "sg_lib.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #define DEF_TIMEOUT 60 /* 60 seconds */ struct sg_pt_solaris_scsi { struct uscsi_cmd uscsi; int max_sense_len; int in_err; int os_err; }; struct sg_pt_base { struct sg_pt_solaris_scsi impl; }; /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose) { int oflags = 0 /* O_NONBLOCK*/ ; oflags |= (read_only ? O_RDONLY : O_RDWR); return scsi_pt_open_flags(device_name, oflags, verbose); } /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. The 'flags' argument is ignored in Solaris. * Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags_arg, int verbose) { int oflags = O_NONBLOCK | O_RDWR; int fd; flags_arg = flags_arg; /* ignore flags argument, suppress warning */ if (verbose > 1) { fprintf(stderr, "open %s with flags=0x%x\n", device_name, oflags); } fd = open(device_name, oflags); if (fd < 0) fd = -errno; return fd; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { int res; res = close(device_fd); if (res < 0) res = -errno; return res; } struct sg_pt_base * construct_scsi_pt_obj() { struct sg_pt_solaris_scsi * ptp; ptp = (struct sg_pt_solaris_scsi *) calloc(1, sizeof(struct sg_pt_solaris_scsi)); if (ptp) { ptp->uscsi.uscsi_timeout = DEF_TIMEOUT; ptp->uscsi.uscsi_flags = USCSI_READ | USCSI_ISOLATE | USCSI_RQENABLE; ptp->uscsi.uscsi_timeout = DEF_TIMEOUT; } return (struct sg_pt_base *)ptp; } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_solaris_scsi * ptp = &vp->impl; if (ptp) free(ptp); } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_solaris_scsi * ptp = &vp->impl; if (ptp) { memset(ptp, 0, sizeof(struct sg_pt_solaris_scsi)); ptp->uscsi.uscsi_timeout = DEF_TIMEOUT; ptp->uscsi.uscsi_flags = USCSI_READ | USCSI_ISOLATE | USCSI_RQENABLE; ptp->uscsi.uscsi_timeout = DEF_TIMEOUT; } } void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, int cdb_len) { struct sg_pt_solaris_scsi * ptp = &vp->impl; if (ptp->uscsi.uscsi_cdb) ++ptp->in_err; ptp->uscsi.uscsi_cdb = (char *)cdb; ptp->uscsi.uscsi_cdblen = cdb_len; } void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, int max_sense_len) { struct sg_pt_solaris_scsi * ptp = &vp->impl; if (ptp->uscsi.uscsi_rqbuf) ++ptp->in_err; memset(sense, 0, max_sense_len); ptp->uscsi.uscsi_rqbuf = (char *)sense; ptp->uscsi.uscsi_rqlen = max_sense_len; ptp->max_sense_len = max_sense_len; } /* from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, int dxfer_len) { struct sg_pt_solaris_scsi * ptp = &vp->impl; if (ptp->uscsi.uscsi_bufaddr) ++ptp->in_err; if (dxfer_len > 0) { ptp->uscsi.uscsi_bufaddr = (char *)dxferp; ptp->uscsi.uscsi_buflen = dxfer_len; ptp->uscsi.uscsi_flags = USCSI_READ | USCSI_ISOLATE | USCSI_RQENABLE; } } /* to device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, int dxfer_len) { struct sg_pt_solaris_scsi * ptp = &vp->impl; if (ptp->uscsi.uscsi_bufaddr) ++ptp->in_err; if (dxfer_len > 0) { ptp->uscsi.uscsi_bufaddr = (char *)dxferp; ptp->uscsi.uscsi_buflen = dxfer_len; ptp->uscsi.uscsi_flags = USCSI_WRITE | USCSI_ISOLATE | USCSI_RQENABLE; } } void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id) { // struct sg_pt_solaris_scsi * ptp = &vp->impl; vp = vp; /* ignore and suppress warning */ pack_id = pack_id; /* ignore and suppress warning */ } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag) { // struct sg_pt_solaris_scsi * ptp = &vp->impl; vp = vp; /* ignore and suppress warning */ tag = tag; /* ignore and suppress warning */ } /* Note that task management function codes are transport specific */ void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code) { struct sg_pt_solaris_scsi * ptp = &vp->impl; ++ptp->in_err; tmf_code = tmf_code; /* dummy to silence compiler */ } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority) { struct sg_pt_solaris_scsi * ptp = &vp->impl; ++ptp->in_err; attribute = attribute; /* dummy to silence compiler */ priority = priority; /* dummy to silence compiler */ } void set_scsi_pt_flags(struct sg_pt_base * objp, int flags) { /* do nothing, suppress warnings */ objp = objp; flags = flags; } /* Executes SCSI command (or at least forwards it to lower layers). * Clears os_err field prior to active call (whose result may set it * again). */ int do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose) { struct sg_pt_solaris_scsi * ptp = &vp->impl; ptp->os_err = 0; if (ptp->in_err) { if (verbose) fprintf(stderr, "Replicated or unused set_scsi_pt... " "functions\n"); return SCSI_PT_DO_BAD_PARAMS; } if (NULL == ptp->uscsi.uscsi_cdb) { if (verbose) fprintf(stderr, "No SCSI command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } if (time_secs > 0) ptp->uscsi.uscsi_timeout = time_secs; if (ioctl(fd, USCSICMD, &ptp->uscsi)) { ptp->os_err = errno; if ((EIO == ptp->os_err) && ptp->uscsi.uscsi_status) { ptp->os_err = 0; return 0; } if (verbose) fprintf(stderr, "ioctl(USCSICMD) failed with os_err " "(errno) = %d\n", ptp->os_err); return -ptp->os_err; } return 0; } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { const struct sg_pt_solaris_scsi * ptp = &vp->impl; int scsi_st = ptp->uscsi.uscsi_status; if (ptp->os_err) return SCSI_PT_RESULT_OS_ERR; else if ((SAM_STAT_CHECK_CONDITION == scsi_st) || (SAM_STAT_COMMAND_TERMINATED == scsi_st)) return SCSI_PT_RESULT_SENSE; else if (scsi_st) return SCSI_PT_RESULT_STATUS; else return SCSI_PT_RESULT_GOOD; } int get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_solaris_scsi * ptp = &vp->impl; return ptp->uscsi.uscsi_resid; } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { const struct sg_pt_solaris_scsi * ptp = &vp->impl; return ptp->uscsi.uscsi_status; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { const struct sg_pt_solaris_scsi * ptp = &vp->impl; int res; if (ptp->max_sense_len > 0) { res = ptp->max_sense_len - ptp->uscsi.uscsi_rqresid; return (res > 0) ? res : 0; } return 0; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp) { // const struct sg_pt_solaris_scsi * ptp = &vp->impl; vp = vp; /* ignore and suppress warning */ return -1; /* not available */ } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { // const struct sg_pt_solaris_scsi * ptp = &vp->impl; vp = vp; /* ignore and suppress warning */ return 0; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { const struct sg_pt_solaris_scsi * ptp = &vp->impl; return ptp->os_err; } char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { // const struct sg_pt_solaris_scsi * ptp = &vp->impl; vp = vp; /* ignore and suppress warning */ if (max_b_len > 0) b[0] = '\0'; return b; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_solaris_scsi * ptp = &vp->impl; const char * cp; cp = safe_strerror(ptp->os_err); strncpy(b, cp, max_b_len); if ((int)strlen(cp) >= max_b_len) b[max_b_len - 1] = '\0'; return b; } ddpt-0.94/lib/sg_pt_osf1.c0000644000175000017500000003033412061626602014357 0ustar douggdougg/* * Copyright (c) 2005-2010 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sg_pt.h" #include "sg_lib.h" /* Changed to use struct sg_pt_base 20070403 */ #define OSF1_MAXDEV 64 struct osf1_dev_channel { int bus; int tgt; int lun; }; // Private table of open devices: guaranteed zero on startup since // part of static data. static struct osf1_dev_channel *devicetable[OSF1_MAXDEV] = {0}; static char *cam_dev = "/dev/cam"; static int camfd; static int camopened = 0; struct sg_pt_osf1_scsi { unsigned char * cdb; int cdb_len; unsigned char * sense; int sense_len; unsigned char * dxferp; int dxfer_len; int dxfer_dir; int scsi_status; int resid; int sense_resid; int in_err; int os_err; int transport_err; }; struct sg_pt_base { struct sg_pt_osf1_scsi impl; }; /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose) { int oflags = 0 /* O_NONBLOCK*/ ; oflags |= (read_only ? O_RDONLY : O_RDWR); return scsi_pt_open_flags(device_name, oflags, verbose); } /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. The 'flags' argument is ignored in OSF-1. * Returns >= 0 if successful, otherwise returns negated errno. */ int scsi_pt_open_flags(const char * device_name, int flags, int verbose) { struct osf1_dev_channel *fdchan; int fd, k; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (!camopened) { camfd = open(cam_dev, O_RDWR, 0); if (camfd < 0) return -1; camopened++; } // Search table for a free entry for (k = 0; k < OSF1_MAXDEV; k++) if (! devicetable[k]) break; if (k == OSF1_MAXDEV) { if (verbose) fprintf(sg_warnings_strm, "too many open devices " "(%d)\n", OSF1_MAXDEV); errno=EMFILE; return -1; } fdchan = (struct osf1_dev_channel *)calloc(1, sizeof(struct osf1_dev_channel)); if (fdchan == NULL) { // errno already set by call to malloc() return -1; } fd = open(device_name, O_RDONLY|O_NONBLOCK); if (fd > 0) { device_info_t devinfo; bzero(&devinfo, sizeof(devinfo)); if (ioctl(fd, DEVGETINFO, &devinfo) == 0) { fdchan->bus = devinfo.v1.businfo.bus.scsi.bus_num; fdchan->tgt = devinfo.v1.businfo.bus.scsi.tgt_id; fdchan->lun = devinfo.v1.businfo.bus.scsi.lun; } close (fd); } else { free(fdchan); return -1; } devicetable[k] = fdchan; return k; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { struct osf1_dev_channel *fdchan; int i; if ((device_fd < 0) || (device_fd >= OSF1_MAXDEV)) { errno = ENODEV; return -1; } fdchan = devicetable[device_fd]; if (NULL == fdchan) { errno = ENODEV; return -1; } free(fdchan); devicetable[device_fd] = NULL; for (i = 0; i < OSF1_MAXDEV; i++) { if (devicetable[i]) break; } if (i == OSF1_MAXDEV) { close(camfd); camopened = 0; } return 0; } struct sg_pt_base * construct_scsi_pt_obj() { struct sg_pt_osf1_scsi * ptp; ptp = (struct sg_pt_osf1_scsi *)malloc(sizeof(struct sg_pt_osf1_scsi)); if (ptp) { bzero(ptp, sizeof(struct sg_pt_osf1_scsi)); ptp->dxfer_dir = CAM_DIR_NONE; } return (struct sg_pt_base *)ptp; } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp) free(ptp); } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp) { bzero(ptp, sizeof(struct sg_pt_osf1_scsi)); ptp->dxfer_dir = CAM_DIR_NONE; } } void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, int cdb_len) { struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp->cdb) ++ptp->in_err; ptp->cdb = (unsigned char *)cdb; ptp->cdb_len = cdb_len; } void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, int max_sense_len) { struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp->sense) ++ptp->in_err; bzero(sense, max_sense_len); ptp->sense = sense; ptp->sense_len = max_sense_len; } /* from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, int dxfer_len) { struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp->dxferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->dxferp = dxferp; ptp->dxfer_len = dxfer_len; ptp->dxfer_dir = CAM_DIR_IN; } } /* to device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, int dxfer_len) { struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp->dxferp) ++ptp->in_err; if (dxfer_len > 0) { ptp->dxferp = (unsigned char *)dxferp; ptp->dxfer_len = dxfer_len; ptp->dxfer_dir = CAM_DIR_OUT; } } void set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id) { } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag) { struct sg_pt_osf1_scsi * ptp = &vp->impl; ++ptp->in_err; } void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code) { struct sg_pt_osf1_scsi * ptp = &vp->impl; ++ptp->in_err; } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attrib, int priority) { struct sg_pt_osf1_scsi * ptp = &vp->impl; ++ptp->in_err; } void set_scsi_pt_flags(struct sg_pt_base * objp, int flags) { /* do nothing, suppress warnings */ objp = objp; flags = flags; } static int release_sim(struct sg_pt_base *vp, int device_fd, int verbose) { struct sg_pt_osf1_scsi * ptp = &vp->impl; struct osf1_dev_channel *fdchan = devicetable[device_fd]; UAGT_CAM_CCB uagt; CCB_RELSIM relsim; int retval; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; bzero(&uagt, sizeof(uagt)); bzero(&relsim, sizeof(relsim)); uagt.uagt_ccb = (CCB_HEADER *) &relsim; uagt.uagt_ccblen = sizeof(relsim); relsim.cam_ch.cam_ccb_len = sizeof(relsim); relsim.cam_ch.cam_func_code = XPT_REL_SIMQ; relsim.cam_ch.cam_flags = CAM_DIR_IN | CAM_DIS_CALLBACK; relsim.cam_ch.cam_path_id = fdchan->bus; relsim.cam_ch.cam_target_id = fdchan->tgt; relsim.cam_ch.cam_target_lun = fdchan->lun; retval = ioctl(camfd, UAGT_CAM_IO, &uagt); if (retval < 0) { if (verbose) fprintf(sg_warnings_strm, "CAM ioctl error (Release SIM Queue)\n"); } return retval; } int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { struct sg_pt_osf1_scsi * ptp = &vp->impl; struct osf1_dev_channel *fdchan; int len, retval; CCB_SCSIIO ccb; UAGT_CAM_CCB uagt; unsigned char sensep[ADDL_SENSE_LENGTH]; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; ptp->os_err = 0; if (ptp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused set_scsi_pt...\n"); return SCSI_PT_DO_BAD_PARAMS; } if (NULL == ptp->cdb) { if (verbose) fprintf(sg_warnings_strm, "No command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } if ((device_fd < 0) || (device_fd >= OSF1_MAXDEV)) { if (verbose) fprintf(sg_warnings_strm, "Bad file descriptor\n"); ptp->os_err = ENODEV; return -ptp->os_err; } fdchan = devicetable[device_fd]; if (NULL == fdchan) { if (verbose) fprintf(sg_warnings_strm, "File descriptor closed??\n"); ptp->os_err = ENODEV; return -ptp->os_err; } if (0 == camopened) { if (verbose) fprintf(sg_warnings_strm, "No open CAM device\n"); return SCSI_PT_DO_BAD_PARAMS; } bzero(&uagt, sizeof(uagt)); bzero(&ccb, sizeof(ccb)); uagt.uagt_ccb = (CCB_HEADER *) &ccb; uagt.uagt_ccblen = sizeof(ccb); uagt.uagt_snsbuf = ccb.cam_sense_ptr = ptp->sense ? ptp->sense : sensep; uagt.uagt_snslen = ccb.cam_sense_len = ptp->sense ? ptp->sense_len : sizeof sensep; uagt.uagt_buffer = ccb.cam_data_ptr = ptp->dxferp; uagt.uagt_buflen = ccb.cam_dxfer_len = ptp->dxfer_len; ccb.cam_timeout = time_secs; ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb; ccb.cam_ch.cam_ccb_len = sizeof(ccb); ccb.cam_ch.cam_func_code = XPT_SCSI_IO; ccb.cam_ch.cam_flags = ptp->dxfer_dir; ccb.cam_cdb_len = ptp->cdb_len; memcpy(ccb.cam_cdb_io.cam_cdb_bytes, ptp->cdb, ptp->cdb_len); ccb.cam_ch.cam_path_id = fdchan->bus; ccb.cam_ch.cam_target_id = fdchan->tgt; ccb.cam_ch.cam_target_lun = fdchan->lun; if (ioctl(camfd, UAGT_CAM_IO, &uagt) < 0) { if (verbose) fprintf(sg_warnings_strm, "CAN I/O Error\n"); ptp->os_err = EIO; return -ptp->os_err; } if (((ccb.cam_ch.cam_status & CAM_STATUS_MASK) == CAM_REQ_CMP) || ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) == CAM_REQ_CMP_ERR)) { ptp->scsi_status = ccb.cam_scsi_status; ptp->resid = ccb.cam_resid; if (ptp->sense) ptp->sense_resid = ccb.cam_sense_resid; } else { ptp->transport_err = 1; } /* If the SIM queue is frozen, release SIM queue. */ if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN) release_sim(vp, device_fd, verbose); return 0; } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; if (ptp->os_err) return SCSI_PT_RESULT_OS_ERR; else if (ptp->transport_err) return SCSI_PT_RESULT_TRANSPORT_ERR; else if ((SAM_STAT_CHECK_CONDITION == ptp->scsi_status) || (SAM_STAT_COMMAND_TERMINATED == ptp->scsi_status)) return SCSI_PT_RESULT_SENSE; else if (ptp->scsi_status) return SCSI_PT_RESULT_STATUS; else return SCSI_PT_RESULT_GOOD; } int get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; return ptp->resid; } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; return ptp->scsi_status; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; int len; len = ptp->sense_len - ptp->sense_resid; return (len > 0) ? len : 0; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp) { // const struct sg_pt_osf1_scsi * ptp = &vp->impl; return -1; } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; return ptp->transport_err; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; return ptp->os_err; } char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; if (0 == ptp->transport_err) { strncpy(b, "no transport error available", max_b_len); b[max_b_len - 1] = '\0'; return b; } strncpy(b, "no transport error available", max_b_len); b[max_b_len - 1] = '\0'; return b; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_osf1_scsi * ptp = &vp->impl; const char * cp; cp = safe_strerror(ptp->os_err); strncpy(b, cp, max_b_len); if ((int)strlen(cp) >= max_b_len) b[max_b_len - 1] = '\0'; return b; } ddpt-0.94/lib/BSD_LICENSE0000644000175000017500000000275211346470114013647 0ustar douggdougg/* * Copyright (c) 1999-2010 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ ddpt-0.94/lib/sg_cmds_basic2.c0000644000175000017500000011061012176051475015160 0ustar douggdougg/* * Copyright (c) 1999-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* * CONTENTS * Some SCSI commands are executed in many contexts and hence began * to appear in several sg3_utils utilities. This files centralizes * some of the low level command execution code. In most cases the * interpretation of the command response is left to the each * utility. */ #include #include #include #include #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_pt.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define EBUFF_SZ 256 #define DEF_PT_TIMEOUT 60 /* 60 seconds */ #define START_PT_TIMEOUT 120 /* 120 seconds == 2 minutes */ #define LONG_PT_TIMEOUT 7200 /* 7,200 seconds == 120 minutes */ #define SYNCHRONIZE_CACHE_CMD 0x35 #define SYNCHRONIZE_CACHE_CMDLEN 10 #define SERVICE_ACTION_IN_16_CMD 0x9e #define SERVICE_ACTION_IN_16_CMDLEN 16 #define READ_CAPACITY_16_SA 0x10 #define READ_CAPACITY_10_CMD 0x25 #define READ_CAPACITY_10_CMDLEN 10 #define MODE_SENSE6_CMD 0x1a #define MODE_SENSE6_CMDLEN 6 #define MODE_SENSE10_CMD 0x5a #define MODE_SENSE10_CMDLEN 10 #define MODE_SELECT6_CMD 0x15 #define MODE_SELECT6_CMDLEN 6 #define MODE_SELECT10_CMD 0x55 #define MODE_SELECT10_CMDLEN 10 #define LOG_SENSE_CMD 0x4d #define LOG_SENSE_CMDLEN 10 #define LOG_SELECT_CMD 0x4c #define LOG_SELECT_CMDLEN 10 #define START_STOP_CMD 0x1b #define START_STOP_CMDLEN 6 #define PREVENT_ALLOW_CMD 0x1e #define PREVENT_ALLOW_CMDLEN 6 #define MODE6_RESP_HDR_LEN 4 #define MODE10_RESP_HDR_LEN 8 #define MODE_RESP_ARB_LEN 1024 #define INQUIRY_RESP_INITIAL_LEN 36 /* Invokes a SCSI SYNCHRONIZE CACHE (10) command. Return of 0 -> success, * SG_LIB_CAT_UNIT_ATTENTION -> repeat, * SG_LIB_CAT_INVALID_OP -> cdb not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group, unsigned int lba, unsigned int count, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char scCmdBlk[SYNCHRONIZE_CACHE_CMDLEN] = {SYNCHRONIZE_CACHE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (sync_nv) scCmdBlk[1] |= 4; if (immed) scCmdBlk[1] |= 2; scCmdBlk[2] = (lba >> 24) & 0xff; scCmdBlk[3] = (lba >> 16) & 0xff; scCmdBlk[4] = (lba >> 8) & 0xff; scCmdBlk[5] = lba & 0xff; scCmdBlk[6] = group & 0x1f; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (count > 0xffff) { fprintf(sg_warnings_strm, "count too big\n"); return -1; } scCmdBlk[7] = (count >> 8) & 0xff; scCmdBlk[8] = count & 0xff; if (verbose) { fprintf(sg_warnings_strm, " synchronize cache(10) cdb: "); for (k = 0; k < SYNCHRONIZE_CACHE_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", scCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "synchronize cache(10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, scCmdBlk, sizeof(scCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "synchronize cache(10)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ CAPACITY (16) command. Returns 0 -> success, * SG_LIB_CAT_UNIT_ATTENTION -> media changed??, SG_LIB_CAT_INVALID_OP * -> cdb not supported, SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> device not ready, * -1 -> other failure */ int sg_ll_readcap_16(int sg_fd, int pmi, uint64_t llba, void * resp, int mx_resp_len, int noisy, int verbose) { int k, ret, res, sense_cat; unsigned char rcCmdBlk[SERVICE_ACTION_IN_16_CMDLEN] = {SERVICE_ACTION_IN_16_CMD, READ_CAPACITY_16_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (pmi) { /* lbs only valid when pmi set */ rcCmdBlk[14] |= 1; rcCmdBlk[2] = (llba >> 56) & 0xff; rcCmdBlk[3] = (llba >> 48) & 0xff; rcCmdBlk[4] = (llba >> 40) & 0xff; rcCmdBlk[5] = (llba >> 32) & 0xff; rcCmdBlk[6] = (llba >> 24) & 0xff; rcCmdBlk[7] = (llba >> 16) & 0xff; rcCmdBlk[8] = (llba >> 8) & 0xff; rcCmdBlk[9] = llba & 0xff; } /* Allocation length, no guidance in SBC-2 rev 15b */ rcCmdBlk[10] = (mx_resp_len >> 24) & 0xff; rcCmdBlk[11] = (mx_resp_len >> 16) & 0xff; rcCmdBlk[12] = (mx_resp_len >> 8) & 0xff; rcCmdBlk[13] = mx_resp_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " read capacity (16) cdb: "); for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rcCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read capacity (16): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rcCmdBlk, sizeof(rcCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read capacity (16)", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ CAPACITY (10) command. Returns 0 -> success, * SG_LIB_CAT_UNIT_ATTENTION -> media changed??, SG_LIB_CAT_INVALID_OP * -> cdb not supported, SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> device not ready, * -1 -> other failure */ int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba, void * resp, int mx_resp_len, int noisy, int verbose) { int k, ret, res, sense_cat; unsigned char rcCmdBlk[READ_CAPACITY_10_CMDLEN] = {READ_CAPACITY_10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (pmi) { /* lbs only valid when pmi set */ rcCmdBlk[8] |= 1; rcCmdBlk[2] = (lba >> 24) & 0xff; rcCmdBlk[3] = (lba >> 16) & 0xff; rcCmdBlk[4] = (lba >> 8) & 0xff; rcCmdBlk[5] = lba & 0xff; } if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " read capacity (10) cdb: "); for (k = 0; k < READ_CAPACITY_10_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rcCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read capacity (10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rcCmdBlk, sizeof(rcCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read capacity (10)", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI MODE SENSE (6) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_UNIT_ATTENTION, * -1 -> other failure */ int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code, void * resp, int mx_resp_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char modesCmdBlk[MODE_SENSE6_CMDLEN] = {MODE_SENSE6_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; modesCmdBlk[1] = (unsigned char)(dbd ? 0x8 : 0); modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); modesCmdBlk[3] = (unsigned char)(sub_pg_code & 0xff); modesCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (mx_resp_len > 0xff) { fprintf(sg_warnings_strm, "mx_resp_len too big\n"); return -1; } if (verbose) { fprintf(sg_warnings_strm, " mode sense (6) cdb: "); for (k = 0; k < MODE_SENSE6_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", modesCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "mode sense (6): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, modesCmdBlk, sizeof(modesCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "mode sense (6)", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " mode sense (6): response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_UNIT_ATTENTION, * -1 -> other failure */ int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code, int sub_pg_code, void * resp, int mx_resp_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char modesCmdBlk[MODE_SENSE10_CMDLEN] = {MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; modesCmdBlk[1] = (unsigned char)((dbd ? 0x8 : 0) | (llbaa ? 0x10 : 0)); modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); modesCmdBlk[3] = (unsigned char)(sub_pg_code & 0xff); modesCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff); modesCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (mx_resp_len > 0xffff) { fprintf(sg_warnings_strm, "mx_resp_len too big\n"); return -1; } if (verbose) { fprintf(sg_warnings_strm, " mode sense (10) cdb: "); for (k = 0; k < MODE_SENSE10_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", modesCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "mode sense (10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, modesCmdBlk, sizeof(modesCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "mode sense (10)", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " mode sense (10): response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_UNIT_ATTENTION, * -1 -> other failure */ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp, int param_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char modesCmdBlk[MODE_SELECT6_CMDLEN] = {MODE_SELECT6_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; modesCmdBlk[1] = (unsigned char)(((pf << 4) & 0x10) | (sp & 0x1)); modesCmdBlk[4] = (unsigned char)(param_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (param_len > 0xff) { fprintf(sg_warnings_strm, "mode select (6): param_len too big\n"); return -1; } if (verbose) { fprintf(sg_warnings_strm, " mode select (6) cdb: "); for (k = 0; k < MODE_SELECT6_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", modesCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } if (verbose > 1) { fprintf(sg_warnings_strm, " mode select (6) parameter list\n"); dStrHexErr((const char *)paramp, param_len, -1); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "mode select (6): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, modesCmdBlk, sizeof(modesCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "mode select (6)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_UNIT_ATTENTION, * -1 -> other failure */ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp, int param_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char modesCmdBlk[MODE_SELECT10_CMDLEN] = {MODE_SELECT10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; modesCmdBlk[1] = (unsigned char)(((pf << 4) & 0x10) | (sp & 0x1)); modesCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff); modesCmdBlk[8] = (unsigned char)(param_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (param_len > 0xffff) { fprintf(sg_warnings_strm, "mode select (10): param_len too big\n"); return -1; } if (verbose) { fprintf(sg_warnings_strm, " mode select (10) cdb: "); for (k = 0; k < MODE_SELECT10_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", modesCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } if (verbose > 1) { fprintf(sg_warnings_strm, " mode select (10) parameter list\n"); dStrHexErr((const char *)paramp, param_len, -1); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "mode select (10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, modesCmdBlk, sizeof(modesCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "mode select (10)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* MODE SENSE commands yield a response that has block descriptors followed * by mode pages. In most cases users are interested in the first mode page. * This function returns the (byte) offset of the start of the first mode * page. Set mode_sense_6 to 1 for MODE SENSE (6) and 0 for MODE SENSE (10). * Returns >= 0 is successful or -1 if failure. If there is a failure * a message is written to err_buff. */ int sg_mode_page_offset(const unsigned char * resp, int resp_len, int mode_sense_6, char * err_buff, int err_buff_len) { int bd_len; int calc_len; int offset; if ((NULL == resp) || (resp_len < 4) || ((! mode_sense_6) && (resp_len < 8))) { if (err_buff_len > 0) snprintf(err_buff, err_buff_len, "given response length too " "short: %d\n", resp_len); return -1; } if (mode_sense_6) { calc_len = resp[0] + 1; bd_len = resp[3]; offset = bd_len + MODE6_RESP_HDR_LEN; } else { calc_len = (resp[0] << 8) + resp[1] + 2; bd_len = (resp[6] << 8) + resp[7]; /* LongLBA doesn't change this calculation */ offset = bd_len + MODE10_RESP_HDR_LEN; } if ((offset + 2) > resp_len) { if (err_buff_len > 0) snprintf(err_buff, err_buff_len, "given response length " "too small, offset=%d given_len=%d bd_len=%d\n", offset, resp_len, bd_len); offset = -1; } else if ((offset + 2) > calc_len) { if (err_buff_len > 0) snprintf(err_buff, err_buff_len, "calculated response " "length too small, offset=%d calc_len=%d bd_len=%d\n", offset, calc_len, bd_len); offset = -1; } return offset; } /* Fetches current, changeable, default and/or saveable modes pages as * indicated by pcontrol_arr for given pg_code and sub_pg_code. If * mode6==0 then use MODE SENSE (10) else use MODE SENSE (6). If * flexible set and mode data length seems wrong then try and * fix (compensating hack for bad device or driver). pcontrol_arr * should have 4 elements for output of current, changeable, default * and saved values respectively. Each element should be NULL or * at least mx_mpage_len bytes long. * Return of 0 -> overall success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_MALFORMED -> bad response, -1 -> other failure. * If success_mask pointer is not NULL then first zeros it. Then set bits * 0, 1, 2 and/or 3 if the current, changeable, default and saved values * respectively have been fetched. If error on current page * then stops and returns that error; otherwise continues if an error is * detected but returns the first error encountered. */ int sg_get_mode_page_controls(int sg_fd, int mode6, int pg_code, int sub_pg_code, int dbd, int flexible, int mx_mpage_len, int * success_mask, void * pcontrol_arr[], int * reported_len, int verbose) { int k, n, res, offset, calc_len, xfer_len, resp_mode6; unsigned char buff[MODE_RESP_ARB_LEN]; char ebuff[EBUFF_SZ]; int first_err = 0; if (success_mask) *success_mask = 0; if (reported_len) *reported_len = 0; if (mx_mpage_len < 4) return 0; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; memset(ebuff, 0, sizeof(ebuff)); /* first try to find length of current page response */ memset(buff, 0, MODE10_RESP_HDR_LEN); if (mode6) /* want first 8 bytes just in case */ res = sg_ll_mode_sense6(sg_fd, dbd, 0 /* pc */, pg_code, sub_pg_code, buff, MODE10_RESP_HDR_LEN, 1, verbose); else res = sg_ll_mode_sense10(sg_fd, 0 /* llbaa */, dbd, 0 /* pc */, pg_code, sub_pg_code, buff, MODE10_RESP_HDR_LEN, 1, verbose); if (0 != res) return res; n = buff[0]; if (reported_len) *reported_len = mode6 ? (n + 1) : ((n << 8) + buff[1] + 2); resp_mode6 = mode6; if (flexible) { if (mode6 && (n < 3)) { resp_mode6 = 0; if (verbose) fprintf(sg_warnings_strm, ">>> msense(6) but resp[0]=%d so " "try msense(10) response processing\n", n); } if ((0 == mode6) && (n > 5)) { if ((n > 11) && (0 == (n % 2)) && (0 == buff[4]) && (0 == buff[5]) && (0 == buff[6])) { buff[1] = n; buff[0] = 0; if (verbose) fprintf(sg_warnings_strm, ">>> msense(10) but resp[0]=%d " "and not msense(6) response so fix length\n", n); } else resp_mode6 = 1; } } if (verbose && (resp_mode6 != mode6)) fprintf(sg_warnings_strm, ">>> msense(%d) but resp[0]=%d " "so switch response processing\n", (mode6 ? 6 : 10), buff[0]); calc_len = resp_mode6 ? (buff[0] + 1) : ((buff[0] << 8) + buff[1] + 2); if (calc_len > MODE_RESP_ARB_LEN) calc_len = MODE_RESP_ARB_LEN; offset = sg_mode_page_offset(buff, calc_len, resp_mode6, ebuff, EBUFF_SZ); if (offset < 0) { if (('\0' != ebuff[0]) && (verbose > 0)) fprintf(sg_warnings_strm, "sg_get_mode_page_controls: %s\n", ebuff); return SG_LIB_CAT_MALFORMED; } xfer_len = calc_len - offset; if (xfer_len > mx_mpage_len) xfer_len = mx_mpage_len; for (k = 0; k < 4; ++k) { if (NULL == pcontrol_arr[k]) continue; memset(pcontrol_arr[k], 0, mx_mpage_len); if (mode6) res = sg_ll_mode_sense6(sg_fd, dbd, k /* pc */, pg_code, sub_pg_code, buff, calc_len, 1, verbose); else res = sg_ll_mode_sense10(sg_fd, 0 /* llbaa */, dbd, k /* pc */, pg_code, sub_pg_code, buff, calc_len, 1, verbose); if (0 != res) { if (0 == first_err) first_err = res; if (0 == k) break; /* if problem on current page, it won't improve */ else continue; } if (xfer_len > 0) memcpy(pcontrol_arr[k], buff + offset, xfer_len); if (success_mask) *success_mask |= (1 << k); } return first_err; } /* Invokes a SCSI LOG SENSE command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Log Sense not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code, int subpg_code, int paramp, unsigned char * resp, int mx_resp_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char logsCmdBlk[LOG_SENSE_CMDLEN] = {LOG_SENSE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (mx_resp_len > 0xffff) { fprintf(sg_warnings_strm, "mx_resp_len too big\n"); return -1; } logsCmdBlk[1] = (unsigned char)((ppc ? 2 : 0) | (sp ? 1 : 0)); logsCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); logsCmdBlk[3] = (unsigned char)(subpg_code & 0xff); logsCmdBlk[5] = (unsigned char)((paramp >> 8) & 0xff); logsCmdBlk[6] = (unsigned char)(paramp & 0xff); logsCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff); logsCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff); if (verbose) { fprintf(sg_warnings_strm, " log sense cdb: "); for (k = 0; k < LOG_SENSE_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", logsCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "log sense: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, logsCmdBlk, sizeof(logsCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "log sense", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((mx_resp_len > 3) && (ret < 4)) { /* resid indicates LOG SENSE response length bad, so zero it */ resp[2] = 0; resp[3] = 0; } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI LOG SELECT command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Log Select not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_log_select(int sg_fd, int pcr, int sp, int pc, int pg_code, int subpg_code, unsigned char * paramp, int param_len, int noisy, int verbose) { int res, ret, k, sense_cat; unsigned char logsCmdBlk[LOG_SELECT_CMDLEN] = {LOG_SELECT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (param_len > 0xffff) { fprintf(sg_warnings_strm, "log select: param_len too big\n"); return -1; } logsCmdBlk[1] = (unsigned char)((pcr ? 2 : 0) | (sp ? 1 : 0)); logsCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); logsCmdBlk[3] = (unsigned char)(subpg_code & 0xff); logsCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff); logsCmdBlk[8] = (unsigned char)(param_len & 0xff); if (verbose) { fprintf(sg_warnings_strm, " log select cdb: "); for (k = 0; k < LOG_SELECT_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", logsCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } if ((verbose > 1) && (param_len > 0)) { fprintf(sg_warnings_strm, " log select parameter list\n"); dStrHexErr((const char *)paramp, param_len, -1); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "log select: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, logsCmdBlk, sizeof(logsCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "log select", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI START STOP UNIT command (SBC + MMC). * Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Start stop unit not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure * SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and * format_layer_number(mmc) fields. They also overlap on the noflush(sbc) * and fl(mmc) one bit field. This is the cause of the awkardly named * pc_mod__fl_num and noflush__fl arguments to this function. * */ int sg_ll_start_stop_unit(int sg_fd, int immed, int pc_mod__fl_num, int power_cond, int noflush__fl, int loej, int start, int noisy, int verbose) { unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; int k, res, ret, sense_cat; struct sg_pt_base * ptvp; ssuBlk[1] = immed & 1; ssuBlk[3] = pc_mod__fl_num & 0xf; /* bits 2 and 3 are reserved in MMC */ ssuBlk[4] = ((power_cond & 0xf) << 4) | (noflush__fl ? 0x4 : 0) | (loej ? 0x2 : 0) | (start ? 0x1 : 0); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Start stop unit command:"); for (k = 0; k < (int)sizeof(ssuBlk); ++k) fprintf (sg_warnings_strm, " %02x", ssuBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "start stop unit: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, ssuBlk, sizeof(ssuBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); res = do_scsi_pt(ptvp, sg_fd, START_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "start stop unit", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command * [was in SPC-3 but displaced from SPC-4 into SBC-3, MMC-5, SSC-3] * prevent==0 allows removal, prevent==1 prevents removal ... * Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> command not supported * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char pCmdBlk[PREVENT_ALLOW_CMDLEN] = {PREVENT_ALLOW_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if ((prevent < 0) || (prevent > 3)) { fprintf(sg_warnings_strm, "prevent argument should be 0, 1, 2 or 3\n"); return -1; } pCmdBlk[4] |= (prevent & 0x3); if (verbose) { fprintf(sg_warnings_strm, " Prevent allow medium removal cdb: "); for (k = 0; k < PREVENT_ALLOW_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", pCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "prevent allow medium removal: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, pCmdBlk, sizeof(pCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "prevent allow medium removal", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } ddpt-0.94/lib/sg_pt_win32.c0000644000175000017500000005747312207377272014476 0ustar douggdougg/* * Copyright (c) 2006-2012 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* sg_pt_win32 version 1.14 20121026 */ #include #include #include #include #include #include #include #include "sg_pt.h" #include "sg_lib.h" #include "sg_pt_win32.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef O_EXCL // #define O_EXCL 0x80 // cygwin ?? // #define O_EXCL 0x80 // Linux #define O_EXCL 0x400 // mingw #warning "O_EXCL not defined" #endif /* Use the Microsoft SCSI Pass Through (SPT) interface. It has two * variants: "SPT" where data is double buffered; and "SPTD" where data * pointers to the user space are passed to the OS. Only Windows * 2000 and later (i.e. not 95,98 or ME). * There is no ASPI interface which relies on a dll from adaptec. * This code uses cygwin facilities and is built in a cygwin * shell. It can be run in a normal DOS shell if the cygwin1.dll * file is put in an appropriate place. * This code can build in a MinGW environment. * * N.B. MSDN says that the "SPT" interface (i.e. double buffered) * should be used for small amounts of data (it says "< 16 KB"). * The direct variant (i.e. IOCTL_SCSI_PASS_THROUGH_DIRECT) should * be used for larger amounts of data but the buffer needs to be * "cache aligned". Is that 16 byte alignment or greater? * * This code will default to indirect (i.e. double buffered) access * unless the WIN32_SPT_DIRECT preprocessor constant is defined in * config.h . In version 1.12 runtime selection of direct and indirect * access was added; the default is still determined by the * WIN32_SPT_DIRECT preprocessor constant. */ #define DEF_TIMEOUT 60 /* 60 seconds */ #define MAX_OPEN_SIMULT 8 #define WIN32_FDOFFSET 32 struct sg_pt_handle { int in_use; HANDLE fh; char adapter[32]; int bus; int target; int lun; }; struct sg_pt_handle handle_arr[MAX_OPEN_SIMULT]; struct sg_pt_win32_scsi { unsigned char * dxferp; int dxfer_len; unsigned char * sensep; int sense_len; int scsi_status; int resid; int sense_resid; int in_err; int os_err; /* pseudo unix error */ int transport_err; /* windows error number */ union { SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb_d; /* Last entry in structure so data buffer can be extended */ SCSI_PASS_THROUGH_WITH_BUFFERS swb_i; }; }; /* embed pointer so can change on fly if (non-direct) data buffer * is not big enough */ struct sg_pt_base { struct sg_pt_win32_scsi * implp; }; #ifdef WIN32_SPT_DIRECT static int spt_direct = 1; #else static int spt_direct = 0; #endif /* Request SPT direct interface when state_direct is 1, state_direct set * to 0 for the SPT indirect interface. */ void scsi_pt_win32_direct(int state_direct) { spt_direct = state_direct; } /* Returns current SPT interface state, 1 for direct, 0 for indirect */ int scsi_pt_win32_spt_state(void) { return spt_direct; } /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose) { int oflags = 0 /* O_NONBLOCK*/ ; oflags |= (read_only ? 0 : 0); /* was ... ? O_RDONLY : O_RDWR) */ return scsi_pt_open_flags(device_name, oflags, verbose); } /* * Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. The 'flags' argument is ignored in Windows. * Returns >= 0 if successful, otherwise returns negated errno. * Optionally accept leading "\\.\". If given something of the form * "SCSI:,," where the values in angle brackets * are integers, then will attempt to open "\\.\SCSI:" and save the * other three values for the DeviceIoControl call. The trailing "." * is optionally and if not given 0 is assumed. Since "PhysicalDrive" * is a lot of keystrokes, "PD" is accepted and converted to the longer * form. */ int scsi_pt_open_flags(const char * device_name, int flags, int verbose) { int len, k, adapter_num, bus, target, lun, off, got_scsi_name; int index, num, got_pd_name, pd_num, share_mode; struct sg_pt_handle * shp; char buff[8]; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; share_mode = (O_EXCL & flags) ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); /* lock */ for (k = 0; k < MAX_OPEN_SIMULT; k++) if (0 == handle_arr[k].in_use) break; if (k == MAX_OPEN_SIMULT) { if (verbose) fprintf(sg_warnings_strm, "too many open handles " "(%d)\n", MAX_OPEN_SIMULT); return -EMFILE; } else handle_arr[k].in_use = 1; /* unlock */ index = k; shp = handle_arr + index; adapter_num = 0; bus = 0; /* also known as 'PathId' in MS docs */ target = 0; lun = 0; got_pd_name = 0; got_scsi_name = 0; len = strlen(device_name); if ((len > 4) && (0 == strncmp("\\\\.\\", device_name, 4))) off = 4; else off = 0; if (len > (off + 2)) { buff[0] = toupper((int)device_name[off + 0]); buff[1] = toupper((int)device_name[off + 1]); if (0 == strncmp("PD", buff, 2)) { num = sscanf(device_name + off + 2, "%d", &pd_num); if (1 == num) got_pd_name = 1; } if (0 == got_pd_name) { buff[2] = toupper((int)device_name[off + 2]); buff[3] = toupper((int)device_name[off + 3]); if (0 == strncmp("SCSI", buff, 4)) { num = sscanf(device_name + off + 4, "%d:%d,%d,%d", &adapter_num, &bus, &target, &lun); if (num < 3) { if (verbose) fprintf(sg_warnings_strm, "expected format like: " "'SCSI:.[.]'\n"); shp->in_use = 0; return -EINVAL; } got_scsi_name = 1; } } } shp->bus = bus; shp->target = target; shp->lun = lun; memset(shp->adapter, 0, sizeof(shp->adapter)); strncpy(shp->adapter, "\\\\.\\", 4); if (got_pd_name) snprintf(shp->adapter + 4, sizeof(shp->adapter) - 5, "PhysicalDrive%d", pd_num); else if (got_scsi_name) snprintf(shp->adapter + 4, sizeof(shp->adapter) - 5, "SCSI%d:", adapter_num); else snprintf(shp->adapter + 4, sizeof(shp->adapter) - 5, "%s", device_name + off); shp->fh = CreateFile(shp->adapter, GENERIC_READ | GENERIC_WRITE, share_mode, NULL, OPEN_EXISTING, 0, NULL); if (shp->fh == INVALID_HANDLE_VALUE) { if (verbose) fprintf(sg_warnings_strm, "Windows CreateFile error=%ld\n", GetLastError()); shp->in_use = 0; return -ENODEV; } return index + WIN32_FDOFFSET; } /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd) { struct sg_pt_handle * shp; int index; index = device_fd - WIN32_FDOFFSET; if ((index < 0) || (index >= WIN32_FDOFFSET)) return -ENODEV; shp = handle_arr + index; CloseHandle(shp->fh); shp->bus = 0; shp->target = 0; shp->lun = 0; memset(shp->adapter, 0, sizeof(shp->adapter)); shp->in_use = 0; return 0; } struct sg_pt_base * construct_scsi_pt_obj() { struct sg_pt_win32_scsi * psp; struct sg_pt_base * vp = NULL; psp = (struct sg_pt_win32_scsi *)calloc(sizeof(struct sg_pt_win32_scsi), 1); if (psp) { if (spt_direct) { psp->swb_d.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; psp->swb_d.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN; psp->swb_d.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf); psp->swb_d.spt.TimeOutValue = DEF_TIMEOUT; } else { psp->swb_i.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; psp->swb_i.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN; psp->swb_i.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf); psp->swb_i.spt.TimeOutValue = DEF_TIMEOUT; } vp = malloc(sizeof(struct sg_pt_win32_scsi *)); // yes a pointer if (vp) vp->implp = psp; else free(psp); } return vp; } void destruct_scsi_pt_obj(struct sg_pt_base * vp) { if (vp) { struct sg_pt_win32_scsi * psp = vp->implp; if (psp) { free(psp); } free(vp); } } void clear_scsi_pt_obj(struct sg_pt_base * vp) { struct sg_pt_win32_scsi * psp = vp->implp; if (psp) { memset(psp, 0, sizeof(struct sg_pt_win32_scsi)); if (spt_direct) { psp->swb_d.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; psp->swb_d.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN; psp->swb_d.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf); psp->swb_d.spt.TimeOutValue = DEF_TIMEOUT; } else { psp->swb_i.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; psp->swb_i.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN; psp->swb_i.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf); psp->swb_i.spt.TimeOutValue = DEF_TIMEOUT; } } } void set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, int cdb_len) { struct sg_pt_win32_scsi * psp = vp->implp; if (spt_direct) { if (psp->swb_d.spt.CdbLength > 0) ++psp->in_err; if (cdb_len > (int)sizeof(psp->swb_d.spt.Cdb)) { ++psp->in_err; return; } memcpy(psp->swb_d.spt.Cdb, cdb, cdb_len); psp->swb_d.spt.CdbLength = cdb_len; } else { if (psp->swb_i.spt.CdbLength > 0) ++psp->in_err; if (cdb_len > (int)sizeof(psp->swb_i.spt.Cdb)) { ++psp->in_err; return; } memcpy(psp->swb_i.spt.Cdb, cdb, cdb_len); psp->swb_i.spt.CdbLength = cdb_len; } } void set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, int sense_len) { struct sg_pt_win32_scsi * psp = vp->implp; if (psp->sensep) ++psp->in_err; memset(sense, 0, sense_len); psp->sensep = sense; psp->sense_len = sense_len; } /* from device */ void set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, int dxfer_len) { struct sg_pt_win32_scsi * psp = vp->implp; if (psp->dxferp) ++psp->in_err; if (dxfer_len > 0) { psp->dxferp = dxferp; psp->dxfer_len = dxfer_len; if (spt_direct) psp->swb_d.spt.DataIn = SCSI_IOCTL_DATA_IN; else psp->swb_i.spt.DataIn = SCSI_IOCTL_DATA_IN; } } /* to device */ void set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, int dxfer_len) { struct sg_pt_win32_scsi * psp = vp->implp; if (psp->dxferp) ++psp->in_err; if (dxfer_len > 0) { psp->dxferp = (unsigned char *)dxferp; psp->dxfer_len = dxfer_len; if (spt_direct) psp->swb_d.spt.DataIn = SCSI_IOCTL_DATA_OUT; else psp->swb_i.spt.DataIn = SCSI_IOCTL_DATA_OUT; } } void set_scsi_pt_packet_id(struct sg_pt_base * vp __attribute__ ((unused)), int pack_id __attribute__ ((unused))) { } void set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag __attribute__ ((unused))) { struct sg_pt_win32_scsi * psp = vp->implp; ++psp->in_err; } void set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code __attribute__ ((unused))) { struct sg_pt_win32_scsi * psp = vp->implp; ++psp->in_err; } void set_scsi_pt_task_attr(struct sg_pt_base * vp, int attrib __attribute__ ((unused)), int priority __attribute__ ((unused))) { struct sg_pt_win32_scsi * psp = vp->implp; ++psp->in_err; } void set_scsi_pt_flags(struct sg_pt_base * objp, int flags) { /* do nothing, suppress warnings */ objp = objp; flags = flags; } /* Executes SCSI command (or at least forwards it to lower layers) * using direct interface. Clears os_err field prior to active call (whose * result may set it again). */ int do_scsi_pt_direct(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { int index = device_fd - WIN32_FDOFFSET; struct sg_pt_win32_scsi * psp = vp->implp; struct sg_pt_handle * shp; BOOL status; ULONG returned; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; psp->os_err = 0; if (psp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused set_scsi_pt...\n"); return SCSI_PT_DO_BAD_PARAMS; } if (0 == psp->swb_d.spt.CdbLength) { if (verbose) fprintf(sg_warnings_strm, "No command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } index = device_fd - WIN32_FDOFFSET; if ((index < 0) || (index >= WIN32_FDOFFSET)) { if (verbose) fprintf(sg_warnings_strm, "Bad file descriptor\n"); psp->os_err = ENODEV; return -psp->os_err; } shp = handle_arr + index; if (0 == shp->in_use) { if (verbose) fprintf(sg_warnings_strm, "File descriptor closed??\n"); psp->os_err = ENODEV; return -psp->os_err; } psp->swb_d.spt.Length = sizeof (SCSI_PASS_THROUGH_DIRECT); psp->swb_d.spt.PathId = shp->bus; psp->swb_d.spt.TargetId = shp->target; psp->swb_d.spt.Lun = shp->lun; psp->swb_d.spt.TimeOutValue = time_secs; psp->swb_d.spt.DataTransferLength = psp->dxfer_len; if (verbose > 4) { fprintf(stderr, " spt_direct, adapter: %s Length=%d ScsiStatus=%d " "PathId=%d TargetId=%d Lun=%d\n", shp->adapter, (int)psp->swb_d.spt.Length, (int)psp->swb_d.spt.ScsiStatus, (int)psp->swb_d.spt.PathId, (int)psp->swb_d.spt.TargetId, (int)psp->swb_d.spt.Lun); fprintf(stderr, " CdbLength=%d SenseInfoLength=%d DataIn=%d " "DataTransferLength=%lu\n", (int)psp->swb_d.spt.CdbLength, (int)psp->swb_d.spt.SenseInfoLength, (int)psp->swb_d.spt.DataIn, psp->swb_d.spt.DataTransferLength); fprintf(stderr, " TimeOutValue=%lu SenseInfoOffset=%lu\n", psp->swb_d.spt.TimeOutValue, psp->swb_d.spt.SenseInfoOffset); } psp->swb_d.spt.DataBuffer = psp->dxferp; status = DeviceIoControl(shp->fh, IOCTL_SCSI_PASS_THROUGH_DIRECT, &psp->swb_d, sizeof(psp->swb_d), &psp->swb_d, sizeof(psp->swb_d), &returned, NULL); if (! status) { psp->transport_err = GetLastError(); if (verbose) fprintf(sg_warnings_strm, "Windows DeviceIoControl error=%d\n", psp->transport_err); psp->os_err = EIO; return 0; /* let app find transport error */ } psp->scsi_status = psp->swb_d.spt.ScsiStatus; if ((SAM_STAT_CHECK_CONDITION == psp->scsi_status) || (SAM_STAT_COMMAND_TERMINATED == psp->scsi_status)) memcpy(psp->sensep, psp->swb_d.ucSenseBuf, psp->sense_len); else psp->sense_len = 0; psp->sense_resid = 0; if ((psp->dxfer_len > 0) && (psp->swb_d.spt.DataTransferLength > 0)) psp->resid = psp->dxfer_len - psp->swb_d.spt.DataTransferLength; else psp->resid = 0; return 0; } /* Executes SCSI command (or at least forwards it to lower layers) using * indirect interface. Clears os_err field prior to active call (whose * result may set it again). */ static int do_scsi_pt_indirect(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { int index = device_fd - WIN32_FDOFFSET; struct sg_pt_win32_scsi * psp = vp->implp; struct sg_pt_handle * shp; BOOL status; ULONG returned; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; psp->os_err = 0; if (psp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused " "set_scsi_pt...\n"); return SCSI_PT_DO_BAD_PARAMS; } if (0 == psp->swb_i.spt.CdbLength) { if (verbose) fprintf(sg_warnings_strm, "No command (cdb) given\n"); return SCSI_PT_DO_BAD_PARAMS; } index = device_fd - WIN32_FDOFFSET; if ((index < 0) || (index >= WIN32_FDOFFSET)) { if (verbose) fprintf(sg_warnings_strm, "Bad file descriptor\n"); psp->os_err = ENODEV; return -psp->os_err; } shp = handle_arr + index; if (0 == shp->in_use) { if (verbose) fprintf(sg_warnings_strm, "File descriptor closed??\n"); psp->os_err = ENODEV; return -psp->os_err; } if (psp->dxfer_len > (int)sizeof(psp->swb_i.ucDataBuf)) { int extra = psp->dxfer_len - (int)sizeof(psp->swb_i.ucDataBuf); struct sg_pt_win32_scsi * epsp; if (verbose > 4) fprintf(sg_warnings_strm, "spt_indirect: dxfer_len (%d) too " "large for initial data\n buffer (%d bytes), try " "enlarging\n", psp->dxfer_len, sizeof(psp->swb_i.ucDataBuf)); epsp = (struct sg_pt_win32_scsi *) calloc(sizeof(struct sg_pt_win32_scsi) + extra, 1); if (NULL == epsp) { fprintf(sg_warnings_strm, "do_scsi_pt: failed to enlarge data " "buffer to %d bytes\n", psp->dxfer_len); psp->os_err = ENOMEM; return -psp->os_err; } memcpy(epsp, psp, sizeof(struct sg_pt_win32_scsi)); free(psp); vp->implp = epsp; psp = epsp; } psp->swb_i.spt.Length = sizeof (SCSI_PASS_THROUGH); psp->swb_i.spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf); psp->swb_i.spt.PathId = shp->bus; psp->swb_i.spt.TargetId = shp->target; psp->swb_i.spt.Lun = shp->lun; psp->swb_i.spt.TimeOutValue = time_secs; psp->swb_i.spt.DataTransferLength = psp->dxfer_len; if (verbose > 4) { fprintf(stderr, " spt_indirect, adapter: %s Length=%d ScsiStatus=%d " "PathId=%d TargetId=%d Lun=%d\n", shp->adapter, (int)psp->swb_i.spt.Length, (int)psp->swb_i.spt.ScsiStatus, (int)psp->swb_i.spt.PathId, (int)psp->swb_i.spt.TargetId, (int)psp->swb_i.spt.Lun); fprintf(stderr, " CdbLength=%d SenseInfoLength=%d DataIn=%d " "DataTransferLength=%lu\n", (int)psp->swb_i.spt.CdbLength, (int)psp->swb_i.spt.SenseInfoLength, (int)psp->swb_i.spt.DataIn, psp->swb_i.spt.DataTransferLength); fprintf(stderr, " TimeOutValue=%lu DataBufferOffset=%lu " "SenseInfoOffset=%lu\n", psp->swb_i.spt.TimeOutValue, psp->swb_i.spt.DataBufferOffset, psp->swb_i.spt.SenseInfoOffset); } if ((psp->dxfer_len > 0) && (SCSI_IOCTL_DATA_OUT == psp->swb_i.spt.DataIn)) memcpy(psp->swb_i.ucDataBuf, psp->dxferp, psp->dxfer_len); status = DeviceIoControl(shp->fh, IOCTL_SCSI_PASS_THROUGH, &psp->swb_i, sizeof(psp->swb_i), &psp->swb_i, sizeof(psp->swb_i), &returned, NULL); if (! status) { psp->transport_err = GetLastError(); if (verbose) fprintf(sg_warnings_strm, "Windows DeviceIoControl error=%d\n", psp->transport_err); psp->os_err = EIO; return 0; /* let app find transport error */ } if ((psp->dxfer_len > 0) && (SCSI_IOCTL_DATA_IN == psp->swb_i.spt.DataIn)) memcpy(psp->dxferp, psp->swb_i.ucDataBuf, psp->dxfer_len); psp->scsi_status = psp->swb_i.spt.ScsiStatus; if ((SAM_STAT_CHECK_CONDITION == psp->scsi_status) || (SAM_STAT_COMMAND_TERMINATED == psp->scsi_status)) memcpy(psp->sensep, psp->swb_i.ucSenseBuf, psp->sense_len); else psp->sense_len = 0; psp->sense_resid = 0; if ((psp->dxfer_len > 0) && (psp->swb_i.spt.DataTransferLength > 0)) psp->resid = psp->dxfer_len - psp->swb_i.spt.DataTransferLength; else psp->resid = 0; return 0; } /* Executes SCSI command (or at least forwards it to lower layers). * Clears os_err field prior to active call (whose result may set it * again). */ int do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { if (spt_direct) return do_scsi_pt_direct(vp, device_fd, time_secs, verbose); else return do_scsi_pt_indirect(vp, device_fd, time_secs, verbose); } int get_scsi_pt_result_category(const struct sg_pt_base * vp) { const struct sg_pt_win32_scsi * psp = vp->implp; if (psp->transport_err) /* give transport error highest priority */ return SCSI_PT_RESULT_TRANSPORT_ERR; else if (psp->os_err) return SCSI_PT_RESULT_OS_ERR; else if ((SAM_STAT_CHECK_CONDITION == psp->scsi_status) || (SAM_STAT_COMMAND_TERMINATED == psp->scsi_status)) return SCSI_PT_RESULT_SENSE; else if (psp->scsi_status) return SCSI_PT_RESULT_STATUS; else return SCSI_PT_RESULT_GOOD; } int get_scsi_pt_resid(const struct sg_pt_base * vp) { const struct sg_pt_win32_scsi * psp = vp->implp; return psp->resid; } int get_scsi_pt_status_response(const struct sg_pt_base * vp) { const struct sg_pt_win32_scsi * psp = vp->implp; return psp->scsi_status; } int get_scsi_pt_sense_len(const struct sg_pt_base * vp) { const struct sg_pt_win32_scsi * psp = vp->implp; int len; len = psp->sense_len - psp->sense_resid; return (len > 0) ? len : 0; } int get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused))) { // const struct sg_pt_freebsd_scsi * psp = vp->implp; return -1; } int get_scsi_pt_transport_err(const struct sg_pt_base * vp) { const struct sg_pt_win32_scsi * psp = vp->implp; return psp->transport_err; } int get_scsi_pt_os_err(const struct sg_pt_base * vp) { const struct sg_pt_win32_scsi * psp = vp->implp; return psp->os_err; } char * get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { struct sg_pt_win32_scsi * psp = (struct sg_pt_win32_scsi *)vp->implp; LPVOID lpMsgBuf; int k, num, ch; if (max_b_len < 2) { if (1 == max_b_len) b[0] = '\0'; return b; } memset(b, 0, max_b_len); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, psp->transport_err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); num = lstrlen((LPCTSTR)lpMsgBuf); if (num < 1) return b; num = (num < max_b_len) ? num : (max_b_len - 1); for (k = 0; k < num; ++k) { ch = *((LPCTSTR)lpMsgBuf + k); if ((ch >= 0x0) && (ch < 0x7f)) b[k] = ch & 0x7f; else b[k] = '?'; } return b; } char * get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) { const struct sg_pt_win32_scsi * psp = vp->implp; const char * cp; cp = safe_strerror(psp->os_err); strncpy(b, cp, max_b_len); if ((int)strlen(cp) >= max_b_len) b[max_b_len - 1] = '\0'; return b; } ddpt-0.94/lib/sg_cmds_extra.c0000644000175000017500000026274012270322342015141 0ustar douggdougg/* * Copyright (c) 1999-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include "sg_lib.h" #include "sg_lib_data.h" #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" #include "sg_pt.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_PT_TIMEOUT 60 /* 60 seconds */ #define LONG_PT_TIMEOUT 7200 /* 7,200 seconds == 120 minutes */ #define SERVICE_ACTION_IN_16_CMD 0x9e #define SERVICE_ACTION_IN_16_CMDLEN 16 #define SERVICE_ACTION_OUT_16_CMD 0x9f #define SERVICE_ACTION_OUT_16_CMDLEN 16 #define MAINTENANCE_IN_CMD 0xa3 #define MAINTENANCE_IN_CMDLEN 12 #define MAINTENANCE_OUT_CMD 0xa4 #define MAINTENANCE_OUT_CMDLEN 12 #define ATA_PT_12_CMD 0xa1 #define ATA_PT_12_CMDLEN 12 #define ATA_PT_16_CMD 0x85 #define ATA_PT_16_CMDLEN 16 #define FORMAT_UNIT_CMD 0x4 #define FORMAT_UNIT_CMDLEN 6 #define PERSISTENT_RESERVE_IN_CMD 0x5e #define PERSISTENT_RESERVE_IN_CMDLEN 10 #define PERSISTENT_RESERVE_OUT_CMD 0x5f #define PERSISTENT_RESERVE_OUT_CMDLEN 10 #define READ_BLOCK_LIMITS_CMD 0x5 #define READ_BLOCK_LIMITS_CMDLEN 6 #define READ_BUFFER_CMD 0x3c #define READ_BUFFER_CMDLEN 10 #define READ_DEFECT10_CMD 0x37 #define READ_DEFECT10_CMDLEN 10 #define REASSIGN_BLKS_CMD 0x7 #define REASSIGN_BLKS_CMDLEN 6 #define RECEIVE_DIAGNOSTICS_CMD 0x1c #define RECEIVE_DIAGNOSTICS_CMDLEN 6 #define THIRD_PARTY_COPY_OUT_CMD 0x83 /* was EXTENDED_COPY_CMD */ #define THIRD_PARTY_COPY_OUT_CMDLEN 16 #define THIRD_PARTY_COPY_IN_CMD 0x84 /* was RECEIVE_COPY_RESULTS_CMD */ #define THIRD_PARTY_COPY_IN_CMDLEN 16 #define SEND_DIAGNOSTIC_CMD 0x1d #define SEND_DIAGNOSTIC_CMDLEN 6 #define SERVICE_ACTION_IN_12_CMD 0xab #define SERVICE_ACTION_IN_12_CMDLEN 12 #define READ_LONG10_CMD 0x3e #define READ_LONG10_CMDLEN 10 #define UNMAP_CMD 0x42 #define UNMAP_CMDLEN 10 #define VERIFY10_CMD 0x2f #define VERIFY10_CMDLEN 10 #define VERIFY16_CMD 0x8f #define VERIFY16_CMDLEN 16 #define WRITE_LONG10_CMD 0x3f #define WRITE_LONG10_CMDLEN 10 #define WRITE_BUFFER_CMD 0x3b #define WRITE_BUFFER_CMDLEN 10 #define GET_LBA_STATUS_SA 0x12 #define READ_LONG_16_SA 0x11 #define READ_MEDIA_SERIAL_NUM_SA 0x1 #define REPORT_IDENTIFYING_INFORMATION_SA 0x5 #define REPORT_TGT_PRT_GRP_SA 0xa #define SET_IDENTIFYING_INFORMATION_SA 0x6 #define SET_TGT_PRT_GRP_SA 0xa #define WRITE_LONG_16_SA 0x11 #define REPORT_REFERRALS_SA 0x13 #define EXTENDED_COPY_LID1_SA 0x0 /* Invokes a SCSI GET LBA STATUS command (SBC). Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> GET LBA STATUS not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp, int alloc_len, int noisy, int verbose) { int k, res, sense_cat, ret; unsigned char getLbaStatCmd[SERVICE_ACTION_IN_16_CMDLEN]; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; memset(getLbaStatCmd, 0, sizeof(getLbaStatCmd)); getLbaStatCmd[0] = SERVICE_ACTION_IN_16_CMD; getLbaStatCmd[1] = GET_LBA_STATUS_SA; getLbaStatCmd[2] = (start_llba >> 56) & 0xff; getLbaStatCmd[3] = (start_llba >> 48) & 0xff; getLbaStatCmd[4] = (start_llba >> 40) & 0xff; getLbaStatCmd[5] = (start_llba >> 32) & 0xff; getLbaStatCmd[6] = (start_llba >> 24) & 0xff; getLbaStatCmd[7] = (start_llba >> 16) & 0xff; getLbaStatCmd[8] = (start_llba >> 8) & 0xff; getLbaStatCmd[9] = start_llba & 0xff; getLbaStatCmd[10] = (alloc_len >> 24) & 0xff; getLbaStatCmd[11] = (alloc_len >> 16) & 0xff; getLbaStatCmd[12] = (alloc_len >> 8) & 0xff; getLbaStatCmd[13] = alloc_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Get LBA status cmd: "); for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", getLbaStatCmd[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "get LBA status: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, getLbaStatCmd, sizeof(getLbaStatCmd)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, alloc_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "get LBA status", res, alloc_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " get LBA status: response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose) { return sg_ll_report_tgt_prt_grp2(sg_fd, resp, mx_resp_len, 0, noisy, verbose); } /* Invokes a SCSI REPORT TARGET PORT GROUPS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Target Port Groups not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len, int extended, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char rtpgCmdBlk[MAINTENANCE_IN_CMDLEN] = {MAINTENANCE_IN_CMD, REPORT_TGT_PRT_GRP_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (extended) { rtpgCmdBlk[1] |= 0x20; } rtpgCmdBlk[6] = (mx_resp_len >> 24) & 0xff; rtpgCmdBlk[7] = (mx_resp_len >> 16) & 0xff; rtpgCmdBlk[8] = (mx_resp_len >> 8) & 0xff; rtpgCmdBlk[9] = mx_resp_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " report target port groups cdb: "); for (k = 0; k < MAINTENANCE_IN_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rtpgCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "report target port groups: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rtpgCmdBlk, sizeof(rtpgCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "report target port group", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " report target port group: " "response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI SET TARGET PORT GROUPS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Set Target Port Groups not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_set_tgt_prt_grp(int sg_fd, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char stpgCmdBlk[MAINTENANCE_OUT_CMDLEN] = {MAINTENANCE_OUT_CMD, SET_TGT_PRT_GRP_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; stpgCmdBlk[6] = (param_len >> 24) & 0xff; stpgCmdBlk[7] = (param_len >> 16) & 0xff; stpgCmdBlk[8] = (param_len >> 8) & 0xff; stpgCmdBlk[9] = param_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " set target port groups cdb: "); for (k = 0; k < MAINTENANCE_OUT_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", stpgCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " set target port groups " "parameter list:\n"); dStrHexErr((const char *)paramp, param_len, -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "set target port groups: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, stpgCmdBlk, sizeof(stpgCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "set target port group", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI REPORT REFERRALS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Referrals not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg, void * resp, int mx_resp_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char repRefCmdBlk[SERVICE_ACTION_IN_16_CMDLEN] = {SERVICE_ACTION_IN_16_CMD, REPORT_REFERRALS_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; repRefCmdBlk[2] = (start_llba >> 56) & 0xff; repRefCmdBlk[3] = (start_llba >> 48) & 0xff; repRefCmdBlk[4] = (start_llba >> 40) & 0xff; repRefCmdBlk[5] = (start_llba >> 32) & 0xff; repRefCmdBlk[6] = (start_llba >> 24) & 0xff; repRefCmdBlk[7] = (start_llba >> 16) & 0xff; repRefCmdBlk[8] = (start_llba >> 8) & 0xff; repRefCmdBlk[9] = start_llba & 0xff; repRefCmdBlk[10] = (mx_resp_len >> 24) & 0xff; repRefCmdBlk[11] = (mx_resp_len >> 16) & 0xff; repRefCmdBlk[12] = (mx_resp_len >> 8) & 0xff; repRefCmdBlk[13] = mx_resp_len & 0xff; repRefCmdBlk[14] = one_seg & 0x1; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " report referrals cdb: "); for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", repRefCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "report target port groups: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, repRefCmdBlk, sizeof(repRefCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "report referrals", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " report referrals: response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI SEND DIAGNOSTIC command. Foreground, extended self tests can * take a long time, if so set long_duration flag in which case the timout * is set to 7200 seconds; if the value of long_duration is > 7200 then that * value is taken as the timeout value in seconds. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Send diagnostic not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit, int devofl_bit, int unitofl_bit, int long_duration, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat, tmout; unsigned char senddiagCmdBlk[SEND_DIAGNOSTIC_CMDLEN] = {SEND_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; senddiagCmdBlk[1] = (unsigned char)((sf_code << 5) | (pf_bit << 4) | (sf_bit << 2) | (devofl_bit << 1) | unitofl_bit); senddiagCmdBlk[3] = (unsigned char)((param_len >> 8) & 0xff); senddiagCmdBlk[4] = (unsigned char)(param_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Send diagnostic cmd: "); for (k = 0; k < SEND_DIAGNOSTIC_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", senddiagCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " Send diagnostic parameter " "list:\n"); dStrHexErr((const char *)paramp, param_len, -1); } } if (long_duration > LONG_PT_TIMEOUT) tmout = long_duration; else tmout = long_duration ? LONG_PT_TIMEOUT : DEF_PT_TIMEOUT; ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "send diagnostic: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, senddiagCmdBlk, sizeof(senddiagCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, tmout, verbose); ret = sg_cmds_process_resp(ptvp, "send diagnostic", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI RECEIVE DIAGNOSTIC RESULTS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Receive diagnostic results not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp, int mx_resp_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char rcvdiagCmdBlk[RECEIVE_DIAGNOSTICS_CMDLEN] = {RECEIVE_DIAGNOSTICS_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; rcvdiagCmdBlk[1] = (unsigned char)(pcv ? 0x1 : 0); rcvdiagCmdBlk[2] = (unsigned char)(pg_code); rcvdiagCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff); rcvdiagCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Receive diagnostic results cmd: "); for (k = 0; k < RECEIVE_DIAGNOSTICS_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rcvdiagCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "receive diagnostic results: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rcvdiagCmdBlk, sizeof(rcvdiagCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "receive diagnostic results", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " receive diagnostic results: " "response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ DEFECT DATA (10) command (SBC). Return of 0 -> * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist, int dl_format, void * resp, int mx_resp_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char rdefCmdBlk[READ_DEFECT10_CMDLEN] = {READ_DEFECT10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; rdefCmdBlk[2] = (unsigned char)(((req_plist << 4) & 0x10) | ((req_glist << 3) & 0x8) | (dl_format & 0x7)); rdefCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff); rdefCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (mx_resp_len > 0xffff) { fprintf(sg_warnings_strm, "mx_resp_len too big\n"); return -1; } if (verbose) { fprintf(sg_warnings_strm, " read defect (10) cdb: "); for (k = 0; k < READ_DEFECT10_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rdefCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read defect (10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rdefCmdBlk, sizeof(rdefCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read defect (10)", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " read defect (10): response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ MEDIA SERIAL NUMBER command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Read media serial number not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char rmsnCmdBlk[SERVICE_ACTION_IN_12_CMDLEN] = {SERVICE_ACTION_IN_12_CMD, READ_MEDIA_SERIAL_NUM_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; rmsnCmdBlk[6] = (mx_resp_len >> 24) & 0xff; rmsnCmdBlk[7] = (mx_resp_len >> 16) & 0xff; rmsnCmdBlk[8] = (mx_resp_len >> 8) & 0xff; rmsnCmdBlk[9] = mx_resp_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " read media serial number cdb: "); for (k = 0; k < SERVICE_ACTION_IN_12_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rmsnCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read media serial number: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rmsnCmdBlk, sizeof(rmsnCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read media serial number", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " read media serial number: respon" "se%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI REPORT IDENTIFYING INFORMATION command. This command was * called REPORT DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report identifying information not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_report_id_info(int sg_fd, int itype, void * resp, int max_resp_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char riiCmdBlk[MAINTENANCE_IN_CMDLEN] = {MAINTENANCE_IN_CMD, REPORT_IDENTIFYING_INFORMATION_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; riiCmdBlk[6] = (max_resp_len >> 24) & 0xff; riiCmdBlk[7] = (max_resp_len >> 16) & 0xff; riiCmdBlk[8] = (max_resp_len >> 8) & 0xff; riiCmdBlk[9] = max_resp_len & 0xff; riiCmdBlk[10] |= (itype << 1) & 0xfe; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Report identifying information cdb: "); for (k = 0; k < MAINTENANCE_IN_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", riiCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "report identifying information: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, riiCmdBlk, sizeof(riiCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, max_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "report identifying information", res, max_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " report identifying information: " "response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI SET IDENTIFYING INFORMATION command. This command was * called SET DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Set identifying information not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_set_id_info(int sg_fd, int itype, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char siiCmdBlk[MAINTENANCE_OUT_CMDLEN] = {MAINTENANCE_OUT_CMD, SET_IDENTIFYING_INFORMATION_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; siiCmdBlk[6] = (param_len >> 24) & 0xff; siiCmdBlk[7] = (param_len >> 16) & 0xff; siiCmdBlk[8] = (param_len >> 8) & 0xff; siiCmdBlk[9] = param_len & 0xff; siiCmdBlk[10] |= (itype << 1) & 0xfe; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Set identifying information cdb: "); for (k = 0; k < MAINTENANCE_OUT_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", siiCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " Set identifying information " "parameter list:\n"); dStrHexErr((const char *)paramp, param_len, -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "Set identifying information: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, siiCmdBlk, sizeof(siiCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "set identifying information", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a FORMAT UNIT (SBC-3) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Format unit not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_format_unit(int sg_fd, int fmtpinfo, int longlist, int fmtdata, int cmplst, int dlist_format, int timeout_secs, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat, tmout; unsigned char fuCmdBlk[FORMAT_UNIT_CMDLEN] = {FORMAT_UNIT_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (fmtpinfo) fuCmdBlk[1] |= (fmtpinfo << 6); if (longlist) fuCmdBlk[1] |= 0x20; if (fmtdata) fuCmdBlk[1] |= 0x10; if (cmplst) fuCmdBlk[1] |= 0x8; if (dlist_format) fuCmdBlk[1] |= (dlist_format & 0x7); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT; if (verbose) { fprintf(sg_warnings_strm, " format cdb: "); for (k = 0; k < 6; ++k) fprintf(sg_warnings_strm, "%02x ", fuCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } if ((verbose > 1) && (param_len > 0)) { fprintf(sg_warnings_strm, " format parameter list:\n"); dStrHexErr((const char *)paramp, param_len, -1); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "format unit: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, fuCmdBlk, sizeof(fuCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, tmout, verbose); ret = sg_cmds_process_resp(ptvp, "format unit", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI REASSIGN BLOCKS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist, void * paramp, int param_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char reassCmdBlk[REASSIGN_BLKS_CMDLEN] = {REASSIGN_BLKS_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; reassCmdBlk[1] = (unsigned char)(((longlba << 1) & 0x2) | (longlist & 0x1)); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " reassign blocks cdb: "); for (k = 0; k < REASSIGN_BLKS_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", reassCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } if (verbose > 1) { fprintf(sg_warnings_strm, " reassign blocks parameter list\n"); dStrHexErr((const char *)paramp, param_len, -1); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "reassign blocks: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, reassCmdBlk, sizeof(reassCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "reassign blocks", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI PERSISTENT RESERVE IN command (SPC). Returns 0 * when successful, SG_LIB_CAT_INVALID_OP if command not supported, * SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp, int mx_resp_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char prinCmdBlk[PERSISTENT_RESERVE_IN_CMDLEN] = {PERSISTENT_RESERVE_IN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (rq_servact > 0) prinCmdBlk[1] = (unsigned char)(rq_servact & 0x1f); prinCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff); prinCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Persistent Reservation In cmd: "); for (k = 0; k < PERSISTENT_RESERVE_IN_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", prinCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "persistent reservation in: out of " "memory\n"); return -1; } set_scsi_pt_cdb(ptvp, prinCmdBlk, sizeof(prinCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "persistent reservation in", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " persistent reserve in: " "response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI PERSISTENT RESERVE OUT command (SPC). Returns 0 * when successful, SG_LIB_CAT_INVALID_OP if command not supported, * SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, int rq_scope, unsigned int rq_type, void * paramp, int param_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char proutCmdBlk[PERSISTENT_RESERVE_OUT_CMDLEN] = {PERSISTENT_RESERVE_OUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (rq_servact > 0) proutCmdBlk[1] = (unsigned char)(rq_servact & 0x1f); proutCmdBlk[2] = (((rq_scope & 0xf) << 4) | (rq_type & 0xf)); proutCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff); proutCmdBlk[8] = (unsigned char)(param_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Persistent Reservation Out cmd: "); for (k = 0; k < PERSISTENT_RESERVE_OUT_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", proutCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if (verbose > 1) { fprintf(sg_warnings_strm, " Persistent Reservation Out " "parameters:\n"); dStrHexErr((const char *)paramp, param_len, 0); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "persistent reserve out: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, proutCmdBlk, sizeof(proutCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "persistent reserve out", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } static int has_blk_ili(unsigned char * sensep, int sb_len) { int resp_code; const unsigned char * cup; if (sb_len < 8) return 0; resp_code = (0x7f & sensep[0]); if (resp_code >= 0x72) { /* descriptor format */ /* find block command descriptor */ if ((cup = sg_scsi_sense_desc_find(sensep, sb_len, 0x5))) return ((cup[3] & 0x20) ? 1 : 0); } else /* fixed */ return ((sensep[2] & 0x20) ? 1 : 0); return 0; } /* Invokes a SCSI READ LONG (10) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> READ LONG(10) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned int lba, void * resp, int xfer_len, int * offsetp, int noisy, int verbose) { int k, res, sense_cat, ret; unsigned char readLongCmdBlk[READ_LONG10_CMDLEN]; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; memset(readLongCmdBlk, 0, READ_LONG10_CMDLEN); readLongCmdBlk[0] = READ_LONG10_CMD; if (pblock) readLongCmdBlk[1] |= 0x4; if (correct) readLongCmdBlk[1] |= 0x2; readLongCmdBlk[2] = (lba >> 24) & 0xff; readLongCmdBlk[3] = (lba >> 16) & 0xff; readLongCmdBlk[4] = (lba >> 8) & 0xff; readLongCmdBlk[5] = lba & 0xff; readLongCmdBlk[7] = (xfer_len >> 8) & 0xff; readLongCmdBlk[8] = xfer_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Read Long (10) cmd: "); for (k = 0; k < READ_LONG10_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", readLongCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read long (10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, readLongCmdBlk, sizeof(readLongCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, xfer_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read long (10)", res, xfer_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_ILLEGAL_REQ: { int valid, slen, ili; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); ili = has_blk_ili(sense_b, slen); if (valid && ili) { if (offsetp) *offsetp = (int)(int64_t)ull; ret = SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO; } else { if (verbose > 1) fprintf(sg_warnings_strm, " info field: 0x%" PRIx64 ", valid: %d, ili: %d\n", ull, valid, ili); ret = SG_LIB_CAT_ILLEGAL_REQ; } } break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " read long(10): response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ LONG (16) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> READ LONG(16) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_read_long16(int sg_fd, int pblock, int correct, uint64_t llba, void * resp, int xfer_len, int * offsetp, int noisy, int verbose) { int k, res, sense_cat, ret; unsigned char readLongCmdBlk[SERVICE_ACTION_IN_16_CMDLEN]; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; memset(readLongCmdBlk, 0, sizeof(readLongCmdBlk)); readLongCmdBlk[0] = SERVICE_ACTION_IN_16_CMD; readLongCmdBlk[1] = READ_LONG_16_SA; if (pblock) readLongCmdBlk[14] |= 0x2; if (correct) readLongCmdBlk[14] |= 0x1; readLongCmdBlk[2] = (llba >> 56) & 0xff; readLongCmdBlk[3] = (llba >> 48) & 0xff; readLongCmdBlk[4] = (llba >> 40) & 0xff; readLongCmdBlk[5] = (llba >> 32) & 0xff; readLongCmdBlk[6] = (llba >> 24) & 0xff; readLongCmdBlk[7] = (llba >> 16) & 0xff; readLongCmdBlk[8] = (llba >> 8) & 0xff; readLongCmdBlk[9] = llba & 0xff; readLongCmdBlk[12] = (xfer_len >> 8) & 0xff; readLongCmdBlk[13] = xfer_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Read Long (16) cmd: "); for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", readLongCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read long (16): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, readLongCmdBlk, sizeof(readLongCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, xfer_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read long (16)", res, xfer_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_ILLEGAL_REQ: { int valid, slen, ili; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); ili = has_blk_ili(sense_b, slen); if (valid && ili) { if (offsetp) *offsetp = (int)(int64_t)ull; ret = SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO; } else { if (verbose > 1) fprintf(sg_warnings_strm, " info field: 0x%" PRIx64 ", valid: %d, ili: %d\n", ull, valid, ili); ret = SG_LIB_CAT_ILLEGAL_REQ; } } break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " read long(16): response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI WRITE LONG (10) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> WRITE LONG(10) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other failure */ int sg_ll_write_long10(int sg_fd, int cor_dis, int wr_uncor, int pblock, unsigned int lba, void * data_out, int xfer_len, int * offsetp, int noisy, int verbose) { int k, res, sense_cat, ret; unsigned char writeLongCmdBlk[WRITE_LONG10_CMDLEN]; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; memset(writeLongCmdBlk, 0, WRITE_LONG10_CMDLEN); writeLongCmdBlk[0] = WRITE_LONG10_CMD; if (cor_dis) writeLongCmdBlk[1] |= 0x80; if (wr_uncor) writeLongCmdBlk[1] |= 0x40; if (pblock) writeLongCmdBlk[1] |= 0x20; writeLongCmdBlk[2] = (lba >> 24) & 0xff; writeLongCmdBlk[3] = (lba >> 16) & 0xff; writeLongCmdBlk[4] = (lba >> 8) & 0xff; writeLongCmdBlk[5] = lba & 0xff; writeLongCmdBlk[7] = (xfer_len >> 8) & 0xff; writeLongCmdBlk[8] = xfer_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Write Long (10) cmd: "); for (k = 0; k < (int)sizeof(writeLongCmdBlk); ++k) fprintf(sg_warnings_strm, "%02x ", writeLongCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "write long(10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, writeLongCmdBlk, sizeof(writeLongCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)data_out, xfer_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "write long(10)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_ILLEGAL_REQ: { int valid, slen, ili; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); ili = has_blk_ili(sense_b, slen); if (valid && ili) { if (offsetp) *offsetp = (int)(int64_t)ull; ret = SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO; } else { if (verbose > 1) fprintf(sg_warnings_strm, " info field: 0x%" PRIx64 ", valid: %d, ili: %d\n", ull, valid, ili); ret = SG_LIB_CAT_ILLEGAL_REQ; } } break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI WRITE LONG (16) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> WRITE LONG(16) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other failure */ int sg_ll_write_long16(int sg_fd, int cor_dis, int wr_uncor, int pblock, uint64_t llba, void * data_out, int xfer_len, int * offsetp, int noisy, int verbose) { int k, res, sense_cat, ret; unsigned char writeLongCmdBlk[SERVICE_ACTION_OUT_16_CMDLEN]; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; memset(writeLongCmdBlk, 0, sizeof(writeLongCmdBlk)); writeLongCmdBlk[0] = SERVICE_ACTION_OUT_16_CMD; writeLongCmdBlk[1] = WRITE_LONG_16_SA; if (cor_dis) writeLongCmdBlk[1] |= 0x80; if (wr_uncor) writeLongCmdBlk[1] |= 0x40; if (pblock) writeLongCmdBlk[1] |= 0x20; writeLongCmdBlk[2] = (llba >> 56) & 0xff; writeLongCmdBlk[3] = (llba >> 48) & 0xff; writeLongCmdBlk[4] = (llba >> 40) & 0xff; writeLongCmdBlk[5] = (llba >> 32) & 0xff; writeLongCmdBlk[6] = (llba >> 24) & 0xff; writeLongCmdBlk[7] = (llba >> 16) & 0xff; writeLongCmdBlk[8] = (llba >> 8) & 0xff; writeLongCmdBlk[9] = llba & 0xff; writeLongCmdBlk[12] = (xfer_len >> 8) & 0xff; writeLongCmdBlk[13] = xfer_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Write Long (16) cmd: "); for (k = 0; k < SERVICE_ACTION_OUT_16_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", writeLongCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "write long(16): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, writeLongCmdBlk, sizeof(writeLongCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)data_out, xfer_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "write long(16)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_ILLEGAL_REQ: { int valid, slen, ili; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); ili = has_blk_ili(sense_b, slen); if (valid && ili) { if (offsetp) *offsetp = (int)(int64_t)ull; ret = SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO; } else { if (verbose > 1) fprintf(sg_warnings_strm, " info field: 0x%" PRIx64 ", valid: %d, ili: %d\n", ull, valid, ili); ret = SG_LIB_CAT_ILLEGAL_REQ; } } break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI VERIFY (10) command (SBC and MMC). * Note that 'veri_len' is in blocks while 'data_out_len' is in bytes. * Returns of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Verify(10) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_MEDIUM_HARD -> medium or hardware error, no valid info, * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> as previous, with valid info, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_MISCOMPARE, -1 -> other failure */ int sg_ll_verify10(int sg_fd, int vrprotect, int dpo, int bytchk, unsigned int lba, int veri_len, void * data_out, int data_out_len, unsigned int * infop, int noisy, int verbose) { int k, res, ret, sense_cat, slen; unsigned char vCmdBlk[VERIFY10_CMDLEN] = {VERIFY10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; /* N.B. BYTCHK field expanded to 2 bits sbc3r34 */ vCmdBlk[1] = ((vrprotect & 0x7) << 5) | ((dpo & 0x1) << 4) | ((bytchk & 0x3) << 1) ; vCmdBlk[2] = (unsigned char)((lba >> 24) & 0xff); vCmdBlk[3] = (unsigned char)((lba >> 16) & 0xff); vCmdBlk[4] = (unsigned char)((lba >> 8) & 0xff); vCmdBlk[5] = (unsigned char)(lba & 0xff); vCmdBlk[7] = (unsigned char)((veri_len >> 8) & 0xff); vCmdBlk[8] = (unsigned char)(veri_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose > 1) { fprintf(sg_warnings_strm, " Verify(10) cdb: "); for (k = 0; k < VERIFY10_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", vCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 3) && bytchk && data_out && (data_out_len > 0)) { k = data_out_len > 4104 ? 4104 : data_out_len; fprintf(sg_warnings_strm, " data_out buffer%s\n", (data_out_len > 4104 ? ", first 4104 bytes" : "")); dStrHexErr((const char *)data_out, k, verbose < 5); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "verify (10): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, vCmdBlk, sizeof(vCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); if (data_out_len > 0) set_scsi_pt_data_out(ptvp, (unsigned char *)data_out, data_out_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "verify (10)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: case SG_LIB_CAT_MISCOMPARE: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_MEDIUM_HARD: { int valid; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); if (valid) { if (infop) *infop = (unsigned int)ull; ret = SG_LIB_CAT_MEDIUM_HARD_WITH_INFO; } else ret = SG_LIB_CAT_MEDIUM_HARD; } break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI VERIFY (16) command (SBC and MMC). * Note that 'veri_len' is in blocks while 'data_out_len' is in bytes. * Returns of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Verify(16) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_MEDIUM_HARD -> medium or hardware error, no valid info, * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> as previous, with valid info, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_MISCOMPARE, -1 -> other failure */ int sg_ll_verify16(int sg_fd, int vrprotect, int dpo, int bytchk, uint64_t llba, int veri_len, int group_num, void * data_out, int data_out_len, uint64_t * infop, int noisy, int verbose) { int k, res, ret, sense_cat, slen; unsigned char vCmdBlk[VERIFY16_CMDLEN] = {VERIFY16_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; /* N.B. BYTCHK field expanded to 2 bits sbc3r34 */ vCmdBlk[1] = ((vrprotect & 0x7) << 5) | ((dpo & 0x1) << 4) | ((bytchk & 0x3) << 1) ; vCmdBlk[2] = (llba >> 56) & 0xff; vCmdBlk[3] = (llba >> 48) & 0xff; vCmdBlk[4] = (llba >> 40) & 0xff; vCmdBlk[5] = (llba >> 32) & 0xff; vCmdBlk[6] = (llba >> 24) & 0xff; vCmdBlk[7] = (llba >> 16) & 0xff; vCmdBlk[8] = (llba >> 8) & 0xff; vCmdBlk[9] = llba & 0xff; vCmdBlk[10] = (veri_len >> 24) & 0xff; vCmdBlk[11] = (veri_len >> 16) & 0xff; vCmdBlk[12] = (veri_len >> 8) & 0xff; vCmdBlk[13] = veri_len & 0xff; vCmdBlk[14] = group_num & 0x1f; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose > 1) { fprintf(sg_warnings_strm, " Verify(16) cdb: "); for (k = 0; k < VERIFY16_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", vCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 3) && bytchk && data_out && (data_out_len > 0)) { k = data_out_len > 4104 ? 4104 : data_out_len; fprintf(sg_warnings_strm, " data_out buffer%s\n", (data_out_len > 4104 ? ", first 4104 bytes" : "")); dStrHexErr((const char *)data_out, k, verbose < 5); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "verify (16): out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, vCmdBlk, sizeof(vCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); if (data_out_len > 0) set_scsi_pt_data_out(ptvp, (unsigned char *)data_out, data_out_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "verify (16)", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: case SG_LIB_CAT_MISCOMPARE: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_MEDIUM_HARD: { int valid; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); if (valid) { if (infop) *infop = ull; ret = SG_LIB_CAT_MEDIUM_HARD_WITH_INFO; } else ret = SG_LIB_CAT_MEDIUM_HARD; } break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a ATA PASS-THROUGH (12 or 16) SCSI command (SAT). If cdb_len * is 12 then a ATA PASS-THROUGH (12) command is called. If cdb_len is 16 * then a ATA PASS-THROUGH (16) command is called. If cdb_len is any other * value -1 is returned. After copying from cdbp to an internal buffer, * the first byte (i.e. offset 0) is set to 0xa1 if cdb_len is 12; or is * set to 0x85 if cdb_len is 16. The last byte (offset 11 or offset 15) is * set to 0x0 in the internal buffer. If timeout_secs <= 0 then the timeout * is set to 60 seconds. For data in or out transfers set dinp or doutp, * and dlen to the number of bytes to transfer. If dlen is zero then no data * transfer is assumed. If sense buffer obtained then it is written to * sensep, else sensep[0] is set to 0x0. If ATA return descriptor is obtained * then written to ata_return_dp, else ata_return_dp[0] is set to 0x0. Either * sensep or ata_return_dp (or both) may be NULL pointers. Returns SCSI * status value (>= 0) or -1 if other error. Users are expected to check the * sense buffer themselves. If available the data in resid is written to * residp. Note in SAT-2 and later, fixed format sense data may be placed in * *sensep in which case sensep[0]==0x70 . */ int sg_ll_ata_pt(int sg_fd, const unsigned char * cdbp, int cdb_len, int timeout_secs, void * dinp, void * doutp, int dlen, unsigned char * sensep, int max_sense_len, unsigned char * ata_return_dp, int max_ata_return_len, int * residp, int verbose) { int k, res, slen, duration; unsigned char aptCmdBlk[ATA_PT_16_CMDLEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; unsigned char * sp; const unsigned char * ucp; struct sg_pt_base * ptvp; const char * cnamep; char b[256]; int ret = -1; b[0] = '\0'; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; cnamep = (12 == cdb_len) ? "ATA pass through (12)" : "ATA pass through (16)"; if ((NULL == cdbp) || ((12 != cdb_len) && (16 != cdb_len))) { if (verbose) { if (NULL == cdbp) fprintf(sg_warnings_strm, "%s NULL cdb pointer\n", cnamep); else fprintf(sg_warnings_strm, "cdb_len must be 12 or 16\n"); } return -1; } aptCmdBlk[0] = (12 == cdb_len) ? ATA_PT_12_CMD : ATA_PT_16_CMD; if (sensep && (max_sense_len >= (int)sizeof(sense_b))) { sp = sensep; slen = max_sense_len; } else { sp = sense_b; slen = sizeof(sense_b); } if (12 == cdb_len) memcpy(aptCmdBlk + 1, cdbp + 1, ((cdb_len > 11) ? 10 : (cdb_len - 1))); else memcpy(aptCmdBlk + 1, cdbp + 1, ((cdb_len > 15) ? 14 : (cdb_len - 1))); if (verbose) { fprintf(sg_warnings_strm, " %s cdb: ", cnamep); for (k = 0; k < cdb_len; ++k) fprintf(sg_warnings_strm, "%02x ", aptCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "%s: out of memory\n", cnamep); return -1; } set_scsi_pt_cdb(ptvp, aptCmdBlk, cdb_len); set_scsi_pt_sense(ptvp, sp, slen); if (dlen > 0) { if (dinp) set_scsi_pt_data_in(ptvp, (unsigned char *)dinp, dlen); else if (doutp) set_scsi_pt_data_out(ptvp, (unsigned char *)doutp, dlen); } res = do_scsi_pt(ptvp, sg_fd, ((timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT), verbose); if (SCSI_PT_DO_BAD_PARAMS == res) { if (verbose) fprintf(sg_warnings_strm, "%s: bad parameters\n", cnamep); goto out; } else if (SCSI_PT_DO_TIMEOUT == res) { if (verbose) fprintf(sg_warnings_strm, "%s: timeout\n", cnamep); goto out; } else if (res > 2) { if (verbose) fprintf(sg_warnings_strm, "%s: do_scsi_pt: errno=%d\n", cnamep, -res); } if ((verbose > 2) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0)) fprintf(sg_warnings_strm, " duration=%d ms\n", duration); switch (get_scsi_pt_result_category(ptvp)) { case SCSI_PT_RESULT_GOOD: if ((sensep) && (max_sense_len > 0)) *sensep = 0; if ((ata_return_dp) && (max_ata_return_len > 0)) *ata_return_dp = 0; if (residp && (dlen > 0)) *residp = get_scsi_pt_resid(ptvp); ret = 0; break; case SCSI_PT_RESULT_STATUS: /* other than GOOD + CHECK CONDITION */ if ((sensep) && (max_sense_len > 0)) *sensep = 0; if ((ata_return_dp) && (max_ata_return_len > 0)) *ata_return_dp = 0; ret = get_scsi_pt_status_response(ptvp); break; case SCSI_PT_RESULT_SENSE: if (sensep && (sp != sensep)) { k = get_scsi_pt_sense_len(ptvp); k = (k > max_sense_len) ? max_sense_len : k; memcpy(sensep, sp, k); } if (ata_return_dp && (max_ata_return_len > 0)) { /* search for ATA return descriptor */ ucp = sg_scsi_sense_desc_find(sp, slen, 0x9); if (ucp) { k = ucp[1] + 2; k = (k > max_ata_return_len) ? max_ata_return_len : k; memcpy(ata_return_dp, ucp, k); } else ata_return_dp[0] = 0x0; } if (residp && (dlen > 0)) *residp = get_scsi_pt_resid(ptvp); ret = get_scsi_pt_status_response(ptvp); break; case SCSI_PT_RESULT_TRANSPORT_ERR: if (verbose) fprintf(sg_warnings_strm, "%s: transport error: %s\n", cnamep, get_scsi_pt_transport_err_str(ptvp, sizeof(b) , b)); break; case SCSI_PT_RESULT_OS_ERR: if (verbose) fprintf(sg_warnings_strm, "%s: os error: %s\n", cnamep, get_scsi_pt_os_err_str(ptvp, sizeof(b) , b)); break; default: if (verbose) fprintf(sg_warnings_strm, "%s: unknown pt_result_category=%d\n", cnamep, get_scsi_pt_result_category(ptvp)); break; } out: destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ BUFFER command (SPC). Return of 0 -> * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset, void * resp, int mx_resp_len, int noisy, int verbose) { int res, k, ret, sense_cat; unsigned char rbufCmdBlk[READ_BUFFER_CMDLEN] = {READ_BUFFER_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; rbufCmdBlk[1] = (unsigned char)(mode & 0x1f); rbufCmdBlk[2] = (unsigned char)(buffer_id & 0xff); rbufCmdBlk[3] = (unsigned char)((buffer_offset >> 16) & 0xff); rbufCmdBlk[4] = (unsigned char)((buffer_offset >> 8) & 0xff); rbufCmdBlk[5] = (unsigned char)(buffer_offset & 0xff); rbufCmdBlk[6] = (unsigned char)((mx_resp_len >> 16) & 0xff); rbufCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff); rbufCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " read buffer cdb: "); for (k = 0; k < READ_BUFFER_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rbufCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read buffer: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rbufCmdBlk, sizeof(rbufCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read buffer", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " read buffer: response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI WRITE BUFFER command (SPC). Return of 0 -> * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char wbufCmdBlk[WRITE_BUFFER_CMDLEN] = {WRITE_BUFFER_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; wbufCmdBlk[1] = (unsigned char)(mode & 0x1f); wbufCmdBlk[2] = (unsigned char)(buffer_id & 0xff); wbufCmdBlk[3] = (unsigned char)((buffer_offset >> 16) & 0xff); wbufCmdBlk[4] = (unsigned char)((buffer_offset >> 8) & 0xff); wbufCmdBlk[5] = (unsigned char)(buffer_offset & 0xff); wbufCmdBlk[6] = (unsigned char)((param_len >> 16) & 0xff); wbufCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff); wbufCmdBlk[8] = (unsigned char)(param_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " Write buffer cmd: "); for (k = 0; k < WRITE_BUFFER_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", wbufCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " Write buffer parameter list%s:\n", ((param_len > 256) ? " (first 256 bytes)" : "")); dStrHexErr((const char *)paramp, ((param_len > 256) ? 256 : param_len), -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "write buffer: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, wbufCmdBlk, sizeof(wbufCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "write buffer", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI UNMAP command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> command not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_unmap(int sg_fd, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose) { return sg_ll_unmap_v2(sg_fd, 0, group_num, timeout_secs, paramp, param_len, noisy, verbose); } /* Invokes a SCSI UNMAP (SBC-3) command. Version 2 adds anchor field * (sbc3r22). Otherwise same as sg_ll_unmap() . */ int sg_ll_unmap_v2(int sg_fd, int anchor, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat, tmout; unsigned char uCmdBlk[UNMAP_CMDLEN] = {UNMAP_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (anchor) uCmdBlk[1] |= 0x1; tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT; uCmdBlk[7] = group_num & 0x1f; uCmdBlk[7] = (param_len >> 8) & 0xff; uCmdBlk[8] = param_len & 0xff; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " unmap cdb: "); for (k = 0; k < UNMAP_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", uCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " unmap parameter list:\n"); dStrHexErr((const char *)paramp, param_len, -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "unmap: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, uCmdBlk, sizeof(uCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, tmout, verbose); ret = sg_cmds_process_resp(ptvp, "unmap", res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI READ BLOCK LIMITS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Read block limits not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ int sg_ll_read_block_limits(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose) { int k, ret, res, sense_cat; unsigned char rlCmdBlk[READ_BLOCK_LIMITS_CMDLEN] = {READ_BLOCK_LIMITS_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " read block limits cdb: "); for (k = 0; k < READ_BLOCK_LIMITS_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rlCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "read block limits: out of memory\n"); return -1; } set_scsi_pt_cdb(ptvp, rlCmdBlk, sizeof(rlCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, "read block limits", res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: case SG_LIB_CAT_NOT_READY: /* shouldn't happen ?? */ ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else { if ((verbose > 2) && (ret > 0)) { fprintf(sg_warnings_strm, " read block limits: response%s\n", (ret > 256 ? ", first 256 bytes" : "")); dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1); } ret = 0; } destruct_scsi_pt_obj(ptvp); return ret; } /* Invokes a SCSI RECEIVE COPY RESULTS command. Actually cover all current * uses of opcode 0x84 (Third-party copy IN). Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Receive copy results not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp, int mx_resp_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char rcvcopyresCmdBlk[THIRD_PARTY_COPY_IN_CMDLEN] = {THIRD_PARTY_COPY_IN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; char b[64]; sg_get_opcode_sa_name(THIRD_PARTY_COPY_IN_CMD, sa, 0, (int)sizeof(b), b); rcvcopyresCmdBlk[1] = (unsigned char)(sa & 0x1f); if (sa <= 4) /* LID1 variants */ rcvcopyresCmdBlk[2] = (unsigned char)(list_id); else if ((sa >= 5) && (sa <= 7)) { /* LID4 variants */ rcvcopyresCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff); rcvcopyresCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff); rcvcopyresCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff); rcvcopyresCmdBlk[5] = (unsigned char)(list_id & 0xff); } rcvcopyresCmdBlk[10] = (unsigned char)((mx_resp_len >> 24) & 0xff); rcvcopyresCmdBlk[11] = (unsigned char)((mx_resp_len >> 16) & 0xff); rcvcopyresCmdBlk[12] = (unsigned char)((mx_resp_len >> 8) & 0xff); rcvcopyresCmdBlk[13] = (unsigned char)(mx_resp_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " %s cmd: ", b); for (k = 0; k < THIRD_PARTY_COPY_IN_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", rcvcopyresCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "%s: out of memory\n", b); return -1; } set_scsi_pt_cdb(ptvp, rcvcopyresCmdBlk, sizeof(rcvcopyresCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, b, res, mx_resp_len, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* SPC-4 rev 35 and later calls this opcode (0x83) "Third-party copy OUT" * The original EXTENDED COPY command (now called EXTENDED COPY (LID1)) * is the only one supported by sg_ll_extended_copy(). See function * sg_ll_3party_copy_out() for the other service actions ( > 0 ). */ /* Invokes a SCSI EXTENDED COPY (LID1) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Receive copy results not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_extended_copy(int sg_fd, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat; unsigned char xcopyCmdBlk[THIRD_PARTY_COPY_OUT_CMDLEN] = {THIRD_PARTY_COPY_OUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; const char * opcode_name = "Extended copy (LID1)"; xcopyCmdBlk[1] = (unsigned char)(EXTENDED_COPY_LID1_SA & 0x1f); xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff); xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff); xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff); xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff); if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; if (verbose) { fprintf(sg_warnings_strm, " %s cmd: ", opcode_name); for (k = 0; k < THIRD_PARTY_COPY_OUT_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", xcopyCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " %s parameter list:\n", opcode_name); dStrHexErr((const char *)paramp, param_len, -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "%s: out of memory\n", opcode_name); return -1; } set_scsi_pt_cdb(ptvp, xcopyCmdBlk, sizeof(xcopyCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); ret = sg_cmds_process_resp(ptvp, opcode_name, res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } /* Handles various service actions associated with opcode 0x83 which is * called THIRD PARTY COPY OUT. These include the EXTENDED COPY(LID1 and * LID4), POPULATE TOKEN and WRITE USING TOKEN commands. * Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> opcode 0x83 not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_3party_copy_out(int sg_fd, int sa, unsigned int list_id, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose) { int k, res, ret, sense_cat, tmout; unsigned char xcopyCmdBlk[THIRD_PARTY_COPY_OUT_CMDLEN] = {THIRD_PARTY_COPY_OUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; char cname[80]; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; sg_get_opcode_sa_name(THIRD_PARTY_COPY_OUT_CMD, sa, 0, sizeof(cname), cname); xcopyCmdBlk[1] = (unsigned char)(sa & 0x1f); switch (sa) { case 0x0: /* XCOPY(LID1) */ case 0x1: /* XCOPY(LID4) */ xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff); xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff); xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff); xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff); break; case 0x10: /* POPULATE TOKEN (SBC-3) */ case 0x11: /* WRITE USING TOKEN (SBC-3) */ xcopyCmdBlk[6] = (unsigned char)((list_id >> 24) & 0xff); xcopyCmdBlk[7] = (unsigned char)((list_id >> 16) & 0xff); xcopyCmdBlk[8] = (unsigned char)((list_id >> 8) & 0xff); xcopyCmdBlk[9] = (unsigned char)(list_id & 0xff); xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff); xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff); xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff); xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff); xcopyCmdBlk[14] = (unsigned char)(group_num & 0x1f); break; case 0x1c: /* COPY OPERATION ABORT */ xcopyCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff); xcopyCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff); xcopyCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff); xcopyCmdBlk[5] = (unsigned char)(list_id & 0xff); break; default: fprintf(sg_warnings_strm, "sg_ll_3party_copy_out: unknown service " "action 0x%x\n", sa); return -1; } tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT; if (verbose) { fprintf(sg_warnings_strm, " %s cmd: ", cname); for (k = 0; k < THIRD_PARTY_COPY_OUT_CMDLEN; ++k) fprintf(sg_warnings_strm, "%02x ", xcopyCmdBlk[k]); fprintf(sg_warnings_strm, "\n"); if ((verbose > 1) && paramp && param_len) { fprintf(sg_warnings_strm, " %s parameter list:\n", cname); dStrHexErr((const char *)paramp, param_len, -1); } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(sg_warnings_strm, "%s: out of memory\n", cname); return -1; } set_scsi_pt_cdb(ptvp, xcopyCmdBlk, sizeof(xcopyCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, tmout, verbose); ret = sg_cmds_process_resp(ptvp, cname, res, 0, sense_b, noisy, verbose, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; destruct_scsi_pt_obj(ptvp); return ret; } ddpt-0.94/TODO0000644000175000017500000000036411440271346012072 0ustar douggdouggSome suggestions: - look into supporting the SCSI EXTENDED COPY command. Syntax should be interesting [20090320] - cope with MEDIUM/HARDWARE ERROR when no valid INFO field given and bpt>1 . Broken devices are out there [20100903] ddpt-0.94/ChangeLog0000644000175000017500000001323012320426132013141 0ustar douggdouggThe version number is hard-coded into src/ddpt.c (in a C string); the rpm spec file: ddpt.spec ; the debian/changelog file; and the configure.ac file (in the AC_INIT item). Changelog for ddpt-0.94 [20140407] [svn: r277] - xcopy: change default to send xcopy command to dst - add XCOPY_TO_SRC and XCOPY_TO_DST environment variables to guide where to send xcopy command - odx: add new offloaded copy technique, also known as "xcopy v2, lite", that exposes ROD Tokens - ddpt supports 4 odx variants: full copy, zero output blocks, read to tokens and write from tokens. Latter two facilitate network copies - add scatter-gather list capability to seek=, skip= to read from command line, file or stdin - ddptctl: add odx helper utility - can issue individual PT, WUT, RRTI, Report All Rod Tokens, and Copy Operation Abort commands - can decode T10 defined info in Rod Token - improve CL handling of short options (e.g. '-vv') - point svn:externals to rev 563 of sg3_utils - configure: add --disable-libsgutils option so build bypasses that library if present Changelog for ddpt-0.93 [20131113] [svn: r242] - add xcopy support, new flags: xcopy, cat, dc; new options: id_usage=, list_id=, prio= - add intio=0|1 ; rework signal handling - allow tape device in non-pt mode - fix fifo read when bs is large - add delay=MS,W_MS for bandwidth limiting - add oflag=ignoreew,pad,nofm,nopad for tape - add iseek= option, synonym for skip= - add oseek= option, synonym for seek= - add protect=RDP,WRP option - add cdbsz=32 option for READ(32) and WRITE(32) - add rarc flag for scsi read cdbs - add block flag for pt (non blocking by default) - fix overflow on OFILE when input fifo - ./configure options: - change --enable-no-linux-bsg to --disable-linuxbsg - add --disable-scsistrings to reduce utility size with non-libsgutils build - reduce ddpt.c size by adding ddpt_pt.c - win32: fixes for cygwin version 1.7.17 headers - translate O_EXCL to no sharing - point svn:externals to rev 522 of sg3_utils - upgrade automake to version 1.13.3 Changelog for ddpt-0.92 [20110217] [svn: r157] - when pt used on block device and discrepancy between size of block device and read capacity size, require force flag - add coe support for input block devices and regular files - support conv=fdatasync, conv=fsync, oflag=fdatasync and oflag=fsync; called at end of copy - allow partial writes of trailing bytes when output is regular file or fifo (stdout), ignore if block or pt device - fix stdin, stdout and fifo handling problems - if iflag=sparse and of=/dev/null (or not given) warn but set oflag=sparse and continue - treat unrecovered errors as partial (as dd does) - win32: add '--wscan' option to scan for devices and volumes - select SPT direct pt interface - add estimate of remaining time in progress signal handler - accept but ignore cbs= option - error reporting clean up - add AM_MAINTAINER_MODE to configure.ac to lessen build issues Changelog for ddpt-0.91 [20100920] [svn: r121] - rework copy loop. - extend bpt=BPT to bpt=BPR[,OBPC] spare+sparse granularity - change BPT default to vary from 8192 to 1 depending on IBS - add oflag=resume logic - change oflag=sparse to extend regular OFILE with a final block write, if required - add oflag=strunc to also do sparse writes but to extend regular OFILE with ftruncate, if required - change 'bs=' option to set IBS and OBS; 'ibs=' and 'obs=' can coexist but not with 'bs='. [Closer to dd semantics] - conv=noerror,null,resume,sparing,sparse,sync now permitted - add oflag=trunc and conv=trunc (default: overwrite) - quietly ignored if resume, needed due to sequence - add oflag=trim for TRIM/UNMAP on pt OFILEs - add iflag=self or oflag=self for self-trim - add oflag=nowrite to bypass writes+truncates (does trims) - add iflag=errblk to write bad LBAs to file - if sense data deficient, write a LBA range to file - add iflag=norcap or oflag=norcap to bypass the SCSI READ CAPACITY command on pt devices - discrepancies between ibs or obs and READ CAPACITY supplied block lengths abort the copy. This can be overridden by iflag=force or oflag=force on pt devices - optical memory devices (pdt=7) added to cd/dvd readers (pdt=5) that don't need sense valid=1 to accept info field (when > 0) - rework short read logic for block and regular files - treat linux bsg devices as implicit pt devices Changelog for ddpt-0.90 [20100508] [svn: r85] - copied from sg_dd utility in sg3_utils package - change name from sgdd to ddpt (package and utility name) - ibs and obs can differ when ((ibs * bpt) % obs) == 0) - change 'sg_io' flag to 'pt' (for pass-through) - change 'dsync' flag to 'sync'; 'ssync' flag for SCSI SYNCHRONIZE CACHE command; add 'nocache' flag - 'if=IFILE' must be given, to read from stdin use 'if=-' - 'of=OFILE' changed to default to /dev/null (was stdout) - if 'nocache' flag call posix_fadvise(SEQUENTIAL) on input fd and posix_fadvise(DONTNEED) during copy - add 'fua_nv' flag - when multiple unrecovered errors report lowest and highest LBA - call sg_set_binary_mode() on fds (for windows) - resubmit pass-through reads and writes if interrupted - drop Linux raw file support - drop READ LONG logic (coe=2 and coe=3) - add write sparing support (oflag=sparing) - add linux bsg support - sg_pt_win32: define WIN32_SPT_DIRECT via config.h - calculate COUNT for regular files when required - accept 'count=-1' to mean calculate COUNT - accept '-V' as synonym for '--version' - point svn:externals to rev 334 of sg3_utils ddpt-0.94/Makefile.am0000644000175000017500000000012311100510330013405 0ustar douggdouggSUBDIRS = src doc EXTRA_DIST=autogen.sh distclean-local: rm -rf autom4te.cache ddpt-0.94/depcomp0000755000175000017500000005601612234471250012762 0ustar douggdougg#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # 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 distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ddpt-0.94/config.sub0000755000175000017500000010535412234471250013370 0ustar douggdougg#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-08-10' # This file 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 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ddpt-0.94/autogen.sh0000755000175000017500000013014111173672404013403 0ustar douggdougg#!/bin/sh # a u t o g e n . s h # # Copyright (c) 2005-2007 United States Government as represented by # the U.S. Army Research Laboratory. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # 3. The name of the author may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ### # # Script for automatically preparing the sources for compilation by # performing the myrid of necessary steps. The script attempts to # detect proper version support, and outputs warnings about particular # systems that have autotool peculiarities. # # Basically, if everything is set up and installed correctly, the # script will validate that minimum versions of the GNU Build System # tools are installed, account for several common configuration # issues, and then simply run autoreconf for you. # # If autoreconf fails, which can happen for many valid configurations, # this script proceeds to run manual preparation steps effectively # providing a POSIX shell script (mostly complete) reimplementation of # autoreconf. # # The AUTORECONF, AUTOCONF, AUTOMAKE, LIBTOOLIZE, ACLOCAL, AUTOHEADER # environment variables and corresponding _OPTIONS variables (e.g. # AUTORECONF_OPTIONS) may be used to override the default automatic # detection behaviors. Similarly the _VERSION variables will override # the minimum required version numbers. # # Examples: # # To obtain help on usage: # ./autogen.sh --help # # To obtain verbose output: # ./autogen.sh --verbose # # To skip autoreconf and prepare manually: # AUTORECONF=false ./autogen.sh # # To verbosely try running with an older (unsupported) autoconf: # AUTOCONF_VERSION=2.50 ./autogen.sh --verbose # # Author: Christopher Sean Morrison # ###################################################################### # set to minimum acceptible version of autoconf if [ "x$AUTOCONF_VERSION" = "x" ] ; then AUTOCONF_VERSION=2.52 fi # set to minimum acceptible version of automake if [ "x$AUTOMAKE_VERSION" = "x" ] ; then AUTOMAKE_VERSION=1.6.0 fi # set to minimum acceptible version of libtool if [ "x$LIBTOOL_VERSION" = "x" ] ; then LIBTOOL_VERSION=1.4.2 fi ################## # ident function # ################## ident ( ) { # extract copyright from header __copyright="`grep Copyright $AUTOGEN_SH | head -${HEAD_N}1 | awk '{print $4}'`" if [ "x$__copyright" = "x" ] ; then __copyright="`date +%Y`" fi # extract version from CVS Id string __id="$Id: autogen.sh,v 14.97 2007/06/18 22:25:02 brlcad Exp $" __version="`echo $__id | sed 's/.*\([0-9][0-9][0-9][0-9]\)[-\/]\([0-9][0-9]\)[-\/]\([0-9][0-9]\).*/\1\2\3/'`" if [ "x$__version" = "x" ] ; then __version="" fi echo "autogen.sh build preparation script by Christopher Sean Morrison" echo "revised 3-clause BSD-style license, copyright (c) $__copyright" echo "script version $__version, ISO/IEC 9945 POSIX shell script" } ################## # USAGE FUNCTION # ################## usage ( ) { echo "Usage: $AUTOGEN_SH [-h|--help] [-v|--verbose] [-q|--quiet] [--version]" echo " --help Help on $NAME_OF_AUTOGEN usage" echo " --verbose Verbose progress output" echo " --quiet Quiet suppressed progress output" echo " --version Only perform GNU Build System version checks" echo echo "Description: This script will validate that minimum versions of the" echo "GNU Build System tools are installed and then run autoreconf for you." echo "Should autoreconf fail, manual preparation steps will be run" echo "potentially accounting for several common preparation issues. The" echo "AUTORECONF, AUTOCONF, AUTOMAKE, LIBTOOLIZE, ACLOCAL, AUTOHEADER," echo "PROJECT, & CONFIGURE environment variables and corresponding _OPTIONS" echo "variables (e.g. AUTORECONF_OPTIONS) may be used to override the" echo "default automatic detection behavior." echo ident return 0 } ########################## # VERSION_ERROR FUNCTION # ########################## version_error ( ) { if [ "x$1" = "x" ] ; then echo "INTERNAL ERROR: version_error was not provided a version" exit 1 fi if [ "x$2" = "x" ] ; then echo "INTERNAL ERROR: version_error was not provided an application name" exit 1 fi $ECHO $ECHO "ERROR: To prepare the ${PROJECT} build system from scratch," $ECHO " at least version $1 of $2 must be installed." $ECHO $ECHO "$NAME_OF_AUTOGEN does not need to be run on the same machine that will" $ECHO "run configure or make. Either the GNU Autotools will need to be installed" $ECHO "or upgraded on this system, or $NAME_OF_AUTOGEN must be run on the source" $ECHO "code on another system and then transferred to here. -- Cheers!" $ECHO } ########################## # VERSION_CHECK FUNCTION # ########################## version_check ( ) { if [ "x$1" = "x" ] ; then echo "INTERNAL ERROR: version_check was not provided a minimum version" exit 1 fi _min="$1" if [ "x$2" = "x" ] ; then echo "INTERNAL ERROR: version check was not provided a comparison version" exit 1 fi _cur="$2" # needed to handle versions like 1.10 and 1.4-p6 _min="`echo ${_min}. | sed 's/[^0-9]/./g' | sed 's/\.\././g'`" _cur="`echo ${_cur}. | sed 's/[^0-9]/./g' | sed 's/\.\././g'`" _min_major="`echo $_min | cut -d. -f1`" _min_minor="`echo $_min | cut -d. -f2`" _min_patch="`echo $_min | cut -d. -f3`" _cur_major="`echo $_cur | cut -d. -f1`" _cur_minor="`echo $_cur | cut -d. -f2`" _cur_patch="`echo $_cur | cut -d. -f3`" if [ "x$_min_major" = "x" ] ; then _min_major=0 fi if [ "x$_min_minor" = "x" ] ; then _min_minor=0 fi if [ "x$_min_patch" = "x" ] ; then _min_patch=0 fi if [ "x$_cur_minor" = "x" ] ; then _cur_major=0 fi if [ "x$_cur_minor" = "x" ] ; then _cur_minor=0 fi if [ "x$_cur_patch" = "x" ] ; then _cur_patch=0 fi $VERBOSE_ECHO "Checking if ${_cur_major}.${_cur_minor}.${_cur_patch} is greater than ${_min_major}.${_min_minor}.${_min_patch}" if [ $_min_major -lt $_cur_major ] ; then return 0 elif [ $_min_major -eq $_cur_major ] ; then if [ $_min_minor -lt $_cur_minor ] ; then return 0 elif [ $_min_minor -eq $_cur_minor ] ; then if [ $_min_patch -lt $_cur_patch ] ; then return 0 elif [ $_min_patch -eq $_cur_patch ] ; then return 0 fi fi fi return 1 } ###################################### # LOCATE_CONFIGURE_TEMPLATE FUNCTION # ###################################### locate_configure_template ( ) { _pwd="`pwd`" if test -f "./configure.ac" ; then echo "./configure.ac" elif test -f "./configure.in" ; then echo "./configure.in" elif test -f "$_pwd/configure.ac" ; then echo "$_pwd/configure.ac" elif test -f "$_pwd/configure.in" ; then echo "$_pwd/configure.in" elif test -f "$PATH_TO_AUTOGEN/configure.ac" ; then echo "$PATH_TO_AUTOGEN/configure.ac" elif test -f "$PATH_TO_AUTOGEN/configure.in" ; then echo "$PATH_TO_AUTOGEN/configure.in" fi } ################## # argument check # ################## ARGS="$*" PATH_TO_AUTOGEN="`dirname $0`" NAME_OF_AUTOGEN="`basename $0`" AUTOGEN_SH="$PATH_TO_AUTOGEN/$NAME_OF_AUTOGEN" LIBTOOL_M4="${PATH_TO_AUTOGEN}/misc/libtool.m4" if [ "x$HELP" = "x" ] ; then HELP=no fi if [ "x$QUIET" = "x" ] ; then QUIET=no fi if [ "x$VERBOSE" = "x" ] ; then VERBOSE=no fi if [ "x$VERSION_ONLY" = "x" ] ; then VERSION_ONLY=no fi if [ "x$AUTORECONF_OPTIONS" = "x" ] ; then AUTORECONF_OPTIONS="-i -f" fi if [ "x$AUTOCONF_OPTIONS" = "x" ] ; then AUTOCONF_OPTIONS="-f" fi if [ "x$AUTOMAKE_OPTIONS" = "x" ] ; then AUTOMAKE_OPTIONS="-a -c -f" fi ALT_AUTOMAKE_OPTIONS="-a -c" if [ "x$LIBTOOLIZE_OPTIONS" = "x" ] ; then LIBTOOLIZE_OPTIONS="--automake -c -f" fi ALT_LIBTOOLIZE_OPTIONS="--automake --copy --force" if [ "x$ACLOCAL_OPTIONS" = "x" ] ; then ACLOCAL_OPTIONS="" fi if [ "x$AUTOHEADER_OPTIONS" = "x" ] ; then AUTOHEADER_OPTIONS="" fi for arg in $ARGS ; do case "x$arg" in x--help) HELP=yes ;; x-[hH]) HELP=yes ;; x--quiet) QUIET=yes ;; x-[qQ]) QUIET=yes ;; x--verbose) VERBOSE=yes ;; x-[vV]) VERBOSE=yes ;; x--version) VERSION_ONLY=yes ;; *) echo "Unknown option: $arg" echo usage exit 1 ;; esac done ##################### # environment check # ##################### # sanity check before recursions potentially begin if [ ! -f "$AUTOGEN_SH" ] ; then echo "INTERNAL ERROR: $AUTOGEN_SH does not exist" if [ ! "x$0" = "x$AUTOGEN_SH" ] ; then echo "INTERNAL ERROR: dirname/basename inconsistency: $0 != $AUTOGEN_SH" fi exit 1 fi # force locale setting to C so things like date output as expected LC_ALL=C # commands that this script expects for __cmd in echo head tail pwd ; do echo "test" | $__cmd > /dev/null 2>&1 if [ $? != 0 ] ; then echo "INTERNAL ERROR: '${__cmd}' command is required" exit 2 fi done echo "test" | grep "test" > /dev/null 2>&1 if test ! x$? = x0 ; then echo "INTERNAL ERROR: grep command is required" exit 1 fi echo "test" | sed "s/test/test/" > /dev/null 2>&1 if test ! x$? = x0 ; then echo "INTERNAL ERROR: sed command is required" exit 1 fi # determine the behavior of echo case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac # determine the behavior of head case "x`echo 'head' | head -n 1 2>&1`" in *xhead*) HEAD_N="n " ;; *) HEAD_N="" ;; esac # determine the behavior of tail case "x`echo 'tail' | tail -n 1 2>&1`" in *xtail*) TAIL_N="n " ;; *) TAIL_N="" ;; esac VERBOSE_ECHO=: ECHO=: if [ "x$QUIET" = "xyes" ] ; then if [ "x$VERBOSE" = "xyes" ] ; then echo "Verbose output quelled by quiet option. Further output disabled." fi else ECHO=echo if [ "x$VERBOSE" = "xyes" ] ; then echo "Verbose output enabled" VERBOSE_ECHO=echo fi fi # allow a recursive run to disable further recursions if [ "x$RUN_RECURSIVE" = "x" ] ; then RUN_RECURSIVE=yes fi ################################################ # check for help arg and bypass version checks # ################################################ if [ "x`echo $ARGS | sed 's/.*[hH][eE][lL][pP].*/help/'`" = "xhelp" ] ; then HELP=yes fi if [ "x$HELP" = "xyes" ] ; then usage $ECHO "---" $ECHO "Help was requested. No preparation or configuration will be performed." exit 0 fi ####################### # set up signal traps # ####################### untrap_abnormal ( ) { for sig in 1 2 13 15; do trap - $sig done } # do this cleanup whenever we exit. trap ' # start from the root if test -d "$START_PATH" ; then cd "$START_PATH" fi # restore/delete backup files if test "x$PFC_INIT" = "x1" ; then recursive_restore fi ' 0 # trap SIGHUP (1), SIGINT (2), SIGPIPE (13), SIGTERM (15) for sig in 1 2 13 15; do trap ' $ECHO "" $ECHO "Aborting $NAME_OF_AUTOGEN: caught signal '$sig'" # start from the root if test -d "$START_PATH" ; then cd "$START_PATH" fi # clean up on abnormal exit $VERBOSE_ECHO "rm -rf autom4te.cache" rm -rf autom4te.cache if test -f "acinclude.m4.$$.backup" ; then $VERBOSE_ECHO "cat acinclude.m4.$$.backup > acinclude.m4" chmod u+w acinclude.m4 cat acinclude.m4.$$.backup > acinclude.m4 $VERBOSE_ECHO "rm -f acinclude.m4.$$.backup" rm -f acinclude.m4.$$.backup fi { (exit 1); exit 1; } ' $sig done ############################# # look for a configure file # ############################# if [ "x$CONFIGURE" = "x" ] ; then CONFIGURE="`locate_configure_template`" if [ ! "x$CONFIGURE" = "x" ] ; then $VERBOSE_ECHO "Found a configure template: $CONFIGURE" fi else $ECHO "Using CONFIGURE environment variable override: $CONFIGURE" fi if [ "x$CONFIGURE" = "x" ] ; then if [ "x$VERSION_ONLY" = "xyes" ] ; then CONFIGURE=/dev/null else $ECHO $ECHO "A configure.ac or configure.in file could not be located implying" $ECHO "that the GNU Build System is at least not used in this directory. In" $ECHO "any case, there is nothing to do here without one of those files." $ECHO $ECHO "ERROR: No configure.in or configure.ac file found in `pwd`" exit 1 fi fi #################### # get project name # #################### if [ "x$PROJECT" = "x" ] ; then PROJECT="`grep AC_INIT $CONFIGURE | grep -v '.*#.*AC_INIT' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_INIT(\([^,)]*\).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" if [ "x$PROJECT" = "xAC_INIT" ] ; then # projects might be using the older/deprecated arg-less AC_INIT .. look for AM_INIT_AUTOMAKE instead PROJECT="`grep AM_INIT_AUTOMAKE $CONFIGURE | grep -v '.*#.*AM_INIT_AUTOMAKE' | tail -${TAIL_N}1 | sed 's/^[ ]*AM_INIT_AUTOMAKE(\([^,)]*\).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" fi if [ "x$PROJECT" = "xAM_INIT_AUTOMAKE" ] ; then PROJECT="project" fi if [ "x$PROJECT" = "x" ] ; then PROJECT="project" fi else $ECHO "Using PROJECT environment variable override: $PROJECT" fi $ECHO "Preparing the $PROJECT build system...please wait" $ECHO ######################## # check for autoreconf # ######################## HAVE_AUTORECONF=no if [ "x$AUTORECONF" = "x" ] ; then for AUTORECONF in autoreconf ; do $VERBOSE_ECHO "Checking autoreconf version: $AUTORECONF --version" $AUTORECONF --version > /dev/null 2>&1 if [ $? = 0 ] ; then HAVE_AUTORECONF=yes break fi done else HAVE_AUTORECONF=yes $ECHO "Using AUTORECONF environment variable override: $AUTORECONF" fi ########################## # autoconf version check # ########################## _acfound=no if [ "x$AUTOCONF" = "x" ] ; then for AUTOCONF in autoconf ; do $VERBOSE_ECHO "Checking autoconf version: $AUTOCONF --version" $AUTOCONF --version > /dev/null 2>&1 if [ $? = 0 ] ; then _acfound=yes break fi done else _acfound=yes $ECHO "Using AUTOCONF environment variable override: $AUTOCONF" fi _report_error=no if [ ! "x$_acfound" = "xyes" ] ; then $ECHO "ERROR: Unable to locate GNU Autoconf." _report_error=yes else _version="`$AUTOCONF --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" if [ "x$_version" = "x" ] ; then _version="0.0.0" fi $ECHO "Found GNU Autoconf version $_version" version_check "$AUTOCONF_VERSION" "$_version" if [ $? -ne 0 ] ; then _report_error=yes fi fi if [ "x$_report_error" = "xyes" ] ; then version_error "$AUTOCONF_VERSION" "GNU Autoconf" exit 1 fi ########################## # automake version check # ########################## _amfound=no if [ "x$AUTOMAKE" = "x" ] ; then for AUTOMAKE in automake ; do $VERBOSE_ECHO "Checking automake version: $AUTOMAKE --version" $AUTOMAKE --version > /dev/null 2>&1 if [ $? = 0 ] ; then _amfound=yes break fi done else _amfound=yes $ECHO "Using AUTOMAKE environment variable override: $AUTOMAKE" fi _report_error=no if [ ! "x$_amfound" = "xyes" ] ; then $ECHO $ECHO "ERROR: Unable to locate GNU Automake." _report_error=yes else _version="`$AUTOMAKE --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" if [ "x$_version" = "x" ] ; then _version="0.0.0" fi $ECHO "Found GNU Automake version $_version" version_check "$AUTOMAKE_VERSION" "$_version" if [ $? -ne 0 ] ; then _report_error=yes fi fi if [ "x$_report_error" = "xyes" ] ; then version_error "$AUTOMAKE_VERSION" "GNU Automake" exit 1 fi ######################## # check for libtoolize # ######################## HAVE_LIBTOOLIZE=yes HAVE_ALT_LIBTOOLIZE=no _ltfound=no if [ "x$LIBTOOLIZE" = "x" ] ; then LIBTOOLIZE=libtoolize $VERBOSE_ECHO "Checking libtoolize version: $LIBTOOLIZE --version" $LIBTOOLIZE --version > /dev/null 2>&1 if [ ! $? = 0 ] ; then HAVE_LIBTOOLIZE=no $ECHO if [ "x$HAVE_AUTORECONF" = "xno" ] ; then $ECHO "Warning: libtoolize does not appear to be available." else $ECHO "Warning: libtoolize does not appear to be available. This means that" $ECHO "the automatic build preparation via autoreconf will probably not work." $ECHO "Preparing the build by running each step individually, however, should" $ECHO "work and will be done automatically for you if autoreconf fails." fi # look for some alternates for tool in glibtoolize libtoolize15 libtoolize14 libtoolize13 ; do $VERBOSE_ECHO "Checking libtoolize alternate: $tool --version" _glibtoolize="`$tool --version > /dev/null 2>&1`" if [ $? = 0 ] ; then $VERBOSE_ECHO "Found $tool --version" _glti="`which $tool`" if [ "x$_glti" = "x" ] ; then $VERBOSE_ECHO "Cannot find $tool with which" continue; fi if test ! -f "$_glti" ; then $VERBOSE_ECHO "Cannot use $tool, $_glti is not a file" continue; fi _gltidir="`dirname $_glti`" if [ "x$_gltidir" = "x" ] ; then $VERBOSE_ECHO "Cannot find $tool path with dirname of $_glti" continue; fi if test ! -d "$_gltidir" ; then $VERBOSE_ECHO "Cannot use $tool, $_gltidir is not a directory" continue; fi HAVE_ALT_LIBTOOLIZE=yes LIBTOOLIZE="$tool" $ECHO $ECHO "Fortunately, $tool was found which means that your system may simply" $ECHO "have a non-standard or incomplete GNU Autotools install. If you have" $ECHO "sufficient system access, it may be possible to quell this warning by" $ECHO "running:" $ECHO sudo -V > /dev/null 2>&1 if [ $? = 0 ] ; then $ECHO " sudo ln -s $_glti $_gltidir/libtoolize" $ECHO else $ECHO " ln -s $_glti $_gltidir/libtoolize" $ECHO $ECHO "Run that as root or with proper permissions to the $_gltidir directory" $ECHO fi _ltfound=yes break fi done else _ltfound=yes fi else _ltfound=yes $ECHO "Using LIBTOOLIZE environment variable override: $LIBTOOLIZE" fi ############################ # libtoolize version check # ############################ _report_error=no if [ ! "x$_ltfound" = "xyes" ] ; then $ECHO $ECHO "ERROR: Unable to locate GNU Libtool." _report_error=yes else _version="`$LIBTOOLIZE --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" if [ "x$_version" = "x" ] ; then _version="0.0.0" fi $ECHO "Found GNU Libtool version $_version" version_check "$LIBTOOL_VERSION" "$_version" if [ $? -ne 0 ] ; then _report_error=yes fi fi if [ "x$_report_error" = "xyes" ] ; then version_error "$LIBTOOL_VERSION" "GNU Libtool" exit 1 fi ##################### # check for aclocal # ##################### if [ "x$ACLOCAL" = "x" ] ; then for ACLOCAL in aclocal ; do $VERBOSE_ECHO "Checking aclocal version: $ACLOCAL --version" $ACLOCAL --version > /dev/null 2>&1 if [ $? = 0 ] ; then break fi done else $ECHO "Using ACLOCAL environment variable override: $ACLOCAL" fi ######################## # check for autoheader # ######################## if [ "x$AUTOHEADER" = "x" ] ; then for AUTOHEADER in autoheader ; do $VERBOSE_ECHO "Checking autoheader version: $AUTOHEADER --version" $AUTOHEADER --version > /dev/null 2>&1 if [ $? = 0 ] ; then break fi done else $ECHO "Using AUTOHEADER environment variable override: $AUTOHEADER" fi ######################### # check if version only # ######################### $VERBOSE_ECHO "Checking whether to only output version information" if [ "x$VERSION_ONLY" = "xyes" ] ; then $ECHO ident $ECHO "---" $ECHO "Version requested. No preparation or configuration will be performed." exit 0 fi ################################# # PROTECT_FROM_CLOBBER FUNCTION # ################################# protect_from_clobber ( ) { PFC_INIT=1 # protect COPYING & INSTALL from overwrite by automake. the # automake force option will (inappropriately) ignore the existing # contents of a COPYING and/or INSTALL files (depending on the # version) instead of just forcing *missing* files like it does # for AUTHORS, NEWS, and README. this is broken but extremely # prevalent behavior, so we protect against it by keeping a backup # of the file that can later be restored. if test -f COPYING ; then if test -f COPYING.$$.protect_from_automake.backup ; then $VERBOSE_ECHO "Already backed up COPYING in `pwd`" else $VERBOSE_ECHO "Backing up COPYING in `pwd`" $VERBOSE_ECHO "cp -p COPYING COPYING.$$.protect_from_automake.backup" cp -p COPYING COPYING.$$.protect_from_automake.backup fi fi if test -f INSTALL ; then if test -f INSTALL.$$.protect_from_automake.backup ; then $VERBOSE_ECHO "Already backed up INSTALL in `pwd`" else $VERBOSE_ECHO "Backing up INSTALL in `pwd`" $VERBOSE_ECHO "cp -p INSTALL INSTALL.$$.protect_from_automake.backup" cp -p INSTALL INSTALL.$$.protect_from_automake.backup fi fi } ############################## # RECURSIVE_PROTECT FUNCTION # ############################## recursive_protect ( ) { # for projects using recursive configure, run the build # preparation steps for the subdirectories. this function assumes # START_PATH was set to pwd before recursion begins so that # relative paths work. # git 'r done, protect COPYING and INSTALL from being clobbered protect_from_clobber if test -d autom4te.cache ; then $VERBOSE_ECHO "Found an autom4te.cache directory, deleting it" $VERBOSE_ECHO "rm -rf autom4te.cache" rm -rf autom4te.cache fi # find configure template _configure="`locate_configure_template`" if [ "x$_configure" = "x" ] ; then return fi # $VERBOSE_ECHO "Looking for configure template found `pwd`/$_configure" # look for subdirs # $VERBOSE_ECHO "Looking for subdirs in `pwd`" _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $_configure | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" CHECK_DIRS="" for dir in $_det_config_subdirs ; do if test -d "`pwd`/$dir" ; then CHECK_DIRS="$CHECK_DIRS \"`pwd`/$dir\"" fi done # process subdirs if [ ! "x$CHECK_DIRS" = "x" ] ; then $VERBOSE_ECHO "Recursively scanning the following directories:" $VERBOSE_ECHO " $CHECK_DIRS" for dir in $CHECK_DIRS ; do $VERBOSE_ECHO "Protecting files from automake in $dir" cd "$START_PATH" eval "cd $dir" # recursively git 'r done recursive_protect done fi } # end of recursive_protect ############################# # RESTORE_CLOBBERED FUNCION # ############################# restore_clobbered ( ) { # The automake (and autoreconf by extension) -f/--force-missing # option may overwrite COPYING and INSTALL even if they do exist. # Here we restore the files if necessary. spacer=no # COPYING if test -f COPYING.$$.protect_from_automake.backup ; then if test -f COPYING ; then # compare entire content, restore if needed if test "x`cat COPYING`" != "x`cat COPYING.$$.protect_from_automake.backup`" ; then if test "x$spacer" = "xno" ; then $VERBOSE_ECHO spacer=yes fi # restore the backup $VERBOSE_ECHO "Restoring COPYING from backup (automake -f likely clobbered it)" $VERBOSE_ECHO "rm -f COPYING" rm -f COPYING $VERBOSE_ECHO "mv COPYING.$$.protect_from_automake.backup COPYING" mv COPYING.$$.protect_from_automake.backup COPYING fi # check contents elif test -f COPYING.$$.protect_from_automake.backup ; then $VERBOSE_ECHO "mv COPYING.$$.protect_from_automake.backup COPYING" mv COPYING.$$.protect_from_automake.backup COPYING fi # -f COPYING # just in case $VERBOSE_ECHO "rm -f COPYING.$$.protect_from_automake.backup" rm -f COPYING.$$.protect_from_automake.backup fi # -f COPYING.$$.protect_from_automake.backup # INSTALL if test -f INSTALL.$$.protect_from_automake.backup ; then if test -f INSTALL ; then # compare entire content, restore if needed if test "x`cat INSTALL`" != "x`cat INSTALL.$$.protect_from_automake.backup`" ; then if test "x$spacer" = "xno" ; then $VERBOSE_ECHO spacer=yes fi # restore the backup $VERBOSE_ECHO "Restoring INSTALL from backup (automake -f likely clobbered it)" $VERBOSE_ECHO "rm -f INSTALL" rm -f INSTALL $VERBOSE_ECHO "mv INSTALL.$$.protect_from_automake.backup INSTALL" mv INSTALL.$$.protect_from_automake.backup INSTALL fi # check contents elif test -f INSTALL.$$.protect_from_automake.backup ; then $VERBOSE_ECHO "mv INSTALL.$$.protect_from_automake.backup INSTALL" mv INSTALL.$$.protect_from_automake.backup INSTALL fi # -f INSTALL # just in case $VERBOSE_ECHO "rm -f INSTALL.$$.protect_from_automake.backup" rm -f INSTALL.$$.protect_from_automake.backup fi # -f INSTALL.$$.protect_from_automake.backup CONFIGURE="`locate_configure_template`" if [ "x$CONFIGURE" = "x" ] ; then return fi _aux_dir="`grep AC_CONFIG_AUX_DIR $CONFIGURE | grep -v '.*#.*AC_CONFIG_AUX_DIR' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_CONFIG_AUX_DIR(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" if test ! -d "$_aux_dir" ; then _aux_dir=. fi for file in config.guess config.sub ltmain.sh ; do if test -f "${_aux_dir}/${file}" ; then $VERBOSE_ECHO "rm -f \"${_aux_dir}/${file}.backup\"" rm -f "${_aux_dir}/${file}.backup" fi done } # end of restore_clobbered ############################## # RECURSIVE_RESTORE FUNCTION # ############################## recursive_restore ( ) { # restore COPYING and INSTALL from backup if they were clobbered # for each directory recursively. # git 'r undone restore_clobbered # find configure template _configure="`locate_configure_template`" if [ "x$_configure" = "x" ] ; then return fi # look for subdirs _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $_configure | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" CHECK_DIRS="" for dir in $_det_config_subdirs ; do if test -d "`pwd`/$dir" ; then CHECK_DIRS="$CHECK_DIRS \"`pwd`/$dir\"" fi done # process subdirs if [ ! "x$CHECK_DIRS" = "x" ] ; then $VERBOSE_ECHO "Recursively scanning the following directories:" $VERBOSE_ECHO " $CHECK_DIRS" for dir in $CHECK_DIRS ; do $VERBOSE_ECHO "Checking files for automake damage in $dir" cd "$START_PATH" eval "cd $dir" # recursively git 'r undone recursive_restore done fi } # end of recursive_restore ####################### # INITIALIZE FUNCTION # ####################### initialize ( ) { # this routine performs a variety of directory-specific # initializations. some are sanity checks, some are preventive, # and some are necessary setup detection. # # this function sets: # CONFIGURE # SEARCH_DIRS # CONFIG_SUBDIRS ################################## # check for a configure template # ################################## CONFIGURE="`locate_configure_template`" if [ "x$CONFIGURE" = "x" ] ; then $ECHO $ECHO "A configure.ac or configure.in file could not be located implying" $ECHO "that the GNU Build System is at least not used in this directory. In" $ECHO "any case, there is nothing to do here without one of those files." $ECHO $ECHO "ERROR: No configure.in or configure.ac file found in `pwd`" exit 1 fi ##################### # detect an aux dir # ##################### _aux_dir="`grep AC_CONFIG_AUX_DIR $CONFIGURE | grep -v '.*#.*AC_CONFIG_AUX_DIR' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_CONFIG_AUX_DIR(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" if test ! -d "$_aux_dir" ; then _aux_dir=. else $VERBOSE_ECHO "Detected auxillary directory: $_aux_dir" fi ################################ # detect a recursive configure # ################################ CONFIG_SUBDIRS="" _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $CONFIGURE | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" for dir in $_det_config_subdirs ; do if test -d "`pwd`/$dir" ; then $VERBOSE_ECHO "Detected recursive configure directory: `pwd`/$dir" CONFIG_SUBDIRS="$CONFIG_SUBDIRS `pwd`/$dir" fi done ########################################## # make sure certain required files exist # ########################################## for file in AUTHORS COPYING ChangeLog INSTALL NEWS README ; do if test ! -f $file ; then $VERBOSE_ECHO "Touching ${file} since it does not exist" touch $file fi done ################################################## # make sure certain generated files do not exist # ################################################## for file in config.guess config.sub ltmain.sh ; do if test -f "${_aux_dir}/${file}" ; then $VERBOSE_ECHO "mv -f \"${_aux_dir}/${file}\" \"${_aux_dir}/${file}.backup\"" mv -f "${_aux_dir}/${file}" "${_aux_dir}/${file}.backup" fi done ############################ # search alternate m4 dirs # ############################ SEARCH_DIRS="" for dir in m4 ; do if [ -d $dir ] ; then $VERBOSE_ECHO "Found extra aclocal search directory: $dir" SEARCH_DIRS="$SEARCH_DIRS -I $dir" fi done ###################################### # remove any previous build products # ###################################### if test -d autom4te.cache ; then $VERBOSE_ECHO "Found an autom4te.cache directory, deleting it" $VERBOSE_ECHO "rm -rf autom4te.cache" rm -rf autom4te.cache fi # tcl/tk (and probably others) have a customized aclocal.m4, so can't delete it # if test -f aclocal.m4 ; then # $VERBOSE_ECHO "Found an aclocal.m4 file, deleting it" # $VERBOSE_ECHO "rm -f aclocal.m4" # rm -f aclocal.m4 # fi } # end of initialize() ############## # initialize # ############## # stash path START_PATH="`pwd`" # Before running autoreconf or manual steps, some prep detection work # is necessary or useful. Only needs to occur once per directory, but # does need to traverse the entire subconfigure hierarchy to protect # files from being clobbered even by autoreconf. recursive_protect # start from where we started cd "$START_PATH" # get ready to process initialize ############################################ # prepare build via autoreconf or manually # ############################################ reconfigure_manually=no if [ "x$HAVE_AUTORECONF" = "xyes" ] ; then $ECHO $ECHO $ECHO_N "Automatically preparing build ... $ECHO_C" $VERBOSE_ECHO "$AUTORECONF $SEARCH_DIRS $AUTORECONF_OPTIONS" autoreconf_output="`$AUTORECONF $SEARCH_DIRS $AUTORECONF_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$autoreconf_output" if [ ! $ret = 0 ] ; then if [ "x$HAVE_ALT_LIBTOOLIZE" = "xyes" ] ; then if [ ! "x`echo \"$autoreconf_output\" | grep libtoolize | grep \"No such file or directory\"`" = "x" ] ; then $ECHO $ECHO "Warning: autoreconf failed but due to what is usually a common libtool" $ECHO "misconfiguration issue. This problem is encountered on systems that" $ECHO "have installed libtoolize under a different name without providing a" $ECHO "symbolic link or without setting the LIBTOOLIZE environment variable." $ECHO $ECHO "Restarting the preparation steps with LIBTOOLIZE set to $LIBTOOLIZE" export LIBTOOLIZE RUN_RECURSIVE=no export RUN_RECURSIVE untrap_abnormal $VERBOSE_ECHO sh $AUTOGEN_SH "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" sh "$AUTOGEN_SH" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" exit $? fi fi $ECHO "Warning: $AUTORECONF failed" if test -f ltmain.sh ; then $ECHO "libtoolize being run by autoreconf is not creating ltmain.sh in the auxillary directory like it should" fi $ECHO "Attempting to run the preparation steps individually" reconfigure_manually=yes fi else reconfigure_manually=yes fi ############################ # LIBTOOL_FAILURE FUNCTION # ############################ libtool_failure ( ) { # libtool is rather error-prone in comparison to the other # autotools and this routine attempts to compensate for some # common failures. the output after a libtoolize failure is # parsed for an error related to AC_PROG_LIBTOOL and if found, we # attempt to inject a project-provided libtool.m4 file. _autoconf_output="$1" if [ "x$RUN_RECURSIVE" = "xno" ] ; then # we already tried the libtool.m4, don't try again return 1 fi if test -f "$LIBTOOL_M4" ; then found_libtool="`$ECHO $_autoconf_output | grep AC_PROG_LIBTOOL`" if test ! "x$found_libtool" = "x" ; then if test -f acinclude.m4 ; then rm -f acinclude.m4.$$.backup $VERBOSE_ECHO "cat acinclude.m4 > acinclude.m4.$$.backup" cat acinclude.m4 > acinclude.m4.$$.backup fi $VERBOSE_ECHO "cat \"$LIBTOOL_M4\" >> acinclude.m4" chmod u+w acinclude.m4 cat "$LIBTOOL_M4" >> acinclude.m4 # don't keep doing this RUN_RECURSIVE=no export RUN_RECURSIVE untrap_abnormal $ECHO $ECHO "Restarting the preparation steps with libtool macros in acinclude.m4" $VERBOSE_ECHO sh $AUTOGEN_SH "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" sh "$AUTOGEN_SH" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" exit $? fi fi } ########################### # MANUAL_AUTOGEN FUNCTION # ########################### manual_autogen ( ) { ################################################## # Manual preparation steps taken are as follows: # # aclocal [-I m4] # # libtoolize --automake -c -f # # aclocal [-I m4] # # autoconf -f # # autoheader # # automake -a -c -f # ################################################## ########### # aclocal # ########### $VERBOSE_ECHO "$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS" aclocal_output="`$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$aclocal_output" if [ ! $ret = 0 ] ; then $ECHO "ERROR: $ACLOCAL failed" && exit 2 ; fi ############## # libtoolize # ############## need_libtoolize=no for feature in AC_PROG_LIBTOOL LT_INIT ; do $VERBOSE_ECHO "Searching for $feature in $CONFIGURE" found="`grep \"^$feature.*\" $CONFIGURE`" if [ ! "x$found" = "x" ] ; then need_libtoolize=yes break fi done if [ "x$need_libtoolize" = "xyes" ] ; then if [ "x$HAVE_LIBTOOLIZE" = "xyes" ] ; then $VERBOSE_ECHO "$LIBTOOLIZE $LIBTOOLIZE_OPTIONS" libtoolize_output="`$LIBTOOLIZE $LIBTOOLIZE_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$libtoolize_output" if [ ! $ret = 0 ] ; then $ECHO "ERROR: $LIBTOOLIZE failed" && exit 2 ; fi else if [ "x$HAVE_ALT_LIBTOOLIZE" = "xyes" ] ; then $VERBOSE_ECHO "$LIBTOOLIZE $ALT_LIBTOOLIZE_OPTIONS" libtoolize_output="`$LIBTOOLIZE $ALT_LIBTOOLIZE_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$libtoolize_output" if [ ! $ret = 0 ] ; then $ECHO "ERROR: $LIBTOOLIZE failed" && exit 2 ; fi fi fi ########### # aclocal # ########### # re-run again as instructed by libtoolize $VERBOSE_ECHO "$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS" aclocal_output="`$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$aclocal_output" # libtoolize might put ltmain.sh in the wrong place if test -f ltmain.sh ; then if test ! -f "${_aux_dir}/ltmain.sh" ; then $ECHO $ECHO "Warning: $LIBTOOLIZE is creating ltmain.sh in the wrong directory" $ECHO $ECHO "Fortunately, the problem can be worked around by simply copying the" $ECHO "file to the appropriate location (${_aux_dir}/). This has been done for you." $ECHO $VERBOSE_ECHO "cp -p ltmain.sh \"${_aux_dir}/ltmain.sh\"" cp -p ltmain.sh "${_aux_dir}/ltmain.sh" $ECHO $ECHO_N "Continuing build preparation ... $ECHO_C" fi fi # ltmain.sh fi # need_libtoolize ############ # autoconf # ############ $VERBOSE_ECHO $VERBOSE_ECHO "$AUTOCONF $AUTOCONF_OPTIONS" autoconf_output="`$AUTOCONF $AUTOCONF_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$autoconf_output" if [ ! $ret = 0 ] ; then # retry without the -f and check for usage of macros that are too new ac2_59_macros="AC_C_RESTRICT AC_INCLUDES_DEFAULT AC_LANG_ASSERT AC_LANG_WERROR AS_SET_CATFILE" ac2_55_macros="AC_COMPILER_IFELSE AC_FUNC_MBRTOWC AC_HEADER_STDBOOL AC_LANG_CONFTEST AC_LANG_SOURCE AC_LANG_PROGRAM AC_LANG_CALL AC_LANG_FUNC_TRY_LINK AC_MSG_FAILURE AC_PREPROC_IFELSE" ac2_54_macros="AC_C_BACKSLASH_A AC_CONFIG_LIBOBJ_DIR AC_GNU_SOURCE AC_PROG_EGREP AC_PROG_FGREP AC_REPLACE_FNMATCH AC_FUNC_FNMATCH_GNU AC_FUNC_REALLOC AC_TYPE_MBSTATE_T" macros_to_search="" ac_major="`echo ${AUTOCONF_VERSION}. | cut -d. -f1 | sed 's/[^0-9]//g'`" ac_minor="`echo ${AUTOCONF_VERSION}. | cut -d. -f2 | sed 's/[^0-9]//g'`" if [ $ac_major -lt 2 ] ; then macros_to_search="$ac2_59_macros $ac2_55_macros $ac2_54_macros" else if [ $ac_minor -lt 54 ] ; then macros_to_search="$ac2_59_macros $ac2_55_macros $ac2_54_macros" elif [ $ac_minor -lt 55 ] ; then macros_to_search="$ac2_59_macros $ac2_55_macros" elif [ $ac_minor -lt 59 ] ; then macros_to_search="$ac2_59_macros" fi fi configure_ac_macros=__none__ for feature in $macros_to_search ; do $VERBOSE_ECHO "Searching for $feature in $CONFIGURE" found="`grep \"^$feature.*\" $CONFIGURE`" if [ ! "x$found" = "x" ] ; then if [ "x$configure_ac_macros" = "x__none__" ] ; then configure_ac_macros="$feature" else configure_ac_macros="$feature $configure_ac_macros" fi fi done if [ ! "x$configure_ac_macros" = "x__none__" ] ; then $ECHO $ECHO "Warning: Unsupported macros were found in $CONFIGURE" $ECHO $ECHO "The `echo $CONFIGURE | basename` file was scanned in order to determine if any" $ECHO "unsupported macros are used that exceed the minimum version" $ECHO "settings specified within this file. As such, the following macros" $ECHO "should be removed from configure.ac or the version numbers in this" $ECHO "file should be increased:" $ECHO $ECHO "$configure_ac_macros" $ECHO $ECHO $ECHO_N "Ignorantly continuing build preparation ... $ECHO_C" fi ################### # autoconf, retry # ################### $VERBOSE_ECHO $VERBOSE_ECHO "$AUTOCONF" autoconf_output="`$AUTOCONF 2>&1`" ret=$? $VERBOSE_ECHO "$autoconf_output" if [ ! $ret = 0 ] ; then # test if libtool is busted libtool_failure "$autoconf_output" # let the user know what went wrong cat <&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/config.h.in COPYING TODO config.guess config.sub \ depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SGUTILS_LIBS = @SGUTILS_LIBS@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ os_deps = @os_deps@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ rt_libs = @rt_libs@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src doc EXTRA_DIST = autogen.sh all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-local \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ distcheck distclean distclean-generic distclean-hdr \ distclean-local distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-am uninstall uninstall-am distclean-local: rm -rf autom4te.cache # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ddpt-0.94/README0000644000175000017500000001436712320426132012263 0ustar douggdouggIntroduction ------------ ddpt is a utility for copying files like its namesake, the Unix dd command. ddpt is specialized for files that are actually block devices. And if those block devices understand SCSI commands then the copy can be done by using either SCSI READ or WRITE commands (or both). This latter facility is done using a pass-through interface that bypasses the normal operating system block handling. This can give very fine-grained control over the copy process. ddpt also supports two forms of offloaded copies, one based on the EXTENDED COPY command introduced in T10's SPC-2 standard. EXTENDED COPY is often abbreviated to XCOPY or xcopy. As new forms of offloaded copy have been added (especially in SPC-4) the original XCOPY is now called XCOPY(LID1) with lot of new feature added to XCOPY(LID4). A subset of XCOPY(LID4) which only supports disk to disk, token based copies, has the market name of ODX. So ddpt supports the original XCOPY(LID1) and uses the term "xcopy" to refer to it. ddpt now also supports ODX and uses the term "odx" to refer to it. ddptctl is a helper/auxiliary for the ddpt utility. ddptctl mainly supplies extra functionality for ODX. This utility was originally written for Linux. It has been ported to FreeBSD and Windows. Relationship to sg3_utils ------------------------- The sg3_utils (version 1.33) package contains several utilities that mimic the standard Unix dd command. Currently those utilities are sg_dd, sgm_dd, sgp_dd and sg_xcopy. Even though most of the other utilities in the sg3_utils package are ported to other operating systems, sg_dd and friends are not ported since they are too tightly bound to Linux and some of the idiosyncrasies of its SCSI generic (sg) and bsg drivers and the associated SG_IO ioctl. So the ddpt utility drops some Linux specific features while adding some more general features (e.g. write sparing). An attempt has also been made to simplify the command line syntax which is still based on the distinctive dd command command line syntax. Note that the dd command line syntax is unlike any other Unix command (probably imported from some IBM OS many years ago). This package shares code with sg3_utils (version 1.38). With the subversion revision control system this is done by having ddpt's "include/" and "lib/" sub-directories pointing to the correspondingly named directories in the sg3_utils package using the "svn:externals" property. These two "external" directories include more files than ddpt uses. The excess files include "lib/Makefile.am" and "lib/Makefile.in". The "Makefile.am" in ddpt's "src/" directory does the main part of the build. When the tarball is generated for this utility, various files are "exported" out of the subversion repository and "svn:externals" redirection is no longer visible (but the unused files are visible). The ddpt executable may or may not be built depending on the libsgutils (shared) library. Currently the ./configure rules are looking for a library called libsgutils2.a or libsgutils2.so . In Debian those libraries are found only in the libsgutils2-dev package, not the libsgutils2 package. If one of those libraries is detected then ddpt will be built depending on libsgutils (check 'ldd ddpt'). If neither of those libraries is detected at build time, then the ddpt executable built will compile and link the relevant code from its "include/" and "lib/" subdirectories. Documentation ------------- The utility outputs a usage message when the "--help" (or '-?') option is given. Many syntax errors also result in the usage message being printed. There is also a man page which is in section 8 (administration and privileged commands). It can be accessed with "man ddpt" once this package is installed. Prior to installation the man page can be viewed from this package's main directory with "man doc/ddpt.8". There is a web page at http://sg.danny.cz/sg/ddpt.html and a copy of that html file is placed in the "doc" directory. Build infrastructure -------------------- This packages uses the automake and autoconf tools. The generating files (scripts) are configure.ac, Makefile.am, doc/Makefile.am, src/Makefile.am and autogen.sh . The autogen.sh script only needs to be executed if one of the other generating files in the above list is changed. There is a rpm "spec" file in the main directory: ddpt.spec . There are Debian build files in the "debian" directory and a script called build_debian.sh in the main directory. Amongst other things debian builds are sensitive to the value in the debian/compat file. If it contains "7" then it works on lenny and gives warning on squeeze (but fails on the earlier etch). The ./configure script supports these extra options: - '--disable-libsgutils' stops the build using the libsgutils library if it is found. Instead the copy of those files found under the include and lib directories is used. - '--disable-linuxbsg' drops Linux bsg driver support. This is only for testing and should no longer be necessary. - '--disable-scsistrings' excludes the asc/ascq and command name strings (defined by SCSI/T10) in an attempt to reduce the size of executables. License ------- This utility is covered by a FreeBSD license also known as the BSD 3-clause license (see Wikipedia). The intention of the author is that both open source and commercial entities can re-use this code. Naturally attribution and improvement/bug feedback are encouraged. Notes ----- Generic information about building this package (i.e. './configure ; make; make install') can be found in the INSTALL file. The contents of COPYING is a FreeBSD license (rather than the GPL v2 found in the usual template). Linux port ---------- The utility can be used on any storage device. To use the "pt" interface the device needs to support the SG_IO ioctl. In the Linux 2.4 series that is only the scsi generic (i.e. /dev/sg* ) device nodes. In the Linux 2.6 and 3 series the supported device nodes have expanded to all other SCSI device nodes (e.g. /dev/sd* and /dev/sr*) plus block devices such as /dev/hdc when the associated device is a DVD drive. The man page and sg.danny.cz/sg/ddpt.html web page examples use Linux device node names. FreeBSD port ------------ See README.freebsd Solaris port ------------ See README.solaris Win32 port ---------- See README.win32 Douglas Gilbert 7th April 2014 ddpt-0.94/README.freebsd0000644000175000017500000000215111532246024013664 0ustar douggdouggDisk devices in FreeBSD have names like '/dev/da0' while the corresponding pass-through devices have names like '/dev/pass0'. See the 'camcontrol devlist' command for a list of available devices (registered with the CAM subsystem) and the mapping between "block" devices names and the corresponding pass-through device name. The usual sequence of "./configure ; make ; make install" can be used to build and install this package. If that fails try the "./autogen.sh" script prior to that sequence. Attempts to copy chunks around 64 KB and larger through the pt interface failed on a FreeBSD 7.0 with an "argument list too long" error message. There is an associated kernel message (viewable with dmesg) that an attempt has been made to map bytes which is greater than DFLTPHYS(65536). Still a problem in FreeBSD 8.1 so restrict default bpt so bpt*ibs is less than or equal to 32 KB since there is pt overhead (over 700 bytes). ddpt can be built into a Debian package for kFreeBSD using the ./build_debian.sh script in the top level directory. This has been tested with Debian 6.0 release. Doug Gilbert 26th February 2011 ddpt-0.94/COPYING0000644000175000017500000000263711527261361012444 0ustar douggdouggCopyright (c) 2008-2011 Douglas Gilbert. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ddpt-0.94/src/0000755000175000017500000000000012320426231012157 5ustar douggdouggddpt-0.94/src/ddpt_com.c0000644000175000017500000017451512320426132014131 0ustar douggdougg/* * Copyright (c) 2013-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This file contains some common functions for ddpt. */ /* Was needed for posix_fadvise() */ /* #define _XOPEN_SOURCE 600 */ /* Need _GNU_SOURCE for O_DIRECT */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #define __STDC_LIMIT_MACROS 1 /* for UINT64_MAX, UINT32_MAX, etc */ #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include /* N.B. config.h must precede anything that depends on HAVE_* */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_NANOSLEEP #include #endif #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) #include #elif defined(HAVE_GETTIMEOFDAY) #include #include #endif #include "ddpt.h" /* includes */ #ifdef SG_LIB_LINUX #include #include #include #include #include /* */ #include /* For tape ioctls */ #ifndef MTWEOFI #define MTWEOFI 35 /* write an end-of-file record (mark) in immediate mode */ #endif #ifdef HAVE_FALLOCATE #include #ifndef FALLOC_FL_KEEP_SIZE #define FALLOC_FL_KEEP_SIZE 0x01 /* from lk 3.1 linux/falloc.h */ #endif #endif #endif /* SG_LIB_LINUX */ #ifdef SG_LIB_FREEBSD #include #include #include #include #endif #ifdef SG_LIB_SOLARIS #include #include #endif #ifdef SG_LIB_WIN32 #ifndef SG_LIB_MINGW /* cygwin */ #include #endif #endif /* end SG_LIB_WIN32 */ #include "sg_lib.h" static const char * errblk_file = "errblk.txt"; /* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of * functions. Returns number number of chars placed in cp excluding the * trailing null char. So for cp_max_len > 0 the return value is always * < cp_max_len; for cp_max_len <= 1 the return value is 0 and no chars * are written to cp. Note this means that when cp_max_len = 1, this * function assumes that cp[0] is the null character and does nothing * (and returns 0). */ static int my_snprintf(char * cp, int cp_max_len, const char * fmt, ...) { va_list args; int n; if (cp_max_len < 2) return 0; va_start(args, fmt); n = vsnprintf(cp, cp_max_len, fmt, args); va_end(args); return (n < cp_max_len) ? n : (cp_max_len - 1); } /* Abbreviation of fprintf(stderr, ...) */ int /* Global function */ pr2serr(const char * fmt, ...) { va_list args; int n; va_start(args, fmt); n = vfprintf(stderr, fmt, args); va_end(args); return n; } void sleep_ms(int millisecs) { #ifdef SG_LIB_WIN32 win32_sleep_ms(millisecs); #elif defined(HAVE_NANOSLEEP) struct timespec request; if (millisecs > 0) { request.tv_sec = millisecs / 1000; request.tv_nsec = (millisecs % 1000) * 1000000; if ((nanosleep(&request, NULL) < 0) && (EINTR != errno)) perror("nanosleep"); } #endif } void state_init(struct opts_t * op, struct flags_t * ifp, struct flags_t * ofp, struct dev_info_t * idip, struct dev_info_t * odip, struct dev_info_t * o2dip) { memset(op, 0, sizeof(struct opts_t)); op->dd_count = -1; op->highest_unrecovered = -1; op->do_time = 1; /* default was 0 in sg_dd */ op->id_usage = -1; op->list_id = 1; op->prio = 1; op->max_uas = MAX_UNIT_ATTENTIONS; op->max_aborted = MAX_ABORTED_CMDS; memset(ifp, 0, sizeof(struct flags_t)); memset(ofp, 0, sizeof(struct flags_t)); op->iflagp = ifp; op->oflagp = ofp; memset(idip, 0, sizeof(struct dev_info_t)); memset(odip, 0, sizeof(struct dev_info_t)); memset(o2dip, 0, sizeof(struct dev_info_t)); idip->d_type = FT_OTHER; idip->fd = -1; odip->d_type = FT_OTHER; odip->fd = -1; o2dip->d_type = FT_OTHER; o2dip->fd = -1; op->idip = idip; op->odip = odip; op->o2dip = o2dip; ifp->cdbsz = DEF_SCSI_CDBSZ; ofp->cdbsz = DEF_SCSI_CDBSZ; #ifdef HAVE_POSIX_FADVISE op->lowest_skip = -1; op->lowest_seek = -1; #endif op->idip->pdt = -1; op->odip->pdt = -1; op->rtf_fd = -1; } /* When who<=0 print both in+out, when who==1 print in, else print out */ void print_stats(const char * str, struct opts_t * op, int who) { #ifdef SG_LIB_LINUX /* Print tape read summary if necessary . */ print_tape_summary(op, 0, str); #endif if ((op->dd_count > 0) && (! op->reading_fifo)) pr2serr(" remaining block count=%" PRId64 "\n", op->dd_count); if (who < 2) pr2serr("%s%" PRId64 "+%d records in\n", str, op->in_full, op->in_partial); if (1 != who) pr2serr("%s%" PRId64 "+%d records out\n", str, op->out_full, op->out_partial); if (op->out_sparse_active || op->out_sparing_active) { if (op->out_trim_active) { const char * cp; cp = op->trim_errs ? "attempted trim" : "trimmed"; if (op->out_sparse_partial > 0) pr2serr("%s%" PRId64 "+%d %s records out\n", str, op->out_sparse, op->out_sparse_partial, cp); else pr2serr("%s%" PRId64 " %s records out\n", str, op->out_sparse, cp); } else if (op->out_sparse_partial > 0) pr2serr("%s%" PRId64 "+%d bypassed records out\n", str, op->out_sparse, op->out_sparse_partial); else pr2serr("%s%" PRId64 " bypassed records out\n", str, op->out_sparse); } if (op->recovered_errs > 0) pr2serr("%s%d recovered read errors\n", str, op->recovered_errs); if (op->num_retries > 0) pr2serr("%s%d retries attempted\n", str, op->num_retries); if (op->unrecovered_errs > 0) pr2serr("%s%d unrecovered read error%s\n", str, op->unrecovered_errs, ((1 == op->unrecovered_errs) ? "" : "s")); if (op->unrecovered_errs && (op->highest_unrecovered >= 0)) pr2serr("lowest unrecovered read lba=%" PRId64 ", highest " "unrecovered lba=%" PRId64 "\n", op->lowest_unrecovered, op->highest_unrecovered); if (op->wr_recovered_errs > 0) pr2serr("%s%d recovered write errors\n", str, op->wr_recovered_errs); if (op->wr_unrecovered_errs > 0) pr2serr("%s%d unrecovered write error%s\n", str, op->wr_unrecovered_errs, ((1 == op->wr_unrecovered_errs) ? "" : "s")); if (op->trim_errs) pr2serr("%s%d trim errors\n", str, op->trim_errs); if (op->interrupted_retries > 0) pr2serr("%s%d %s after interrupted system call(s)\n", str, op->interrupted_retries, ((1 == op->interrupted_retries) ? "retry" : "retries")); if (op->has_xcopy) pr2serr("%s%" PRId64 " xcopy command%s done\n", str, op->num_xcopy, ((1 == op->num_xcopy) ? "" : "s")); } /* Attempt to categorize the file type from the given filename. * Separate version for Windows and Unix. Windows version does some * file name processing. */ #ifndef SG_LIB_WIN32 #ifdef SG_LIB_LINUX static int bsg_major_checked = 0; static int bsg_major = 0; /* In Linux search /proc/devices for bsg character driver in order to * find its major device number since it is allocated dynamically. */ static void find_bsg_major(int verbose) { const char * proc_devices = "/proc/devices"; FILE *fp; char a[128]; char b[128]; char * cp; int n; if (NULL == (fp = fopen(proc_devices, "r"))) { if (verbose) pr2serr("fopen %s failed: %s\n", proc_devices, strerror(errno)); return; } while ((cp = fgets(b, sizeof(b), fp))) { if ((1 == sscanf(b, "%s", a)) && (0 == memcmp(a, "Character", 9))) break; } while (cp && (cp = fgets(b, sizeof(b), fp))) { if (2 == sscanf(b, "%d %s", &n, a)) { if (0 == strcmp("bsg", a)) { bsg_major = n; break; } } else break; } if (verbose > 5) { if (cp) pr2serr("found bsg_major=%d\n", bsg_major); else pr2serr("found no bsg char device in %s\n", proc_devices); } fclose(fp); } #endif /* Categorize file by using the stat() system call on its filename. * If not found FT_ERROR returned. The FT_* constants are a bit mask * and later logic can combine them (e.g. FT_BLOCK | FT_PT). */ static int unix_dd_filetype(const char * filename, int verbose) { struct stat st; size_t len = strlen(filename); if (verbose) { ; } /* suppress warning */ if ((1 == len) && ('.' == filename[0])) return FT_DEV_NULL; if (stat(filename, &st) < 0) return FT_ERROR; if (S_ISREG(st.st_mode)) { // pr2serr("dd_filetype: regular file, st_size=%" PRId64 "\n", // st.st_size); return FT_REG; } else if (S_ISCHR(st.st_mode)) { #ifdef SG_LIB_LINUX /* major() and minor() defined in sys/sysmacros.h */ if ((MEM_MAJOR == major(st.st_rdev)) && (DEV_NULL_MINOR_NUM == minor(st.st_rdev))) return FT_DEV_NULL; if (SCSI_GENERIC_MAJOR == major(st.st_rdev)) return FT_PT; if (SCSI_TAPE_MAJOR == major(st.st_rdev)) return FT_TAPE; if (! bsg_major_checked) { bsg_major_checked = 1; find_bsg_major(verbose); } if (bsg_major == (int)major(st.st_rdev)) return FT_PT; return FT_CHAR; /* assume something like /dev/zero */ #elif SG_LIB_FREEBSD { /* int d_flags; for FIOFTYPE ioctl see sys/filio.h */ char s[STR_SZ]; char * bname; strcpy(s, filename); bname = basename(s); if (0 == strcmp("null", bname)) return FT_DEV_NULL; else if (0 == memcmp("pass", bname, 4)) return FT_PT; else if (0 == memcmp("sa", bname, 2)) return FT_TAPE; else return FT_BLOCK; /* freebsd doesn't have block devices! */ } #elif SG_LIB_SOLARIS /* might be /dev/rdsk or /dev/scsi , require pt override */ return FT_BLOCK; #else return FT_PT; #endif } else if (S_ISBLK(st.st_mode)) return FT_BLOCK; else if (S_ISFIFO(st.st_mode)) return FT_FIFO; return FT_OTHER; } #endif /* if not SG_LIB_WIN32 */ /* Categorize file by using the stat() system call on its filename. * If not found FT_ERROR returned. The FT_* constants are a bit mask * and later logic can combine them (e.g. FT_BLOCK | FT_PT). */ int dd_filetype(const char * filename, int verbose) { #ifdef SG_LIB_WIN32 return win32_dd_filetype(filename, verbose); #else return unix_dd_filetype(filename, verbose); #endif } char * dd_filetype_str(int ft, char * buff, int max_bufflen, const char * fname) { int off = 0; if (FT_DEV_NULL & ft) off += my_snprintf(buff + off, max_bufflen - off, "null device "); if (FT_PT & ft) off += my_snprintf(buff + off, max_bufflen - off, "pass-through [pt] device "); if (FT_TAPE & ft) off += my_snprintf(buff + off, max_bufflen - off, "SCSI tape device "); if (FT_BLOCK & ft) off += my_snprintf(buff + off, max_bufflen - off, "block device "); if (FT_FIFO & ft) off += my_snprintf(buff + off, max_bufflen - off, "fifo [stdin, stdout, named pipe] "); if (FT_REG & ft) off += my_snprintf(buff + off, max_bufflen - off, "regular file "); if (FT_CHAR & ft) off += my_snprintf(buff + off, max_bufflen - off, "char device "); if (FT_OTHER & ft) off += my_snprintf(buff + off, max_bufflen - off, "other file type "); if (FT_ERROR & ft) off += my_snprintf(buff + off, max_bufflen - off, "unable to 'stat' %s ", (fname ? fname : "file")); return buff; } #ifdef SG_LIB_LINUX static int lin_get_blkdev_capacity(struct opts_t * op, int which_arg, int64_t * num_blks, int * blk_sz) { int blk_fd; const char * fname; blk_fd = (DDPT_ARG_IN == which_arg) ? op->idip->fd : op->odip->fd; fname = (DDPT_ARG_IN == which_arg) ? op->idip->fn : op->odip->fn; if (op->verbose > 2) pr2serr("lin_get_blkdev_capacity: for %s\n", fname); /* BLKGETSIZE64, BLKGETSIZE and BLKSSZGET macros problematic (from * or ). */ #ifdef BLKSSZGET if ((ioctl(blk_fd, BLKSSZGET, blk_sz) < 0) && (*blk_sz > 0)) { perror("BLKSSZGET ioctl error"); return -1; } else { #ifdef BLKGETSIZE64 uint64_t ull; if (ioctl(blk_fd, BLKGETSIZE64, &ull) < 0) { perror("BLKGETSIZE64 ioctl error"); return -1; } *num_blks = ((int64_t)ull / (int64_t)*blk_sz); if (op->verbose > 5) pr2serr("Used Linux BLKGETSIZE64 ioctl\n"); #else unsigned long ul; if (ioctl(blk_fd, BLKGETSIZE, &ul) < 0) { perror("BLKGETSIZE ioctl error"); return -1; } *num_blks = (int64_t)ul; if (op->verbose > 5) pr2serr("Used Linux BLKGETSIZE ioctl\n"); #endif } return 0; #else /* not BLKSSZGET */ blk_fd = blk_fd; if (op->verbose) pr2serr(" BLKSSZGET+BLKGETSIZE ioctl not available\n"); *num_blks = 0; *blk_sz = 0; return -1; #endif } #endif /* BLKSSZGET */ #ifdef SG_LIB_FREEBSD static int fbsd_get_blkdev_capacity(struct opts_t * op, int which_arg, int64_t * num_blks, int * blk_sz) { // Why do kernels invent their own typedefs and not use C standards? #define u_int unsigned int off_t mediasize; unsigned int sectorsize; int blk_fd; const char * fname; blk_fd = (DDPT_ARG_IN == which_arg) ? op->idip->fd : op->odip->fd; fname = (DDPT_ARG_IN == which_arg) ? op->idip->fn : op->odip->fn; if (op->verbose > 2) pr2serr("fbsd_get_blkdev_capacity: for %s\n", fname); /* For FreeBSD post suggests that /usr/sbin/diskinfo uses * ioctl(fd, DIOCGMEDIASIZE, &mediasize), where mediasize is an off_t. * also: ioctl(fd, DIOCGSECTORSIZE, §orsize) */ if (ioctl(blk_fd, DIOCGSECTORSIZE, §orsize) < 0) { perror("DIOCGSECTORSIZE ioctl error"); return -1; } *blk_sz = sectorsize; if (ioctl(blk_fd, DIOCGMEDIASIZE, &mediasize) < 0) { perror("DIOCGMEDIASIZE ioctl error"); return -1; } if (sectorsize) *num_blks = mediasize / sectorsize; else *num_blks = 0; return 0; } #endif #ifdef SG_LIB_SOLARIS static int sol_get_blkdev_capacity(struct opts_t * op, int which_arg, int64_t * num_blks, int * blk_sz) { struct dk_minfo info; int blk_fd; const char * fname; blk_fd = (DDPT_ARG_IN == which_arg) ? op->idip->fd : op->odip->fd; fname = (DDPT_ARG_IN == which_arg) ? op->idip->fn : op->odip->fn; if (op->verbose > 2) pr2serr("sol_get_blkdev_capacity: for %s\n", fname); /* this works on "char" block devs (e.g. in /dev/rdsk) but not /dev/dsk */ if (ioctl(blk_fd, DKIOCGMEDIAINFO , &info) < 0) { perror("DKIOCGMEDIAINFO ioctl error"); *num_blks = 0; *blk_sz = 0; return -1; } *num_blks = info.dki_capacity; *blk_sz = info.dki_lbsize; return 0; } #endif /* get_blkdev_capacity() returns 0 -> success or -1 -> failure. * which_arg should either be DDPT_ARG_IN, DDPT_ARG_OUT or DDPT_ARG_OUT2. * If successful writes back logical block size using the blk_sz pointer. * Also writes back the number of logical blocks) on the block device using * num_blks pointer. */ int get_blkdev_capacity(struct opts_t * op, int which_arg, int64_t * num_blks, int * blk_sz) { #ifdef SG_LIB_LINUX return lin_get_blkdev_capacity(op, which_arg, num_blks, blk_sz); #elif defined(SG_LIB_FREEBSD) return fbsd_get_blkdev_capacity(op, which_arg, num_blks, blk_sz); #elif defined(SG_LIB_SOLARIS) return sol_get_blkdev_capacity(op, which_arg, num_blks, blk_sz); #elif defined(SG_LIB_WIN32) return win32_get_blkdev_capacity(op, which_arg, num_blks, blk_sz); #else return -1; #endif } void zero_coe_limit_count(struct opts_t * op) { if (op->coe_limit > 0) op->coe_count = 0; } /* Print number of blocks, block size. If over 1 MB print size in MB * (10**6 bytes), GB (10**9 bytes) or TB (10**12 bytes) to stderr. */ void print_blk_sizes(const char * fname, const char * access_typ, int64_t num_blks, int blk_sz, int to_stderr) { int mb, gb, tb; size_t len; int64_t n = 0; char b[32]; char dec[4]; int (*print_p)(const char *, ...); print_p = to_stderr ? pr2serr : printf; if (num_blks <= 0) { print_p(" %s [%s]: num_blocks=%" PRId64 ", block_size=%d\n", fname, access_typ, num_blks, blk_sz); return; } gb = 0; if ((num_blks > 0) && (blk_sz > 0)) { n = num_blks * blk_sz; gb = n / 1000000000; } if (gb > 999999) { tb = gb / 1000; snprintf(b, sizeof(b), "%d", tb); len = strlen(b); // len must be >= 4 dec[0] = b[len - 3]; dec[1] = b[len - 2]; dec[2] = '\0'; b[len - 3] = '\0'; print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d, %s.%s PB\n", fname, access_typ, num_blks, num_blks, blk_sz, b, dec); } else if (gb > 99999) { tb = gb / 1000; print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d, %d TB\n", fname, access_typ, num_blks, num_blks, blk_sz, tb); } else { mb = n / 1000000; if (mb > 999999) { gb = mb / 1000; snprintf(b, sizeof(b), "%d", gb); len = strlen(b); // len must be >= 4 dec[0] = b[len - 3]; dec[1] = b[len - 2]; dec[2] = '\0'; b[len - 3] = '\0'; print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d, %s.%s TB\n", fname, access_typ, num_blks, num_blks, blk_sz, b, dec); } else if (mb > 99999) { gb = mb / 1000; print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d, %d GB\n", fname, access_typ, num_blks, num_blks, blk_sz, gb); } else if (mb > 999) { snprintf(b, sizeof(b), "%d", mb); len = strlen(b); // len must be >= 4 dec[0] = b[len - 3]; dec[1] = b[len - 2]; dec[2] = '\0'; b[len - 3] = '\0'; print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d, %s.%s GB\n", fname, access_typ, num_blks, num_blks, blk_sz, b, dec); } else if (mb > 0) { print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d, %d MB%s\n", fname, access_typ, num_blks, num_blks, blk_sz, mb, ((mb < 10) ? " approx" : "")); } else print_p(" %s [%s]: num_blocks=%" PRId64 " [0x%" PRIx64 "], " "block_size=%d\n", fname, access_typ, num_blks, num_blks, blk_sz); } } void calc_duration_init(struct opts_t * op) { #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) if (op->do_time) { op->start_tm.tv_sec = 0; op->start_tm.tv_nsec = 0; if (0 == clock_gettime(CLOCK_MONOTONIC, &op->start_tm)) op->start_tm_valid = 1; } #elif defined(HAVE_GETTIMEOFDAY) if (op->do_time) { op->start_tm.tv_sec = 0; op->start_tm.tv_usec = 0; gettimeofday(&op->start_tm, NULL); op->start_tm_valid = 1; } #else if (op) { ; } #endif } /* Calculates transfer throughput, typically in Megabytes per second. * A megabyte in this context is 1000000 bytes (gives bigger numbers so * is preferred by industry). The clock_gettime() interface is preferred * since time is guaranteed to advance; gettimeofday() is impacted if the * user (or something like ntpd) changes the time. * Also if the transfer is large enough and isn't about to finish, it * makes an estimate of the time remaining. */ void calc_duration_throughput(const char * leadin, int contin, struct opts_t * op) { #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) struct timespec end_tm, res_tm; double a, b, r; int secs, h, m, use_out_full; if (op->start_tm_valid && (op->start_tm.tv_sec || op->start_tm.tv_nsec)) { use_out_full = ((0 == op->in_full) && (op->obs > 0)); clock_gettime(CLOCK_MONOTONIC, &end_tm); res_tm.tv_sec = end_tm.tv_sec - op->start_tm.tv_sec; res_tm.tv_nsec = end_tm.tv_nsec - op->start_tm.tv_nsec; if (res_tm.tv_nsec < 0) { --res_tm.tv_sec; res_tm.tv_nsec += 1000000000; } a = res_tm.tv_sec; a += (0.000001 * (res_tm.tv_nsec / 1000)); if (use_out_full) b = (double)op->obs * op->out_full; else b = (double)op->ibs_hold * op->in_full; pr2serr("%stime to %s data%s: %d.%06d secs", leadin, (op->read1_or_transfer ? "read" : "transfer"), (contin ? " so far" : ""), (int)res_tm.tv_sec, (int)(res_tm.tv_nsec / 1000)); r = 0.0; if ((a > 0.00001) && (b > 511)) { r = b / (a * 1000000.0); if (r < 1.0) pr2serr(" at %.1f KB/sec\n", r * 1000); else pr2serr(" at %.2f MB/sec\n", r); } else pr2serr("\n"); if (contin && (! op->reading_fifo) && (r > 0.01) && (op->dd_count > 100)) { secs = (int)(((double)op->ibs_hold * op->dd_count) / (r * 1000000)); if (secs > 10) { h = secs / 3600; secs = secs - (h * 3600); m = secs / 60; secs = secs - (m * 60); if (h > 0) pr2serr("%sestimated time remaining: %d:%02d:%02d\n", leadin, h, m, secs); else pr2serr("%sestimated time remaining: %d:%02d\n", leadin, m, secs); } } } #elif defined(HAVE_GETTIMEOFDAY) struct timeval end_tm, res_tm; double a, b, r; int secs, h, m; int64_t blks; if (op->start_tm_valid && (op->start_tm.tv_sec || op->start_tm.tv_usec)) { blks = op->in_full; gettimeofday(&end_tm, NULL); res_tm.tv_sec = end_tm.tv_sec - op->start_tm.tv_sec; res_tm.tv_usec = end_tm.tv_usec - op->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)op->ibs_hold * blks; pr2serr("%stime to %s data%s: %d.%06d secs", leadin, (op->read1_or_transfer ? "read" : "transfer"), (contin ? " so far" : ""), (int)res_tm.tv_sec, (int)res_tm.tv_usec); r = 0.0; if ((a > 0.00001) && (b > 511)) { r = b / (a * 1000000.0); if (r < 1.0) pr2serr(" at %.1f KB/sec\n", r * 1000); else pr2serr(" at %.2f MB/sec\n", r); } else pr2serr("\n"); if (contin && (! op->reading_fifo) && (r > 0.01) && (op->dd_count > 100)) { secs = (int)(((double)op->ibs_hold * op->dd_count) / (r * 1000000)); if (secs > 10) { h = secs / 3600; secs = secs - (h * 3600); m = secs / 60; secs = secs - (m * 60); if (h > 0) pr2serr("%sestimated time remaining: " "%d:%02d:%02d\n", leadin, h, m, secs); else pr2serr("%sestimated time remaining: " "%d:%02d\n", leadin, m, secs); } } } #else /* no clock reading functions available */ if (leadin) { ; } // suppress warning if (contin) { ; } // suppress warning #endif } /* Create errblk file (see iflag=errblk) and if we have gettimeofday * puts are start timestampl on the first line. */ void errblk_open(struct opts_t * op) { op->errblk_fp = fopen(errblk_file, "a"); /* append */ if (NULL == op->errblk_fp) pr2serr("unable to open or create %s\n", errblk_file); else { #ifdef HAVE_GETTIMEOFDAY { time_t t; char b[64]; t = time(NULL); strftime(b, sizeof(b), "# start: %Y-%m-%d %H:%M:%S\n", localtime(&t)); fputs(b, op->errblk_fp); } #else fputs("# start\n", op->errblk_fp); #endif } } void /* Global function, used by ddpt_pt.c */ errblk_put(uint64_t lba, struct opts_t * op) { if (op->errblk_fp) fprintf(op->errblk_fp, "0x%" PRIx64 "\n", lba); } void /* Global function, used by ddpt_pt.c */ errblk_put_range(uint64_t lba, int num, struct opts_t * op) { if (op->errblk_fp) { if (1 == num) errblk_put(lba, op); else if (num > 1) fprintf(op->errblk_fp, "0x%" PRIx64 "-0x%" PRIx64 "\n", lba, lba + (num - 1)); } } void errblk_close(struct opts_t * op) { if (op->errblk_fp) { #ifdef HAVE_GETTIMEOFDAY { time_t t; char b[64]; t = time(NULL); strftime(b, sizeof(b), "# stop: %Y-%m-%d %H:%M:%S\n", localtime(&t)); fputs(b, op->errblk_fp); } #else fputs("# stop\n", op->errblk_fp); #endif fclose(op->errblk_fp); op->errblk_fp = NULL; } } #ifdef SG_LIB_LINUX /* Summarise previous consecutive same-length reads. Do that when: * - read length (res) differs from the previous read length, and * - there were more than one consecutive reads of the same length * The str argument is a prefix string, typically one or two spaces, used * to e.g. make output line up when printing on kill -USR1. */ void print_tape_summary(struct opts_t * op, int res, const char * str) { int len = op->last_tape_read_len; int num = op->read_tape_numbytes; if ((op->verbose > 1) && (res != len) && (op->consec_same_len_reads >= 1)) pr2serr("%s(%d%s read%s of %d byte%s)\n", str, op->consec_same_len_reads, (len < num) ? " short" : "", (op->consec_same_len_reads != 1) ? "s" : "", len, (len != 1) ? "s" : ""); } static void show_tape_pos_error(const char * postfix) { pr2serr("Could not get tape position%s: %s\n", postfix, safe_strerror(errno)); } /* Print tape position(s) if verbose > 1. If both reading from and writing to * tape, make clear in output which is which. Also only print the position if * necessary, i.e. not already printed. * Prefix argument is e.g. "Initial " or "Final ". */ void print_tape_pos(const char * prefix, const char * postfix, struct opts_t * op) { static int lastreadpos, lastwritepos; static char lastreadposvalid = 0; static char lastwriteposvalid = 0; int res; struct mtpos pos; if (op->verbose > 1) { if (FT_TAPE & op->idip->d_type) { res = ioctl(op->idip->fd, MTIOCPOS, &pos); if (0 == res) { if ((pos.mt_blkno != lastreadpos) || (0 == lastreadposvalid)) { lastreadpos = pos.mt_blkno; lastreadposvalid = 1; pr2serr("%stape position%s: %u%s\n", prefix, (FT_TAPE & op->odip->d_type) ? " (reading)" : "", lastreadpos, postfix); } } else { lastreadposvalid = 0; show_tape_pos_error((FT_TAPE & op->odip->d_type) ? " (reading)" : ""); } } if (FT_TAPE & op->odip->d_type) { res = ioctl(op->odip->fd, MTIOCPOS, &pos); if (0 == res) { if ((pos.mt_blkno != lastwritepos) || (0 == lastwriteposvalid)) { lastwritepos = pos.mt_blkno; lastwriteposvalid = 1; pr2serr("%stape position%s: %u%s\n", prefix, (FT_TAPE & op->idip->d_type) ? " (writing)" : "", lastwritepos, postfix); } } else { lastwriteposvalid = 0; show_tape_pos_error((FT_TAPE & op->idip->d_type) ? " (writing)" : ""); } } } } #endif /* SG_LIB_LINUX */ /* The use of signals is borrowed from GNU's dd source code which is * found in their coreutils package. If SA_NOCLDSTOP is non-zero then * a modern Posix compliant version of signals is assumed. Still * thinking about SIGHUP which will be delivered if the controlling * process/terminal is terminated or receives SIGHUP. */ /* If nonzero, the value of the pending fatal signal. */ static sig_atomic_t volatile interrupt_signal; /* A count of pending info(usr1) signals, decremented as processed */ static sig_atomic_t volatile info_signals_pending; static struct val_str_t signum_name_arr[] = { {SIGINT, "SIGINT"}, {SIGQUIT, "SIGQUIT"}, {SIGPIPE, "SIGPIPE"}, #if SIGINFO == SIGUSR1 {SIGUSR1, "SIGUSR1"}, #else {SIGINFO, "SIGINFO"}, #endif #ifndef SG_LIB_WIN32 {SIGHUP, "SIGHUP"}, #endif {0, NULL}, }; /* Return signal name for signum if known, else return signum as a string. */ static const char * get_signal_name(int signum, char * b, int blen) { const struct val_str_t * sp; for (sp = signum_name_arr; sp->num; ++sp) { if (signum == sp->num) break; } if (blen < 1) return b; b[blen - 1] = '\0'; if (sp->num) strncpy(b, sp->name, blen - 1); else snprintf(b, blen, "%d", signum); return b; } /* An ordinary signal was received; arrange for the program to exit. */ static void interrupt_handler(int sig) { if (! SA_RESETHAND) signal(sig, SIG_DFL); interrupt_signal = sig; } /* An info signal was received; arrange for the program to print status. */ static void siginfo_handler(int sig) { if (! SA_NOCLDSTOP) signal(sig, siginfo_handler); ++info_signals_pending; } /* Install the signal handlers. We try to cope gracefully with signals whose * disposition is 'ignored'. SUSv3 recommends that a process should start * with no blocked signals; if needed unblock SIGINFO, SIGINT or SIGPIPE. */ void install_signal_handlers(struct opts_t * op) { #if SIGINFO == SIGUSR1 const char * sname = "SIGUSR1"; #else const char * sname = "SIGINFO"; #endif if (op->verbose > 2) pr2serr(" >> %s signal implementation assumed " "[SA_NOCLDSTOP=%d], %smasking during IO\n", (SA_NOCLDSTOP ? "modern" : "old"), SA_NOCLDSTOP, (op->interrupt_io ? "not " : "")); #if SA_NOCLDSTOP struct sigaction act; sigset_t starting_mask; int num_members = 0; int unblock_starting_mask = 0; sigemptyset(&op->caught_signals); sigemptyset(&op->orig_mask); sigaction(SIGINFO, NULL, &act); if (act.sa_handler != SIG_IGN) sigaddset(&op->caught_signals, SIGINFO); else if (op->verbose) pr2serr("%s ignored, progress reports not available\n", sname); sigaction(SIGINT, NULL, &act); if (act.sa_handler != SIG_IGN) sigaddset(&op->caught_signals, SIGINT); else if (op->verbose) pr2serr("SIGINT ignored\n"); sigaction(SIGPIPE, NULL, &act); if (act.sa_handler != SIG_IGN) sigaddset(&op->caught_signals, SIGPIPE); else if (op->verbose) pr2serr("SIGPIPE ignored\n"); sigprocmask(SIG_UNBLOCK /* ignored */, NULL, &starting_mask); if (sigismember(&starting_mask, SIGINFO)) { if (op->verbose) pr2serr("%s blocked on entry, unblock\n", sname); ++unblock_starting_mask; } if (sigismember(&starting_mask, SIGINT)) { if (op->verbose) pr2serr("SIGINT blocked on entry, unblock\n"); ++unblock_starting_mask; } if (sigismember(&starting_mask, SIGPIPE)) { if (op->verbose) pr2serr("SIGPIPE blocked on entry, unblock\n"); ++unblock_starting_mask; } act.sa_mask = op->caught_signals; if (sigismember(&op->caught_signals, SIGINFO)) { act.sa_handler = siginfo_handler; act.sa_flags = 0; sigaction(SIGINFO, &act, NULL); ++num_members; } if (sigismember(&op->caught_signals, SIGINT)) { act.sa_handler = interrupt_handler; act.sa_flags = SA_NODEFER | SA_RESETHAND; sigaction(SIGINT, &act, NULL); ++num_members; } if (sigismember(&op->caught_signals, SIGPIPE)) { act.sa_handler = interrupt_handler; act.sa_flags = SA_NODEFER | SA_RESETHAND; sigaction(SIGPIPE, &act, NULL); ++num_members; } if (unblock_starting_mask) sigprocmask(SIG_UNBLOCK, &op->caught_signals, NULL); if ((0 == op->interrupt_io) && (num_members > 0)) sigprocmask(SIG_BLOCK, &op->caught_signals, &op->orig_mask); #else /* not SA_NOCLDSTOP */ if (op) { ; } /* suppress warning */ if (signal(SIGINFO, SIG_IGN) != SIG_IGN) { signal(SIGINFO, siginfo_handler); siginterrupt(SIGINFO, 1); } else if (op->verbose) pr2serr("old %s ignored, progress report not available\n", sname); if (signal(SIGINT, SIG_IGN) != SIG_IGN) { signal(SIGINT, interrupt_handler); siginterrupt(SIGINT, 1); } else if (op->verbose) pr2serr("old SIGINT ignored\n"); #endif /* SA_NOCLDSTOP */ } /* Process any pending signals and perhaps do delay. If signals are caught, * this function should be called periodically. Ideally there should never * be an unbounded amount of time when signals are not being processed. */ void /* Global function, used by ddpt_xcopy.c */ signals_process_delay(struct opts_t * op, int delay_type) { char b[32]; int got_something = 0; int delay = 0; #if SA_NOCLDSTOP int found_pending = 0; if ((0 == op->interrupt_io) && (sigismember(&op->caught_signals, SIGINT) || sigismember(&op->caught_signals, SIGPIPE) || sigismember(&op->caught_signals, SIGINFO))) { sigset_t pending_set; sigpending(&pending_set); if (sigismember(&pending_set, SIGINT) || sigismember(&pending_set, SIGPIPE) || sigismember(&pending_set, SIGINFO)) { /* Signal handler for a pending signal run during suspend */ sigsuspend(&op->orig_mask); found_pending = 1; } else { /* nothing pending so perhaps delay */ if ((op->delay > 0) && (DELAY_COPY_SEGMENT == delay_type)) delay = op->delay; else if ((op->wdelay > 0) && (DELAY_WRITE == delay_type)) { if (op->subsequent_wdelay) delay = op->wdelay; else op->subsequent_wdelay = 1; } if (delay) { sigprocmask(SIG_SETMASK, &op->orig_mask, NULL); if (op->verbose > 3) pr2serr("delay=%d milliseconds [%s]\n", delay, ((DELAY_WRITE == delay_type) ? "write" : "copy")); sleep_ms(delay); sigprocmask(SIG_BLOCK, &op->caught_signals, NULL); } if (! (interrupt_signal || info_signals_pending)) return; } } #endif while (interrupt_signal || info_signals_pending) { int interrupt; int infos; got_something = 1; #if SA_NOCLDSTOP if (! found_pending) sigprocmask(SIG_BLOCK, &op->caught_signals, NULL); #endif /* Reload interrupt_signal and info_signals_pending, in case a new signal was handled before sigprocmask took effect. */ interrupt = interrupt_signal; infos = info_signals_pending; if (infos) info_signals_pending = infos - 1; #if SA_NOCLDSTOP if (! found_pending) sigprocmask(SIG_SETMASK, &op->orig_mask, NULL); #endif if (interrupt) { pr2serr("Interrupted by signal %s\n", get_signal_name(interrupt, b, sizeof(b))); print_stats("", op, 0); /* Don't show next message if using oflag=pre-alloc and we didn't * use FALLOC_FL_KEEP_SIZE */ if ((0 == op->reading_fifo) && (FT_REG & op->odip->d_type_hold) && (0 == op->oflagp->prealloc)) pr2serr("To resume, invoke with same arguments plus " "oflag=resume\n"); ; // >>>>>>>>>>>>> cleanup (); } else { pr2serr("Progress report:\n"); print_stats(" ", op, 0); if (op->do_time) calc_duration_throughput(" ", 1, op); pr2serr(" continuing ...\n"); } if (interrupt) { #if SA_NOCLDSTOP if (found_pending) { sigset_t int_set; sigemptyset(&int_set); sigaddset(&int_set, interrupt); sigprocmask(SIG_UNBLOCK, &int_set, NULL); } #endif raise(interrupt); } } if (! got_something) { delay = 0; if ((op->delay > 0) && (DELAY_COPY_SEGMENT == delay_type)) delay = op->delay; else if ((op->wdelay > 0) && (DELAY_WRITE == delay_type)) { if (op->subsequent_wdelay) delay = op->wdelay; else op->subsequent_wdelay = 1; } if (delay) sleep_ms(op->delay); } } static const char * assoc_arr[] = { "addressed logical unit", "target port", /* that received request; unless SCSI ports VPD */ "target device that contains addressed lu", "reserved [0x3]", }; static const char * code_set_arr[] = { "Reserved [0x0]", "Binary", "ASCII", "UTF-8", "[0x4]", "[0x5]", "[0x6]", "[0x7]", "[0x8]", "[0x9]", "[0xa]", "[0xb]", "[0xc]", "[0xd]", "[0xe]", "[0xf]", }; static const char * desig_type_arr[] = { "vendor specific [0x0]", /* SCSI_IDENT_DEVICE_VENDOR */ "T10 vendor identification", /* SCSI_IDENT_DEVICE_T10 */ "EUI-64 based", /* SCSI_IDENT_DEVICE_EUI64 */ "NAA", /* SCSI_IDENT_DEVICE_NAA */ "Relative target port", /* SCSI_IDENT_PORT_RELATIVE */ "Target port group", /* SCSI_IDENT_PORT_TP_GROUP */ "Logical unit group", /* SCSI_IDENT_PORT_LU_GROUP */ "MD5 logical unit identifier", /* SCSI_IDENT_DEVICE_MD5 */ "SCSI name string", /* SCSI_IDENT_DEVICE_SCSINAME */ "Protocol specific port identifier", /* spc4r36 */ "[0xa]", "[0xb]", "[0xc]", "[0xd]", "[0xe]", "[0xf]", }; void decode_designation_descriptor(const unsigned char * ucp, int len_less_4, int to_stderr, int verb) { int m, p_id, piv, c_set, assoc, desig_type, d_id, naa, i_len; int k; const unsigned char * ip; uint64_t vsei; char b[80]; int (*print_p)(const char *, ...); void (*dStrHexp)(const char *, int, int); print_p = to_stderr ? pr2serr : printf; dStrHexp = to_stderr ? dStrHexErr : dStrHex; ip = ucp + 4; i_len = len_less_4; /* valid ucp length is (len_less_4 + 4) */ p_id = ((ucp[0] >> 4) & 0xf); c_set = (ucp[0] & 0xf); piv = ((ucp[1] & 0x80) ? 1 : 0); assoc = ((ucp[1] >> 4) & 0x3); desig_type = (ucp[1] & 0xf); print_p(" designator_type: %s, code_set: %s\n", desig_type_arr[desig_type], code_set_arr[c_set]); print_p(" associated with the %s\n", assoc_arr[assoc]); if (piv && ((1 == assoc) || (2 == assoc))) print_p(" transport: %s\n", sg_get_trans_proto_str(p_id, sizeof(b), b)); switch (desig_type) { case 0: /* vendor specific */ k = 0; if ((1 == c_set) || (2 == c_set)) { /* ASCII or UTF-8 */ for (k = 0; (k < i_len) && isprint(ip[k]); ++k) ; if (k >= i_len) k = 1; } if (k) print_p(" vendor specific: %.*s\n", i_len, ip); else { print_p(" vendor specific:\n"); dStrHexp((const char *)ip, i_len, -1); } break; case 1: /* T10 vendor identification */ print_p(" vendor id: %.8s\n", ip); if (i_len > 8) print_p(" vendor specific: %.*s\n", i_len - 8, ip + 8); break; case 2: /* EUI-64 based */ if ((8 != i_len) && (12 != i_len) && (16 != i_len)) { print_p(" << expect 8, 12 and 16 byte EUI, got %d>>\n", i_len); dStrHexp((const char *)ip, i_len, 0); break; } print_p(" 0x"); for (m = 0; m < i_len; ++m) print_p("%02x", (unsigned int)ip[m]); print_p("\n"); break; case 3: /* NAA */ naa = (ip[0] >> 4) & 0xff; if (1 != c_set) { print_p(" << expected binary code set (1), got %d for " "NAA=%d>>\n", c_set, naa); dStrHexp((const char *)ip, i_len, -1); break; } if ((5 == naa) && (0x10 == i_len)) { if (verb > 2) print_p(" << unexpected NAA 5 len 16, assuming NAA 6 " ">>\n"); naa = 6; } switch (naa) { case 2: /* NAA: IEEE extended */ if (8 != i_len) { print_p(" << unexpected NAA 2 identifier length: " "0x%x>>\n", i_len); dStrHexp((const char *)ip, i_len, -1); break; } d_id = (((ip[0] & 0xf) << 8) | ip[1]); /* c_id = ((ip[2] << 16) | (ip[3] << 8) | ip[4]); */ /* vsi = ((ip[5] << 16) | (ip[6] << 8) | ip[7]); */ print_p(" 0x"); for (m = 0; m < 8; ++m) print_p("%02x", (unsigned int)ip[m]); print_p("\n"); break; case 3: /* NAA: Locally assigned */ case 5: /* NAA: IEEE Registered */ if (8 != i_len) { print_p(" << unexpected NAA 5 identifier length: " "0x%x>>\n", i_len); dStrHexp((const char *)ip, i_len, -1); break; } /* c_id = (((ip[0] & 0xf) << 20) | (ip[1] << 12) | */ /* (ip[2] << 4) | ((ip[3] & 0xf0) >> 4)); */ vsei = ip[3] & 0xf; for (m = 1; m < 5; ++m) { vsei <<= 8; vsei |= ip[3 + m]; } print_p(" 0x"); for (m = 0; m < 8; ++m) print_p("%02x", (unsigned int)ip[m]); print_p("\n"); break; case 6: /* NAA IEEE registered extended */ if (16 != i_len) { print_p(" << unexpected NAA 6 identifier length: " "0x%x>>\n", i_len); dStrHexp((const char *)ip, i_len, -1); break; } /* c_id = (((ip[0] & 0xf) << 20) | (ip[1] << 12) | */ /* (ip[2] << 4) | ((ip[3] & 0xf0) >> 4)); */ vsei = ip[3] & 0xf; for (m = 1; m < 5; ++m) { vsei <<= 8; vsei |= ip[3 + m]; } print_p(" 0x"); for (m = 0; m < 16; ++m) print_p("%02x", (unsigned int)ip[m]); print_p("\n"); break; default: print_p(" << expected NAA nibble of 2, 3, 5 or 6, got " "%d>>\n", naa); dStrHexp((const char *)ip, i_len, -1); break; } break; case 4: /* Relative target port */ if ((1 != c_set) || (1 != assoc) || (4 != i_len)) { print_p(" << expected binary code_set, target port " "association, length 4>>\n"); dStrHexp((const char *)ip, i_len, 0); break; } d_id = ((ip[2] << 8) | ip[3]); print_p(" Relative target port: 0x%x\n", d_id); break; case 5: /* (primary) Target port group */ if ((1 != c_set) || (1 != assoc) || (4 != i_len)) { print_p(" << expected binary code_set, target port " "association, length 4>>\n"); dStrHexp((const char *)ip, i_len, 0); break; } d_id = ((ip[2] << 8) | ip[3]); print_p(" Target port group: 0x%x\n", d_id); break; case 6: /* Logical unit group */ if ((1 != c_set) || (0 != assoc) || (4 != i_len)) { print_p(" << expected binary code_set, logical unit " "association, length 4>>\n"); dStrHexp((const char *)ip, i_len, 0); break; } d_id = ((ip[2] << 8) | ip[3]); print_p(" Logical unit group: 0x%x\n", d_id); break; case 7: /* MD5 logical unit identifier */ if ((1 != c_set) || (0 != assoc)) { print_p(" << expected binary code_set, logical unit " "association>>\n"); dStrHexp((const char *)ip, i_len, 0); break; } print_p(" MD5 logical unit identifier:\n"); dStrHexp((const char *)ip, i_len, 0); break; case 8: /* SCSI name string */ if (3 != c_set) { print_p(" << expected UTF-8 code_set>>\n"); dStrHexp((const char *)ip, i_len, 0); break; } print_p(" SCSI name string:\n"); /* does %s print out UTF-8 ok?? * Seems to depend on the locale. Looks ok here with my * locale setting: en_AU.UTF-8 */ print_p(" %s\n", (const char *)ip); break; case 9: /* Protocol specific port identifier */ /* added in spc4r36, PIV must be set, proto_id indicates */ /* whether UAS (USB) or SOP (PCIe) or ... */ if (! piv) print_p(" >>>> Protocol specific port identifier " "expects protocol\n" " identifier to be valid and it is not\n"); if (TPROTO_UAS == p_id) { print_p(" USB device address: 0x%x\n", 0x7f & ip[0]); print_p(" USB interface number: 0x%x\n", ip[2]); } else if (TPROTO_SOP == p_id) { print_p(" PCIe routing ID, bus number: 0x%x\n", ip[0]); print_p(" function number: 0x%x\n", ip[1]); print_p(" [or device number: 0x%x, function number: " "0x%x]\n", (0x1f & (ip[1] >> 3)), 0x7 & ip[1]); } else print_p(" >>>> unexpected protocol indentifier: 0x%x\n" " with Protocol specific port " "identifier\n", p_id); break; default: /* reserved */ print_p(" reserved designator=0x%x\n", desig_type); dStrHexp((const char *)ip, i_len, 0); break; } } /* Helper for case when EIO or EREMOTE errno suggests the equivalent * of a medium error. Returns 0 unless coe_limit exceeded. */ int /* Global function, used by ddpt_win32.c */ coe_process_eio(struct opts_t * op, int64_t skip) { if ((op->coe_limit > 0) && (++op->coe_count > op->coe_limit)) { pr2serr(">> coe_limit on consecutive reads " "exceeded\n"); return SG_LIB_CAT_MEDIUM_HARD; } if (op->highest_unrecovered < 0) { op->highest_unrecovered = skip; op->lowest_unrecovered = skip; } else { if (skip < op->lowest_unrecovered) op->lowest_unrecovered = skip; if (skip > op->highest_unrecovered) op->highest_unrecovered = skip; } ++op->unrecovered_errs; ++op->in_partial; --op->in_full; pr2serr(">> unrecovered read error at blk=%" PRId64 ", " "substitute zeros\n", skip); return 0; } char * rod_type_str(uint32_t rt, char * b, int b_mlen) { int got_pit = 0; const char * cp = NULL; const char * pitp = "point in time copy - "; switch (rt) { case RODT_CM_INTERNAL: cp = "copy manager internal"; break; case RODT_ACCESS_ON_REF: cp = "access upon reference"; break; case RODT_PIT_DEF: cp = "default"; got_pit = 1; break; case RODT_PIT_VULN: cp = "change vulnerable"; got_pit = 1; break; case RODT_PIT_PERS: cp = "persistent"; got_pit = 1; break; case RODT_PIT_ANY: cp = "any"; got_pit = 1; break; case RODT_BLK_ZERO: cp = "block device zero"; break; default: if (rt >= 0xfffffff0) cp = "vendor specific"; else if (rt >= 0xff000000) cp = "device type specific"; else cp = "reserved"; break; } if (cp) snprintf(b, b_mlen, "%s%s [0x%" PRIx32 "]", (got_pit ? pitp : ""), cp, rt); else snprintf(b, b_mlen, "0x%" PRIx32 "", rt); return b; } char * rt_cm_id_str(const unsigned char * rtp, int rt_len, char * b, int b_mlen) { int m, num; if (rt_len < 16) snprintf(b, b_mlen, "ROD Token too short (%d < 16)\n", rt_len); num = 0; num += snprintf(b, b_mlen, "0x"); for (m = 0; ((m < 8) && (num < b_mlen)); ++m) num += snprintf(b + num, b_mlen - num, "%02x", (unsigned int)rtp[8 + m]); return b; } void print_exit_status_msg(const char * prefix, int exit_stat, int to_stderr) { int (*print_p)(const char *, ...); char b[80]; print_p = to_stderr ? pr2serr : printf; if (prefix && exit_stat) snprintf(b, sizeof(b), "%s: ", prefix); else b[0] = '\0'; switch(exit_stat) { case SG_LIB_CAT_CLEAN: /* 0 */ break; case SG_LIB_SYNTAX_ERROR: /* 1 */ print_p("%ssyntax error\n", b); break; case SG_LIB_CAT_NOT_READY: /* 2 */ print_p("%sdevice not ready\n", b); break; case SG_LIB_CAT_MEDIUM_HARD: /* 3 */ print_p("%smedium or hardware error\n", b); break; case SG_LIB_CAT_ILLEGAL_REQ: /* 5 */ print_p("%sillegal request\n", b); break; case SG_LIB_CAT_UNIT_ATTENTION: /* 6 */ print_p("%sunit attention\n", b); break; case DDPT_CAT_SK_DATA_PROTECT: /* 7 */ print_p("%sdata protect\n", b); break; case SG_LIB_CAT_INVALID_OP: /* 9 */ print_p("%sinvalid opcode\n", b); break; case DDPT_CAT_SK_COPY_ABORTED: /* 10 */ print_p("%scopy aborted\n", b); break; case SG_LIB_CAT_ABORTED_COMMAND: /* 11 */ print_p("%saborted command\n", b); break; case SG_LIB_CAT_MISCOMPARE: /* 14 */ print_p("%smiscompare\n", b); break; case SG_LIB_FILE_ERROR: /* 15 */ print_p("%sfile error\n", b); break; case SG_LIB_CAT_NO_SENSE: /* 20 */ print_p("%sno sense (but possible warning/error)\n", b); break; case SG_LIB_CAT_RECOVERED: /* 21 */ print_p("%srecovered error (possible future errors)\n", b); break; case DDPT_CAT_RESERVATION_CONFLICT: /* 30 */ print_p("%sSCSI command timeout\n", b); break; case SG_LIB_CAT_TIMEOUT: /* 33 */ print_p("%sSCSI status: reservation conflict\n", b); break; case SG_LIB_CAT_PROTECTION: /* 40 */ print_p("%sprotection error\n", b); break; case SG_LIB_CAT_PROTECTION_WITH_INFO: /* 41 */ print_p("%sprotection error with info\n", b); break; case DDPT_CAT_PARAM_LST_LEN_ERR: /* 50 */ print_p("%sparameter list length error\n", b); break; case DDPT_CAT_INVALID_FLD_IN_PARAM: /* 51 */ print_p("%sinvalid field in parameter list\n", b); break; case DDPT_CAT_TOO_MANY_SEGS_IN_PARAM: /* 52 */ print_p("%stoo many segments in parameter list\n", b); break; case DDPT_CAT_TARGET_UNDERRUN: /* 53 */ print_p("%starget underrun\n", b); break; case DDPT_CAT_TARGET_OVERRUN: /* 54 */ print_p("%starget overrun\n", b); break; case DDPT_CAT_OP_IN_PROGRESS: /* 55 */ print_p("%soperation in progress [list_id in use]\n", b); break; case DDPT_CAT_INSUFF_RES_CREATE_ROD: /* 56 */ print_p("%sinsufficient resources to create ROD\n", b); break; case DDPT_CAT_INSUFF_RES_CREATE_RODTOK: /* 57 */ print_p("%sinsufficient resources to create ROD Token\n", b); break; case DDPT_CAT_CMDS_CLEARED_BY_DEV_SVR: /* 58 */ print_p("%scommands cleared by device servers\n", b); break; case SG_LIB_CAT_MALFORMED: /* 97 */ print_p("%sresponse to SCSI command malformed\n", b); break; case SG_LIB_CAT_SENSE: /* 98 */ print_p("%ssome other error/warning in sense data\n", b); break; case SG_LIB_CAT_OTHER: /* 99 */ print_p("%ssome other error/warning, not sense data related\n", b); break; default: if ((exit_stat >= DDPT_CAT_TOKOP_BASE) && (exit_stat < (DDPT_CAT_TOKOP_BASE + 20))) { print_p("%sinvalid token operation, ", b); switch (exit_stat - DDPT_CAT_TOKOP_BASE) { /* asc=0x23 */ case 0: /* asc=0x23, asq=0x0 */ print_p("cause not reportable\n"); break; case 1: /* asc=0x23, asq=0x1 */ print_p("unsupported token type\n"); break; case 2: print_p("remote token usage not supported\n"); break; case 3: print_p("remote ROD token creation not supported\n"); break; case 4: print_p("token unknown\n"); break; case 5: print_p("token corrupt\n"); break; case 6: print_p("token revoked\n"); break; case 7: print_p("token expired\n"); break; case 8: print_p("token cancelled\n"); break; case 9: print_p("token deleted\n"); break; case 0xa: print_p("invalid token length\n"); break; default: print_p("asc=0x23, asq=0x%x\n", exit_stat - DDPT_CAT_TOKOP_BASE); break; } } else { if (exit_stat >= 0) print_p("%sunexpected exit status value: %d [0x%x]\n", b, exit_stat, exit_stat); else print_p("%sunexpected exit status value: %d\n", b, exit_stat); } break; } } /* Read numbers (up to 64 bits in size) from command line (comma (or * (single) space) separated list). Assumed decimal unless prefixed * by '0x', '0X' or contains trailing 'h' or 'H' (which indicate hex). * Returns 0 if ok, or 1 if error. */ int cl_to_sgl(const char * inp, struct scat_gath_elem * sgl_arr, int * arr_len, int max_arr_len) { int in_len, k; const char * lcp; int64_t ll; char * cp; char * c2p; if ((NULL == inp) || (NULL == sgl_arr) || (NULL == arr_len)) return 1; lcp = inp; in_len = strlen(inp); if (0 == in_len) *arr_len = 0; if ('-' == inp[0]) { /* read from stdin */ pr2serr("'--lba' cannot be read from stdin\n"); return 1; } else { /* list of numbers (default decimal) on command line */ k = strspn(inp, "0123456789aAbBcCdDeEfFhHxXbBdDiIkKmMgGtTpP, "); if (in_len != k) { pr2serr("cl_to_sgl: error at pos %d\n", k + 1); return 1; } for (k = 0; k < max_arr_len; ++k) { ll = sg_get_llnum(lcp); if (-1 != ll) { sgl_arr[k].lba = (uint64_t)ll; cp = (char *)strchr(lcp, ','); c2p = (char *)strchr(lcp, ' '); if (NULL == cp) { cp = c2p; if (NULL == cp) break; } if (c2p && (c2p < cp)) cp = c2p; lcp = cp + 1; } else { pr2serr("cl_to_sgl: error at pos %d\n", (int)(lcp - inp + 1)); return 1; } ll = sg_get_llnum(lcp); if (-1 != ll) { if (ll > UINT32_MAX) { pr2serr("cl_to_sgl: number exceeds 32 bits at pos %d\n", (int)(lcp - inp + 1)); return 1; } sgl_arr[k].num = (uint32_t)ll; cp = (char *)strchr(lcp, ','); c2p = (char *)strchr(lcp, ' '); if (NULL == cp) { cp = c2p; if (NULL == cp) break; } if (c2p && (c2p < cp)) cp = c2p; lcp = cp + 1; } else { pr2serr("cl_to_sgl: error at pos %d\n", (int)(lcp - inp + 1)); return 1; } } *arr_len = k + 1; if (k == max_arr_len) { pr2serr("cl_to_sgl: array length exceeded\n"); return 1; } } return 0; } /* Read numbers from filename (or stdin) line by line (comma (or * (single) space) separated list). Assumed decimal unless prefixed * by '0x', '0X' or contains trailing 'h' or 'H' (which indicate hex). * Returns 0 if ok, or 1 if error. */ int file_to_sgl(const char * file_name, struct scat_gath_elem * sgl_arr, int * arr_len, int max_arr_len) { char line[1024]; int off = 0; int in_len, k, j, m, have_stdin, ind, bit0; char * lcp; FILE * fp; int64_t ll; have_stdin = ((1 == strlen(file_name)) && ('-' == file_name[0])); if (have_stdin) fp = stdin; else { fp = fopen(file_name, "r"); if (NULL == fp) { pr2serr("file_to_sgl: unable to open %s\n", file_name); return 1; } } for (j = 0; j < 512; ++j) { if (NULL == fgets(line, sizeof(line), fp)) break; // could improve with carry_over logic if sizeof(line) too small in_len = strlen(line); if (in_len > 0) { if ('\n' == line[in_len - 1]) { --in_len; line[in_len] = '\0'; } else { pr2serr("file_to_sgl: line too long, max %d bytes\n", (int)(sizeof(line) - 1)); return 1; } } if (in_len < 1) continue; lcp = line; m = strspn(lcp, " \t"); if (m == in_len) continue; lcp += m; in_len -= m; if ('#' == *lcp) continue; k = strspn(lcp, "0123456789aAbBcCdDeEfFhHxXbBdDiIkKmMgGtTpP, \t"); if ((k < in_len) && ('#' != lcp[k])) { pr2serr("file_to_sgl: syntax error at line %d, pos %d\n", j + 1, m + k + 1); return 1; } for (k = 0; k < 1024; ++k) { ll = sg_get_llnum(lcp); if (-1 != ll) { ind = ((off + k) >> 1); bit0 = 0x1 & (off + k); if (ind >= max_arr_len) { pr2serr("file_to_sgl: array length exceeded\n"); return 1; } if (bit0) { if (ll > UINT32_MAX) { pr2serr("file_to_sgl: number exceeds 32 bits in " "line %d, at pos %d\n", j + 1, (int)(lcp - line + 1)); return 1; } sgl_arr[ind].num = (uint32_t)ll; } else sgl_arr[ind].lba = (uint64_t)ll; lcp = strpbrk(lcp, " ,\t#"); if ((NULL == lcp) || ('#' == *lcp)) break; lcp += strspn(lcp, " ,\t"); if ('\0' == *lcp) break; } else { if ('#' == *lcp) { --k; break; } pr2serr("file_to_sgl: error in line %d, at pos %d\n", j + 1, (int)(lcp - line + 1)); return 1; } } off += (k + 1); } if (0x1 & off) { pr2serr("file_to_sgl: expect LBA,NUM pairs but decoded odd number\n" " from %s\n", have_stdin ? "stdin" : file_name); return 1; } *arr_len = off >> 1; return 0; } ddpt-0.94/src/ddpt.c0000644000175000017500000026241412320426132013267 0ustar douggdougg/* * Copyright (c) 2008-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* ddpt is a utility program for copying files. It broadly follows the syntax * and semantics of the "dd" program found in Unix. ddpt is specialised for * "files" that represent storage devices, especially those that understand * the SCSI command set accessed via a pass-through. */ /* * The ddpt utility is a rewritten and extended version of the sg_dd utility * found in the sg3_utils package. sg_dd has a GPL (version 2) which has been * changed to a somewhat freer FreeBSD style license in ddpt. * Both licenses are considered "open source". * * Windows "block" devices, when _not_ accessed via the pass-through, don't * seem to work when POSIX/Unix like IO calls are used (e.g. write()). * So need CreateFile, ReadFile, WriteFile, SetFilePointer and friends. */ /* Need _GNU_SOURCE for O_DIRECT */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include /* N.B. config.h must precede anything that depends on HAVE_* */ #ifdef HAVE_CONFIG_H #include "config.h" #endif static const char * ddpt_version_str = "0.94 20140407 [svn: r277]"; #ifdef SG_LIB_LINUX #include #include #include #include #include /* */ #include /* For tape ioctls */ #ifndef MTWEOFI #define MTWEOFI 35 /* write an end-of-file record (mark) in immediate mode */ #endif #ifdef HAVE_FALLOCATE #include #ifndef FALLOC_FL_KEEP_SIZE #define FALLOC_FL_KEEP_SIZE 0x01 /* from lk 3.1 linux/falloc.h */ #endif #endif #endif /* SG_LIB_LINUX */ #ifdef SG_LIB_FREEBSD #include #include #include #include #endif #ifdef SG_LIB_SOLARIS #include #include #endif #ifdef SG_LIB_WIN32 #ifndef SG_LIB_MINGW /* cygwin */ #include #endif #endif #include "ddpt.h" #include "sg_lib.h" #ifndef EREMOTEIO #define EREMOTEIO EIO #endif /* Used for outputting diagnostic messages for oflag=pre-alloc */ #define PREALLOC_DEBUG 1 /* Returns open input file descriptor (>= 0) or a negative value * (-SG_LIB_FILE_ERROR or -SG_LIB_CAT_OTHER) if error. */ static int open_if(struct opts_t * op) { int flags; int fd = -SG_LIB_FILE_ERROR; char ebuff[EBUFF_SZ]; struct flags_t * ifp = op->iflagp; struct dev_info_t * idip = op->idip; const char * ifn = idip->fn; idip->d_type = dd_filetype(ifn, op->verbose); if (FT_ERROR & idip->d_type) { pr2serr("unable to access %s\n", ifn); goto file_err; } else if (((FT_BLOCK | FT_TAPE | FT_OTHER) & idip->d_type) && ifp->pt) idip->d_type |= FT_PT; if (op->verbose) pr2serr(" >> Input file type: %s\n", dd_filetype_str(idip->d_type, ebuff, EBUFF_SZ, ifn)); if (!(FT_PT & idip->d_type) && op->rdprotect) pr2serr("rdprotect ignored on non-pt device\n"); if ((FT_FIFO | FT_CHAR | FT_TAPE) & idip->d_type) ++op->reading_fifo; if ((FT_TAPE & idip->d_type) && (FT_PT & idip->d_type)) { pr2serr("SCSI tape device %s not supported via pt\n", ifn); goto file_err; } if (FT_PT & idip->d_type) { fd = pt_open_if(op, NULL); if (-1 == fd) goto file_err; else if (fd < -1) goto other_err; } #ifdef SG_LIB_WIN32 else if (FT_BLOCK & idip->d_type) { if (win32_open_if(op, (ifp->excl ? O_EXCL : 0), op->verbose)) goto file_err; fd = 0; } #endif else { flags = O_RDONLY; if (ifp->direct) flags |= O_DIRECT; if (ifp->excl) flags |= O_EXCL; if (ifp->sync) flags |= O_SYNC; fd = open(ifn, flags); if (fd < 0) { pr2serr("could not open %s for reading: %s\n", ifn, safe_strerror(errno)); goto file_err; } else { if (sg_set_binary_mode(fd) < 0) perror("sg_set_binary_mode"); if (op->verbose) pr2serr(" open %s, flags=0x%x\n", ifn, flags); #ifdef HAVE_POSIX_FADVISE if (ifp->nocache) { int rt; rt = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); if (rt) pr2serr("open_if: posix_fadvise(SEQUENTIAL), err=%d\n", rt); } #endif } } #ifdef SG_LIB_LINUX if (ifp->flock) { int res; res = flock(fd, LOCK_EX | LOCK_NB); if (res < 0) { close(fd); pr2serr("flock(LOCK_EX | LOCK_NB) on %s failed: %s\n", ifn, safe_strerror(errno)); return -SG_LIB_FLOCK_ERR; } } #endif return fd; file_err: return -SG_LIB_FILE_ERROR; other_err: return -SG_LIB_CAT_OTHER; } /* Returns open output file descriptor (>= 0), -1 for don't * bother opening (e.g. /dev/null), or a more negative value * (-SG_LIB_FILE_ERROR or -SG_LIB_CAT_OTHER) if error. */ static int open_of(struct opts_t * op) { int flags; int fd = -SG_LIB_FILE_ERROR; int outf_exists = 0; char ebuff[EBUFF_SZ]; struct stat st; struct flags_t * ofp = op->oflagp; struct dev_info_t * odip = op->odip; const char * ofn = odip->fn; odip->d_type = dd_filetype(ofn, op->verbose); if (((FT_BLOCK | FT_TAPE | FT_OTHER) & odip->d_type) && ofp->pt) odip->d_type |= FT_PT; odip->d_type_hold = odip->d_type; if (op->verbose) pr2serr(" >> Output file type: %s\n", dd_filetype_str(odip->d_type, ebuff, EBUFF_SZ, ofn)); if (!(FT_PT & odip->d_type) && op->wrprotect) pr2serr("wrprotect ignored on non-pt device\n"); if ((FT_TAPE & odip->d_type) && (FT_PT & odip->d_type)) { pr2serr("SCSI tape device %s not supported via pt\n", ofn); goto file_err; } if (FT_PT & odip->d_type) { fd = pt_open_of(op, NULL); if (-1 == fd) goto file_err; else if (fd < -1) goto other_err; } else if (FT_DEV_NULL & odip->d_type) fd = -1; /* don't bother opening */ #ifdef SG_LIB_WIN32 else if (FT_BLOCK & odip->d_type) { if (win32_open_of(op, (ofp->excl ? O_EXCL : 0), op->verbose)) goto file_err; fd = 0; } #endif else { /* typically regular file or block device node */ int needs_ftruncate = 0; int64_t offset = 0; memset(&st, 0, sizeof(st)); if (0 == stat(ofn, &st)) outf_exists = 1; else if (ofp->pt) { /* if oflag=pt, then creating a regular file is unhelpful */ pr2serr("Cannot create a regular file called %s as a pt\n", ofn); goto other_err; } flags = ofp->sparing ? O_RDWR : O_WRONLY; if (0 == outf_exists) flags |= O_CREAT; if (ofp->direct) flags |= O_DIRECT; if (ofp->excl) flags |= O_EXCL; if (ofp->sync) flags |= O_SYNC; if (ofp->append) flags |= O_APPEND; if ((FT_REG & odip->d_type) && outf_exists && ofp->trunc && (! ofp->nowrite)) { if (op->seek > 0) { offset = op->seek * op->obs; if (st.st_size > offset) ++needs_ftruncate; // only truncate to shorten } else flags |= O_TRUNC; } if ((fd = open(ofn, flags, 0666)) < 0) { pr2serr("could not open %s for writing: %s\n", ofn, safe_strerror(errno)); goto file_err; } if (needs_ftruncate && (offset > 0)) { if (ftruncate(fd, offset) < 0) { pr2serr("could not ftruncate %s after open (seek): %s\n", ofn, safe_strerror(errno)); goto file_err; } /* N.B. file offset (pointer) not changed by ftruncate */ } if ((! outf_exists) && (FT_ERROR & odip->d_type)) { odip->d_type = FT_REG; /* exists now */ odip->d_type_hold = odip->d_type; } if (sg_set_binary_mode(fd) < 0) perror("sg_set_binary_mode"); if (op->verbose) { pr2serr(" %s %s, flags=0x%x\n", (outf_exists ? "open" : "create"), ofn, flags); if (needs_ftruncate && (offset > 0)) pr2serr(" truncated file at byte offset " "%" PRId64 " \n", offset); } } #ifdef SG_LIB_LINUX if (ofp->flock) { int res; res = flock(fd, LOCK_EX | LOCK_NB); if (res < 0) { close(fd); pr2serr("flock(LOCK_EX | LOCK_NB) on %s failed: %s\n", ofn, safe_strerror(errno)); return -SG_LIB_FLOCK_ERR; } } #endif return fd; file_err: return -SG_LIB_FILE_ERROR; other_err: return -SG_LIB_CAT_OTHER; } /* Helper for calc_count(). Attempts to size IFILE. Returns 0 if no error * detected. */ static int calc_count_in(struct opts_t * op, int64_t * in_num_blksp) { int res; struct stat st; int64_t num_blks, t; int in_blk_sz, blk_sz, in_type; const char * ifn = op->idip->fn; *in_num_blksp = -1; in_type = op->idip->d_type; if (FT_PT & in_type) { if (op->iflagp->norcap) { if ((FT_BLOCK & in_type) && (0 == op->iflagp->force)) { pr2serr(">> warning: norcap on input block device " "accessed via pt is risky.\n"); pr2serr(">> Abort copy, use iflag=force to override.\n"); return -1; } return 0; } res = pt_read_capacity(op, DDPT_ARG_IN, in_num_blksp, &in_blk_sz); if (SG_LIB_CAT_UNIT_ATTENTION == res) { pr2serr("Unit attention (readcap in), continuing\n"); res = pt_read_capacity(op, DDPT_ARG_IN, in_num_blksp, &in_blk_sz); } else if (SG_LIB_CAT_ABORTED_COMMAND == res) { pr2serr("Aborted command (readcap in), continuing\n"); res = pt_read_capacity(op, DDPT_ARG_IN, in_num_blksp, &in_blk_sz); } if (0 != res) { if (res == SG_LIB_CAT_INVALID_OP) pr2serr("read capacity not supported on %s\n", ifn); else if (res == SG_LIB_CAT_NOT_READY) pr2serr("read capacity failed on %s - not ready\n", ifn); else pr2serr("Unable to read capacity on %s\n", ifn); *in_num_blksp = -1; return res; } else { if (op->verbose) { print_blk_sizes(ifn, "readcap", *in_num_blksp, in_blk_sz, 1); if (op->idip->prot_type > 0) pr2serr(" reports Protection_type=%d, p_i_exp=%d\n", op->idip->prot_type, op->idip->p_i_exp); } if ((*in_num_blksp > 0) && (in_blk_sz != op->ibs)) { pr2serr(">> warning: %s block size confusion: ibs=%d, " "device claims=%d\n", ifn, op->ibs, in_blk_sz); if (0 == op->iflagp->force) { pr2serr(">> abort copy, use iflag=force to override\n"); return -1; } } } if ((FT_BLOCK & in_type) && (0 == op->iflagp->force) && (0 == get_blkdev_capacity(op, DDPT_ARG_IN, &num_blks, &blk_sz))) { t = (*in_num_blksp) * in_blk_sz; if (t != (num_blks * blk_sz)) { pr2serr(">> warning: Size of input block device is " "different from pt size.\n>> Pass-through on block " "partition can give unexpected offsets.\n"); pr2serr(">> Abort copy, use iflag=force to override.\n"); return -1; } } } else if ((op->dd_count > 0) && (0 == op->oflagp->resume)) return 0; else if (FT_BLOCK & in_type) { if (0 != get_blkdev_capacity(op, DDPT_ARG_IN, in_num_blksp, &in_blk_sz)) { pr2serr("Unable to read block capacity on %s\n", ifn); *in_num_blksp = -1; } if (op->verbose) print_blk_sizes(ifn, "blk", *in_num_blksp, in_blk_sz, 1); if ((*in_num_blksp > 0) && (op->ibs != in_blk_sz)) { pr2serr(">> warning: %s block size confusion: bs=%d, " "device claims=%d\n", ifn, op->ibs, in_blk_sz); *in_num_blksp = -1; } } else if (FT_REG & in_type) { if (fstat(op->idip->fd, &st) < 0) { perror("fstat(idip->fd) error"); *in_num_blksp = -1; } else { *in_num_blksp = st.st_size / op->ibs; res = st.st_size % op->ibs; if (op->verbose) { print_blk_sizes(ifn, "reg", *in_num_blksp, op->ibs, 1); if (res) pr2serr(" residual_bytes=%d\n", res); } if (res) ++*in_num_blksp; } } return 0; } /* Helper for calc_count(). Attempts to size OFILE. Returns 0 if no error * detected. */ static int calc_count_out(struct opts_t * op, int64_t * out_num_blksp) { int res; struct stat st; int64_t num_blks, t; int out_blk_sz, blk_sz, out_type; const char * ofn = op->odip->fn; *out_num_blksp = -1; out_type = op->odip->d_type; if (FT_PT & out_type) { if (op->oflagp->norcap) { if ((FT_BLOCK & out_type) && (0 == op->oflagp->force)) { pr2serr(">> warning: norcap on output block device " "accessed via pt is risky.\n"); pr2serr(">> Abort copy, use oflag=force to override.\n"); return -1; } return 0; } res = pt_read_capacity(op, DDPT_ARG_OUT, out_num_blksp, &out_blk_sz); if (SG_LIB_CAT_UNIT_ATTENTION == res) { pr2serr("Unit attention (readcap out), continuing\n"); res = pt_read_capacity(op, DDPT_ARG_OUT, out_num_blksp, &out_blk_sz); } else if (SG_LIB_CAT_ABORTED_COMMAND == res) { pr2serr("Aborted command (readcap out), continuing\n"); res = pt_read_capacity(op, DDPT_ARG_OUT, out_num_blksp, &out_blk_sz); } if (0 != res) { if (res == SG_LIB_CAT_INVALID_OP) pr2serr("read capacity not supported on %s\n", ofn); else pr2serr("Unable to read capacity on %s\n", ofn); *out_num_blksp = -1; return res; } else { if (op->verbose) { print_blk_sizes(ofn, "readcap", *out_num_blksp, out_blk_sz, 1); if (op->odip->prot_type > 0) pr2serr(" reports Protection_type=%d, p_i_exp=%d\n", op->odip->prot_type, op->odip->p_i_exp); } if ((*out_num_blksp > 0) && (op->obs != out_blk_sz)) { pr2serr(">> warning: %s block size confusion: " "obs=%d, device claims=%d\n", ofn, op->obs, out_blk_sz); if (0 == op->oflagp->force) { pr2serr(">> abort copy, use oflag=force to override\n"); return -1; } } } if ((FT_BLOCK & out_type) && (0 == op->oflagp->force) && (0 == get_blkdev_capacity(op, DDPT_ARG_OUT, &num_blks, &blk_sz))) { t = (*out_num_blksp) * out_blk_sz; if (t != (num_blks * blk_sz)) { pr2serr(">> warning: size of output block device is " "different from pt size.\n>> Pass-through on block " "partition can give unexpected results.\n"); pr2serr(">> abort copy, use oflag=force to override\n"); return -1; } } } else if ((op->dd_count > 0) && (0 == op->oflagp->resume)) return 0; if (FT_BLOCK & out_type) { if (0 != get_blkdev_capacity(op, DDPT_ARG_OUT, out_num_blksp, &out_blk_sz)) { pr2serr("Unable to read block capacity on %s\n", ofn); *out_num_blksp = -1; } else { if (op->verbose) print_blk_sizes(ofn, "blk", *out_num_blksp, out_blk_sz, 1); if ((*out_num_blksp > 0) && (op->obs != out_blk_sz)) { pr2serr(">> warning: %s block size confusion: obs=%d, " "device claims=%d\n", ofn, op->obs, out_blk_sz); *out_num_blksp = -1; } } } else if (FT_REG & out_type) { if (fstat(op->odip->fd, &st) < 0) { perror("fstat(odip->fd) error"); *out_num_blksp = -1; } else { *out_num_blksp = st.st_size / op->obs; res = st.st_size % op->obs; if (op->verbose) { print_blk_sizes(ofn, "reg", *out_num_blksp, op->obs, 1); if (res) pr2serr(" residual_bytes=%d\n", res); } if (res) ++*out_num_blksp; } } return 0; } /* Calculates the number of blocks associated with the in and out files. * May also yield the block size in bytes of devices. For regular files * uses ibs or obs as the logical block size. Returns 0 for continue, * otherwise bypass copy and exit. */ static int calc_count(struct opts_t * op, int64_t * in_num_blksp, int64_t * out_num_blksp) { int res; res = calc_count_in(op, in_num_blksp); if (res) { *out_num_blksp = -1; return res; } return calc_count_out(op, out_num_blksp); } #ifdef HAVE_POSIX_FADVISE /* Used by iflag=nocache and oflag=nocache to suggest (via posix_fadvise() * system call) that the OS doesn't cache data it has just read or written * since it is unlikely to be used again in the short term. iflag=nocache * additionally increases the read-ahead. Errors ignored. */ static void do_fadvise(struct opts_t * op, int bytes_if, int bytes_of, int bytes_of2) { int rt, in_valid, out2_valid, out_valid, id_type, od_type, o2d_type; id_type = op->idip->d_type; od_type = op->odip->d_type; o2d_type = op->o2dip->d_type; in_valid = ((FT_REG == id_type) || (FT_BLOCK == id_type)); out2_valid = ((FT_REG == o2d_type) || (FT_BLOCK == o2d_type)); out_valid = ((FT_REG == od_type) || (FT_BLOCK == od_type)); if (op->iflagp->nocache && (bytes_if > 0) && in_valid) { if ((op->lowest_skip < 0) || (op->skip > op->lowest_skip)) op->lowest_skip = op->skip; rt = posix_fadvise(op->idip->fd, (op->lowest_skip * op->ibs), ((op->skip - op->lowest_skip) * op->ibs) + bytes_if, POSIX_FADV_DONTNEED); if (rt) /* returns error as result */ pr2serr("posix_fadvise on read, skip=%" PRId64 " ,err=%d\n", op->skip, rt); } if ((op->oflagp->nocache & 2) && (bytes_of2 > 0) && out2_valid) { rt = posix_fadvise(op->o2dip->fd, 0, 0, POSIX_FADV_DONTNEED); if (rt) pr2serr("posix_fadvise on of2, seek=%" PRId64 " ,err=%d\n", op->seek, rt); } if ((op->oflagp->nocache & 1) && (bytes_of > 0) && out_valid) { if ((op->lowest_seek < 0) || (op->seek > op->lowest_seek)) op->lowest_seek = op->seek; rt = posix_fadvise(op->odip->fd, (op->lowest_seek * op->obs), ((op->seek - op->lowest_seek) * op->obs) + bytes_of, POSIX_FADV_DONTNEED); if (rt) pr2serr("posix_fadvise on output, seek=%" PRId64 " , err=%d\n", op->seek, rt); } } #endif /* Main copy loop's read (input) via pt. Returns 0 on success, else see * pt_read()'s return values. */ static int cp_read_pt(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp) { int res; int blks_read = 0; res = pt_read(op, 0, bp, csp->icbpt, &blks_read); if (res) { if (0 == blks_read) { pr2serr("pt_read failed,%s at or after lba=%" PRId64 " " "[0x%" PRIx64 "]\n", ((-2 == res) ? " try reducing bpt," : ""), op->skip, op->skip); return res; } /* limp on if data, should stop after write; hold err number */ op->err_to_report = res; } if (blks_read < csp->icbpt) { /* assume close to end, or some data prior to read error */ if (op->verbose > 1) pr2serr("short read, requested %d blocks, got %d blocks\n", csp->icbpt, blks_read); ++csp->leave_after_write; /* csp->leave_reason = 0; assume at end rather than error */ csp->icbpt = blks_read; /* round down since don't do partial writes from pt reads */ csp->ocbpt = (blks_read * op->ibs) / op->obs; } op->in_full += csp->icbpt; return 0; } /* Error occurred on block/regular read. coe active so assume all full * blocks prior to error are good (if any) and start to read from the * block containing the error, one block at a time, until ibpt. Supply * zeros for unreadable blocks. Return 0 if successful, SG_LIB_CAT_OTHER * if error other than EIO or EREMOTEIO, SG_LIB_FILE_ERROR if lseek fails, * and SG_LIB_CAT_MEDIUM_HARD if the coe_limit is exceeded. */ static int coe_cp_read_block_reg(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp, int numread_errno) { int res, res2, k, total_read, num_read; int ibs = op->ibs_pi; int64_t offset, off_res, my_skip; if (0 == numread_errno) { csp->icbpt = 0; csp->ocbpt = 0; ++csp->leave_after_write; csp->leave_reason = 0; return 0; /* EOF */ } else if (numread_errno < 0) { if ((-EIO == numread_errno) || (-EREMOTEIO == numread_errno)) { num_read = 0; if (1 == csp->icbpt) { // Don't read again, this must be bad block memset(bp, 0, ibs); if ((res2 = coe_process_eio(op, op->skip))) return res2; ++op->in_full; csp->bytes_read += ibs; return 0; } } else return SG_LIB_CAT_OTHER; } else num_read = (numread_errno / ibs) * ibs; k = num_read / ibs; if (k > 0) { op->in_full += k; zero_coe_limit_count(op); } csp->bytes_read = num_read; my_skip = op->skip + k; offset = my_skip * ibs; bp += num_read; for ( ; k < csp->icbpt; ++k, ++my_skip, bp += ibs, offset += ibs) { if (offset != csp->if_filepos) { if (op->verbose > 2) pr2serr("moving if filepos: new_pos=%" PRId64 "\n", (int64_t)offset); off_res = lseek(op->idip->fd, offset, SEEK_SET); if (off_res < 0) { pr2serr("failed moving if filepos: new_pos=" "%" PRId64 "\nlseek on input: %s\n", (int64_t)offset, safe_strerror(errno)); return SG_LIB_FILE_ERROR; } csp->if_filepos = offset; } memset(bp, 0, ibs); while (((res = read(op->idip->fd, bp, ibs)) < 0) && (EINTR == errno)) ++op->interrupted_retries; if (0 == res) { csp->leave_reason = 0; goto short_read; } else if (res < 0) { if ((EIO == errno) || (EREMOTEIO == errno)) { if ((res2 = coe_process_eio(op, my_skip))) return res2; } else { pr2serr("reading 1 block, skip=%" PRId64 " : %s\n", my_skip, safe_strerror(errno)); csp->leave_reason = SG_LIB_CAT_OTHER; goto short_read; } } else if (res < ibs) { if (op->verbose) pr2serr("short read at skip=%" PRId64 " , wanted=%d, " "got=%d bytes\n", my_skip, ibs, res); csp->leave_reason = 0; /* assume EOF */ goto short_read; } else { /* if (res == ibs) */ zero_coe_limit_count(op); csp->if_filepos += ibs; if (op->verbose > 2) pr2serr("reading 1 block, skip=%" PRId64 " : okay\n", my_skip); } ++op->in_full; csp->bytes_read += ibs; } return 0; short_read: total_read = (ibs * k) + ((res > 0) ? res : 0); csp->icbpt = total_read / ibs; if ((total_read % ibs) > 0) { ++csp->icbpt; ++op->in_partial; } csp->ocbpt = total_read / op->obs; ++csp->leave_after_write; if (0 == csp->leave_reason) { csp->partial_write_bytes = total_read % op->obs; } else { /* if short read (not EOF) implies partial writes, bump obpt */ if ((total_read % op->obs) > 0) ++csp->ocbpt; } return 0; } /* Main copy loop's read (input) for block device or regular file. * Returns 0 on success, else SG_LIB_FILE_ERROR, SG_LIB_CAT_MEDIUM_HARD, * SG_LIB_CAT_OTHER or -1 . */ static int cp_read_block_reg(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp) { int res, res2, in_type; int64_t offset = op->skip * op->ibs_pi; int numbytes = csp->icbpt * op->ibs_pi; int ibs = op->ibs_pi; in_type = op->idip->d_type; #ifdef SG_LIB_WIN32 if (FT_BLOCK & in_type) { int ifull_extra; if ((res = win32_cp_read_block(op, csp, bp, &ifull_extra, op->verbose))) return res; op->in_full += ifull_extra; return 0; } #endif if (offset != csp->if_filepos) { int64_t off_res; if (op->verbose > 2) pr2serr("moving if filepos: new_pos=%" PRId64 "\n", (int64_t)offset); off_res = lseek(op->idip->fd, offset, SEEK_SET); if (off_res < 0) { pr2serr("failed moving if filepos: new_pos=" "%" PRId64 "\nlseek on input: %s\n", (int64_t)offset, safe_strerror(errno)); return SG_LIB_FILE_ERROR; } csp->if_filepos = offset; } while (((res = read(op->idip->fd, bp, numbytes)) < 0) && (EINTR == errno)) ++op->interrupted_retries; if (op->verbose > 2) pr2serr("read(unix): requested bytes=%d, res=%d\n", numbytes, res); if ((op->iflagp->coe) && (res < numbytes)) { res2 = (res >= 0) ? res : -errno; if ((res < 0) && op->verbose) { pr2serr("reading, skip=%" PRId64 " : %s, go to coe\n", op->skip, safe_strerror(errno)); } else if (op->verbose) pr2serr("reading, skip=%" PRId64 " : short read, go to coe\n", op->skip); if (res2 > 0) csp->if_filepos += res2; return coe_cp_read_block_reg(op, csp, bp, res2); } if (res < 0) { pr2serr("reading, skip=%" PRId64 " : %s\n", op->skip, safe_strerror(errno)); if ((EIO == errno) || (EREMOTEIO == errno)) return SG_LIB_CAT_MEDIUM_HARD; else return SG_LIB_CAT_OTHER; } else if (res < numbytes) { csp->icbpt = res / ibs; if ((res % ibs) > 0) { ++csp->icbpt; ++op->in_partial; --op->in_full; } csp->ocbpt = res / op->obs; ++csp->leave_after_write; csp->leave_reason = 0; /* fall through is assumed EOF */ if (op->verbose > 1) { if (FT_BLOCK & in_type) pr2serr("short read at skip=%" PRId64 ", requested " "%d blocks, got %d blocks\n", op->skip, numbytes / ibs, csp->icbpt); else pr2serr("short read, requested %d bytes, got %d bytes\n", numbytes, res); } res2 = 0; if ((res >= ibs) && (res <= (numbytes - ibs))) { /* Want to check for a EIO lurking */ while (((res2 = read(op->idip->fd, bp + res, ibs)) < 0) && (EINTR == errno)) ++op->interrupted_retries; if (res2 < 0) { if ((EIO == errno) || (EREMOTEIO == errno)) { csp->leave_reason = SG_LIB_CAT_MEDIUM_HARD; ++op->unrecovered_errs; } else csp->leave_reason = SG_LIB_CAT_OTHER; if (op->verbose) pr2serr("after short read, read at skip=%" PRId64 ": %s\n", op->skip + csp->icbpt, safe_strerror(errno)); } else { /* actually expect 0==res2 indicating EOF */ csp->if_filepos += res2; /* could have moved filepos */ if (op->verbose > 1) pr2serr("extra read after short read, res=%d\n", res2); } } if (0 == csp->leave_reason) /* if EOF, allow for partial write */ csp->partial_write_bytes = (res + res2) % op->obs; else if ((res % op->obs) > 0) /* else if extra bytes bump obpt */ ++csp->ocbpt; } csp->if_filepos += res; csp->bytes_read = res; op->in_full += csp->icbpt; return 0; } #ifdef SG_LIB_LINUX /* Main copy loop's read (input) for tape device. Returns 0 on success, * else SG_LIB_CAT_MEDIUM_HARD, SG_LIB_CAT_OTHER or -1 . */ static int cp_read_tape(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp) { int res, err, num; num = csp->icbpt * op->ibs; op->read_tape_numbytes = num; while (((res = read(op->idip->fd, bp, num)) < 0) && (EINTR == errno)) ++op->interrupted_retries; err = errno; /* Summarise previous consecutive same-length reads. */ print_tape_summary(op, res, ""); if (op->verbose > 2) pr2serr("read(tape%s): requested bytes=%d, res=%d\n", ((res >= num) || (res < 0)) ? "" : ", short", num, res); if (op->verbose > 3) print_tape_pos("", "", op); if (res < 0) { /* If a tape block larger than the requested read length is * encountered, the Linux st driver returns ENOMEM. Handle that case * otherwise we would print a confusing/incorrect message * "Cannot allocate memory". */ pr2serr("reading, skip=%" PRId64 " : %s\n", op->skip, (ENOMEM == err) ? "Tape block larger than requested read" " length" : safe_strerror(err)); /* So print_stats() doesn't print summary. */ op->last_tape_read_len = 0; if ((EIO == err) || (EREMOTEIO == err)) return SG_LIB_CAT_MEDIUM_HARD; else return SG_LIB_CAT_OTHER; } else { if (op->verbose > 1) { if (res == op->last_tape_read_len) op->consec_same_len_reads++; else { op->last_tape_read_len = res; op->consec_same_len_reads = 1; } } if (res < num) { csp->icbpt = res / op->ibs; if ((res % op->ibs) > 0) { ++csp->icbpt; ++op->in_partial; --op->in_full; } csp->ocbpt = res / op->obs; ++csp->leave_after_write; csp->leave_reason = REASON_TAPE_SHORT_READ; csp->partial_write_bytes = res % op->obs; if ((op->verbose == 2) && (op->consec_same_len_reads == 1)) pr2serr("short read: requested %d bytes, got %d\n", op->read_tape_numbytes, res); } } csp->if_filepos += res; csp->bytes_read = res; op->in_full += csp->icbpt; return 0; } #endif /* SG_LIB_LINUX */ /* Main copy loop's read (input) for a fifo. Returns 0 on success, else * SG_LIB_CAT_OTHER or -1 . */ static int cp_read_fifo(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp) { int res, k, err; int64_t offset = op->skip * op->ibs; int numbytes = csp->icbpt * op->ibs; if (offset != csp->if_filepos) { if (op->verbose > 2) pr2serr("fifo: _not_ moving IFILE filepos to %" PRId64 "\n", (int64_t)offset); csp->if_filepos = offset; } for (k = 0; k < numbytes; k += res) { while (((res = read(op->idip->fd, bp + k, numbytes - k)) < 0) && (EINTR == errno)) ++op->interrupted_retries; err = errno; if (op->verbose > 2) pr2serr("read(fifo): requested bytes=%d, res=%d\n", numbytes, res); if (res < 0) { pr2serr("read(fifo), skip=%" PRId64 " : %s\n", op->skip, safe_strerror(err)); return SG_LIB_CAT_OTHER; } else if (0 == res) { csp->icbpt = k / op->ibs; if ((k % op->ibs) > 0) { ++csp->icbpt; ++op->in_partial; --op->in_full; } csp->ocbpt = k / op->obs; ++csp->leave_after_write; csp->leave_reason = 0; /* EOF */ csp->partial_write_bytes = k % op->obs; break; } } csp->if_filepos += k; csp->bytes_read = k; op->in_full += csp->icbpt; return 0; } /* Main copy loop's write (to of2) for regular file. Returns 0 if success, * else -1 on error. */ static int cp_write_of2(struct opts_t * op, struct cp_state_t * csp, const unsigned char * bp) { int res, off, part, err; int numbytes = (csp->ocbpt * op->obs) + csp->partial_write_bytes; // write to fifo (reg file ?) is non-atomic so loop if making progress off = 0; part = 0; do { while (((res = write(op->o2dip->fd, bp + off, numbytes - off)) < 0) && (EINTR == errno)) ++op->interrupted_retries; err = errno; if ((res > 0) && (res < (numbytes - off))) ++part; } while ((FT_FIFO & op->o2dip->d_type) && (res > 0) && ((off += res) < numbytes)); if (off >= numbytes) { res = numbytes; if (part && op->verbose) pr2serr("write to of2 splintered\n"); } else if (off > 0) pr2serr("write to of2 fifo problem: count=%d, off=%d, res=%d\n", numbytes, off, res); if ((op->verbose > 2) && (0 == off)) pr2serr("write to of2: count=%d, res=%d\n", numbytes, res); if (res < 0) { pr2serr("writing to of2, seek=%" PRId64 " : %s\n", op->seek, safe_strerror(err)); return -1; } csp->bytes_of2 = res; return 0; } /* Main copy loop's read (output (of)) via pt. Returns 0 on success, else * see pt_read()'s return values. */ static int cp_read_of_pt(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp) { int res, blks_read; res = pt_read(op, 1, bp, csp->ocbpt, &blks_read); if (res) { pr2serr("pt_read(sparing) failed, at or after " "lba=%" PRId64 " [0x%" PRIx64 "]\n", op->seek, op->seek); return res; } else if (blks_read != csp->ocbpt) return 1; return 0; } /* Main copy loop's read (output (of)) for block device or regular file. * Returns 0 on success, else SG_LIB_FILE_ERROR, SG_LIB_CAT_MEDIUM_HARD * or -1 . */ static int cp_read_of_block_reg(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp) { int res, err; int64_t offset = op->seek * op->obs; int numbytes = csp->ocbpt * op->obs; #ifdef SG_LIB_WIN32 if (FT_BLOCK & op->odip->d_type) { if (offset != csp->of_filepos) { if (op->verbose > 2) pr2serr("moving of filepos: new_pos=%" PRId64 "\n", (int64_t)offset); if (win32_set_file_pos(op, DDPT_ARG_OUT, offset, op->verbose)) return SG_LIB_FILE_ERROR; csp->of_filepos = offset; } res = win32_block_read_from_of(op, bp, numbytes, op->verbose); if (op->verbose > 2) pr2serr("read(sparing): requested bytes=%d, res=%d\n", numbytes, res); if (res < 0) { pr2serr("read(sparing), seek=%" PRId64 "\n", op->seek); return (-SG_LIB_CAT_MEDIUM_HARD == res) ? -res : -1; } else if (res == numbytes) { csp->of_filepos += numbytes; return 0; } else { if (op->verbose > 2) pr2serr("short read\n"); return -1; } } else #endif { if (offset != csp->of_filepos) { int64_t off_res; if (op->verbose > 2) pr2serr("moving of filepos: new_pos=%" PRId64 "\n", (int64_t)offset); off_res = lseek(op->odip->fd, offset, SEEK_SET); if (off_res < 0) { pr2serr("failed moving of filepos: new_pos=" "%" PRId64 "\nlseek on output: %s\n", (int64_t)offset, safe_strerror(errno)); return SG_LIB_FILE_ERROR; } csp->of_filepos = offset; } if (csp->partial_write_bytes > 0) { numbytes += csp->partial_write_bytes; if (op->verbose) pr2serr("read(sparing): %d bytes extra to fetch " "due to partial read\n", csp->partial_write_bytes); } while (((res = read(op->odip->fd, bp, numbytes)) < 0) && (EINTR == errno)) ++op->interrupted_retries; err = errno; if (op->verbose > 2) pr2serr("read(sparing): requested bytes=%d, res=%d\n", numbytes, res); if (res < 0) { pr2serr("read(sparing), seek=%" PRId64 " : %s\n", op->seek, safe_strerror(err)); return -1; } else if (res == numbytes) { csp->of_filepos += numbytes; return 0; } else { if (op->verbose > 2) pr2serr("short read\n"); return 1; } } } /* Main copy loop's write (output (of)) via pt. Returns 0 on success, else * see pt_write()'s return values. */ static int cp_write_pt(struct opts_t * op, struct cp_state_t * csp, int seek_delta, int blks, const unsigned char * bp) { int res; int numbytes; int64_t aseek = op->seek + seek_delta; if (op->oflagp->nowrite) return 0; if (csp->partial_write_bytes > 0) { if (op->oflagp->pad) { unsigned char * ncbp = (unsigned char *)bp; numbytes = blks * op->obs; numbytes += csp->partial_write_bytes; ++csp->ocbpt; ++blks; res = blks * op->obs; if (res > numbytes) memset(ncbp + numbytes, 0, res - numbytes); if (op->verbose > 1) pr2serr("pt_write: padding probable final write at " "seek=%" PRId64 "\n", aseek); } else pr2serr(">>> ignore partial write of %d bytes to pt " "(unless oflag=pad given)\n", csp->partial_write_bytes); } res = pt_write(op, bp, blks, aseek); if (0 != res) { pr2serr("pt_write failed,%s seek=%" PRId64 "\n", ((-2 == res) ? " try reducing bpt," : ""), aseek); return res; } else op->out_full += blks; return 0; } #ifdef SG_LIB_LINUX /* Main copy loop's write (output (of)) for a tape device. * Returns 0 on success, else SG_LIB_CAT_OTHER, SG_LIB_CAT_MEDIUM_HARD * or -1 . */ static int cp_write_tape(struct opts_t * op, struct cp_state_t * csp, const unsigned char * bp, int could_be_last) { int res, err; int numbytes; int partial = 0; int blks = csp->ocbpt; int64_t aseek = op->seek; int got_early_warning = 0; /* Only print early warning message once when verbose=2 */ static int printed_ew_message = 0; numbytes = blks * op->obs; if (op->oflagp->nowrite) return 0; if (csp->partial_write_bytes > 0) { ++partial; numbytes += csp->partial_write_bytes; if (op->oflagp->nopad) ++op->out_partial; else { unsigned char * ncbp = (unsigned char *)bp; ++csp->ocbpt; ++blks; res = blks * op->obs; if (res > numbytes) memset(ncbp + numbytes, 0, res - numbytes); numbytes = res; } } ew_retry: while (((res = write(op->odip->fd, bp, numbytes)) < 0) && (EINTR == errno)) ++op->interrupted_retries; err = errno; if ((op->verbose > 2) || ((op->verbose > 0) && could_be_last)) { const char * cp; cp = ((! op->oflagp->nopad) && partial) ? ", padded" : ""; pr2serr("write(tape%s%s): requested bytes=%d, res=%d\n", (partial ? ", partial" : ""), cp, numbytes, res); } /* Handle EOM early warning. */ /* The Linux st driver returns -1 and ENOSPC to indicate the drive has reached * end of medium early warning. It is still possible to write a significant * amount of data before reaching end of tape (e.g. over 200MB for LTO 1). If * the user specified oflag=ignoreew (ignore early warning) retry the write. * The st driver should allow it; writes alternate until EOM, i.e. write okay, * ENOSPC, write okay, ENOSPC, etc. Exit if more than one ENOSPC in a row. */ if ((op->oflagp->ignoreew) && (-1 == res) && (ENOSPC == err) && (0 == got_early_warning)) { got_early_warning = 1; if (0 == printed_ew_message) { if (op->verbose > 1) pr2serr("writing, seek=%" PRId64 " : EOM early " "warning, continuing...\n", aseek); if (2 == op->verbose) { pr2serr("(suppressing further early warning messages)\n"); printed_ew_message = 1; } } goto ew_retry; } if (op->verbose > 3) print_tape_pos("", "", op); if (res < 0) { pr2serr("writing, seek=%" PRId64 " : %s\n", aseek, safe_strerror(err)); if ((EIO == err) || (EREMOTEIO == err)) return SG_LIB_CAT_MEDIUM_HARD; else return SG_LIB_CAT_OTHER; } else if (res < numbytes) { pr2serr("write(tape): wrote less than requested, exit\n"); csp->of_filepos += res; csp->bytes_of = res; op->out_full += res / op->obs; /* can get a partial write due to a short write */ if ((res % op->obs) > 0) { ++op->out_partial; ++op->out_full; } return -1; } else { /* successful write */ csp->of_filepos += numbytes; csp->bytes_of = numbytes; op->out_full += blks; } return 0; } #endif /* SG_LIB_LINUX */ /* Main copy loop's write (output (of)) for block device fifo or regular * file. Returns 0 on success, else SG_LIB_FILE_ERROR, * SG_LIB_CAT_MEDIUM_HARD or -1 . */ static int cp_write_block_reg(struct opts_t * op, struct cp_state_t * csp, int seek_delta, int blks, const unsigned char * bp) { int64_t offset; int64_t aseek = op->seek + seek_delta; int res, off, part, out_type, err; int numbytes = blks * op->obs_pi; int obs = op->obs_pi; if (op->oflagp->nowrite) return 0; out_type = op->odip->d_type; offset = aseek * obs; #ifdef SG_LIB_WIN32 if (FT_BLOCK & out_type) { if (csp->partial_write_bytes > 0) { if (op->oflagp->pad) { numbytes += csp->partial_write_bytes; ++csp->ocbpt; ++blks; res = blks * obs; if (res > numbytes) memset((unsigned char *)bp + numbytes, 0, res - numbytes); numbytes = res; if (op->verbose > 1) pr2serr("write(win32_block): padding probable " "final write at seek=%" PRId64 "\n", aseek); } else pr2serr(">>> ignore partial write of %d bytes to " "block device\n", csp->partial_write_bytes); } if (offset != csp->of_filepos) { if (op->verbose > 2) pr2serr("moving of filepos: new_pos=%" PRId64 "\n", (int64_t)offset); if (win32_set_file_pos(op, DDPT_ARG_OUT, offset, op->verbose)) return SG_LIB_FILE_ERROR; csp->of_filepos = offset; } res = win32_block_write(op, bp, numbytes, op->verbose); if (res < 0) { pr2serr("write(win32_block), seek=%" PRId64 " ", aseek); return (-SG_LIB_CAT_MEDIUM_HARD == res) ? -res : -1; } else if (res < numbytes) { pr2serr("output file probably full, seek=%" PRId64 " ", aseek); csp->of_filepos += res; csp->bytes_of = res; op->out_full += res / obs; /* can get a partial write due to a short write */ if ((res % obs) > 0) { ++op->out_partial; ++op->out_full; } return -1; } else { csp->of_filepos += numbytes; csp->bytes_of = numbytes; op->out_full += blks; } return 0; } else #endif { if (csp->partial_write_bytes > 0) { if (op->oflagp->pad) { unsigned char * ncbp = (unsigned char *)bp; numbytes += csp->partial_write_bytes; ++csp->ocbpt; ++blks; res = blks * obs; if (res > numbytes) memset(ncbp + numbytes, 0, res - numbytes); numbytes = res; if (op->verbose > 1) pr2serr("write(unix): padding probable final " "write at seek=%" PRId64 "\n", aseek); } else { if (FT_BLOCK & out_type) pr2serr(">>> ignore partial write of %d bytes to block " "device\n", csp->partial_write_bytes); else { numbytes += csp->partial_write_bytes; ++op->out_partial; } } } if ((offset != csp->of_filepos) && (! (REASON_TAPE_SHORT_READ == csp->leave_reason))) { int64_t off_res; if (op->verbose > 2) pr2serr("moving of filepos: new_pos=%" PRId64 "\n", (int64_t)offset); off_res = lseek(op->odip->fd, offset, SEEK_SET); if (off_res < 0) { pr2serr("failed moving of filepos: new_pos=" "%" PRId64 "\nlseek on output: %s\n", (int64_t)offset, safe_strerror(errno)); return SG_LIB_FILE_ERROR; } csp->of_filepos = offset; } // write to fifo (reg file ?) is non-atomic so loop if making progress off = 0; part = 0; do { while (((res = write(op->odip->fd, bp + off, numbytes - off)) < 0) && (EINTR == errno)) ++op->interrupted_retries; err = errno; if ((res > 0) && (res < (numbytes - off))) ++part; } while ((FT_FIFO & out_type) && (res > 0) && ((off += res) < numbytes)); if (off >= numbytes) { res = numbytes; if (part && op->verbose) pr2serr("write to output file splintered\n"); } else if (off > 0) pr2serr("write to of fifo problem: count=%d, off=%d, " "res=%d\n", numbytes, off, res); if ((op->verbose > 2) && (0 == off)) pr2serr("write(unix): requested bytes=%d, res=%d\n", numbytes, res); if (res < 0) { pr2serr("writing, seek=%" PRId64 " : %s\n", aseek, safe_strerror(err)); if ((EIO == err) || (EREMOTEIO == err)) return SG_LIB_CAT_MEDIUM_HARD; else return SG_LIB_CAT_OTHER; } else if (res < numbytes) { pr2serr("output file probably full, seek=%" PRId64 "\n", aseek); csp->of_filepos += res; csp->bytes_of = res; op->out_full += res / obs; /* can get a partial write due to a short write */ if ((res % obs) > 0) { ++op->out_partial; ++op->out_full; } return -1; } else { /* successful write */ csp->of_filepos += numbytes; csp->bytes_of = numbytes; op->out_full += blks; } return 0; } } /* Only for regular OFILE. Check what to do if last blocks where * not written, may require OFILE length adjustment */ static void cp_sparse_cleanup(struct opts_t * op, struct cp_state_t * csp) { int64_t offset = op->seek * op->obs; struct stat a_st; if (offset > csp->of_filepos) { if ((0 == op->oflagp->strunc) && (op->oflagp->sparse > 1)) { if (op->verbose > 1) pr2serr("asked to bypass writing sparse last block of " "zeros\n"); return; } if (fstat(op->odip->fd, &a_st) < 0) { pr2serr("cp_sparse_cleanup: fstat: %s\n", safe_strerror(errno)); return; } if (offset == a_st.st_size) { if (op->verbose > 1) pr2serr("cp_sparse_cleanup: OFILE already correct length\n"); return; } if (offset < a_st.st_size) { if (op->verbose > 1) pr2serr("cp_sparse_cleanup: OFILE longer than required, do " "nothing\n"); return; } if (op->oflagp->strunc) { if (op->verbose > 1) pr2serr("About to truncate %s to byte offset " "%" PRId64 "\n", op->odip->fn, offset); if (ftruncate(op->odip->fd, offset) < 0) { pr2serr("could not ftruncate after copy: %s\n", safe_strerror(errno)); return; } /* N.B. file offset (pointer) not changed by ftruncate */ } else if (1 == op->oflagp->sparse) { if (op->verbose > 1) pr2serr("writing sparse last block of zeros\n"); signals_process_delay(op, DELAY_WRITE); if (cp_write_block_reg(op, csp, -1, 1, op->zeros_buff) < 0) pr2serr("writing sparse last block of zeros " "error, seek=%" PRId64 "\n", op->seek - 1); else --op->out_sparse; } } } /* Main copy loop's finer grain comparison and possible write (to OFILE) * for all file types. Returns 0 on success. */ static int cp_finer_comp_wr(struct opts_t * op, struct cp_state_t * csp, const unsigned char * b1p, const unsigned char * b2p) { int res, k, n, oblks, numbytes, chunk, need_wr, wr_len, wr_k, obs; int trim_check, need_tr, tr_len, tr_k, out_type; int done_sigs_delay = 0; oblks = csp->ocbpt; obs = op->obs; out_type = op->odip->d_type; if (op->obpch >= oblks) { if (FT_DEV_NULL & out_type) ; else if (FT_PT & out_type) { signals_process_delay(op, DELAY_WRITE); if ((res = cp_write_pt(op, csp, 0, oblks, b1p))) return res; } else { signals_process_delay(op, DELAY_WRITE); if ((res = cp_write_block_reg(op, csp, 0, oblks, b1p))) return res; } return 0; } numbytes = oblks * obs; if ((FT_REG & out_type) && (csp->partial_write_bytes > 0)) numbytes += csp->partial_write_bytes; chunk = op->obpch * obs; trim_check = (op->oflagp->sparse && op->oflagp->wsame16 && (FT_PT & out_type)); need_tr = 0; tr_len = 0; tr_k = 0; for (k = 0, need_wr = 0, wr_len = 0, wr_k = 0; k < numbytes; k += chunk) { n = ((k + chunk) < numbytes) ? chunk : (numbytes - k); if (0 == memcmp(b1p + k, b2p + k, n)) { if (need_wr) { if (FT_DEV_NULL & out_type) ; else if (FT_PT & out_type) { if (! done_sigs_delay) { done_sigs_delay = 1; signals_process_delay(op, DELAY_WRITE); } if ((res = cp_write_pt(op, csp, wr_k / obs, wr_len / obs, b1p + wr_k))) return res; } else { if (! done_sigs_delay) { done_sigs_delay = 1; signals_process_delay(op, DELAY_WRITE); } if ((res = cp_write_block_reg(op, csp, wr_k / obs, wr_len / obs, b1p + wr_k))) return res; } need_wr = 0; } if (need_tr) tr_len += n; else if (trim_check) { need_tr = 1; tr_len = n; tr_k = k; } op->out_sparse += (n / obs); } else { /* look for a sequence of unequals */ if (need_wr) wr_len += n; else { need_wr = 1; wr_len = n; wr_k = k; } if (need_tr) { if (! done_sigs_delay) { done_sigs_delay = 1; signals_process_delay(op, DELAY_WRITE); } res = pt_write_same16(op, b2p, obs, tr_len / obs, op->seek + (tr_k / obs)); if (res) ++op->trim_errs; /* continue past trim errors */ need_tr = 0; } } } if (need_wr) { if (FT_DEV_NULL & out_type) ; else if (FT_PT & out_type) { if (! done_sigs_delay) { done_sigs_delay = 1; signals_process_delay(op, DELAY_WRITE); } if ((res = cp_write_pt(op, csp, wr_k / obs, wr_len / obs, b1p + wr_k))) return res; } else { if (! done_sigs_delay) { done_sigs_delay = 1; signals_process_delay(op, DELAY_WRITE); } if ((res = cp_write_block_reg(op, csp, wr_k / obs, wr_len / obs, b1p + wr_k))) return res; } } if (need_tr) { if (! done_sigs_delay) signals_process_delay(op, DELAY_WRITE); res = pt_write_same16(op, b2p, obs, tr_len / obs, op->seek + (tr_k / obs)); if (res) ++op->trim_errs; /* continue past trim errors */ } return 0; } static int cp_construct_pt_zero_buff(struct opts_t * op, int obpt) { if ((FT_PT & op->idip->d_type) && (NULL == op->idip->ptvp)) { op->idip->ptvp = (struct sg_pt_base *)pt_construct_obj(); if (NULL == op->idip->ptvp) return -1; } if ((FT_PT & op->odip->d_type) && (NULL == op->odip->ptvp)) { op->odip->ptvp = (struct sg_pt_base *)pt_construct_obj(); if (NULL == op->odip->ptvp) return -1; } if ((op->oflagp->sparse) && (NULL == op->zeros_buff)) { op->zeros_buff = (unsigned char *)calloc(obpt * op->obs, 1); if (NULL == op->zeros_buff) { pr2serr("zeros_buff calloc failed\n"); return -1; } } return 0; } /* Look at IFILE and OFILE lengths and blocks sizes. If dd_count * not given, try to deduce a value for it. If oflag=resume do skip, * seek, dd_count adjustments. Returns 0 to start copy, otherwise * bypass copy and exit */ static int count_calculate(struct opts_t * op) { int64_t in_num_blks = -1; int64_t out_num_blks = -1; int64_t ibytes, obytes, ibk; int valid_resume = 0; int res; if ((res = calc_count(op, &in_num_blks, &out_num_blks))) return res; if ((0 == op->oflagp->resume) && (op->dd_count > 0)) return 0; if (op->verbose > 1) pr2serr("calc_count: in_num_blks=%" PRId64 ", out_num_blks" "=%" PRId64 "\n", in_num_blks, out_num_blks); if (op->skip && (FT_REG == op->idip->d_type) && (op->skip > in_num_blks)) { pr2serr("cannot skip to specified offset on %s\n", op->idip->fn); op->dd_count = 0; return -1; } if (op->oflagp->resume) { if (FT_REG == op->odip->d_type) { if (out_num_blks < 0) pr2serr("resume cannot determine size of OFILE, ignore\n"); else valid_resume = 1; } else pr2serr("resume expects OFILE to be regular, ignore\n"); } if ((op->dd_count < 0) && (! valid_resume)) { /* Scale back in_num_blks by value of skip */ if (op->skip && (in_num_blks > op->skip)) in_num_blks -= op->skip; /* Scale back out_num_blks by value of seek */ if (op->seek && (out_num_blks > op->seek)) out_num_blks -= op->seek; if ((out_num_blks < 0) && (in_num_blks > 0)) op->dd_count = in_num_blks; else if ((op->reading_fifo) && (out_num_blks < 0)) ; else if ((out_num_blks < 0) && (in_num_blks <= 0)) ; else { ibytes = (in_num_blks > 0) ? (op->ibs * in_num_blks) : 0; obytes = op->obs * out_num_blks; if (0 == ibytes) op->dd_count = obytes / op->ibs; else if ((ibytes > obytes) && (FT_REG != op->odip->d_type)) { op->dd_count = obytes / op->ibs; } else op->dd_count = in_num_blks; } } if (valid_resume) { if (op->dd_count < 0) op->dd_count = in_num_blks - op->skip; if (out_num_blks <= op->seek) pr2serr("resume finds no previous copy, restarting\n"); else { obytes = op->obs * (out_num_blks - op->seek); ibk = obytes / op->ibs; if (ibk >= op->dd_count) { pr2serr("resume finds copy complete, exiting\n"); op->dd_count = 0; return -1; } /* align to bpt multiple */ ibk = (ibk / op->bpt_i) * op->bpt_i; op->skip += ibk; op->seek += (ibk * op->ibs) / op->obs; op->dd_count -= ibk; pr2serr("resume adjusting skip=%" PRId64 ", seek=%" PRId64 ", and count=%" PRId64 "\n", op->skip, op->seek, op->dd_count); } } return 0; } /* This is the main copy loop (unless an offloaded copy is requested). * Attempts to copy 'dd_count' blocks (size given by bs or ibs) in chunks * of op->bpt_i blocks. Returns 0 if successful. */ static int do_rw_copy(struct opts_t * op) { int ibpt, obpt, res, n, sparse_skip, sparing_skip, continual_read; int ret = 0; int first_time = 1; int id_type = op->idip->d_type; int od_type = op->odip->d_type; struct cp_state_t cp_st; struct cp_state_t * csp; unsigned char * wPos = op->wrkPos; continual_read = op->reading_fifo && (op->dd_count < 0); if (op->verbose > 3) { if (continual_read) pr2serr("do_rw_copy: reading fifo continually\n"); else pr2serr("do_rw_copy: dd_count=%" PRId64 "\n", op->dd_count); } if ((op->dd_count <= 0) && (! op->reading_fifo)) return 0; csp = &cp_st; memset(csp, 0, sizeof(struct cp_state_t)); ibpt = op->bpt_i; obpt = (op->ibs * op->bpt_i) / op->obs; if ((ret = cp_construct_pt_zero_buff(op, obpt))) goto copy_end; /* Both csp->if_filepos and csp->of_filepos are 0 */ /* <<< main loop that does the copy >>> */ while ((op->dd_count > 0) || continual_read) { if (first_time) first_time = 0; else signals_process_delay(op, DELAY_COPY_SEGMENT); csp->bytes_read = 0; csp->bytes_of = 0; csp->bytes_of2 = 0; sparing_skip = 0; sparse_skip = 0; if ((op->dd_count >= ibpt) || continual_read) { csp->icbpt = ibpt; csp->ocbpt = obpt; } else { csp->icbpt = op->dd_count; res = op->dd_count; n = res * op->ibs; csp->ocbpt = n / op->obs; if (n % op->obs) { ++csp->ocbpt; memset(wPos, 0, op->ibs * ibpt); } } /* Start of reading section */ if (FT_PT & id_type) { if ((ret = cp_read_pt(op, csp, wPos))) break; } else if (FT_FIFO & id_type) { if ((ret = cp_read_fifo(op, csp, wPos))) break; } else if (FT_TAPE & id_type) { #ifdef SG_LIB_LINUX if ((ret = cp_read_tape(op, csp, wPos))) break; #else pr2serr("reading from tape not supported in this OS\n"); ret = SG_LIB_CAT_OTHER; break; #endif } else { if ((ret = cp_read_block_reg(op, csp, wPos))) break; } if (0 == csp->icbpt) break; /* nothing read so leave loop */ if ((op->o2dip->fd >= 0) && ((ret = cp_write_of2(op, csp, wPos)))) break; if (op->oflagp->sparse) { n = (csp->ocbpt * op->obs) + csp->partial_write_bytes; if (0 == memcmp(wPos, op->zeros_buff, n)) { sparse_skip = 1; if (op->oflagp->wsame16 && (FT_PT & od_type)) { signals_process_delay(op, DELAY_WRITE); res = pt_write_same16(op, op->zeros_buff, op->obs, csp->ocbpt, op->seek); if (res) ++op->trim_errs; } } else if (op->obpch) { ret = cp_finer_comp_wr(op, csp, wPos, op->zeros_buff); if (ret) break; goto bypass_write; } } if (op->oflagp->sparing && (! sparse_skip)) { /* In write sparing, we read from the output */ if (FT_PT & od_type) res = cp_read_of_pt(op, csp, op->wrkPos2); else res = cp_read_of_block_reg(op, csp, op->wrkPos2); if (0 == res) { n = (csp->ocbpt * op->obs) + csp->partial_write_bytes; if (0 == memcmp(wPos, op->wrkPos2, n)) sparing_skip = 1; else if (op->obpch) { ret = cp_finer_comp_wr(op, csp, wPos, op->wrkPos2); if (ret) break; goto bypass_write; } } else { ret = res; break; } } /* Start of writing section */ if (sparing_skip || sparse_skip) { op->out_sparse += csp->ocbpt; if (csp->partial_write_bytes > 0) ++op->out_sparse_partial; } else { if (FT_DEV_NULL & od_type) ; /* don't bump out_full (earlier revs did) */ else { signals_process_delay(op, DELAY_WRITE); if (FT_PT & od_type) { if ((ret = cp_write_pt(op, csp, 0, csp->ocbpt, wPos))) break; } else if (FT_TAPE & od_type) { #ifdef SG_LIB_LINUX int could_be_last; could_be_last = ((! continual_read) && (csp->icbpt >= op->dd_count)); if ((ret = cp_write_tape(op, csp, wPos, could_be_last))) break; #else pr2serr("writing to tape not supported in this OS\n"); ret = SG_LIB_CAT_OTHER; break; #endif } else if ((ret = cp_write_block_reg(op, csp, 0, csp->ocbpt, wPos))) /* plus fifo */ break; } } bypass_write: #ifdef HAVE_POSIX_FADVISE do_fadvise(op, csp->bytes_read, csp->bytes_of, csp->bytes_of2); #endif if (op->dd_count > 0) op->dd_count -= csp->icbpt; op->skip += csp->icbpt; op->seek += csp->ocbpt; if (csp->leave_after_write) { if (REASON_TAPE_SHORT_READ == csp->leave_reason) { /* allow multiple partial writes for tape */ csp->partial_write_bytes = 0; csp->leave_after_write = 0; } else { /* other cases: stop copy after partial write */ ret = csp->leave_reason; break; } } } /* end of main loop that does the copy ... */ /* sparse: clean up ofile length when last block(s) were not written */ if ((FT_REG & od_type) && (0 == op->oflagp->nowrite) && op->oflagp->sparse) cp_sparse_cleanup(op, csp); #ifdef HAVE_FDATASYNC else if (op->oflagp->fdatasync) { if (fdatasync(op->odip->fd) < 0) perror("fdatasync() error"); if (op->verbose) pr2serr("Called fdatasync() on %s successfully\n", op->odip->fn); } #endif #ifdef HAVE_FSYNC else if (op->oflagp->fsync) { if (fsync(op->odip->fd) < 0) perror("fsync() error"); if (op->verbose) pr2serr("Called fsync() on %s successfully\n", op->odip->fn); } #endif copy_end: if (op->idip->ptvp) { pt_destruct_obj(op->idip->ptvp); op->idip->ptvp = NULL; } if (op->odip->ptvp) { pt_destruct_obj(op->odip->ptvp); op->odip->ptvp = NULL; } return ret; } static int prepare_pi(struct opts_t * op) { #define PI_WORK 1 /* Protection Information */ #ifdef PI_WORK int res; op->ibs_pi = op->ibs; op->obs_pi = op->obs; if (op->rdprotect) { if ((0 == op->idip->prot_type) || (! (FT_PT & op->idip->d_type))) { pr2serr("IFILE is not a pt device or doesn't have " "protection information\n"); return SG_LIB_CAT_OTHER; } if (op->ibs != op->obs) { pr2serr("protect: don't support IFILE and OFILE " "with different block sizes\n"); return SG_LIB_CAT_OTHER; } if (op->wrprotect) { if (op->idip->p_i_exp != op->odip->p_i_exp) { pr2serr("Don't support IFILE and OFILE with " "different P_I_EXP fields\n"); return SG_LIB_CAT_OTHER; } } res = (op->idip->p_i_exp ? (1 << op->idip->p_i_exp) : 1) * 8; op->ibs_pi += res; op->obs_pi += res; } if (op->wrprotect) { if ((0 == op->odip->prot_type) || (! (FT_PT & op->odip->d_type))) { pr2serr("OFILE is not a pt device or doesn't have " "protection information\n"); return SG_LIB_CAT_OTHER; } if (op->ibs != op->obs) { pr2serr("protect: don't support IFILE and OFILE " "with different block sizes\n"); return SG_LIB_CAT_OTHER; } res = (op->odip->p_i_exp ? (1 << op->odip->p_i_exp) : 1) * 8; op->ibs_pi += res; op->obs_pi += res; } #else if (op) { ; } /* suppress warning */ #endif /* PI_WORK */ return 0; } static int open_files_devices(struct opts_t * op) { int fd, ret; struct dev_info_t * idip = op->idip; struct dev_info_t * odip = op->odip; struct dev_info_t * o2dip = op->o2dip; #ifdef SG_LIB_WIN32 win32_adjust_fns_pt(op); #endif if (idip->fn[0]) { if (('-' == idip->fn[0]) && ('\0' == idip->fn[1])) { fd = STDIN_FILENO; idip->d_type = FT_FIFO; ++op->reading_fifo; if (op->verbose) pr2serr(" >> Input file type: fifo [stdin, stdout, named " "pipe]\n"); } else { fd = open_if(op); if (fd < 0) return -fd; } idip->fd = fd; } else { pr2serr("'if=IFILE' option must be given. For stdin as input use " "'if=-'\n"); pr2serr("For more information use '--help'\n"); return SG_LIB_SYNTAX_ERROR; } if ('\0' == odip->fn[0]) strcpy(odip->fn, "."); /* treat no 'of=OFILE' option as /dev/null */ if (('-' == odip->fn[0]) && ('\0' == odip->fn[1])) { fd = STDOUT_FILENO; odip->d_type = FT_FIFO; odip->d_type_hold = odip->d_type; if (op->verbose) pr2serr(" >> Output file type: fifo [stdin, stdout, named " "pipe]\n"); } else { fd = open_of(op); if (fd < -1) return -fd; } odip->fd = fd; if (o2dip->fn[0]) { if (('-' == o2dip->fn[0]) && ('\0' == o2dip->fn[1])) { fd = STDOUT_FILENO; o2dip->d_type = FT_FIFO; if (op->verbose) pr2serr(" >> Output 2 file type: fifo [stdin, stdout, " "named pipe]\n"); } else { o2dip->d_type = dd_filetype(o2dip->fn, op->verbose); if (FT_DEV_NULL & o2dip->d_type) fd = -1; else if (! ((FT_REG | FT_FIFO) & o2dip->d_type)) { pr2serr("Error: output 2 file type must be regular " "file or fifo\n"); return SG_LIB_FILE_ERROR; } else { if ((fd = open(o2dip->fn, O_WRONLY | O_CREAT, 0666)) < 0) { ret = errno; pr2serr("could not open %s for writing: %s\n", o2dip->fn, safe_strerror(errno)); return ret; } if (sg_set_binary_mode(fd) < 0) perror("sg_set_binary_mode"); if (op->verbose) pr2serr(" >> Output 2 file type: regular\n"); } } } else fd = -1; o2dip->fd = fd; return 0; } static void block_size_bpt_check(struct opts_t * op) { if (0 == op->bpt_given) { /* If reading from or writing to tape, use default bpt 1 if user did not * specify. Avoids inadvertent/accidental use of wrong tape block size. */ if ((FT_TAPE & op->idip->d_type) || (FT_TAPE & op->odip->d_type)) { op->bpt_i = 1; } #ifdef SG_LIB_FREEBSD else { /* FreeBSD (7+8 [DFLTPHYS]) doesn't like buffers larger than 64 KB being * sent to its pt interface (CAM), so take that into account when choosing * the default bpt value. There is overhead in the pt interface so reduce * default bpt value so bpt*ibs <= 32 KB .*/ if (((FT_PT & op->idip->d_type) || (FT_PT & op->odip->d_type)) && ((op->ibs <= 32768) && (op->bpt_i * op->ibs) > 32768)) op->bpt_i = 32768 / op->ibs; } #endif } } static void sparse_sparing_check(struct opts_t * op) { if (op->iflagp->sparse && (! op->oflagp->sparse)) { if (FT_DEV_NULL & op->odip->d_type) { pr2serr("sparse flag usually ignored on input; set it " "on output in this case\n"); ++op->oflagp->sparse; } else pr2serr("sparse flag ignored on input\n"); } if (op->oflagp->sparse) { if ((FT_FIFO | FT_TAPE) & op->odip->d_type) { pr2serr("oflag=sparse needs seekable output file, ignore\n"); op->oflagp->sparse = 0; } else { op->out_sparse_active = 1; if (op->oflagp->wsame16) op->out_trim_active = 1; } } if (op->oflagp->sparing) { if ((FT_DEV_NULL | FT_FIFO | FT_TAPE) & op->odip->d_type) { pr2serr("oflag=sparing needs a readable and seekable " "output file, ignore\n"); op->oflagp->sparing = 0; } else op->out_sparing_active = 1; } } static void cdb_size_prealloc(struct opts_t * op) { if (op->oflagp->prealloc) { if ((FT_DEV_NULL | FT_FIFO | FT_TAPE | FT_PT) & op->odip->d_type) { pr2serr("oflag=pre-alloc needs a normal output file, ignore\n"); op->oflagp->prealloc = 0; } } if (! op->cdbsz_given) { if ((FT_PT & op->idip->d_type) && (op->iflagp->cdbsz < 16) && (((op->dd_count + op->skip) > UINT_MAX) || (op->bpt_i > USHRT_MAX))) { if (op->verbose > 0) pr2serr("SCSI command size increased from 10 to 16 " "bytes on %s\n", op->idip->fn); op->iflagp->cdbsz = 16; } if ((FT_PT & op->odip->d_type) && (op->oflagp->cdbsz < 16) && (((op->dd_count + op->seek) > UINT_MAX) || (((op->ibs * op->bpt_i) / op->obs) > USHRT_MAX))) { if (op->verbose) pr2serr("SCSI command size increased from 10 to 16 " "bytes on %s\n", op->odip->fn); op->oflagp->cdbsz = 16; } } } #ifdef SG_LIB_LINUX static void tape_cleanup_of(struct opts_t * op) { /* Before closing OFILE, if writing to tape handle suppressing the * writing of a filemark and/or flushing the drive buffer which the * Linux st driver normally does when tape file is closed after writing. * Possibilities depend on oflags: * nofm: MTWEOFI 0 if possible (kernel 2.6.37+), else MTBSR 0 * nofm & fsync: MTWEOF 0 * fsync: Do nothing; st writes filemark & flushes buffer on close. * neither: MTWEOFI 1 if possible (2.6.37+), else nothing (drive * buffer will be flushed if MTWEOFI not possible). */ struct mtop mt_cmd; int res; if (op->oflagp->nofm || !op->oflagp->fsync) { mt_cmd.mt_op = (op->oflagp->fsync) ? MTWEOF : MTWEOFI; mt_cmd.mt_count = (op->oflagp->nofm) ? 0 : 1; res = ioctl(op->odip->fd, MTIOCTOP, &mt_cmd); if (res != 0) { if (op->verbose > 0) pr2serr("MTWEOF%s %d failed: %s\n", (op->oflagp->fsync) ? "" : "I", mt_cmd.mt_count, safe_strerror(errno)); if (op->oflagp->nofm && !op->oflagp->fsync) { if (op->verbose > 0) pr2serr("Trying MTBSR 0 instead\n"); mt_cmd.mt_op = MTBSR; /* mt_cmd.mt_count = 0 from above */ res = ioctl(op->odip->fd, MTIOCTOP, &mt_cmd); if (res != 0) pr2serr("MTBSR 0 failed: %s\n(Filemark will be written " "when tape file is closed)\n", safe_strerror(errno)); } } } } #endif /* SG_LIB_LINUX */ static int do_falloc(struct opts_t * op) { #ifdef SG_LIB_LINUX #ifdef HAVE_FALLOCATE /* Try to pre-allocate space in the output file. * * If fallocate() does not succeed, exit with an error message. The user * can then either free up some disk space or invoke ddpt without * oflag=pre-alloc (at the risk of running out of disk space). * * TODO/DISCUSSION: Some filesystems (e.g. FAT32) don't support * fallocate(). In that case we should probably have a way to continue if * fallocate() fails, rather than exiting; useful for use in scripts * where the user would like to pre-allocate space when possible. * * On Linux, try fallocate() with the FALLOC_FL_KEEP_SIZE flag, which * allocates space but doesn't change the apparent file size (useful * since oflag=resume can be used). * * If fallocate() with FALLOC_FL_KEEP_SIZE returns ENOTTY, EINVAL or * EOPNOTSUPP, retry without that flag (since the flag is only supported * in recent Linux kernels). */ int res; #ifdef PREALLOC_DEBUG pr2serr("About to call fallocate() with FALLOC_FL_KEEP_SIZE\n"); #endif res = fallocate(op->odip->fd, FALLOC_FL_KEEP_SIZE, op->obs*op->seek, op->obs*op->dd_count); #ifdef PREALLOC_DEBUG pr2serr("fallocate() returned %d\n", res); #endif /* fallocate() fails if the kernel does not support * FALLOC_FL_KEEP_SIZE, so retry without that flag. */ if (-1 == res) { if ((ENOTTY == errno) || (EINVAL == errno) || (EOPNOTSUPP == errno)) { if (op->verbose) pr2serr("Could not pre-allocate with " "FALLOC_FL_KEEP_SIZE (%s), retrying without " "...\n", safe_strerror(errno)); res = fallocate(op->odip->fd, 0, op->obs*op->seek, op->obs*op->dd_count); #ifdef PREALLOC_DEBUG pr2serr("fallocate() without FALLOC_FL_KEEP_SIZE " " returned %d\n", res); #endif } } else { /* fallocate() with FALLOC_FL_KEEP_SIZE succeeded. Set * op->oflagp->prealloc to 0 so the possible message about using * oflag=resume is not suppressed later. */ op->oflagp->prealloc = 0; } if (-1 == res) { pr2serr("Unable to pre-allocate space: %s\n", safe_strerror(errno)); return SG_LIB_CAT_OTHER; } if (op->verbose > 1) pr2serr("Pre-allocated %" PRId64 " bytes at offset %" PRId64 "\n", op->obs*op->dd_count, op->obs*op->seek); #endif /* HAVE_FALLOCATE */ #else /* other than SG_LIB_LINUX */ #ifdef HAVE_POSIX_FALLOCATE int res; /* If not on Linux, use posix_fallocate(). (That sets the file size to its * full length, so re-invoking ddpt with oflag=resume will do nothing.) */ res = posix_fallocate(op->odip->fd, op->obs*op->seek, op->obs*op->dd_count); if (-1 == res) { pr2serr("Unable to pre-allocate space: %s\n", safe_strerror(errno)); return SG_LIB_CAT_OTHER; } if (op->verbose > 1) pr2serr("Pre-allocated %" PRId64 " bytes at offset %" PRId64 "\n", op->obs*op->dd_count, op->obs*op->seek); #else /* do not HAVE_POSIX_FALLOCATE */ if (op) { ; } #endif /* HAVE_POSIX_FALLOCATE else */ #endif /* SG_LIB_LINUX else */ return 0; } static void details_pre_copy_print(struct opts_t * op) { pr2serr("skip=%" PRId64 " (blocks on input), seek=%" PRId64 " (blocks on output)\n", op->skip, op->seek); if (op->verbose > 1) { pr2serr(" ibs=%d bytes, obs=%d bytes, OBPC=%d\n", op->ibs, op->obs, op->obpch); if (op->ibs != op->ibs_pi) pr2serr(" due to protect ibs_pi=%d bytes, " "obs_pi=%d bytes\n", op->ibs_pi, op->obs_pi); } if (op->reading_fifo && (op->dd_count < 0)) pr2serr(" reading fifo, blocks_per_transfer=%d\n", op->bpt_i); else pr2serr(" initial count=%" PRId64 " (blocks of input), " "blocks_per_transfer=%d\n", op->dd_count, op->bpt_i); if ((op->delay > 0) || (op->wdelay > 0)) pr2serr(" delay=%d ms, wdelay=%d ms\n", op->delay, op->wdelay); } static int wrk_buffers_init(struct opts_t * op) { int len = op->ibs_pi * op->bpt_i; if (op->has_xcopy) return 0; if (op->iflagp->direct || op->oflagp->direct) { size_t psz; #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) psz = sysconf(_SC_PAGESIZE); /* POSIX.1 (was getpagesize()) */ #elif defined(SG_LIB_WIN32) psz = win32_pagesize(); #else psz = 4096; /* give up, pick likely figure */ #endif #ifdef HAVE_POSIX_MEMALIGN { int err; void * wp; wp = op->wrkBuff; err = posix_memalign(&wp, psz, len); if (err) { pr2serr("posix_memalign: error [%d] out of memory?\n", err); return SG_LIB_CAT_OTHER; } op->wrkBuff = (unsigned char *)wp; memset(op->wrkBuff, 0, len); op->wrkPos = op->wrkBuff; if (op->oflagp->sparing) { wp = op->wrkBuff2; err = posix_memalign(&wp, psz, len); if (err) { pr2serr("posix_memalign(2): error [%d] out of memory?\n", err); return SG_LIB_CAT_OTHER; } op->wrkBuff2 = (unsigned char *)wp; memset(op->wrkBuff2, 0, len); op->wrkPos2 = op->wrkBuff2; } } #else /* do not HAVE_POSIX_MEMALIGN */ op->wrkBuff = (unsigned char*)calloc(len + psz, 1); if (0 == op->wrkBuff) { pr2serr("Not enough user memory for aligned usage\n"); return SG_LIB_CAT_OTHER; } op->wrkPos = (unsigned char *)(((unsigned long)op->wrkBuff + psz - 1) & (~(psz - 1))); if (op->oflagp->sparing) { op->wrkBuff2 = (unsigned char*)calloc(len + psz, 1); if (0 == op->wrkBuff2) { pr2serr("Not enough user memory for aligned usage(2)\n"); return SG_LIB_CAT_OTHER; } op->wrkPos2 = (unsigned char *) (((unsigned long)op->wrkBuff2 + psz - 1) & (~(psz - 1))); } #endif /* HAVE_POSIX_MEMALIGN */ } else { op->wrkBuff = (unsigned char*)calloc(op->ibs_pi * op->bpt_i, 1); if (0 == op->wrkBuff) { pr2serr("Not enough user memory\n"); return SG_LIB_CAT_OTHER; } op->wrkPos = op->wrkBuff; if (op->oflagp->sparing) { op->wrkBuff2 = (unsigned char*)calloc(op->ibs_pi * op->bpt_i, 1); if (0 == op->wrkBuff2) { pr2serr("Not enough user memory(2)\n"); return SG_LIB_CAT_OTHER; } op->wrkPos2 = op->wrkBuff2; } } return 0; } static void cleanup_resources(struct opts_t * op) { #ifdef SG_LIB_LINUX if ((FT_TAPE & op->idip->d_type) || (FT_TAPE & op->odip->d_type)) { /* For writing, the st driver writes a filemark on closing the file * (unless user specified oflag=nofm), so make clear that the * position shown is prior to closing. */ print_tape_pos("Final ", " (before closing file)", op); if ((FT_TAPE & op->odip->d_type) && (op->verbose > 1) && op->oflagp->nofm) pr2serr("(suppressing writing of filemark on close)\n"); } #endif if (op->iflagp->errblk) errblk_close(op); if (op->wrkBuff) free(op->wrkBuff); if (op->wrkBuff2) free(op->wrkBuff2); if (op->zeros_buff) free(op->zeros_buff); if (FT_PT & op->idip->d_type) pt_close(op->idip->fd); else if ((op->idip->fd >= 0) && (STDIN_FILENO != op->idip->fd)) close(op->idip->fd); if (FT_PT & op->odip->d_type) pt_close(op->odip->fd); if ((op->odip->fd >= 0) && (STDOUT_FILENO != op->odip->fd) && !(FT_DEV_NULL & op->odip->d_type)) { #ifdef SG_LIB_LINUX if (FT_TAPE & op->odip->d_type) tape_cleanup_of(op); #endif close(op->odip->fd); } if ((op->o2dip->fd >= 0) && (STDOUT_FILENO != op->o2dip->fd)) close(op->o2dip->fd); } static int chk_sgl_for_non_offload(struct opts_t * op) { if (op->in_sgl) { if (op->in_sgl_elems > 1) { pr2serr("Only accept a multiple element skip= (gather) list for " "%s with odx\n", op->idip->fn[0] ? op->idip->fn : "?"); return SG_LIB_SYNTAX_ERROR; } if ((op->dd_count >= 0) && (op->dd_count != op->in_sgl[0].num)) { pr2serr("dd_count [%" PRIu64 "] and skip (sgl num) [%" PRIu32 "] " "contradict\n", op->dd_count, op->in_sgl[0].num); return SG_LIB_SYNTAX_ERROR; } op->skip = op->in_sgl[0].lba; op->dd_count = op->in_sgl[0].num; } if (op->out_sgl) { if (op->out_sgl_elems > 1) { pr2serr("Only accept a multiple element seek= (scatter) list for " "%s with odx\n", op->odip->fn[0] ? op->odip->fn : "?"); return SG_LIB_SYNTAX_ERROR; } /* assuming ibs==obs, revisit xxxxxxx */ if ((op->dd_count >= 0) && (op->dd_count != op->out_sgl[0].num)) { pr2serr("dd_count [%" PRIu64 "] and seek (sgl num) [%" PRIu32 "] " "too confusing\n", op->dd_count, op->out_sgl[0].num); return SG_LIB_SYNTAX_ERROR; } op->seek = op->out_sgl[0].lba; op->dd_count = op->out_sgl[0].num; } return 0; } /* The main() function: much of the its complex logic is spawned off to * helper functions shown directly above. */ int main(int argc, char * argv[]) { int ret = 0; int started_copy = 0; struct opts_t ops; struct flags_t iflag, oflag; struct dev_info_t ids, ods, o2ds; struct opts_t * op; state_init(&ops, &iflag, &oflag, &ids, &ods, &o2ds); op = &ops; ret = cl_process(op, argc, argv, ddpt_version_str); if (op->do_help > 0) { ddpt_usage(op->do_help); return 0; } else if (ret) return (ret < 0) ? 0 : ret; if (op->quiet) { if (NULL == freopen("/dev/null", "w", stderr)) pr2serr("freopen: failed to redirect stderr to /dev/null : %s\n", safe_strerror(errno)); } #ifdef SG_LIB_WIN32 if (op->wscan) return sg_do_wscan('\0', op->wscan, op->verbose); #endif install_signal_handlers(op); if (op->has_odx) { started_copy = 1; ret = do_odx(op); goto cleanup; } /* may allow scatter gather lists for non-odx copies in future */ ret = chk_sgl_for_non_offload(op); if (ret) return ret; if ((ret = open_files_devices(op))) return ret; block_size_bpt_check(op); sparse_sparing_check(op); if ((ret = count_calculate(op))) { if (op->verbose) pr2serr("count_calculate() returned %d, exit\n", ret); goto cleanup; } if ((ret = prepare_pi(op))) goto cleanup; if ((op->dd_count < 0) && (! op->reading_fifo)) { pr2serr("Couldn't calculate count, please give one\n"); ret = SG_LIB_CAT_OTHER; goto cleanup; } cdb_size_prealloc(op); if ((ret = wrk_buffers_init(op))) goto cleanup; if (ops.verbose) details_pre_copy_print(op); op->read1_or_transfer = !! (FT_DEV_NULL & op->odip->d_type); if (op->read1_or_transfer && (! op->outf_given) && ((op->dd_count > 0) || op->reading_fifo)) pr2serr("Output file not specified so no copy, just reading input\n"); if (op->do_time) calc_duration_init(op); if (op->iflagp->errblk) errblk_open(op); #ifdef SG_LIB_LINUX if ((FT_TAPE & op->idip->d_type) || (FT_TAPE & op->odip->d_type)) print_tape_pos("Initial ", "", op); #endif if (op->oflagp->prealloc) { if ((ret = do_falloc(op))) goto cleanup; } ++started_copy; if (op->has_xcopy) ret = do_xcopy_lid1(op); else ret = do_rw_copy(op); if (0 == op->status_none) print_stats("", op, 0); if ((op->oflagp->ssync) && (FT_PT & op->odip->d_type)) { if (0 == op->status_none) pr2serr(">> SCSI synchronizing cache on %s\n", op->odip->fn); pt_sync_cache(op->odip->fd); } if (op->do_time) calc_duration_throughput("", 0, op); if (op->sum_of_resids) pr2serr(">> Non-zero sum of residual counts=%d\n", op->sum_of_resids); cleanup: cleanup_resources(op); if ((0 == ret) && op->err_to_report) ret = op->err_to_report; if (started_copy && (0 != op->dd_count) && (! op->reading_fifo)) { if (0 == ret) pr2serr("Early termination, EOF on input?\n"); else if (ret > 0) print_exit_status_msg("Early termination", ret, 1); else pr2serr("Early termination: some error occurred; try again with " "'-vv'\n"); } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; } ddpt-0.94/src/ddpt_cl.c0000644000175000017500000013144012320426132013737 0ustar douggdougg/* * Copyright (c) 2008-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This file contains command line helper functions for ddpt. */ /* Was needed for posix_fadvise() */ /* #define _XOPEN_SOURCE 600 */ /* Need _GNU_SOURCE for O_DIRECT */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #define __STDC_LIMIT_MACROS 1 /* for UINT64_MAX, UINT32_MAX, etc */ #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include /* N.B. config.h must precede anything that depends on HAVE_* */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ddpt.h" /* includes */ #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" #include "sg_pt.h" static struct scat_gath_elem in_fixed_sgl[MAX_FIXED_SGL_ELEMS]; static struct scat_gath_elem out_fixed_sgl[MAX_FIXED_SGL_ELEMS]; void ddpt_usage(int help) { if (help < 2) goto primary_help; else if (2 == help) goto secondary_help; else goto tertiary_help; primary_help: pr2serr("Usage: " "ddpt [bpt=BPT[,OBPC]] [bs=BS] [cdbsz=6|10|12|16|32] [coe=0|1]\n" " [coe_limit=CL] [conv=CONVS] [count=COUNT] " "[delay=MS[,W_MS]]\n" " [ibs=IBS] [id_usage=LIU] if=IFILE [iflag=FLAGS] " "[intio=0|1]\n" " [iseek=SKIP] [ito=ITO] [list_id=LID] [obs=OBS] " "[of=OFILE]\n" " [of2=OFILE2] [oflag=FLAGS] [oseek=SEEK] " "[prio=PRIO]\n" " [protect=RDP[,WRP]] [retries=RETR] [rtf=RTF] " "[rtype=RTYPE]\n" " [seek=SEEK] [skip=SKIP] [status=STAT] [to=TO] " "[verbose=VERB]\n" #ifdef SG_LIB_WIN32 " [--help] [--odx] [--verbose] [--version] [--wscan] " "[--xcopy]\n" #else " [--help] [--odx] [--verbose] [--version] [--xcopy]\n" #endif " where the main options are:\n" " bpt input Blocks Per Transfer (BPT) (def: 128 when " "IBS is 512)\n" " Output Blocks Per Check (OBPC) (def: 0 implies " "BPT*IBS/OBS)\n" " bs block size for input and output (overrides " "ibs and obs)\n"); pr2serr( " coe 0->exit on error (def), 1->continue on " "error (zero fill)\n" " conv conversions, comma separated list of CONVS " "(see '-hhh')\n" " count number of input blocks to copy (def: " "(remaining)\n" " device/file size)\n" " ibs input block size (default 512 bytes)\n" " if file or device to read from (for stdin use " "'-')\n" " iflag input flags, comma separated list from FLAGS " "(see below)\n" " obs output block size (def: 512). When IBS is " "not equal to OBS\n" " then (((IBS * BPT) %% OBS) == 0) is required\n" " of file or device to write to (def: /dev/null)\n"); pr2serr( " oflag output flags, comma separated list from FLAGS " "(see below)\n" " retries retry pass-through errors RETR times " "(def: 0)\n" " seek block position to start writing in OFILE\n" " skip block position to start reading from IFILE\n" " status 'noxfer' suppresses throughput calculation; " "'none'\n" " suppresses all trailing reports (apart from " "errors)\n" " verbose 0->normal(def), 1->some noise, 2->more noise, " "etc\n" " -1->quiet (stderr->/dev/null)\n" " --help print out this usage message then exit\n" " --odx do ODX copy rather than normal rw copy\n" " --verbose equivalent to verbose=1\n" " --version print version information then exit\n" #ifdef SG_LIB_WIN32 " --wscan windows scan for device names and volumes\n" #endif " --xcopy do xcopy(LID1) rather than normal rw copy\n" "\nCopy all or part of IFILE to OFILE, IBS*BPT bytes at a time. " "Similar to\n" "dd command. Support for block devices, especially those " "accessed via a\nSCSI pass-through. Also supports offloaded " "copies: xcopy(LID1) and ODX.\nFor more information use " "'-h' multiple times (e.g. '-hh' or '-hhh').\n"); return; secondary_help: pr2serr(" where the lesser used command line options are:\n" " cdbsz size of SCSI READ or WRITE cdb (default is " "10)\n" " coe_limit limit consecutive 'bad' blocks on reads to CL " "times\n" " when coe=1 (default: 0 which is no limit)\n" " delay wait MS milliseconds between each copy segment " "(def: 0)\n" " wait W_MS milliseconds prior to each write " "(def: 0)\n" " id_usage xcopy: set list_id_usage to hold (0), discard " "(2),\n" " disable (3), or the given number (def: 0 or " "2)\n" " intio interrupt during IO; allow signals during reads " "and writes\n" " (def: 0 causes signals to be masked during IO)\n" " iseek block position to start reading from IFILE " "(same as skip)\n" " ito inactivity timeout (def: 0 (from 3PC VPD); " "units: seconds)\n" " list_id xcopy: list_id (def: 1 or 0) [1 byte]\n" " odx: list_id (def: 257 or 258) [4 bytes]\n" " of2 additional output file (def: /dev/null), " "OFILE2 should be\n" " regular file or pipe\n" " oseek block position to start writing in OFILE\n" " prio xcopy: set priority field to PRIO (def: 1)\n" " protect set rdprotect and/or wrprotect fields on " "pt commands\n" " rtf ROD Token filename (odx)\n" " rtype ROD type (odx), can be pit-any, pit-def, " "pit-pers,\n" " pit-vuln, zero or number (def: 0 -> cm " "decides)\n" " to xcopy, odx: timeout in seconds (def: 600 " "(10 mins))\n\n"); pr2serr("FLAGS: (arguments to oflag= and oflag=; may be comma " "separated)\n" " append (o) append (part of) IFILE to end of OFILE\n" " block (pt) pt opens are non blocking by default\n" " cat (xcopy) set CAT bit in segment descriptor header\n" " coe continue on (read) error\n" " dc (xcopy) set DC bit in segment descriptor header\n" " direct set O_DIRECT flag in open() of IFILE and/or " "OFILE\n" " dpo set disable page out (DPO) on pt READs and " "WRITES\n" " errblk (i,pt) write errored LBAs to errblk.txt file\n" " excl set O_EXCL flag in open() of IFILE and/or " "OFILE\n" " fdatasync (o) flushes data to OFILE at the end of copy\n" " flock use advisory exclusive lock [flock()] on " "IFILE/OFILE\n" " force override inconsistent information that would " "stop copy\n" " fsync (o) like fdatasync but flushes meta-data as well\n" " fua (pt) force unit access on IFILE or OFILE\n" " fua_nv (pt) force unit access, non-volatile (obsoleted by " "T10)\n" " ignoreew (o) ignore early warning (end of tape)\n" " immed (odx) commands poll until complete, report " "progress\n" "... continued on next page (use '-hhh')\n"); return; tertiary_help: pr2serr("FLAGS: (continued)\n" " nocache use posix_fadvise(POSIX_FADV_DONTNEED)\n" " no_del_tkn (odx) do not set DEL_TKN on last write from " "ROD\n" " nofm (o) no File Mark (FM) on close when writing to " "tape\n" " nopad inhibits tapes blocks less than OBS being " "padded\n" " norcap (pt) do not invoke SCSI READ CAPACITY command\n" " nowrite (o) bypass all writes to OFILE\n" " null does nothing, place holder\n" " odx request xcopy(LID4) based on POPULATE TOKEN " "(disk->ROD)\n" " and/or WRITE USING TOKEN (ROD->disk) " "commands\n" " pad (o) pad blocks shorter than OBS with zeroes\n" " pre-alloc (o) use fallocate() before copy to set OFILE to " "its\n" " expected size\n" " pt instruct pass-through interface to be used\n" " rarc (i,pt) set RARC (rebuild assist) bit in SCSI READs\n" " resume (o) attempt to restart an interrupted copy\n" " rtf_len place ROD size after each ROD token in RTF\n" " self (pt) used with trim; IFILE=OFILE; trim zero " "segments\n" " sparing (o) read OFILE prior to a write; don't write if " "same\n" " sparse (o) don't write blocks of zeroes; move file " "pointer\n" " or if OFILE is pt assume it contains zeroes " "already\n" " ssync (o,pt) at end of copy do SCSI SYNCHRONIZE CACHE\n" " strunc (o) sparse copy using ftruncate to extend OFILE " "as needed\n" " sync set O_SYNC flag in open() of IFILE and/or " "OFILE\n" " trim (pt) use SCSI UNMAP (trim) on zero segments " "instead of\n" " writing them to OFILE\n" " trunc (o) truncate a regular OFILE prior to copy (def: " "overwrite)\n" " unmap (pt) same as trim flag\n" " xcopy (pt) invoke SCSI XCOPY; send to IFILE or OFILE.\n\n" "CONVS:\n" " fdatasync same as oflag=fdatasync\n" " fsync same as oflag=fsync\n" " no_del_tkn same as oflag=no_del_tkn\n" " noerror similar to iflag=coe\n" " notrunc does nothing because this is default action " "of ddpt\n" " null does nothing, place holder\n" " resume same as oflag=resume\n" " rtf_len same as oflag=rtf_len\n" " sparing same as oflag=sparing\n" " sparse same as oflag=sparse\n" " sync ignored to allow 'conv=noerror,sync' dd usage " "for coe\n" " trunc same as oflag=trunc\n\n" "ENVIRONMENT VARIABLES:\n" " ODX_RTF_LEN append ROD size (8 byte big-endian) to token " "in RTF\n" " XCOPY_TO_DST send XCOPY command to OFILE (destination) " "if no other\n" " indication\n" " XCOPY_TO_SRC send XCOPY command to IFILE (source)\n"); } /* Returns the number of times 'ch' is found in string 's' given the * string's length. */ static int num_chs_in_str(const char * s, int slen, int ch) { int res = 0; while (--slen >= 0) { if (ch == s[slen]) ++res; } return res; } static int do_skip(struct opts_t * op, const char * key, const char * buf) { int len, res, got; len = (int)strlen(buf); if ((('-' == buf[0]) && (1 == len)) || ((len > 1) && ('@' == buf[0]))) { res = file_to_sgl(((len > 1) ? (buf + 1) : buf), in_fixed_sgl, &got, MAX_FIXED_SGL_ELEMS); if (res) { pr2serr("bad argument to '%s='\n", key); return SG_LIB_SYNTAX_ERROR; } op->in_sgl = in_fixed_sgl; op->in_sgl_elems = got; } else if (num_chs_in_str(buf, len, ',') > 0) { res = cl_to_sgl(buf, in_fixed_sgl, &got, MAX_FIXED_SGL_ELEMS); if (res) { pr2serr("bad argument to '%s='\n", key); return SG_LIB_SYNTAX_ERROR; } op->in_sgl = in_fixed_sgl; op->in_sgl_elems = got; } else { op->skip = sg_get_llnum(buf); if (-1LL == op->skip) { pr2serr("bad argument to '%s='\n", key); return SG_LIB_SYNTAX_ERROR; } } return 0; } static int do_seek(struct opts_t * op, const char * key, const char * buf) { int len, res; int got = 0; len = (int)strlen(buf); if ((('-' == buf[0]) && (1 == len)) || ((len > 1) && ('@' == buf[0]))) { res = file_to_sgl(((len > 1) ? (buf + 1) : buf), out_fixed_sgl, &got, MAX_FIXED_SGL_ELEMS); if (res) { pr2serr("bad argument to '%s='\n", key); return SG_LIB_SYNTAX_ERROR; } op->out_sgl = out_fixed_sgl; op->out_sgl_elems = got; } else if (num_chs_in_str(buf, len, ',') > 0) { res = cl_to_sgl(buf, out_fixed_sgl, &got, MAX_FIXED_SGL_ELEMS); if (res) { pr2serr("bad argument to '%s='\n", key); return SG_LIB_SYNTAX_ERROR; } op->out_sgl = out_fixed_sgl; op->out_sgl_elems = got; } else { op->seek = sg_get_llnum(buf); if (-1LL == op->seek) { pr2serr("bad argument to '%s='\n", key); return SG_LIB_SYNTAX_ERROR; } } return 0; } /* Process arguments given to 'conv=" option. Returns 0 on success, * 1 on error. */ static int conv_process(const char * arg, struct flags_t * ifp, struct flags_t * ofp) { char buff[256]; char * cp; char * np; strncpy(buff, arg, sizeof(buff)); buff[sizeof(buff) - 1] = '\0'; if ('\0' == buff[0]) { pr2serr("no conversions found\n"); return 1; } cp = buff; do { np = strchr(cp, ','); if (np) *np++ = '\0'; if (0 == strcmp(cp, "fdatasync")) ++ofp->fdatasync; else if (0 == strcmp(cp, "fsync")) ++ofp->fsync; else if (0 == strcmp(cp, "no_del_tkn")) ++ofp->no_del_tkn; else if (0 == strcmp(cp, "noerror")) ++ifp->coe; /* will still fail on write error */ else if (0 == strcmp(cp, "notrunc")) ; /* this is the default action of ddpt so ignore */ else if (0 == strcmp(cp, "null")) ; else if (0 == strcmp(cp, "resume")) ++ofp->resume; else if (0 == strcmp(cp, "rtf_len")) ++ofp->rtf_len; else if (0 == strcmp(cp, "sparing")) ++ofp->sparing; else if (0 == strcmp(cp, "sparse")) ++ofp->sparse; else if (0 == strcmp(cp, "sync")) ; /* dd(susv4): pad errored block(s) with zeros but ddpt does * that by default. Typical dd use: 'conv=noerror,sync' */ else if (0 == strcmp(cp, "trunc")) ++ofp->trunc; else { pr2serr("unrecognised flag: %s\n", cp); return 1; } cp = np; } while (cp); return 0; } /* Process arguments given to 'iflag=" and 'oflag=" options. Returns 0 * on success, 1 on error. */ static int flags_process(const char * arg, struct flags_t * fp) { char buff[256]; char * cp; char * np; strncpy(buff, arg, sizeof(buff)); buff[sizeof(buff) - 1] = '\0'; if ('\0' == buff[0]) { pr2serr("no flag found\n"); return 1; } cp = buff; do { np = strchr(cp, ','); if (np) *np++ = '\0'; if (0 == strcmp(cp, "append")) ++fp->append; else if (0 == strcmp(cp, "block")) ++fp->block; else if (0 == strcmp(cp, "cat")) ++fp->cat; else if (0 == strcmp(cp, "coe")) ++fp->coe; else if (0 == strcmp(cp, "dc")) ++fp->dc; else if (0 == strcmp(cp, "direct")) ++fp->direct; else if (0 == strcmp(cp, "dpo")) ++fp->dpo; else if (0 == strcmp(cp, "errblk")) ++fp->errblk; else if (0 == strcmp(cp, "excl")) ++fp->excl; else if (0 == strcmp(cp, "fdatasync")) ++fp->fdatasync; else if (0 == strcmp(cp, "flock")) ++fp->flock; else if (0 == strcmp(cp, "force")) ++fp->force; else if (0 == strcmp(cp, "fsync")) ++fp->fsync; else if (0 == strcmp(cp, "fua_nv")) /* check fua_nv before fua */ ++fp->fua_nv; else if (0 == strcmp(cp, "fua")) ++fp->fua; else if (0 == strcmp(cp, "ignoreew")) /* tape: ignore early warning */ ++fp->ignoreew; else if (0 == strcmp(cp, "immed")) ++fp->immed; else if (0 == strcmp(cp, "nocache")) ++fp->nocache; else if (0 == strcmp(cp, "no_del_tkn")) ++fp->no_del_tkn; else if (0 == strcmp(cp, "nofm")) /* No filemark on tape close */ ++fp->nofm; else if (0 == strcmp(cp, "nopad")) ++fp->nopad; else if (0 == strcmp(cp, "norcap")) ++fp->norcap; else if (0 == strcmp(cp, "nowrite")) ++fp->nowrite; else if (0 == strcmp(cp, "null")) ; else if (0 == strcmp(cp, "odx")) ++fp->odx; else if (0 == strcmp(cp, "pad")) ++fp->pad; else if (0 == strcmp(cp, "pre-alloc") || 0 == strcmp(cp, "prealloc")) ++fp->prealloc; else if (0 == strcmp(cp, "pt")) ++fp->pt; else if (0 == strcmp(cp, "rarc")) ++fp->rarc; else if (0 == strcmp(cp, "resume")) ++fp->resume; else if (0 == strcmp(cp, "rtf_len")) ++fp->rtf_len; else if (0 == strcmp(cp, "self")) ++fp->self; else if (0 == strcmp(cp, "sparing")) ++fp->sparing; else if (0 == strcmp(cp, "sparse")) ++fp->sparse; else if (0 == strcmp(cp, "ssync")) ++fp->ssync; else if (0 == strcmp(cp, "strunc")) ++fp->strunc; else if (0 == strcmp(cp, "sync")) ++fp->sync; else if ((0 == strcmp(cp, "trim")) || (0 == strcmp(cp, "unmap"))) { /* treat trim (ATA term) and unmap (SCSI term) as synonyms */ ++fp->wsame16; } else if (0 == strcmp(cp, "trunc")) ++fp->trunc; else if (0 == strcmp(cp, "xcopy")) ++fp->xcopy; else { pr2serr("unrecognised flag: %s\n", cp); return 1; } cp = np; } while (cp); return 0; } /* Defaulting transfer (copy buffer) size depending on IBS. 128*2048 for * CD/DVDs is too large for the block layer in lk 2.6 and results in an * EIO on the SG_IO ioctl. So reduce it in that case. * N.B. FreeBSD may reduce bpt later if pt is used on IFILE or OFILE. */ static int default_bpt_i(int ibs) { if (ibs < 8) return DEF_BPT_LT8; else if (ibs < 64) return DEF_BPT_LT64; else if (ibs < 1024) return DEF_BPT_LT1024; else if (ibs < 8192) return DEF_BPT_LT8192; else if (ibs < 31768) return DEF_BPT_LT32768; else return DEF_BPT_GE32768; } /* Command line processing helper, checks sanity and applies some * defaults. Returns 0 on success, > 0 for error. */ static int cl_sanity_defaults(struct opts_t * op) { const char * cp; char * csp; char * cdp; char b[80]; if ((0 == op->ibs) && (0 == op->obs)) { op->ibs = DEF_BLOCK_SIZE; op->obs = DEF_BLOCK_SIZE; if (op->idip->fn[0]) pr2serr("Assume block size of %d bytes for both input and " "output\n", DEF_BLOCK_SIZE); } else if (0 == op->obs) { op->obs = DEF_BLOCK_SIZE; if ((op->ibs != DEF_BLOCK_SIZE) && op->odip->fn[0]) pr2serr("Neither obs nor bs given so set obs=%d (default " "block size)\n", op->obs); } else if (0 == op->ibs) { op->ibs = DEF_BLOCK_SIZE; if (op->obs != DEF_BLOCK_SIZE) pr2serr("Neither ibs nor bs given so set ibs=%d (default " "block size)\n", op->ibs); } op->ibs_hold = op->ibs; if (op->bpt_given && (op->bpt_i < 1)) { op->bpt_given = 0; /* want to allow bpt=0, where BPT takes the default, for ODX */ } if (0 == op->bpt_given) op->bpt_i = default_bpt_i(op->ibs); if ((op->ibs != op->obs) && (ODX_REQ_NONE == op->odx_request) && (0 != ((op->ibs * op->bpt_i) % op->obs))) { pr2serr("when 'ibs' and 'obs' differ, ((ibs*bpt)/obs) must have " "no remainder (bpt=%d)\n", op->bpt_i); return SG_LIB_SYNTAX_ERROR; } if ((op->skip < 0) || (op->seek < 0)) { pr2serr("neither skip nor seek can be negative\n"); return SG_LIB_SYNTAX_ERROR; } if ((op->oflagp->append > 0) && (op->seek > 0)) { pr2serr("Can't use both append and seek switches\n"); return SG_LIB_SYNTAX_ERROR; } if (op->bpt_i < 1) { pr2serr("internal BPT value 0, cannot continue\n"); return SG_LIB_SYNTAX_ERROR; } if (op->iflagp->append) pr2serr("append flag ignored on input\n"); if (op->iflagp->ignoreew) pr2serr("ignoreew flag ignored on input\n"); if (op->iflagp->nofm) pr2serr("nofm flag ignored on input\n"); if (op->iflagp->prealloc) pr2serr("pre-alloc flag ignored on input\n"); if (op->iflagp->sparing) pr2serr("sparing flag ignored on input\n"); if (op->iflagp->ssync) pr2serr("ssync flag ignored on input\n"); if (op->oflagp->trunc) { if (op->oflagp->resume) { op->oflagp->trunc = 0; if (op->verbose) pr2serr("trunc ignored due to resume flag, " "otherwise open_of() truncates too early\n"); } else if (op->oflagp->append) { op->oflagp->trunc = 0; pr2serr("trunc ignored due to append flag\n"); } else if (op->oflagp->sparing) { pr2serr("trunc flag conflicts with sparing\n"); return SG_LIB_SYNTAX_ERROR; } } if (op->iflagp->self || op->oflagp->self) { if (! op->oflagp->self) ++op->oflagp->self; if (op->iflagp->wsame16 || op->oflagp->wsame16) { if (! op->oflagp->wsame16) ++op->oflagp->wsame16; if (! op->oflagp->nowrite) ++op->oflagp->nowrite; } if ('\0' == op->odip->fn[0]) strcpy(op->odip->fn, op->idip->fn); if ((0 == op->seek) && (op->skip > 0)) { if (op->ibs == op->obs) op->seek = op->skip; else if (op->obs > 0) { int64_t l; l = op->skip * op->ibs; op->seek = l / op->obs; if ((op->seek * op->obs) != l) { pr2serr("self cannot translate skip to seek " "properly, try different skip value\n"); return SG_LIB_SYNTAX_ERROR; } } if (op->verbose) pr2serr("self: set seek=%" PRId64 "\n", op->seek); } } if (op->oflagp->wsame16) op->oflagp->sparse += 2; if (op->oflagp->strunc && (0 == op->oflagp->sparse)) ++op->oflagp->sparse; if (op->iflagp->xcopy || op->oflagp->xcopy) ++op->has_xcopy; if (op->has_xcopy) { if ((!! op->iflagp->xcopy) == (!! op->oflagp->xcopy)) { csp = getenv(XCOPY_TO_SRC); cdp = getenv(XCOPY_TO_DST); if ((!! csp) == (!! cdp)) { #if DEF_XCOPY_SRC0_DST1 == 0 if (! op->iflagp->xcopy) op->iflagp->xcopy = 1; op->oflagp->xcopy = 0; #else op->iflagp->xcopy = 0; if (! op->oflagp->xcopy) op->oflagp->xcopy = 1; #endif if (op->verbose > 1) pr2serr("Default dictates which device to send xcopy " "command to:\n"); } else { if (csp) { if (! op->iflagp->xcopy) op->iflagp->xcopy = 1; op->oflagp->xcopy = 0; } else { op->iflagp->xcopy = 0; if (! op->oflagp->xcopy) op->oflagp->xcopy = 1; } if (op->verbose > 1) pr2serr("%s dictates which device to send xcopy " "command to:\n", (csp ? XCOPY_TO_SRC : XCOPY_TO_DST)); } } if (op->verbose) { if (op->verbose > 1) pr2serr(" "); pr2serr("Will send xcopy command to %s [%s=%s]\n", (op->iflagp->xcopy ? "src" : "dst"), (op->iflagp->xcopy ? "if" : "of"), (op->iflagp->xcopy ? op->idip->fn : op->odip->fn)); } op->xc_dc = (op->iflagp->dc || op->oflagp->dc); op->xc_cat = (op->iflagp->cat || op->oflagp->cat); if (op->iflagp->xcopy) { if (! op->iflagp->pt) { op->iflagp->pt = 1; if (op->verbose > 3) pr2serr("Setting pt (pass-through) on IFILE for " "xcopy\n"); } } else { if (! op->oflagp->pt) { op->oflagp->pt = 1; if (op->verbose > 3) pr2serr("Setting pt (pass-through) on OFILE for " "xcopy\n"); } } } if (op->iflagp->odx || op->iflagp->odx || op->rtf[0] || op->rod_type_given) op->has_odx = op->has_odx ? op->has_odx : 1; if (op->has_odx) { if (op->has_xcopy) { pr2serr("Can either request xcopy(LID1) or ODX but not " "both\n"); return SG_LIB_SYNTAX_ERROR; } cp = ""; if (op->idip->fn[0] && op->odip->fn[0]) { op->odx_request = ODX_COPY; if (RODT_BLK_ZERO == op->rod_type) { if (op->verbose > 1) cp = "zero output blocks: call WRITE USING TOKEN(s), " "repeatedly"; else cp = "zero output blocks"; } else { if (op->verbose > 1) cp = "full copy: POPULATE TOKEN then WRITE USING " "TOKEN(s), repeatedly"; else cp = "full copy"; } } else if (op->idip->fn[0]) { op->odx_request = ODX_READ_INTO_RODS; if (op->verbose) cp = "read to tokens; disk-->ROD"; } else if (op->odip->fn[0]) { op->odx_request = ODX_WRITE_FROM_RODS; if (op->verbose) cp = "write from tokens; ROD-->disk"; } else { pr2serr("Not enough options given to do ODX (xcopy(LID4))\n"); return SG_LIB_SYNTAX_ERROR; } csp = getenv(ODX_RTF_LEN); if (csp) ++op->rtf_len_add; if (op->verbose) { pr2serr("ODX: %s%s\n", cp, (csp ? "\n [ODX_RTF_LEN " "environment variable present]" : "")); if ((op->verbose > 1) && op->rod_type_given) pr2serr("ODX: ROD type: %s\n", rod_type_str(op->rod_type, b, sizeof(b))); } } if (op->verbose) { /* report flags used but not supported */ #ifndef SG_LIB_LINUX if (op->iflagp->flock || op->oflagp->flock) pr2serr("warning: 'flock' flag not supported on this " "platform\n"); #endif #ifndef HAVE_POSIX_FADVISE if (op->iflagp->nocache || op->oflagp->nocache) pr2serr("warning: 'nocache' flag not supported on this " "platform\n"); #endif #if O_SYNC == 0 if (op->iflagp->sync || op->oflagp->sync) pr2serr("warning: 'sync' flag (O_SYNC) not supported on " "this platform\n"); #endif #if O_DIRECT == 0 if (op->iflagp->direct || op->oflagp->direct) pr2serr("warning: 'direct' flag (O_DIRECT) not supported " "on this platform\n"); #endif } return 0; } /* Process options on the command line. Returns 0 if successful, > 0 for * (syntax) error and -1 for early exit (e.g. after '--help') */ int cl_process(struct opts_t * op, int argc, char * argv[], const char * version_str) { char str[STR_SZ]; char * key; char * buf; char * cp; int k, n, keylen, res; int64_t i64; for (k = 1; k < argc; ++k) { if (argv[k]) { strncpy(str, argv[k], STR_SZ); str[STR_SZ - 1] = '\0'; } else continue; // replace '=' with null and set buf pointer to following char for (key = str, buf = key; *buf && *buf != '=';) ++buf; if (*buf) *buf++ = '\0'; keylen = (int)strlen(key); // check for option names, in alphabetical order if (0 == strcmp(key, "bpt")) { cp = strchr(buf, ','); if (cp) *cp = '\0'; if ((n = sg_get_num(buf)) < 0) { pr2serr("bad BPT argument to 'bpt='\n"); return SG_LIB_SYNTAX_ERROR; } if (n > 0) { op->bpt_i = n; op->bpt_given = 1; } if (cp) { n = sg_get_num(cp + 1); if (n < 0) { pr2serr("bad OBPC argument to 'bpt='\n"); return SG_LIB_SYNTAX_ERROR; } op->obpch = n; } } else if (0 == strcmp(key, "bs")) { n = sg_get_num(buf); if (n < 0) { pr2serr("bad argument to 'bs='\n"); return SG_LIB_SYNTAX_ERROR; } if (op->bs_given) { pr2serr("second 'bs=' option given, dangerous\n"); return SG_LIB_SYNTAX_ERROR; } else op->bs_given = 1; if ((op->ibs_given) || (op->obs_given)) { pr2serr("'bs=' option cannot be combined with " "'ibs=' or 'obs='\n"); return SG_LIB_SYNTAX_ERROR; } op->ibs = n; op->obs = n; } else if (0 == strcmp(key, "cbs")) pr2serr("the cbs= option is ignored\n"); else if (0 == strcmp(key, "cdbsz")) { op->iflagp->cdbsz = sg_get_num(buf); op->oflagp->cdbsz = op->iflagp->cdbsz; op->cdbsz_given = 1; } else if (0 == strcmp(key, "coe")) { op->iflagp->coe = sg_get_num(buf); op->oflagp->coe = op->iflagp->coe; } else if (0 == strcmp(key, "coe_limit")) { op->coe_limit = sg_get_num(buf); if (-1 == op->coe_limit) { pr2serr("bad argument to 'coe_limit='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "conv")) { if (conv_process(buf, op->iflagp, op->oflagp)) { pr2serr("bad argument to 'conv='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "count")) { if (0 != strcmp("-1", buf)) { op->dd_count = sg_get_llnum(buf); if (-1LL == op->dd_count) { pr2serr("bad argument to 'count='\n"); return SG_LIB_SYNTAX_ERROR; } } /* 'count=-1' is accepted, means calculate count */ ++op->count_given; } else if (0 == strcmp(key, "delay")) { cp = strchr(buf, ','); if (cp) *cp = '\0'; n = sg_get_num(buf); if (n < 0) { pr2serr("bad MS argument to 'delay='\n"); return SG_LIB_SYNTAX_ERROR; } op->delay = n; if (cp) { n = sg_get_num(cp + 1); if (n < 0) { pr2serr("bad W_MS argument to 'delay='\n"); return SG_LIB_SYNTAX_ERROR; } op->wdelay = n; } } else if (0 == strcmp(key, "ibs")) { n = sg_get_num(buf); if (n < 0) { pr2serr("bad argument to 'ibs='\n"); return SG_LIB_SYNTAX_ERROR; } if (op->bs_given) { pr2serr("'ibs=' option cannot be combined with " "'bs='; try 'obs=' instead\n"); return SG_LIB_SYNTAX_ERROR; } ++op->ibs_given; op->ibs = n; } else if (0 == strcmp(key, "id_usage")) { if (isdigit(buf[0])) { n = sg_get_num(buf); if (n < 0) { pr2serr("bad numeric argument to 'id_usage='\n"); return SG_LIB_SYNTAX_ERROR; } op->id_usage = n; } else if (! strncmp(buf, "hold", 4)) op->id_usage = 0; else if (! strncmp(buf, "discard", 7)) op->id_usage = 2; else if (! strncmp(buf, "disable", 7)) op->id_usage = 3; else { pr2serr("bad argument to 'id_usage='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (strcmp(key, "if") == 0) { if ('\0' != op->idip->fn[0]) { pr2serr("Second IFILE argument??\n"); return SG_LIB_SYNTAX_ERROR; } else strncpy(op->idip->fn, buf, INOUTF_SZ - 1); } else if (0 == strcmp(key, "iflag")) { if (flags_process(buf, op->iflagp)) { pr2serr("bad argument to 'iflag='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "intio")) { op->interrupt_io = sg_get_num(buf); } else if (0 == strcmp(key, "iseek")) { res = do_skip(op, key, buf); if (res) return res; } else if (0 == strcmp(key, "ito")) { n = sg_get_num(buf); if (-1 == n) { pr2serr("bad argument to 'ito='\n"); return SG_LIB_SYNTAX_ERROR; } op->inactivity_to = n; } else if (0 == strcmp(key, "list_id")) { i64 = sg_get_llnum(buf); if (-1 == i64) { pr2serr("bad argument to 'list_id='\n"); return SG_LIB_SYNTAX_ERROR; } if (i64 > UINT32_MAX) { pr2serr("argument to 'list_id=' too big for 32 bits\n"); return SG_LIB_SYNTAX_ERROR; } op->list_id = (uint32_t)i64; op->list_id_given = 1; } else if (0 == strcmp(key, "obs")) { n = sg_get_num(buf); if (n < 0) { pr2serr("bad argument to 'obs='\n"); return SG_LIB_SYNTAX_ERROR; } if (op->bs_given) { pr2serr("'obs=' option cannot be combined with " "'bs='; try 'ibs=' instead\n"); return SG_LIB_SYNTAX_ERROR; } ++op->obs_given; op->obs = n; } else if (strcmp(key, "of") == 0) { if ('\0' != op->odip->fn[0]) { pr2serr("Second OFILE argument??\n"); return SG_LIB_SYNTAX_ERROR; } strncpy(op->odip->fn, buf, INOUTF_SZ - 1); ++op->outf_given; } else if (strcmp(key, "of2") == 0) { if ('\0' != op->o2dip->fn[0]) { pr2serr("Second OFILE2 argument??\n"); return SG_LIB_SYNTAX_ERROR; } else strncpy(op->o2dip->fn, buf, INOUTF_SZ - 1); } else if (0 == strcmp(key, "oflag")) { if (flags_process(buf, op->oflagp)) { pr2serr("bad argument to 'oflag='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "oseek")) { res = do_seek(op, key, buf); if (res) return res; } else if (0 == strcmp(key, "prio")) { n = sg_get_num(buf); if ((n < 0) || (n > 7)) { pr2serr("bad argument to 'prio=' (max: 7)\n"); return SG_LIB_SYNTAX_ERROR; } op->prio = n; } else if (0 == strcmp(key, "protect")) { cp = strchr(buf, ','); if (cp) *cp = '\0'; n = sg_get_num(buf); if ((n < 0) || (n > 7)) { pr2serr("bad RDP argument to 'protect='\n"); return SG_LIB_SYNTAX_ERROR; } op->rdprotect = n; if (cp) { n = sg_get_num(cp + 1); if ((n < 0) || (n > 7)) { pr2serr("bad WRP argument to 'protect='\n"); return SG_LIB_SYNTAX_ERROR; } op->wrprotect = n; } } else if (0 == strcmp(key, "retries")) { op->iflagp->retries = sg_get_num(buf); op->oflagp->retries = op->iflagp->retries; if (-1 == op->iflagp->retries) { pr2serr("bad argument to 'retries='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "rtf")) { if (op->rtf[0]) { pr2serr("Can only use rtf=RTF once for ROD Token filename\n"); return SG_LIB_SYNTAX_ERROR; } if ((NULL == buf) || (strlen(buf) < 1)) { pr2serr("rtf=RTF requires an non-empty filename for RTF\n"); return SG_LIB_SYNTAX_ERROR; } strncpy(op->rtf, buf, INOUTF_SZ - 1); } else if (0 == strcmp(key, "rtype")) { if (0 == strncmp("pit-def", buf, 7)) op->rod_type = RODT_PIT_DEF; else if (0 == strncmp("pit-vuln", buf, 8)) op->rod_type = RODT_PIT_VULN; else if (0 == strncmp("pit-pers", buf, 8)) op->rod_type = RODT_PIT_PERS; else if (0 == strncmp("pit-any", buf, 7)) op->rod_type = RODT_PIT_ANY; else if (0 == strncmp("zero", buf, 4)) op->rod_type = RODT_BLK_ZERO; else { i64 = sg_get_llnum(buf); if (-1 == i64) { pr2serr("bad argument to 'rtype='; can give (hex) " "number, 'pit-def', 'pit-vuln',\n"); pr2serr("'pit-pers', 'pit-any' or 'zero'\n"); return SG_LIB_SYNTAX_ERROR; } if (i64 > UINT32_MAX) { pr2serr("'rtype=' argument exceeds 32 bits\n"); return SG_LIB_SYNTAX_ERROR; } op->rod_type = (uint32_t)i64; } ++op->rod_type_given; } else if (0 == strcmp(key, "seek")) { res = do_seek(op, key, buf); if (res) return res; } else if (0 == strcmp(key, "skip")) { res = do_skip(op, key, buf); if (res) return res; } else if (0 == strcmp(key, "status")) { if (0 == strncmp(buf, "null", 4)) ; else if (0 == strncmp(buf, "noxfer", 6)) op->do_time = 0; else if (0 == strncmp(buf, "none", 4)) { ++op->status_none; op->do_time = 0; } else { pr2serr("'status=' expects 'none', 'noxfer' or 'null'\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "to")) { op->timeout_xcopy = sg_get_num(buf); if (-1 == op->timeout_xcopy) { pr2serr("bad argument to 'to='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strncmp(key, "verb", 4)) { op->verbose = sg_get_num(buf); if ((-1 == op->verbose) && ('-' != buf[0])) { pr2serr("bad argument to 'verbose='\n"); return SG_LIB_SYNTAX_ERROR; } if (op->verbose < 0) { ++op->quiet; op->verbose = 0; } } /* look for long options that start with '--' */ else if (0 == strncmp(key, "--help", 6)) ++op->do_help; else if (0 == strncmp(key, "--odx", 5)) ++op->has_odx; else if (0 == strncmp(key, "--verb", 6)) ++op->verbose; else if (0 == strncmp(key, "--vers", 6)) { pr2serr("%s\n", version_str); return -1; } #ifdef SG_LIB_WIN32 else if (0 == strncmp(key, "--wscan", 7)) ++op->wscan; #endif else if (0 == strncmp(key, "--xcopy", 7)) ++op->has_xcopy; /* look for short options that start with a single '-', they can be * concaternated (e.g. '-vvvx') */ else if ((keylen > 1) && ('-' == key[0]) && ('-' != key[1])) { res = 0; n = num_chs_in_str(key + 1, keylen - 1, 'h'); op->do_help += n; res += n; n = num_chs_in_str(key + 1, keylen - 1, 'o'); op->has_odx += n; res += n; n = num_chs_in_str(key + 1, keylen - 1, 'v'); op->verbose += n; res += n; if (num_chs_in_str(key + 1, keylen - 1, 'V')) { pr2serr("%s\n", version_str); return -1; } #ifdef SG_LIB_WIN32 n = num_chs_in_str(key + 1, keylen - 1, 'w'); op->wscan += n; res += n; #endif n = num_chs_in_str(key + 1, keylen - 1, 'x'); op->has_xcopy += n; res += n; if (res < (keylen - 1)) { pr2serr("Unrecognised short option in '%s', try '--help'\n", key); if (0 == op->do_help) return -1; } } else { pr2serr("Unrecognized option '%s'\n", key); pr2serr("For more information use '--help'\n"); return SG_LIB_SYNTAX_ERROR; } } if ((op->verbose > 3) && op->in_sgl) { pr2serr("Input (scatter-)gather list (%d elements):\n", op->in_sgl_elems); for (k = 0; k < op->in_sgl_elems; ++k) pr2serr(" lba: 0x%" PRIx64 ", number: 0x%" PRIx32 "\n", op->in_sgl[k].lba, op->in_sgl[k].num); } if ((op->verbose > 3) && op->out_sgl) { pr2serr("Output scatter(-gather) list (%d elements):\n", op->out_sgl_elems); for (k = 0; k < op->out_sgl_elems; ++k) pr2serr(" lba: 0x%" PRIx64 ", number: 0x%" PRIx32 "\n", op->out_sgl[k].lba, op->out_sgl[k].num); } return cl_sanity_defaults(op); } ddpt-0.94/src/ddpt_wscan.c0000644000175000017500000005216212320426132014457 0ustar douggdougg/* * Copyright (c) 2006-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef SG_LIB_WIN32 #include #include #include #include #include #include #include #include "sg_lib.h" #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0602 /* claim its W8 */ #endif #include "sg_pt_win32.h" #include "ddpt.h" /* * This is called when the '--wscan' option is given to ddpt. It is * Win32 only code and shows the relationship between various device names * and volumes in Windows OSes (Windows 2000, 2003, XP, Vista, W7 and W8). * There is an optional scsi adapter scan. */ #define MAX_SCSI_ELEMS 1024 #define MAX_ADAPTER_NUM 64 #define MAX_PHYSICALDRIVE_NUM 512 #define MAX_CDROM_NUM 512 #define MAX_TAPE_NUM 512 #define MAX_HOLE_COUNT 8 // IOCTL_STORAGE_QUERY_PROPERTY #define FILE_DEVICE_MASS_STORAGE 0x0000002d #define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE #define FILE_ANY_ACCESS 0 // #define METHOD_BUFFERED 0 #define IOCTL_STORAGE_QUERY_PROPERTY \ CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) #ifndef _DEVIOCTL_ typedef enum _STORAGE_BUS_TYPE { BusTypeUnknown = 0x00, BusTypeScsi = 0x01, BusTypeAtapi = 0x02, BusTypeAta = 0x03, BusType1394 = 0x04, BusTypeSsa = 0x05, BusTypeFibre = 0x06, BusTypeUsb = 0x07, BusTypeRAID = 0x08, BusTypeiScsi = 0x09, BusTypeSas = 0x0A, BusTypeSata = 0x0B, BusTypeSd = 0x0C, BusTypeMmc = 0x0D, BusTypeVirtual = 0xE, BusTypeFileBackedVirtual = 0xF, BusTypeMax, BusTypeMaxReserved = 0x7F } STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE; typedef struct _STORAGE_DEVICE_DESCRIPTOR { ULONG Version; ULONG Size; UCHAR DeviceType; UCHAR DeviceTypeModifier; BOOLEAN RemovableMedia; BOOLEAN CommandQueueing; ULONG VendorIdOffset; /* 0 if not available */ ULONG ProductIdOffset; /* 0 if not available */ ULONG ProductRevisionOffset;/* 0 if not available */ ULONG SerialNumberOffset; /* -1 if not available ?? */ STORAGE_BUS_TYPE BusType; ULONG RawPropertiesLength; UCHAR RawDeviceProperties[1]; } STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; #endif typedef struct _STORAGE_DEVICE_UNIQUE_IDENTIFIER { ULONG Version; ULONG Size; ULONG StorageDeviceIdOffset; ULONG StorageDeviceOffset; ULONG DriveLayoutSignatureOffset; } STORAGE_DEVICE_UNIQUE_IDENTIFIER, *PSTORAGE_DEVICE_UNIQUE_IDENTIFIER; // Use CompareStorageDuids(PSTORAGE_DEVICE_UNIQUE_IDENTIFIER duid1, duid2) // to test for equality #ifndef _DEVIOCTL_ typedef enum _STORAGE_QUERY_TYPE { PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined } STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; typedef enum _STORAGE_PROPERTY_ID { StorageDeviceProperty = 0, StorageAdapterProperty, StorageDeviceIdProperty, StorageDeviceUniqueIdProperty, StorageDeviceWriteCacheProperty, StorageMiniportProperty, StorageAccessAlignmentProperty } STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; typedef struct _STORAGE_PROPERTY_QUERY { STORAGE_PROPERTY_ID PropertyId; STORAGE_QUERY_TYPE QueryType; UCHAR AdditionalParameters[1]; } STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; #endif ///////////////////////////////////////////////////////////////////////////// union STORAGE_DEVICE_DESCRIPTOR_DATA { STORAGE_DEVICE_DESCRIPTOR desc; char raw[256]; }; union STORAGE_DEVICE_UID_DATA { STORAGE_DEVICE_UNIQUE_IDENTIFIER desc; char raw[512]; }; struct storage_elem { char name[32]; char volume_letters[32]; int qp_descriptor_valid; int qp_uid_valid; union STORAGE_DEVICE_DESCRIPTOR_DATA qp_descriptor; union STORAGE_DEVICE_UID_DATA qp_uid; }; static struct storage_elem * storage_arr; static int next_unused_elem = 0; static int verbose = 0; static char * get_err_str(DWORD err, int max_b_len, char * b) { LPVOID lpMsgBuf; int k, num, ch; if (max_b_len < 2) { if (1 == max_b_len) b[0] = '\0'; return b; } memset(b, 0, max_b_len); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); num = lstrlen((LPCTSTR)lpMsgBuf); if (num < 1) return b; num = (num < max_b_len) ? num : (max_b_len - 1); for (k = 0; k < num; ++k) { ch = *((LPCTSTR)lpMsgBuf + k); if ((ch >= 0x0) && (ch < 0x7f)) b[k] = ch & 0x7f; else b[k] = '?'; } return b; } static const char * get_bus_type(int bt) { switch (bt) { case BusTypeUnknown: return "Unkno"; case BusTypeScsi: return "Scsi "; case BusTypeAtapi: return "Atapi"; case BusTypeAta: return "Ata "; case BusType1394: return "1394 "; case BusTypeSsa: return "Ssa "; case BusTypeFibre: return "Fibre"; case BusTypeUsb: return "Usb "; case BusTypeRAID: return "RAID "; case BusTypeiScsi: return "iScsi"; case BusTypeSas: return "Sas "; case BusTypeSata: return "Sata "; case BusTypeSd: return "Sd "; case BusTypeMmc: return "Mmc "; case BusTypeVirtual: return "Virt "; case BusTypeFileBackedVirtual: return "FBVir"; case BusTypeMax: return "Max "; default: return "_unkn"; } } static int query_dev_property(HANDLE hdevice, union STORAGE_DEVICE_DESCRIPTOR_DATA * data) { DWORD num_out, err; char b[256]; STORAGE_PROPERTY_QUERY query = {StorageDeviceProperty, PropertyStandardQuery, {0} }; memset(data, 0, sizeof(*data)); if (! DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), data, sizeof(*data), &num_out, NULL)) { if (verbose > 2) { err = GetLastError(); pr2serr(" IOCTL_STORAGE_QUERY_PROPERTY(Devprop) failed, " "Error=%ld %s\n", err, get_err_str(err, sizeof(b), b)); } return -ENOSYS; } if (verbose > 3) pr2serr(" IOCTL_STORAGE_QUERY_PROPERTY(DevProp) num_out=%ld\n", num_out); return 0; } static int query_dev_uid(HANDLE hdevice, union STORAGE_DEVICE_UID_DATA * data) { DWORD num_out, err; char b[256]; STORAGE_PROPERTY_QUERY query = {StorageDeviceUniqueIdProperty, PropertyStandardQuery, {0} }; memset(data, 0, sizeof(*data)); if (! DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), data, sizeof(*data), &num_out, NULL)) { if (verbose > 2) { err = GetLastError(); pr2serr(" IOCTL_STORAGE_QUERY_PROPERTY(DevUid) failed, " "Error=%ld %s\n", err, get_err_str(err, sizeof(b), b)); } return -ENOSYS; } if (verbose > 3) pr2serr(" IOCTL_STORAGE_QUERY_PROPERTY(DevUid) num_out=%ld\n", num_out); return 0; } static int check_devices(const struct storage_elem * sep) { int k, j; struct storage_elem * sarr = storage_arr; for (k = 0; k < next_unused_elem; ++k, ++sarr) { if ('\0' == sarr->name[0]) continue; if (sep->qp_descriptor_valid && sarr->qp_descriptor_valid) { if (0 == memcmp(&sep->qp_descriptor, &sarr->qp_descriptor, sizeof(sep->qp_descriptor))) { for (j = 0; j < (int)sizeof(sep->volume_letters); ++j) { if ('\0' == sarr->volume_letters[j]) { sarr->volume_letters[j] = sep->name[0]; break; } } return 1; } } // should do uid check here (probably before descriptor compare) } return 0; } static int enum_scsi_adapters(void) { int k, j; int hole_count = 0; HANDLE fh; ULONG dummy; DWORD err; BYTE bus; BOOL success; char adapter_name[64]; char inqDataBuff[2048]; PSCSI_ADAPTER_BUS_INFO ai; char b[256]; for (k = 0; k < MAX_ADAPTER_NUM; ++k) { snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\SCSI%d:", k); fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (fh != INVALID_HANDLE_VALUE) { hole_count = 0; success = DeviceIoControl(fh, IOCTL_SCSI_GET_INQUIRY_DATA, NULL, 0, inqDataBuff, sizeof(inqDataBuff), &dummy, FALSE); if (success) { PSCSI_BUS_DATA pbd; PSCSI_INQUIRY_DATA pid; int num_lus, off; ai = (PSCSI_ADAPTER_BUS_INFO)inqDataBuff; for (bus = 0; bus < ai->NumberOfBusses; bus++) { pbd = ai->BusData + bus; num_lus = pbd->NumberOfLogicalUnits; off = pbd->InquiryDataOffset; for (j = 0; j < num_lus; ++j) { if ((off < (int)sizeof(SCSI_ADAPTER_BUS_INFO)) || (off > ((int)sizeof(inqDataBuff) - (int)sizeof(SCSI_INQUIRY_DATA)))) break; pid = (PSCSI_INQUIRY_DATA)(inqDataBuff + off); snprintf(b, sizeof(b) - 1, "SCSI%d:%d,%d,%d ", k, pid->PathId, pid->TargetId, pid->Lun); printf("%-15s", b); snprintf(b, sizeof(b) - 1, "claimed=%d pdt=%xh %s ", pid->DeviceClaimed, pid->InquiryData[0] % 0x3f, ((0 == pid->InquiryData[4]) ? "dubious" : "")); printf("%-26s", b); printf("%.8s %.16s %.4s\n", pid->InquiryData + 8, pid->InquiryData + 16, pid->InquiryData + 32); off = pid->NextInquiryDataOffset; } } } else { err = GetLastError(); pr2serr("%s: IOCTL_SCSI_GET_INQUIRY_DATA failed err=%lu\n" "\t%s", adapter_name, err, get_err_str(err, sizeof(b), b)); } CloseHandle(fh); } else { if (verbose > 3) { err = GetLastError(); pr2serr("%s: CreateFile failed err=%lu\n\t%s", adapter_name, err, get_err_str(err, sizeof(b), b)); } if (++hole_count >= MAX_HOLE_COUNT) break; } } return 0; } static int enum_volumes(char letter) { int k; HANDLE fh; char adapter_name[64]; struct storage_elem tmp_se; if (verbose > 2) pr2serr("%s: enter\n", __func__ ); for (k = 0; k < 24; ++k) { memset(&tmp_se, 0, sizeof(tmp_se)); snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\%c:", 'C' + k); tmp_se.name[0] = 'C' + k; fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (fh != INVALID_HANDLE_VALUE) { if (query_dev_property(fh, &tmp_se.qp_descriptor) < 0) pr2serr("%s: query_dev_property failed\n", __func__ ); else tmp_se.qp_descriptor_valid = 1; if (query_dev_uid(fh, &tmp_se.qp_uid) < 0) { if (verbose > 2) pr2serr("%s: query_dev_uid failed\n", __func__ ); } else tmp_se.qp_uid_valid = 1; if (('\0' == letter) || (letter == tmp_se.name[0])) check_devices(&tmp_se); CloseHandle(fh); } } return 0; } static int enum_pds(void) { int k; int hole_count = 0; HANDLE fh; DWORD err; char adapter_name[64]; char b[256]; struct storage_elem tmp_se; if (verbose > 2) pr2serr("%s: enter\n", __func__ ); for (k = 0; k < MAX_PHYSICALDRIVE_NUM; ++k) { memset(&tmp_se, 0, sizeof(tmp_se)); snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\PhysicalDrive%d", k); snprintf(tmp_se.name, sizeof(tmp_se.name), "PD%d", k); fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (fh != INVALID_HANDLE_VALUE) { if (query_dev_property(fh, &tmp_se.qp_descriptor) < 0) pr2serr("%s: query_dev_property failed\n", __func__ ); else tmp_se.qp_descriptor_valid = 1; if (query_dev_uid(fh, &tmp_se.qp_uid) < 0) { if (verbose > 2) pr2serr("%s: query_dev_uid failed\n", __func__ ); } else tmp_se.qp_uid_valid = 1; hole_count = 0; memcpy(&storage_arr[next_unused_elem++], &tmp_se, sizeof(tmp_se)); CloseHandle(fh); } else { if (verbose > 3) { err = GetLastError(); pr2serr("%s: CreateFile failed err=%lu\n\t%s", adapter_name, err, get_err_str(err, sizeof(b), b)); } if (++hole_count >= MAX_HOLE_COUNT) break; } } return 0; } static int enum_cdroms(void) { int k; int hole_count = 0; HANDLE fh; DWORD err; char adapter_name[64]; char b[256]; struct storage_elem tmp_se; if (verbose > 2) pr2serr("%s: enter\n", __func__ ); for (k = 0; k < MAX_CDROM_NUM; ++k) { memset(&tmp_se, 0, sizeof(tmp_se)); snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\CDROM%d", k); snprintf(tmp_se.name, sizeof(tmp_se.name), "CDROM%d", k); fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (fh != INVALID_HANDLE_VALUE) { if (query_dev_property(fh, &tmp_se.qp_descriptor) < 0) pr2serr("%s: query_dev_property failed\n", __func__ ); else tmp_se.qp_descriptor_valid = 1; if (query_dev_uid(fh, &tmp_se.qp_uid) < 0) { if (verbose > 2) pr2serr("%s: query_dev_uid failed\n", __func__ ); } else tmp_se.qp_uid_valid = 1; hole_count = 0; memcpy(&storage_arr[next_unused_elem++], &tmp_se, sizeof(tmp_se)); CloseHandle(fh); } else { if (verbose > 3) { err = GetLastError(); pr2serr("%s: CreateFile failed err=%lu\n\t%s", adapter_name, err, get_err_str(err, sizeof(b), b)); } if (++hole_count >= MAX_HOLE_COUNT) break; } } return 0; } static int enum_tapes(void) { int k; int hole_count = 0; HANDLE fh; DWORD err; char adapter_name[64]; char b[256]; struct storage_elem tmp_se; if (verbose > 2) pr2serr("%s: enter\n", __func__ ); for (k = 0; k < MAX_TAPE_NUM; ++k) { memset(&tmp_se, 0, sizeof(tmp_se)); snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\TAPE%d", k); snprintf(tmp_se.name, sizeof(tmp_se.name), "TAPE%d", k); fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (fh != INVALID_HANDLE_VALUE) { if (query_dev_property(fh, &tmp_se.qp_descriptor) < 0) pr2serr("%s: query_dev_property failed\n", __func__ ); else tmp_se.qp_descriptor_valid = 1; if (query_dev_uid(fh, &tmp_se.qp_uid) < 0) { if (verbose > 2) pr2serr("%s: query_dev_uid failed\n", __func__ ); } else tmp_se.qp_uid_valid = 1; hole_count = 0; memcpy(&storage_arr[next_unused_elem++], &tmp_se, sizeof(tmp_se)); CloseHandle(fh); } else { if (verbose > 3) { err = GetLastError(); pr2serr("%s: CreateFile failed err=%lu\n\t%s", adapter_name, err, get_err_str(err, sizeof(b), b)); } if (++hole_count >= MAX_HOLE_COUNT) break; } } return 0; } static int do_wscan(char letter, int show_bt, int scsi_scan) { int k, j, n; struct storage_elem * sp; if (scsi_scan < 2) { k = enum_pds(); if (k) return k; k = enum_cdroms(); if (k) return k; k = enum_tapes(); if (k) return k; k = enum_volumes(letter); if (k) return k; for (k = 0; k < next_unused_elem; ++k) { sp = storage_arr + k; if ('\0' == sp->name[0]) continue; printf("%-7s ", sp->name); n = strlen(sp->volume_letters); if (0 == n) printf(" "); else if (1 == n) printf("[%s] ", sp->volume_letters); else if (2 == n) printf("[%s] ", sp->volume_letters); else if (3 == n) printf("[%s] ", sp->volume_letters); else if (4 == n) printf("[%s] ", sp->volume_letters); else printf("[%4s+] ", sp->volume_letters); if (sp->qp_descriptor_valid) { if (show_bt) printf("<%s> ", get_bus_type(sp->qp_descriptor.desc.BusType)); j = sp->qp_descriptor.desc.VendorIdOffset; if (j > 0) printf("%s ", sp->qp_descriptor.raw + j); j = sp->qp_descriptor.desc.ProductIdOffset; if (j > 0) printf("%s ", sp->qp_descriptor.raw + j); j = sp->qp_descriptor.desc.ProductRevisionOffset; if (j > 0) printf("%s ", sp->qp_descriptor.raw + j); j = sp->qp_descriptor.desc.SerialNumberOffset; if (j > 0) printf("%s", sp->qp_descriptor.raw + j); printf("\n"); if (verbose > 2) dStrHex(sp->qp_descriptor.raw, 144, 0); } else printf("\n"); } } if (scsi_scan) { if (scsi_scan < 2) printf("\n"); enum_scsi_adapters(); } return 0; } int sg_do_wscan(char letter, int do_scan, int verb) { int ret, show_bt, scsi_scan; verbose = verb; show_bt = (do_scan > 1); scsi_scan = (do_scan > 2) ? (do_scan - 2) : 0; storage_arr = calloc(sizeof(struct storage_elem) * MAX_SCSI_ELEMS, 1); if (storage_arr) { ret = do_wscan(letter, show_bt, scsi_scan); free(storage_arr); } else { pr2serr("Failed to allocate storage_arr on heap\n"); ret = SG_LIB_SYNTAX_ERROR; } return ret; } #endif ddpt-0.94/src/ddpt_win32.c0000644000175000017500000004700712320426132014310 0ustar douggdougg/* * Copyright (c) 2010-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* This is a C source file contains Windows specific code for the ddpt * utility. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef SG_LIB_WIN32 #include #include #include #include #include #include #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include #include #include "ddpt.h" /* includes */ #include #include #ifndef SG_LIB_MINGW /* cygwin */ #include #endif #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" #include "sg_pt.h" #ifdef HAVE_NANOSLEEP #include #elif defined(MSC_VER) || defined(__MINGW32__) #define HAVE_MS_SLEEP #endif #ifndef HAVE_SYSCONF size_t win32_pagesize(void) { SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); return sys_info.dwPageSize; } #endif void win32_sleep_ms(int millisecs) { if (millisecs > 0) { #ifdef HAVE_NANOSLEEP struct timespec request; request.tv_sec = millisecs / 1000; request.tv_nsec = (millisecs % 1000) * 1000000; if ((nanosleep(&request, NULL) < 0) && (EINTR != errno)) pr2serr("nanosleep: failed, errno=%d\n", errno); #elif defined(HAVE_MS_SLEEP) Sleep(millisecs); #endif } } /* Fetches system error message corresponding to errnum, * placing string in b not exceeding blen bytes. Returns * bytes placed in b (excluding trailing NULL) or -1 for * error. MS refers to them as "System Error Codes". */ static int win32_errmsg(int errnum, char * b, int blen) { LPTSTR err_txt = 0; DWORD errn = errnum; int len = 0; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errn, 0, (LPTSTR)&err_txt, 0, NULL) == 0) return -1; else { len = strlen(err_txt); if (len) { if ('\n' == err_txt[len - 1]) { err_txt[len - 1] = '\0'; if ((len > 1) && ('\r' == err_txt[len - 2])) err_txt[len - 2] = '\0'; len = strlen(err_txt); } } if (len < 1) b[0] = '\0'; else if (len < blen) strcpy(b, err_txt); else { strncpy(b, err_txt, blen); if (blen > 0) b[blen - 1] = '\0'; } } if (err_txt) LocalFree(err_txt); return len; } /* Return 1 for filenames starting with '\', or of the form ':' * or of the form PD, PHYSICALDRIVE, CDROM or TAPE. The * is one or two digits with no following characters. Otherwise return 0. */ static int is_win_blk_dev(const char * fn) { int len, off; len = strlen(fn); if ((2 == len) && isalpha((int)fn[0]) && (':' == fn[1])) return 1; if (len < 3) return 0; if ('\\' == fn[0]) return 1; if (0 == strncmp(fn, "PD", 2)) off = 2; else if (0 == strncmp(fn, "CDROM", 5)) off = 5; else if (0 == strncmp(fn, "PHYSICALDRIVE", 13)) off = 13; else if (0 == strncmp(fn, "TAPE", 4)) off = 4; else return 0; if (len <= off) return 0; if (! isdigit((int)fn[off])) return 0; if (len == (off + 1)) return 1; if ((len != off + 2) || (! isdigit((int)fn[off + 1]))) return 0; else return 1; } int win32_dd_filetype(const char * fn, int verbose) { size_t len = strlen(fn); if (verbose) { ; } /* suppress warning */ if ((1 == len) && ('.' == fn[0])) return FT_DEV_NULL; else if ((3 == len) && ( (0 == strcmp("NUL", fn)) || (0 == strcmp("nul", fn)))) return FT_DEV_NULL; else if ((len > 8) && (0 == strncmp("\\\\.\\TAPE", fn, 8))) return FT_TAPE; else if ((len > 4) && (0 == strncmp("\\\\.\\", fn, 4))) return FT_BLOCK; else return FT_REG; } /* Adjust device file name for Windows; pass-through setup */ void win32_adjust_fns_pt(struct opts_t * op) { char b[INOUTF_SZ]; char * fn_arr[2]; char * cp; int k, j, len; memset(fn_arr, 0 , sizeof(fn_arr)); fn_arr[0] = op->idip->fn; fn_arr[1] = op->odip->fn; for (k = 0; k < 2; ++k) { cp = fn_arr[k]; if (NULL == cp) continue; len = strlen(cp); if (len < 2) continue; if ('\\' == cp[0]) continue; for (j = 0; j < len; ++j) b[j] = toupper((int)cp[j]); b[len] = '\0'; if (is_win_blk_dev(b)) { if (0 == strncmp(b, "PD", 2)) { strcpy(cp, "\\\\.\\PHYSICALDRIVE"); if (b[2]) strncat(cp, b + 2, len - 2); } else { strcpy(cp, "\\\\.\\"); strncat(cp, b, len); } } } #ifdef SG_LIB_WIN32_DIRECT if (op->verbose > 4) pr2serr("Initial win32 SPT interface state: %s\n", scsi_pt_win32_spt_state() ? "direct" : "indirect"); scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */); #endif } /* Main copy loop's read (input) for win32 block device. Returns 0 on * success, else SG_LIB_FILE_ERROR, SG_LIB_CAT_MEDIUM_HARD or -1 . */ int win32_cp_read_block(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp, int * ifull_extrap, int verbose) { int k, res, res2; int ibs = op->ibs; int64_t offset = op->skip * ibs; int64_t my_skip; int numbytes = csp->icbpt * ibs; if (ifull_extrap) *ifull_extrap = 0; if (offset != csp->if_filepos) { if (verbose > 2) pr2serr("moving if filepos: new_pos=%" PRId64 "\n", (int64_t)offset); if (win32_set_file_pos(op, DDPT_ARG_IN, offset, verbose)) return SG_LIB_FILE_ERROR; csp->if_filepos = offset; } res = win32_block_read(op, bp, numbytes, verbose); if (res < 0) { if ((-SG_LIB_CAT_MEDIUM_HARD == res) && (op->iflagp->coe)) { if (1 == csp->icbpt) { // Don't read again, this must be bad block memset(bp, 0, ibs); if ((res2 = coe_process_eio(op, op->skip))) return res2; ++*ifull_extrap; csp->bytes_read += ibs; return 0; } else { my_skip = op->skip; for (k = 0; k < csp->icbpt; ++k, ++my_skip, bp += ibs, offset += ibs) { if (offset != csp->if_filepos) { if (verbose > 2) pr2serr("moving if filepos: new_pos=%" PRId64 "\n", (int64_t)offset); if (win32_set_file_pos(op, DDPT_ARG_IN, offset, verbose)) return SG_LIB_FILE_ERROR; csp->if_filepos = offset; } memset(bp, 0, ibs); res = win32_block_read(op, bp, ibs, verbose); if (ibs == res) { zero_coe_limit_count(op); csp->if_filepos += ibs; if (verbose > 2) pr2serr("reading 1 block, skip=%" PRId64 " : " "okay\n", my_skip); } else if (-SG_LIB_CAT_MEDIUM_HARD == res) { if ((res2 = coe_process_eio(op, my_skip))) return res2; } else { pr2serr("reading 1 block, skip=%" PRId64 " failed\n", my_skip); csp->leave_reason = SG_LIB_CAT_OTHER; csp->icbpt = k; csp->ocbpt = (k * ibs) / op->obs; if (((k * ibs) % op->obs) > 0) ++csp->ocbpt; return 0; } ++*ifull_extrap; csp->bytes_read += ibs; } return 0; } } else { pr2serr("read(win32_block), skip=%" PRId64 " error occurred\n", op->skip); return (-SG_LIB_CAT_MEDIUM_HARD == res) ? -res : -1; } } else { if (res < numbytes) { /* assume no partial reads (i.e. non integral blocks) */ csp->icbpt = res / ibs; ++csp->leave_after_write; csp->leave_reason = 0; /* assume at end rather than error */ csp->ocbpt = res / op->obs; if (verbose > 1) pr2serr("short read, requested %d blocks, got %d blocks\n", numbytes / ibs, csp->icbpt); } csp->if_filepos += res; if (ifull_extrap) *ifull_extrap = csp->icbpt; } return 0; } /* Returns 0 on success, 1 on error */ int win32_open_if(struct opts_t * op, int flags, int verbose) { DISK_GEOMETRY g; DWORD count, share_mode, err; char b[80]; if (verbose) pr2serr("CreateFile(%s , in)\n", op->idip->fn); share_mode = (O_EXCL & flags) ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); op->idip->fh = CreateFile(op->idip->fn, GENERIC_READ | GENERIC_WRITE, share_mode, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == op->idip->fh) { err = GetLastError(); if (win32_errmsg(err, b, sizeof(b)) < 0) pr2serr("CreateFile(in) failed, error=%ld [and win32_errmsg()] " "failed\n", err); else pr2serr("CreateFile(in) failed, %s [%ld]\n", b, err); return 1; } if (0 == DeviceIoControl(op->idip->fh, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &g, sizeof(g), &count, NULL)) { err = GetLastError(); if (win32_errmsg(err, b, sizeof(b)) < 0) pr2serr("DeviceIoControl(in, geometry) failed, error=%ld [and " "win32_errmsg()] failed\n", err); else pr2serr("DeviceIoControl(in, geometry) failed, %s [%ld]\n", b, err); return 1; } if ((int)g.BytesPerSector != op->ibs) { pr2serr("Specified in block size (%d) doesn't match device geometry " "block size: %d\n", op->ibs, (int)g.BytesPerSector); return 1; } return 0; } /* Returns 0 on success, 1 on error. */ int win32_open_of(struct opts_t * op, int flags, int verbose) { DISK_GEOMETRY g; DWORD count, share_mode, err; char b[80]; if (verbose) pr2serr("CreateFile(%s , out)\n", op->odip->fn); share_mode = (O_EXCL & flags) ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); op->odip->fh = CreateFile(op->odip->fn, GENERIC_READ | GENERIC_WRITE, share_mode, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == op->odip->fh) { err = GetLastError(); if (win32_errmsg(err, b, sizeof(b)) < 0) pr2serr("CreateFile(out) failed, error=%ld [and win32_errmsg() " "failed]\n", err); else pr2serr("CreateFile(out) failed, %s [%ld]\n", b, err); return 1; } if (0 == DeviceIoControl(op->odip->fh, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &g, sizeof(g), &count, NULL)) { pr2serr("DeviceIoControl(out, geometry) error=%ld\n", GetLastError()); return 1; } if ((int)g.BytesPerSector != op->obs) { pr2serr("Specified out block size (%d) doesn't match device geometry " "block size: %d\n", op->obs, (int)g.BytesPerSector); return 1; } return 0; } /* Returns 0 on success, 1 on error */ int win32_set_file_pos(struct opts_t * op, int which_arg, int64_t pos, int verbose) { LONG lo32 = pos & 0xffffffff; LONG hi32 = (pos >> 32) & 0xffffffff; DWORD err; DWORD lo_ret; HANDLE fh; const char * cp; fh = (DDPT_ARG_IN == which_arg) ? op->idip->fh : op->odip->fh; cp = (DDPT_ARG_IN == which_arg) ? "in" : "out"; if (verbose > 2) pr2serr("SetFilePointer( 0x%" PRIx64 ", %s)\n", pos, cp); lo_ret = SetFilePointer(fh, lo32, &hi32, FILE_BEGIN); if ((INVALID_SET_FILE_POINTER == lo_ret) && (NO_ERROR != (err = GetLastError()))) { if (verbose) pr2serr("SetFilePointer failed to set pos=[0x%" PRIx64 "], " "error=%ld\n", pos, err); return 1; } return 0; } /* Returns number read, -SG_LIB_CAT_MEDIUM_HARD or -1 on error */ int win32_block_read(struct opts_t * op, unsigned char * bp, int num_bytes, int verbose) { DWORD num = num_bytes; DWORD howMany, err; char b[80]; if (verbose > 2) pr2serr("ReadFile(num=%d, in)\n", num_bytes); if (ReadFile(op->idip->fh, bp, num, &howMany, NULL) == 0) { err = GetLastError(); if (verbose) { if (win32_errmsg(err, b, sizeof(b)) < 0) pr2serr("ReadFile failed, error=%ld [and win32_errmsg() " "failed]\n", err); else pr2serr("ReadFile failed, %s [%ld]\n", b, err); } if (23 == err) return -SG_LIB_CAT_MEDIUM_HARD; else return -1; } return (int)howMany; } /* Returns number read from OFILE, -SG_LIB_CAT_MEDIUM_HARD or -1 on error */ int win32_block_read_from_of(struct opts_t * op, unsigned char * bp, int num_bytes, int verbose) { DWORD num = num_bytes; DWORD howMany, err; char b[80]; if (verbose > 2) pr2serr("ReadFile(num=%d, out)\n", num_bytes); if (ReadFile(op->odip->fh, bp, num, &howMany, NULL) == 0) { err = GetLastError(); if (verbose) { if (win32_errmsg(err, b, sizeof(b)) < 0) pr2serr("ReadFile failed, error=%ld [and win32_errmsg() " "failed]\n", err); else pr2serr("ReadFile failed, %s [%ld]\n", b, err); } if (23 == err) return -SG_LIB_CAT_MEDIUM_HARD; else return -1; } return (int)howMany; } /* Returns number written, -SG_LIB_CAT_MEDIUM_HARD or -1 on error */ int win32_block_write(struct opts_t * op, const unsigned char * bp, int num_bytes, int verbose) { DWORD num = num_bytes; DWORD howMany, err; char b[80]; if (verbose > 2) pr2serr("WriteFile(num=%d, out)\n", num_bytes); if (WriteFile(op->odip->fh, bp, num, &howMany, NULL) == 0) { err = GetLastError(); if (verbose) { if (win32_errmsg(err, b, sizeof(b)) < 0) pr2serr("WriteFile failed, error=%ld [and win32_errmsg() " "failed]\n", err); else pr2serr("WriteFile failed, %s [%ld]\n", b, err); } if (23 == err) return -SG_LIB_CAT_MEDIUM_HARD; else return -1; } return (int)howMany; } /* win32_get_blkdev_capacity() returns 0 -> success or -1 -> failure. If * successful writes back sector size (logical block size) using the sect_sz * pointer. Also writes back the number of sectors (logical blocks) on the * block device using num_sect pointer. Win32 version. */ int win32_get_blkdev_capacity(struct opts_t * op, int which_arg, int64_t * num_sect, int * sect_sz) { DISK_GEOMETRY g; GET_LENGTH_INFORMATION gli; ULARGE_INTEGER total_bytes; DWORD count; HANDLE fh; const char * fname; int64_t byte_len, blks; int fname_len; char dirName[64]; fh = (DDPT_ARG_IN == which_arg) ? op->idip->fh : op->odip->fh; fname = (DDPT_ARG_IN == which_arg) ? op->idip->fn : op->odip->fn; if (op->verbose > 2) pr2serr("win32_get_blkdev_capacity: for %s\n", fname); if (0 == DeviceIoControl(fh, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &g, sizeof(g), &count, NULL)) { if (op->verbose) pr2serr("DeviceIoControl(blkdev, geometry) error=%ld\n", GetLastError()); *num_sect = 0; *sect_sz = 0; return -1; } *sect_sz = (int)g.BytesPerSector; /* IOCTL_DISK_GET_LENGTH_INFO not defined before XP */ if (DeviceIoControl(fh, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(gli), &count, NULL)) { byte_len = gli.Length.QuadPart; *num_sect = byte_len / (int)g.BytesPerSector; return 0; } else if (op->verbose > 2) pr2serr("DeviceIoControl(blkdev, length_info) error=%ld\n", GetLastError()); /* Assume if device name finishes in digit then its physical */ fname_len = (int)strlen(fname); if (isdigit((int)fname[fname_len - 1])) { blks = g.Cylinders.QuadPart; blks *= g.TracksPerCylinder; blks *= g.SectorsPerTrack; *num_sect = blks; return 0; } if ((fname_len < 4) || (fname_len > (int)sizeof(dirName))) { pr2serr("win32_get_blkdev_capacity: unable to process %s into " "directory name\n", fname); *num_sect = 0; return -1; } memcpy(dirName, fname + 4, fname_len - 4); dirName[fname_len - 4] = '\\'; dirName[fname_len - 3] = '\0'; if (GetDiskFreeSpaceEx(dirName, NULL, &total_bytes, NULL)) { byte_len = total_bytes.QuadPart; *num_sect = byte_len / (int)g.BytesPerSector; } else if (op->verbose > 1) { pr2serr("GetDiskFreeSpaceEx(%s) error=%ld\n", dirName, GetLastError()); *num_sect = 0; return -1; } return 0; } #endif ddpt-0.94/src/Makefile.am0000644000175000017500000000477012305201013014213 0ustar douggdouggbin_PROGRAMS = ddpt ddptctl # for C++/clang testing ## CC = g++ ## CC = g++ ## CC = clang ## CC = clang++ # INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/include/scsi # -std= can be c99, c11, gnu11, etc. Default is gnu89 (gnu90 is the same) AM_CFLAGS = -I$(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W ## AM_CFLAGS = -I$(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c11 ## AM_CFLAGS = -I$(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c++11 ddpt_SOURCES = ddpt.c \ ddpt.h \ ddpt_cl.c \ ddpt_com.c \ ddpt_pt.c \ ddpt_xcopy.c ddptctl_SOURCES = ddptctl.c \ ddpt.h \ ddpt_com.c \ ddpt_pt.c \ ddpt_xcopy.c sglib_SOURCES = ../lib/sg_lib.c \ ../include/sg_lib.h \ ../lib/sg_lib_data.c \ ../include/sg_lib_data.h \ ../lib/sg_cmds_basic.c \ ../lib/sg_cmds_basic2.c \ ../include/sg_cmds_basic.h \ ../lib/sg_cmds_extra.c \ ../include/sg_cmds_extra.h \ ../include/sg_pt.h \ ../lib/sg_pt_common.c if OS_WIN32_MINGW ddpt_SOURCES += ddpt_win32.c \ ddpt_wscan.c ddptctl_SOURCES += ddpt_win32.c \ ddpt_wscan.c endif if OS_WIN32_CYGWIN ddpt_SOURCES += ddpt_win32.c \ ddpt_wscan.c ddptctl_SOURCES += ddpt_win32.c \ ddpt_wscan.c endif if HAVE_SGUTILS INCLUDES = -I/usr/include/scsi ddpt_LDADD = @os_libs@ @rt_libs@ @SGUTILS_LIBS@ else INCLUDES = -I$(top_srcdir)/include ddpt_SOURCES += $(sglib_SOURCES) ddpt_LDADD = @os_deps@ @os_libs@ @rt_libs@ @SGUTILS_LIBS@ ddpt_DEPENDENCIES = @os_deps@ endif EXTRA_ddpt_SOURCES = ../lib/sg_pt_linux.c \ ../include/sg_linux_inc.h \ ../lib/sg_pt_freebsd.c \ ../lib/sg_pt_osf1.c \ ../lib/sg_pt_solaris.c \ ../lib/sg_pt_win32.c \ ../include/sg_pt_win32.h if HAVE_SGUTILS INCLUDES = -I/usr/include/scsi ddptctl_LDADD = @os_libs@ @rt_libs@ @SGUTILS_LIBS@ else INCLUDES = -I$(top_srcdir)/include ddptctl_SOURCES += $(sglib_SOURCES) ddptctl_LDADD = @os_deps@ @os_libs@ @rt_libs@ @SGUTILS_LIBS@ ddptctl_DEPENDENCIES = @os_deps@ endif EXTRA_ddptctl_SOURCES = ../lib/sg_pt_linux.c \ ../include/sg_linux_inc.h \ ../lib/sg_pt_freebsd.c \ ../lib/sg_pt_osf1.c \ ../lib/sg_pt_solaris.c \ ../lib/sg_pt_win32.c \ ../include/sg_pt_win32.h ddpt-0.94/src/Makefile.in0000644000175000017500000012463512305201013014227 0ustar douggdougg# Makefile.in generated by automake 1.13.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = ddpt$(EXEEXT) ddptctl$(EXEEXT) @OS_WIN32_MINGW_TRUE@am__append_1 = ddpt_win32.c \ @OS_WIN32_MINGW_TRUE@ ddpt_wscan.c @OS_WIN32_MINGW_TRUE@am__append_2 = ddpt_win32.c \ @OS_WIN32_MINGW_TRUE@ ddpt_wscan.c @OS_WIN32_CYGWIN_TRUE@am__append_3 = ddpt_win32.c \ @OS_WIN32_CYGWIN_TRUE@ ddpt_wscan.c @OS_WIN32_CYGWIN_TRUE@am__append_4 = ddpt_win32.c \ @OS_WIN32_CYGWIN_TRUE@ ddpt_wscan.c @HAVE_SGUTILS_FALSE@am__append_5 = $(sglib_SOURCES) @HAVE_SGUTILS_TRUE@ddpt_DEPENDENCIES = @HAVE_SGUTILS_FALSE@am__append_6 = $(sglib_SOURCES) @HAVE_SGUTILS_TRUE@ddptctl_DEPENDENCIES = subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am__ddpt_SOURCES_DIST = ddpt.c ddpt.h ddpt_cl.c ddpt_com.c ddpt_pt.c \ ddpt_xcopy.c ddpt_win32.c ddpt_wscan.c ../lib/sg_lib.c \ ../include/sg_lib.h ../lib/sg_lib_data.c \ ../include/sg_lib_data.h ../lib/sg_cmds_basic.c \ ../lib/sg_cmds_basic2.c ../include/sg_cmds_basic.h \ ../lib/sg_cmds_extra.c ../include/sg_cmds_extra.h \ ../include/sg_pt.h ../lib/sg_pt_common.c @OS_WIN32_MINGW_TRUE@am__objects_1 = ddpt_win32.$(OBJEXT) \ @OS_WIN32_MINGW_TRUE@ ddpt_wscan.$(OBJEXT) @OS_WIN32_CYGWIN_TRUE@am__objects_2 = ddpt_win32.$(OBJEXT) \ @OS_WIN32_CYGWIN_TRUE@ ddpt_wscan.$(OBJEXT) am__objects_3 = sg_lib.$(OBJEXT) sg_lib_data.$(OBJEXT) \ sg_cmds_basic.$(OBJEXT) sg_cmds_basic2.$(OBJEXT) \ sg_cmds_extra.$(OBJEXT) sg_pt_common.$(OBJEXT) @HAVE_SGUTILS_FALSE@am__objects_4 = $(am__objects_3) am_ddpt_OBJECTS = ddpt.$(OBJEXT) ddpt_cl.$(OBJEXT) ddpt_com.$(OBJEXT) \ ddpt_pt.$(OBJEXT) ddpt_xcopy.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) $(am__objects_4) ddpt_OBJECTS = $(am_ddpt_OBJECTS) am__ddptctl_SOURCES_DIST = ddptctl.c ddpt.h ddpt_com.c ddpt_pt.c \ ddpt_xcopy.c ddpt_win32.c ddpt_wscan.c ../lib/sg_lib.c \ ../include/sg_lib.h ../lib/sg_lib_data.c \ ../include/sg_lib_data.h ../lib/sg_cmds_basic.c \ ../lib/sg_cmds_basic2.c ../include/sg_cmds_basic.h \ ../lib/sg_cmds_extra.c ../include/sg_cmds_extra.h \ ../include/sg_pt.h ../lib/sg_pt_common.c am_ddptctl_OBJECTS = ddptctl.$(OBJEXT) ddpt_com.$(OBJEXT) \ ddpt_pt.$(OBJEXT) ddpt_xcopy.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) $(am__objects_4) ddptctl_OBJECTS = $(am_ddptctl_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(ddpt_SOURCES) $(EXTRA_ddpt_SOURCES) $(ddptctl_SOURCES) \ $(EXTRA_ddptctl_SOURCES) DIST_SOURCES = $(am__ddpt_SOURCES_DIST) $(EXTRA_ddpt_SOURCES) \ $(am__ddptctl_SOURCES_DIST) $(EXTRA_ddptctl_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SGUTILS_LIBS = @SGUTILS_LIBS@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ os_deps = @os_deps@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ rt_libs = @rt_libs@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # for C++/clang testing # INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/include/scsi # -std= can be c99, c11, gnu11, etc. Default is gnu89 (gnu90 is the same) AM_CFLAGS = -I$(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W ddpt_SOURCES = ddpt.c ddpt.h ddpt_cl.c ddpt_com.c ddpt_pt.c \ ddpt_xcopy.c $(am__append_1) $(am__append_3) $(am__append_5) ddptctl_SOURCES = ddptctl.c ddpt.h ddpt_com.c ddpt_pt.c ddpt_xcopy.c \ $(am__append_2) $(am__append_4) $(am__append_6) sglib_SOURCES = ../lib/sg_lib.c \ ../include/sg_lib.h \ ../lib/sg_lib_data.c \ ../include/sg_lib_data.h \ ../lib/sg_cmds_basic.c \ ../lib/sg_cmds_basic2.c \ ../include/sg_cmds_basic.h \ ../lib/sg_cmds_extra.c \ ../include/sg_cmds_extra.h \ ../include/sg_pt.h \ ../lib/sg_pt_common.c @HAVE_SGUTILS_FALSE@INCLUDES = -I$(top_srcdir)/include @HAVE_SGUTILS_TRUE@INCLUDES = -I/usr/include/scsi @HAVE_SGUTILS_FALSE@ddpt_LDADD = @os_deps@ @os_libs@ @rt_libs@ @SGUTILS_LIBS@ @HAVE_SGUTILS_TRUE@ddpt_LDADD = @os_libs@ @rt_libs@ @SGUTILS_LIBS@ @HAVE_SGUTILS_FALSE@ddpt_DEPENDENCIES = @os_deps@ EXTRA_ddpt_SOURCES = ../lib/sg_pt_linux.c \ ../include/sg_linux_inc.h \ ../lib/sg_pt_freebsd.c \ ../lib/sg_pt_osf1.c \ ../lib/sg_pt_solaris.c \ ../lib/sg_pt_win32.c \ ../include/sg_pt_win32.h @HAVE_SGUTILS_FALSE@ddptctl_LDADD = @os_deps@ @os_libs@ @rt_libs@ @SGUTILS_LIBS@ @HAVE_SGUTILS_TRUE@ddptctl_LDADD = @os_libs@ @rt_libs@ @SGUTILS_LIBS@ @HAVE_SGUTILS_FALSE@ddptctl_DEPENDENCIES = @os_deps@ EXTRA_ddptctl_SOURCES = ../lib/sg_pt_linux.c \ ../include/sg_linux_inc.h \ ../lib/sg_pt_freebsd.c \ ../lib/sg_pt_osf1.c \ ../lib/sg_pt_solaris.c \ ../lib/sg_pt_win32.c \ ../include/sg_pt_win32.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) ddpt$(EXEEXT): $(ddpt_OBJECTS) $(ddpt_DEPENDENCIES) $(EXTRA_ddpt_DEPENDENCIES) @rm -f ddpt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ddpt_OBJECTS) $(ddpt_LDADD) $(LIBS) ddptctl$(EXEEXT): $(ddptctl_OBJECTS) $(ddptctl_DEPENDENCIES) $(EXTRA_ddptctl_DEPENDENCIES) @rm -f ddptctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ddptctl_OBJECTS) $(ddptctl_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt_cl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt_com.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt_pt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt_win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt_wscan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddpt_xcopy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddptctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_basic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_basic2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_cmds_extra.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib_data.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_freebsd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_linux.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_osf1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_solaris.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_win32.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` sg_lib.o: ../lib/sg_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_lib.o -MD -MP -MF $(DEPDIR)/sg_lib.Tpo -c -o sg_lib.o `test -f '../lib/sg_lib.c' || echo '$(srcdir)/'`../lib/sg_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_lib.Tpo $(DEPDIR)/sg_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_lib.c' object='sg_lib.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_lib.o `test -f '../lib/sg_lib.c' || echo '$(srcdir)/'`../lib/sg_lib.c sg_lib.obj: ../lib/sg_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_lib.obj -MD -MP -MF $(DEPDIR)/sg_lib.Tpo -c -o sg_lib.obj `if test -f '../lib/sg_lib.c'; then $(CYGPATH_W) '../lib/sg_lib.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_lib.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_lib.Tpo $(DEPDIR)/sg_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_lib.c' object='sg_lib.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_lib.obj `if test -f '../lib/sg_lib.c'; then $(CYGPATH_W) '../lib/sg_lib.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_lib.c'; fi` sg_lib_data.o: ../lib/sg_lib_data.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_lib_data.o -MD -MP -MF $(DEPDIR)/sg_lib_data.Tpo -c -o sg_lib_data.o `test -f '../lib/sg_lib_data.c' || echo '$(srcdir)/'`../lib/sg_lib_data.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_lib_data.Tpo $(DEPDIR)/sg_lib_data.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_lib_data.c' object='sg_lib_data.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_lib_data.o `test -f '../lib/sg_lib_data.c' || echo '$(srcdir)/'`../lib/sg_lib_data.c sg_lib_data.obj: ../lib/sg_lib_data.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_lib_data.obj -MD -MP -MF $(DEPDIR)/sg_lib_data.Tpo -c -o sg_lib_data.obj `if test -f '../lib/sg_lib_data.c'; then $(CYGPATH_W) '../lib/sg_lib_data.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_lib_data.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_lib_data.Tpo $(DEPDIR)/sg_lib_data.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_lib_data.c' object='sg_lib_data.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_lib_data.obj `if test -f '../lib/sg_lib_data.c'; then $(CYGPATH_W) '../lib/sg_lib_data.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_lib_data.c'; fi` sg_cmds_basic.o: ../lib/sg_cmds_basic.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_cmds_basic.o -MD -MP -MF $(DEPDIR)/sg_cmds_basic.Tpo -c -o sg_cmds_basic.o `test -f '../lib/sg_cmds_basic.c' || echo '$(srcdir)/'`../lib/sg_cmds_basic.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_cmds_basic.Tpo $(DEPDIR)/sg_cmds_basic.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_cmds_basic.c' object='sg_cmds_basic.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_cmds_basic.o `test -f '../lib/sg_cmds_basic.c' || echo '$(srcdir)/'`../lib/sg_cmds_basic.c sg_cmds_basic.obj: ../lib/sg_cmds_basic.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_cmds_basic.obj -MD -MP -MF $(DEPDIR)/sg_cmds_basic.Tpo -c -o sg_cmds_basic.obj `if test -f '../lib/sg_cmds_basic.c'; then $(CYGPATH_W) '../lib/sg_cmds_basic.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_cmds_basic.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_cmds_basic.Tpo $(DEPDIR)/sg_cmds_basic.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_cmds_basic.c' object='sg_cmds_basic.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_cmds_basic.obj `if test -f '../lib/sg_cmds_basic.c'; then $(CYGPATH_W) '../lib/sg_cmds_basic.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_cmds_basic.c'; fi` sg_cmds_basic2.o: ../lib/sg_cmds_basic2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_cmds_basic2.o -MD -MP -MF $(DEPDIR)/sg_cmds_basic2.Tpo -c -o sg_cmds_basic2.o `test -f '../lib/sg_cmds_basic2.c' || echo '$(srcdir)/'`../lib/sg_cmds_basic2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_cmds_basic2.Tpo $(DEPDIR)/sg_cmds_basic2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_cmds_basic2.c' object='sg_cmds_basic2.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_cmds_basic2.o `test -f '../lib/sg_cmds_basic2.c' || echo '$(srcdir)/'`../lib/sg_cmds_basic2.c sg_cmds_basic2.obj: ../lib/sg_cmds_basic2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_cmds_basic2.obj -MD -MP -MF $(DEPDIR)/sg_cmds_basic2.Tpo -c -o sg_cmds_basic2.obj `if test -f '../lib/sg_cmds_basic2.c'; then $(CYGPATH_W) '../lib/sg_cmds_basic2.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_cmds_basic2.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_cmds_basic2.Tpo $(DEPDIR)/sg_cmds_basic2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_cmds_basic2.c' object='sg_cmds_basic2.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_cmds_basic2.obj `if test -f '../lib/sg_cmds_basic2.c'; then $(CYGPATH_W) '../lib/sg_cmds_basic2.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_cmds_basic2.c'; fi` sg_cmds_extra.o: ../lib/sg_cmds_extra.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_cmds_extra.o -MD -MP -MF $(DEPDIR)/sg_cmds_extra.Tpo -c -o sg_cmds_extra.o `test -f '../lib/sg_cmds_extra.c' || echo '$(srcdir)/'`../lib/sg_cmds_extra.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_cmds_extra.Tpo $(DEPDIR)/sg_cmds_extra.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_cmds_extra.c' object='sg_cmds_extra.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_cmds_extra.o `test -f '../lib/sg_cmds_extra.c' || echo '$(srcdir)/'`../lib/sg_cmds_extra.c sg_cmds_extra.obj: ../lib/sg_cmds_extra.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_cmds_extra.obj -MD -MP -MF $(DEPDIR)/sg_cmds_extra.Tpo -c -o sg_cmds_extra.obj `if test -f '../lib/sg_cmds_extra.c'; then $(CYGPATH_W) '../lib/sg_cmds_extra.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_cmds_extra.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_cmds_extra.Tpo $(DEPDIR)/sg_cmds_extra.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_cmds_extra.c' object='sg_cmds_extra.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_cmds_extra.obj `if test -f '../lib/sg_cmds_extra.c'; then $(CYGPATH_W) '../lib/sg_cmds_extra.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_cmds_extra.c'; fi` sg_pt_common.o: ../lib/sg_pt_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_common.o -MD -MP -MF $(DEPDIR)/sg_pt_common.Tpo -c -o sg_pt_common.o `test -f '../lib/sg_pt_common.c' || echo '$(srcdir)/'`../lib/sg_pt_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_common.Tpo $(DEPDIR)/sg_pt_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_common.c' object='sg_pt_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_common.o `test -f '../lib/sg_pt_common.c' || echo '$(srcdir)/'`../lib/sg_pt_common.c sg_pt_common.obj: ../lib/sg_pt_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_common.obj -MD -MP -MF $(DEPDIR)/sg_pt_common.Tpo -c -o sg_pt_common.obj `if test -f '../lib/sg_pt_common.c'; then $(CYGPATH_W) '../lib/sg_pt_common.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_common.Tpo $(DEPDIR)/sg_pt_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_common.c' object='sg_pt_common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_common.obj `if test -f '../lib/sg_pt_common.c'; then $(CYGPATH_W) '../lib/sg_pt_common.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_common.c'; fi` sg_pt_linux.o: ../lib/sg_pt_linux.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_linux.o -MD -MP -MF $(DEPDIR)/sg_pt_linux.Tpo -c -o sg_pt_linux.o `test -f '../lib/sg_pt_linux.c' || echo '$(srcdir)/'`../lib/sg_pt_linux.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_linux.Tpo $(DEPDIR)/sg_pt_linux.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_linux.c' object='sg_pt_linux.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_linux.o `test -f '../lib/sg_pt_linux.c' || echo '$(srcdir)/'`../lib/sg_pt_linux.c sg_pt_linux.obj: ../lib/sg_pt_linux.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_linux.obj -MD -MP -MF $(DEPDIR)/sg_pt_linux.Tpo -c -o sg_pt_linux.obj `if test -f '../lib/sg_pt_linux.c'; then $(CYGPATH_W) '../lib/sg_pt_linux.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_linux.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_linux.Tpo $(DEPDIR)/sg_pt_linux.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_linux.c' object='sg_pt_linux.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_linux.obj `if test -f '../lib/sg_pt_linux.c'; then $(CYGPATH_W) '../lib/sg_pt_linux.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_linux.c'; fi` sg_pt_freebsd.o: ../lib/sg_pt_freebsd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_freebsd.o -MD -MP -MF $(DEPDIR)/sg_pt_freebsd.Tpo -c -o sg_pt_freebsd.o `test -f '../lib/sg_pt_freebsd.c' || echo '$(srcdir)/'`../lib/sg_pt_freebsd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_freebsd.Tpo $(DEPDIR)/sg_pt_freebsd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_freebsd.c' object='sg_pt_freebsd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_freebsd.o `test -f '../lib/sg_pt_freebsd.c' || echo '$(srcdir)/'`../lib/sg_pt_freebsd.c sg_pt_freebsd.obj: ../lib/sg_pt_freebsd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_freebsd.obj -MD -MP -MF $(DEPDIR)/sg_pt_freebsd.Tpo -c -o sg_pt_freebsd.obj `if test -f '../lib/sg_pt_freebsd.c'; then $(CYGPATH_W) '../lib/sg_pt_freebsd.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_freebsd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_freebsd.Tpo $(DEPDIR)/sg_pt_freebsd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_freebsd.c' object='sg_pt_freebsd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_freebsd.obj `if test -f '../lib/sg_pt_freebsd.c'; then $(CYGPATH_W) '../lib/sg_pt_freebsd.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_freebsd.c'; fi` sg_pt_osf1.o: ../lib/sg_pt_osf1.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_osf1.o -MD -MP -MF $(DEPDIR)/sg_pt_osf1.Tpo -c -o sg_pt_osf1.o `test -f '../lib/sg_pt_osf1.c' || echo '$(srcdir)/'`../lib/sg_pt_osf1.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_osf1.Tpo $(DEPDIR)/sg_pt_osf1.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_osf1.c' object='sg_pt_osf1.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_osf1.o `test -f '../lib/sg_pt_osf1.c' || echo '$(srcdir)/'`../lib/sg_pt_osf1.c sg_pt_osf1.obj: ../lib/sg_pt_osf1.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_osf1.obj -MD -MP -MF $(DEPDIR)/sg_pt_osf1.Tpo -c -o sg_pt_osf1.obj `if test -f '../lib/sg_pt_osf1.c'; then $(CYGPATH_W) '../lib/sg_pt_osf1.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_osf1.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_osf1.Tpo $(DEPDIR)/sg_pt_osf1.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_osf1.c' object='sg_pt_osf1.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_osf1.obj `if test -f '../lib/sg_pt_osf1.c'; then $(CYGPATH_W) '../lib/sg_pt_osf1.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_osf1.c'; fi` sg_pt_solaris.o: ../lib/sg_pt_solaris.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_solaris.o -MD -MP -MF $(DEPDIR)/sg_pt_solaris.Tpo -c -o sg_pt_solaris.o `test -f '../lib/sg_pt_solaris.c' || echo '$(srcdir)/'`../lib/sg_pt_solaris.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_solaris.Tpo $(DEPDIR)/sg_pt_solaris.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_solaris.c' object='sg_pt_solaris.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_solaris.o `test -f '../lib/sg_pt_solaris.c' || echo '$(srcdir)/'`../lib/sg_pt_solaris.c sg_pt_solaris.obj: ../lib/sg_pt_solaris.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_solaris.obj -MD -MP -MF $(DEPDIR)/sg_pt_solaris.Tpo -c -o sg_pt_solaris.obj `if test -f '../lib/sg_pt_solaris.c'; then $(CYGPATH_W) '../lib/sg_pt_solaris.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_solaris.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_solaris.Tpo $(DEPDIR)/sg_pt_solaris.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_solaris.c' object='sg_pt_solaris.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_solaris.obj `if test -f '../lib/sg_pt_solaris.c'; then $(CYGPATH_W) '../lib/sg_pt_solaris.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_solaris.c'; fi` sg_pt_win32.o: ../lib/sg_pt_win32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_win32.o -MD -MP -MF $(DEPDIR)/sg_pt_win32.Tpo -c -o sg_pt_win32.o `test -f '../lib/sg_pt_win32.c' || echo '$(srcdir)/'`../lib/sg_pt_win32.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_win32.Tpo $(DEPDIR)/sg_pt_win32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_win32.c' object='sg_pt_win32.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_win32.o `test -f '../lib/sg_pt_win32.c' || echo '$(srcdir)/'`../lib/sg_pt_win32.c sg_pt_win32.obj: ../lib/sg_pt_win32.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sg_pt_win32.obj -MD -MP -MF $(DEPDIR)/sg_pt_win32.Tpo -c -o sg_pt_win32.obj `if test -f '../lib/sg_pt_win32.c'; then $(CYGPATH_W) '../lib/sg_pt_win32.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_win32.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sg_pt_win32.Tpo $(DEPDIR)/sg_pt_win32.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../lib/sg_pt_win32.c' object='sg_pt_win32.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sg_pt_win32.obj `if test -f '../lib/sg_pt_win32.c'; then $(CYGPATH_W) '../lib/sg_pt_win32.c'; else $(CYGPATH_W) '$(srcdir)/../lib/sg_pt_win32.c'; fi` ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-binPROGRAMS install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ddpt-0.94/src/ddpt_pt.c0000644000175000017500000013453212320426132013771 0ustar douggdougg/* * Copyright (c) 2008-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This file contains SCSI pass-through (pt) helper functions for ddpt. */ /* Was needed for posix_fadvise() */ /* #define _XOPEN_SOURCE 600 */ /* Need _GNU_SOURCE for O_DIRECT */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include /* N.B. config.h must precede anything that depends on HAVE_* */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ddpt.h" /* includes */ #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" #include "sg_pt.h" #define DDPT_READ6_OC 0x8 #define DDPT_READ10_OC 0x28 #define DDPT_READ12_OC 0xa8 #define DDPT_READ16_OC 0x88 #define DDPT_WRITE6_OC 0xa #define DDPT_WRITE10_OC 0x2a #define DDPT_WRITE12_OC 0xaa #define DDPT_WRITE16_OC 0x8a #define DDPT_VARIABLE_LEN_OC 0x7f #define DDPT_READ32_SA 0x9 #define DDPT_WRITE32_SA 0xb #define DDPT_TPC_OUT_CMD 0x83 #define DDPT_TPC_OUT_CMDLEN 16 #define DDPT_TPC_IN_CMD 0x84 #define DDPT_TPC_IN_CMDLEN 16 #define ASC_GENERAL_0 0x0 #define ASQ_OP_IN_PROGRESS 0x16 #define ASC_3PC_GEN 0xd #define ASQ_TARGET_UNDERRUN 0x4 #define ASQ_TARGET_OVERRUN 0x5 #define ASC_PROTECTION_INFO_BAD 0x10 #define ASC_PARAM_LST_LEN_ERR 0x1a /* only asq=00 defined */ #define ASC_INVALID_TOKOP 0x23 #define ASQ_TOKOP_UNK 0x0 /* There are 11 of these ASQs, just add asq to DDPT_CAT base */ #define ASC_INVALID_PARAM 0x26 #define ASQ_INVALID_FLD_IN_PARAM 0x0 #define ASQ_TOO_MANY_SEGS_IN_PARAM 0x8 #define ASC_CMDS_CLEARED 0x2f #define ASQ_CMDS_CLEARED_BY_DEV_SVR 0x2 #define ASC_INSUFF_RES 0x55 #define ASQ_INSUFF_RES_CREATE_ROD 0xc #define ASQ_INSUFF_RES_CREATE_RODTOK 0xd #define DEF_PT_TIMEOUT 60 /* 60 seconds */ void * pt_construct_obj(void) { void * vp; if (NULL == (vp = construct_scsi_pt_obj())) pr2serr("construct_scsi_pt_obj: out of memory\n"); return vp; } void pt_destruct_obj(void * vp) { destruct_scsi_pt_obj((struct sg_pt_base *)vp); } /* Opens given device with the pass-through interface. If successful sends * a standard INQUIRY request. Returns file descriptor (>=0) if successful, * -1 if open fails, -2 if standard INQUIRY fails. */ int pt_open_if(struct opts_t * op, struct sg_simple_inquiry_resp * sirp) { int verb, flags, fl, fd; struct sg_simple_inquiry_resp sir; struct flags_t * fp = op->iflagp; struct dev_info_t * dip = op->idip; const char * fn = op->idip->fn; verb = (op->verbose ? op->verbose - 1: 0); flags = fp->block ? 0 : O_NONBLOCK; if (fp->direct) flags |= O_DIRECT; if (fp->excl) flags |= O_EXCL; if (fp->sync) flags |= O_SYNC; fl = O_RDWR; if ((fd = scsi_pt_open_flags(fn, (fl | flags), op->verbose)) < 0) { if (-EBUSY == fd) { pr2serr("open %s for pass-through reports BUSY,\n" " use iflag=block to wait until ready\n", fn); return -1; } fl = O_RDONLY; if ((fd = scsi_pt_open_flags(fn, (fl | flags), op->verbose)) < 0) { pr2serr("could not open %s for pass-through: %s\n", fn, safe_strerror(-fd)); return -1; } } if (sg_simple_inquiry(fd, &sir, 0, verb)) { pr2serr("INQUIRY failed on %s\n", fn); return -2; } dip->pdt = sir.peripheral_type; if (op->verbose) { if (op->has_xcopy || op->has_odx) pr2serr(" %s: %.8s %.16s %.4s [pdt=%d, 3pc=%d]\n", fn, sir.vendor, sir.product, sir.revision, dip->pdt, !! (0x8 & sir.byte_5)); else pr2serr(" %s: %.8s %.16s %.4s [pdt=%d]\n", fn, sir.vendor, sir.product, sir.revision, dip->pdt); } if (sirp) *sirp = sir; return fd; } /* Opens given device with the pass-through interface. If successful sends * a standard INQUIRY request. Returns file descriptor (>=0) if successful, * -1 if open fails, -2 if standard INQUIRY fails. */ int pt_open_of(struct opts_t * op, struct sg_simple_inquiry_resp * sirp) { int verb, flags, fd; struct sg_simple_inquiry_resp sir; struct flags_t * fp = op->oflagp; struct dev_info_t * dip = op->odip; const char * fn = dip->fn; verb = (op->verbose ? op->verbose - 1: 0); flags = fp->block ? 0 : O_NONBLOCK; flags |= O_RDWR; if (fp->direct) flags |= O_DIRECT; if (fp->excl) flags |= O_EXCL; if (fp->sync) flags |= O_SYNC; if ((fd = scsi_pt_open_flags(fn, flags, op->verbose)) < 0) { if (-EBUSY == fd) { pr2serr("open %s for pass-through reports BUSY,\n" " use oflag=block to wait until ready\n", fn); return -1; } pr2serr("could not open %s for pass-through: %s\n", fn, safe_strerror(-fd)); return -1; } if (sg_simple_inquiry(fd, &sir, 0, verb)) { pr2serr("INQUIRY failed on %s\n", fn); return -2; } dip->pdt = sir.peripheral_type; if (op->verbose) { if (op->has_xcopy || op->has_odx) pr2serr(" %s: %.8s %.16s %.4s [pdt=%d, 3pc=%d]\n", fn, sir.vendor, sir.product, sir.revision, dip->pdt, !! (0x8 & sir.byte_5)); else pr2serr(" %s: %.8s %.16s %.4s [pdt=%d]\n", fn, sir.vendor, sir.product, sir.revision, dip->pdt); } if (sirp) *sirp = sir; return fd; } void pt_close(int fd) { scsi_pt_close_device(fd); } /* Fetch number of blocks and block size of a pt device. * Return of 0 -> success, see sg_ll_read_capacity*() otherwise. */ int pt_read_capacity(struct opts_t * op, int in0_out1, int64_t * num_blks, int * blk_sz) { int k, res; unsigned int ui; unsigned char rcBuff[RCAP16_REPLY_LEN]; int verb; int sg_fd = (in0_out1 ? op->odip->fd : op->idip->fd); int protect = (in0_out1 ? op->wrprotect : op->rdprotect); verb = (op->verbose ? op->verbose - 1: 0); memset(rcBuff, 0, sizeof(rcBuff)); if (! protect) { res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 1, verb); if (0 != res) return res; } if (protect || ((0xff == rcBuff[0]) && (0xff == rcBuff[1]) && (0xff == rcBuff[2]) && (0xff == rcBuff[3]))) { int64_t ls; int prot_typ = 0; int p_i_exp = 0; if (verb && ! protect) pr2serr(" READ CAPACITY (10) response cannot represent this " "capacity\n"); res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 1, verb); if (0 != res) return res; for (k = 0, ls = 0; k < 8; ++k) { ls <<= 8; ls |= rcBuff[k]; } *num_blks = ls + 1; *blk_sz = (rcBuff[8] << 24) | (rcBuff[9] << 16) | (rcBuff[10] << 8) | rcBuff[11]; if (rcBuff[12] & 0x1) { /* PROT_EN */ prot_typ = ((rcBuff[12] >> 1) & 0x7) + 1; p_i_exp = ((rcBuff[13] >> 4) & 0xf); } if (in0_out1) { op->odip->prot_type = prot_typ; op->odip->p_i_exp = p_i_exp; } else { op->idip->prot_type = prot_typ; op->idip->p_i_exp = p_i_exp; } } else { ui = ((rcBuff[0] << 24) | (rcBuff[1] << 16) | (rcBuff[2] << 8) | rcBuff[3]); /* take care not to sign extend values > 0x7fffffff */ *num_blks = (int64_t)ui + 1; *blk_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | (rcBuff[6] << 8) | rcBuff[7]; } return 0; } /* Build a SCSI READ or WRITE CDB. */ static int pt_build_scsi_cdb(unsigned char * cdbp, int cdb_sz, unsigned int blocks, int64_t start_block, int write_true, const struct flags_t * fp, int protect) { int rd_opcode[] = {DDPT_READ6_OC, DDPT_READ10_OC, DDPT_READ12_OC, DDPT_READ16_OC, DDPT_READ32_SA}; int wr_opcode[] = {DDPT_WRITE6_OC, DDPT_WRITE10_OC, DDPT_WRITE12_OC, DDPT_WRITE16_OC, DDPT_WRITE32_SA}; int sz_ind, options_byte, rw_sa; memset(cdbp, 0, cdb_sz); options_byte = 0; if (cdb_sz < 6) { pr2serr("cdb_sz too small\n"); return 1; } if (cdb_sz > 6) { if (fp->dpo) options_byte |= 0x10; if (fp->fua) options_byte |= 0x8; if (fp->fua_nv) options_byte |= 0x2; if (protect) options_byte |= ((protect & 0x7) << 5); } if ((! write_true) && fp->rarc) options_byte |= 0x4; switch (cdb_sz) { case 6: sz_ind = 0; cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] : rd_opcode[sz_ind]); /* Overwrite fua, fua_nv and dpo settings, n/a for 6 byte variants */ cdbp[1] = (unsigned char)((start_block >> 16) & 0x1f); cdbp[2] = (unsigned char)((start_block >> 8) & 0xff); cdbp[3] = (unsigned char)(start_block & 0xff); cdbp[4] = (256 == blocks) ? 0 : (unsigned char)blocks; if (blocks > 256) { pr2serr("for 6 byte commands, maximum number of blocks is 256\n"); return 1; } if ((start_block + blocks - 1) & (~0x1fffff)) { pr2serr("for 6 byte commands, can't address blocks beyond %d\n", 0x1fffff); return 1; } if (fp->dpo || fp->fua || fp->rarc) { pr2serr("for 6 byte commands, neither dpo, fua, nor rarc bits " "supported\n"); return 1; } break; case 10: sz_ind = 1; cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] : rd_opcode[sz_ind]); cdbp[1] = (unsigned char)options_byte; cdbp[2] = (unsigned char)((start_block >> 24) & 0xff); cdbp[3] = (unsigned char)((start_block >> 16) & 0xff); cdbp[4] = (unsigned char)((start_block >> 8) & 0xff); cdbp[5] = (unsigned char)(start_block & 0xff); cdbp[7] = (unsigned char)((blocks >> 8) & 0xff); cdbp[8] = (unsigned char)(blocks & 0xff); if (blocks & (~0xffff)) { pr2serr("for 10 byte commands, maximum number of blocks is %d\n", 0xffff); return 1; } break; case 12: sz_ind = 2; cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] : rd_opcode[sz_ind]); cdbp[1] = (unsigned char)options_byte; cdbp[2] = (unsigned char)((start_block >> 24) & 0xff); cdbp[3] = (unsigned char)((start_block >> 16) & 0xff); cdbp[4] = (unsigned char)((start_block >> 8) & 0xff); cdbp[5] = (unsigned char)(start_block & 0xff); cdbp[6] = (unsigned char)((blocks >> 24) & 0xff); cdbp[7] = (unsigned char)((blocks >> 16) & 0xff); cdbp[8] = (unsigned char)((blocks >> 8) & 0xff); cdbp[9] = (unsigned char)(blocks & 0xff); break; case 16: sz_ind = 3; cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] : rd_opcode[sz_ind]); cdbp[1] = (unsigned char)options_byte; cdbp[2] = (unsigned char)((start_block >> 56) & 0xff); cdbp[3] = (unsigned char)((start_block >> 48) & 0xff); cdbp[4] = (unsigned char)((start_block >> 40) & 0xff); cdbp[5] = (unsigned char)((start_block >> 32) & 0xff); cdbp[6] = (unsigned char)((start_block >> 24) & 0xff); cdbp[7] = (unsigned char)((start_block >> 16) & 0xff); cdbp[8] = (unsigned char)((start_block >> 8) & 0xff); cdbp[9] = (unsigned char)(start_block & 0xff); cdbp[10] = (unsigned char)((blocks >> 24) & 0xff); cdbp[11] = (unsigned char)((blocks >> 16) & 0xff); cdbp[12] = (unsigned char)((blocks >> 8) & 0xff); cdbp[13] = (unsigned char)(blocks & 0xff); break; case 32: sz_ind = 4; cdbp[0] = (unsigned char)DDPT_VARIABLE_LEN_OC; cdbp[7] = (unsigned char)0x18; /* additional length=>32 byte cdb */ rw_sa = write_true ? wr_opcode[sz_ind] : rd_opcode[sz_ind]; cdbp[8] = (unsigned char)((rw_sa >> 8) & 0xff); cdbp[9] = (unsigned char)(rw_sa & 0xff); cdbp[10] = (unsigned char)options_byte; cdbp[12] = (unsigned char)((start_block >> 56) & 0xff); cdbp[13] = (unsigned char)((start_block >> 48) & 0xff); cdbp[14] = (unsigned char)((start_block >> 40) & 0xff); cdbp[15] = (unsigned char)((start_block >> 32) & 0xff); cdbp[16] = (unsigned char)((start_block >> 24) & 0xff); cdbp[17] = (unsigned char)((start_block >> 16) & 0xff); cdbp[18] = (unsigned char)((start_block >> 8) & 0xff); cdbp[19] = (unsigned char)(start_block & 0xff); cdbp[28] = (unsigned char)((blocks >> 24) & 0xff); cdbp[29] = (unsigned char)((blocks >> 16) & 0xff); cdbp[30] = (unsigned char)((blocks >> 8) & 0xff); cdbp[31] = (unsigned char)(blocks & 0xff); break; default: pr2serr("expected cdb size of 6, 10, 12, 16 or 32 but got %d\n", cdb_sz); return 1; } return 0; } /* Read using the pass-through. No retries or remedial work here. * 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, * SG_LIB_CAT_UNIT_ATTENTION -> try again, * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> 'io_addrp' written to, * SG_LIB_CAT_MEDIUM_HARD -> no info field, * SG_LIB_CAT_NOT_READY, SG_LIB_CAT_ABORTED_COMMAND, * -2 -> ENOMEM * -1 other errors */ static int pt_low_read(struct opts_t * op, int in0_out1, unsigned char * buff, int blocks, int64_t from_block, int bs, uint64_t * io_addrp) { unsigned char rdCmd[MAX_SCSI_CDBSZ]; unsigned char sense_b[SENSE_BUFF_LEN]; int res, k, info_valid, slen, sense_cat, ret, vt; struct sg_pt_base * ptvp = (in0_out1 ? op->odip->ptvp : op->idip->ptvp); const struct flags_t * fp = (in0_out1 ? op->oflagp : op->iflagp); const struct dev_info_t * dip = (in0_out1 ? op->odip : op->idip); int protect = (in0_out1 ? op->wrprotect : op->rdprotect); struct sg_scsi_sense_hdr ssh; if (pt_build_scsi_cdb(rdCmd, fp->cdbsz, blocks, from_block, 0, fp, protect)) { pr2serr("bad rd cdb build, from_block=%" PRId64 ", blocks=%d\n", from_block, blocks); return SG_LIB_SYNTAX_ERROR; } if (op->verbose > 2) { pr2serr(" READ cdb: "); for (k = 0; k < fp->cdbsz; ++k) pr2serr("%02x ", rdCmd[k]); pr2serr("\n"); } if (NULL == ptvp) { pr2serr("pt_low_read: ptvp NULL?\n"); return -1; } clear_scsi_pt_obj(ptvp); set_scsi_pt_cdb(ptvp, rdCmd, fp->cdbsz); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, buff, bs * blocks); #ifdef SCSI_PT_FLAGS_FUNCTION set_scsi_pt_flags(ptvp, SCSI_PT_FLAGS_QUEUE_AT_TAIL); #endif vt = (op->verbose ? (op->verbose - 1) : 0); while (((res = do_scsi_pt(ptvp, dip->fd, DEF_RW_TIMEOUT, vt)) < 0) && (-EINTR == res)) ++op->interrupted_retries; /* resubmit if interrupted system call */ vt = ((op->verbose > 1) ? (op->verbose - 1) : op->verbose); ret = sg_cmds_process_resp(ptvp, "READ", res, bs * blocks, sense_b, 0 /* noisy */, vt, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { slen = get_scsi_pt_sense_len(ptvp); ret = sense_cat; switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: ++op->unrecovered_errs; break; case SG_LIB_CAT_UNIT_ATTENTION: break; case SG_LIB_CAT_ABORTED_COMMAND: if (sg_scsi_normalize_sense(sense_b, slen, &ssh) && (ASC_PROTECTION_INFO_BAD == ssh.asc)) { /* Protection problem, so no retry */ ++op->unrecovered_errs; info_valid = sg_get_sense_info_fld(sense_b, slen, io_addrp); if (info_valid) ret = SG_LIB_CAT_PROTECTION_WITH_INFO; else ret = SG_LIB_CAT_PROTECTION; } break; case SG_LIB_CAT_RECOVERED: ++op->recovered_errs; info_valid = sg_get_sense_info_fld(sense_b, slen, io_addrp); if (info_valid) pr2serr(" lba of last recovered error in this READ=0x%" PRIx64 "\n", *io_addrp); else pr2serr("Recovered error: [no info] reading from block=0x%" PRIx64 ", num=%d\n", from_block, blocks); break; case SG_LIB_CAT_MEDIUM_HARD: ++op->unrecovered_errs; info_valid = sg_get_sense_info_fld(sense_b, slen, io_addrp); /* MMC and MO devices don't necessarily set VALID bit */ if (info_valid || ((*io_addrp > 0) && ((5 == dip->pdt) || (7 == dip->pdt)))) ret = SG_LIB_CAT_MEDIUM_HARD_WITH_INFO; // <<<<<<<<<<<< else pr2serr("Medium, hardware or blank check error but no lba " "of failure in sense data\n"); break; case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_ILLEGAL_REQ: if (5 == dip->pdt) { /* MMC READs can go down this path */ int ili; if (sg_scsi_normalize_sense(sense_b, slen, &ssh) && (0x64 == ssh.asc) && (0x0 == ssh.ascq)) { if (sg_get_sense_filemark_eom_ili(sense_b, slen, NULL, NULL, &ili) && ili) { info_valid = sg_get_sense_info_fld(sense_b, slen, io_addrp); if (*io_addrp > 0) { ++op->unrecovered_errs; ret = SG_LIB_CAT_MEDIUM_HARD_WITH_INFO; } else pr2serr("MMC READ gave 'illegal mode for this " "track' and ILI but no LBA of failure\n"); } ++op->unrecovered_errs; ret = SG_LIB_CAT_MEDIUM_HARD; } } default: break; } } else ret = 0; /* We are going to re-read those good blocks */ if ((SG_LIB_CAT_MEDIUM_HARD_WITH_INFO != ret) && (SG_LIB_CAT_PROTECTION_WITH_INFO != ret)) op->sum_of_resids += get_scsi_pt_resid(ptvp); return ret; } /* Control pass-through read retries and coe (continue on error). * Fast path is a call to pt_low_read() that succeeds. If medium * error then back up and re-read good blocks prior to bad block; * then, if coe, use zero for bad block and continue reading at * the next LBA (N.B. more medium errors could occur). * 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, * SG_LIB_CAT_UNIT_ATTENTION -> try again, SG_LIB_CAT_NOT_READY, * SG_LIB_CAT_MEDIUM_HARD, SG_LIB_CAT_ABORTED_COMMAND, * -2 -> ENOMEM, -1 other errors */ int pt_read(struct opts_t * op, int in0_out1, unsigned char * buff, int blocks, int * blks_readp) { uint64_t io_addr; int64_t from_block; int64_t lba; int bs; struct flags_t * fp; int res, blks, use_io_addr, xferred, pi_len; unsigned char * bp; int retries_tmp; int ret = 0; int may_coe = 0; if (in0_out1) { from_block = op->seek; bs = op->obs_pi; pi_len = op->obs_pi - op->obs; fp = op->oflagp; } else { from_block = op->skip; bs = op->ibs_pi; pi_len = op->ibs_pi - op->ibs; fp = op->iflagp; } retries_tmp = fp->retries; for (xferred = 0, blks = blocks, lba = from_block, bp = buff; blks > 0; blks = blocks - xferred) { io_addr = 0; use_io_addr = 0; may_coe = 0; res = pt_low_read(op, in0_out1, bp, blks, lba, bs, &io_addr); switch (res) { case 0: /* this is the fast path after good pt_low_read() */ if (blks_readp) *blks_readp = xferred + blks; if (0 == in0_out1) zero_coe_limit_count(op); return 0; case -2: /* ENOMEM */ return res; case SG_LIB_CAT_NOT_READY: pr2serr("Device (r) not ready\n"); return res; case SG_LIB_CAT_ABORTED_COMMAND: if (--op->max_aborted > 0) pr2serr("Aborted command, continuing (r)\n"); else { pr2serr("Aborted command, too many (r)\n"); return res; } break; case SG_LIB_CAT_UNIT_ATTENTION: if (--op->max_uas > 0) pr2serr("Unit attention, continuing (r)\n"); else { pr2serr("Unit attention, too many (r)\n"); return res; } break; case SG_LIB_CAT_PROTECTION_WITH_INFO: use_io_addr = 1; ret = res; break; /* unrecovered read error at lba=io_addr */ case SG_LIB_CAT_MEDIUM_HARD_WITH_INFO: if (retries_tmp > 0) { pr2serr(">>> retrying pt read: starting lba=%" PRId64 " [0x%" PRIx64 "] blocks=%d\n", lba, (uint64_t)lba, blks); --retries_tmp; ++op->num_retries; if (op->unrecovered_errs > 0) --op->unrecovered_errs; } else use_io_addr = 1; ret = SG_LIB_CAT_MEDIUM_HARD; break; /* unrecovered read error at lba=io_addr */ case SG_LIB_SYNTAX_ERROR: fp->coe = 0; ret = res; goto err_out; case -1: ret = res; goto err_out; case SG_LIB_CAT_MEDIUM_HARD: may_coe = 1; /* No VALID+INFO field but we know the range of lba_s */ if (0 == retries_tmp) errblk_put_range(lba, blks, op); /* fall through */ default: if (retries_tmp > 0) { pr2serr(">>> retrying pt read: starting lba=%" PRId64 " [0x%" PRIx64 "] blocks=%d\n", lba, (uint64_t)lba, blks); --retries_tmp; ++op->num_retries; if (op->unrecovered_errs > 0) --op->unrecovered_errs; break; } ret = res; goto err_out; } if (! use_io_addr) continue; if ((io_addr < (uint64_t)lba) || (io_addr >= (uint64_t)(lba + blks))) { pr2serr(" Unrecovered error lba 0x%" PRIx64 " not in " "correct range:\n\t[0x%" PRIx64 ",0x%" PRIx64 "]\n", io_addr, (uint64_t)lba, (uint64_t)(lba + blks - 1)); may_coe = 1; goto err_out; } if (op->highest_unrecovered < 0) { op->highest_unrecovered = io_addr; op->lowest_unrecovered = io_addr; } else { if ((int64_t)io_addr < op->lowest_unrecovered) op->lowest_unrecovered = io_addr; if ((int64_t)io_addr > op->highest_unrecovered) op->highest_unrecovered = io_addr; } errblk_put(io_addr, op); if (fp->coe) { ++op->in_partial; --op->in_full; } blks = (int)(io_addr - (uint64_t)lba); if (blks > 0) { if (op->verbose) pr2serr(" partial re-read of %d blocks prior to medium " "error\n", blks); res = pt_low_read(op, in0_out1, bp, blks, lba, bs, &io_addr); switch (res) { case 0: break; case -1: fp->coe = 0; ret = res; goto err_out; case -2: pr2serr("ENOMEM again, unexpected (r)\n"); return -1; case SG_LIB_CAT_NOT_READY: pr2serr("device (r) not ready\n"); return res; case SG_LIB_CAT_UNIT_ATTENTION: pr2serr("Unit attention, unexpected (r)\n"); return res; case SG_LIB_CAT_ABORTED_COMMAND: pr2serr("Aborted command, unexpected (r)\n"); return res; case SG_LIB_CAT_MEDIUM_HARD_WITH_INFO: case SG_LIB_CAT_MEDIUM_HARD: ret = SG_LIB_CAT_MEDIUM_HARD; goto err_out; case SG_LIB_CAT_PROTECTION_WITH_INFO: case SG_LIB_CAT_PROTECTION: ret = SG_LIB_CAT_PROTECTION; goto err_out; case SG_LIB_SYNTAX_ERROR: default: pr2serr(">> unexpected result=%d from pt_low_read() 2\n", res); ret = res; goto err_out; } } xferred += blks; if (0 == fp->coe) { /* give up at block before problem unless 'coe' */ if (blks_readp) *blks_readp = xferred; return ret; } bp += (blks * bs); lba += blks; pr2serr(">> unrecovered read error at blk=%" PRId64 ", substitute " "zeros%s\n", lba, ((pi_len > 0) ? " (PI with 0xFFs)" : "")); if (pi_len > 0) { memset(bp, 0, bs - pi_len); memset(bp + bs - pi_len, 0xff, pi_len); } else memset(bp, 0, bs); ++xferred; bp += bs; ++lba; if ((op->coe_limit > 0) && (++op->coe_count > op->coe_limit)) { if (blks_readp) *blks_readp = xferred + blks; pr2serr(">> coe_limit on consecutive reads exceeded\n"); return SG_LIB_CAT_MEDIUM_HARD; } retries_tmp = fp->retries; } if (blks_readp) *blks_readp = xferred; return 0; err_out: if (fp->coe) { memset(bp, 0, bs * blks); pr2serr(">> unable to read at blk=%" PRId64 " for %d bytes, use " "zeros\n", lba, bs * blks); if (blks > 1) pr2serr(">> try reducing bpt to limit number of zeros written " "near bad block(s)\n"); /* fudge success */ if (blks_readp) *blks_readp = xferred + blks; if ((op->coe_limit > 0) && (++op->coe_count > op->coe_limit)) { pr2serr(">> coe_limit on consecutive reads exceeded\n"); return ret; } return may_coe ? 0 : ret; } else return ret ? ret : -1; } /* Write block(s) via the pass-through. * 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, * SG_LIB_CAT_NOT_READY, SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_MEDIUM_HARD, * SG_LIB_CAT_ABORTED_COMMAND, -2 -> recoverable (ENOMEM), * -1 -> unrecoverable error + others */ static int pt_low_write(struct opts_t * op, const unsigned char * buff, int blocks, int64_t to_block, int bs) { unsigned char wrCmd[MAX_SCSI_CDBSZ]; unsigned char sense_b[SENSE_BUFF_LEN]; int res, k, info_valid, ret, sense_cat, slen, vt; int sg_fd = op->odip->fd; uint64_t io_addr = 0; struct sg_pt_base * ptvp = op->odip->ptvp; const struct flags_t * fp = op->oflagp; struct sg_scsi_sense_hdr ssh; if (pt_build_scsi_cdb(wrCmd, fp->cdbsz, blocks, to_block, 1, fp, op->wrprotect)) { pr2serr("bad wr cdb build, to_block=%" PRId64 ", blocks=%d\n", to_block, blocks); return SG_LIB_SYNTAX_ERROR; } if (op->verbose > 2) { pr2serr(" WRITE cdb: "); for (k = 0; k < fp->cdbsz; ++k) pr2serr("%02x ", wrCmd[k]); pr2serr("\n"); } if (NULL == ptvp) { pr2serr("pt_low_write: of_ptvp NULL?\n"); return -1; } clear_scsi_pt_obj(ptvp); set_scsi_pt_cdb(ptvp, wrCmd, fp->cdbsz); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, buff, bs * blocks); vt = (op->verbose ? (op->verbose - 1) : 0); while (((res = do_scsi_pt(ptvp, sg_fd, DEF_RW_TIMEOUT, vt)) < 0) && (-EINTR == res)) ++op->interrupted_retries; /* resubmit if interrupted system call */ vt = ((op->verbose > 1) ? (op->verbose - 1) : op->verbose); ret = sg_cmds_process_resp(ptvp, "WRITE", res, bs * blocks, sense_b, 0 /* noisy */, vt, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { slen = get_scsi_pt_sense_len(ptvp); ret = sense_cat; switch (sense_cat) { case SG_LIB_CAT_RECOVERED: ++op->wr_recovered_errs; info_valid = sg_get_sense_info_fld(sense_b, slen, &io_addr); if (info_valid) pr2serr(" lba of last recovered error in this WRITE=0x%" PRIx64 "\n", io_addr); else pr2serr("Recovered error: [no info] writing to block=0x%" PRIx64 ", num=%d\n", to_block, blocks); break; case SG_LIB_CAT_ABORTED_COMMAND: if (sg_scsi_normalize_sense(sense_b, slen, &ssh) && (ASC_PROTECTION_INFO_BAD == ssh.asc)) { /* Protection problem, so no retry */ ++op->wr_unrecovered_errs; ret = SG_LIB_CAT_PROTECTION; } break; case SG_LIB_CAT_UNIT_ATTENTION: break; case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_SENSE: ++op->wr_unrecovered_errs; break; case SG_LIB_CAT_MEDIUM_HARD: default: ++op->wr_unrecovered_errs; if (fp->coe) { pr2serr(">> ignored errors for out blk=%" PRId64 " for %d " "bytes\n", to_block, bs * blocks); ret = 0; /* fudge success */ } break; } } else ret = 0; return ret; } /* Control pass-through write retries. * 0 -> successful, SG_LIB_SYNTAX_ERROR -> unable to build cdb, * SG_LIB_CAT_UNIT_ATTENTION -> try again, SG_LIB_CAT_NOT_READY, * SG_LIB_CAT_MEDIUM_HARD, SG_LIB_CAT_ABORTED_COMMAND, * -2 -> ENOMEM, -1 other errors */ int pt_write(struct opts_t * op, const unsigned char * buff, int blocks, int64_t to_block) { int retries_tmp; int first = 1; int ret = 0; int bs = op->obs_pi; retries_tmp = op->oflagp->retries; while (1) { ret = pt_low_write(op, buff, blocks, to_block, bs); if (0 == ret) break; if ((SG_LIB_CAT_NOT_READY == ret) || (SG_LIB_SYNTAX_ERROR == ret)) break; else if ((SG_LIB_CAT_UNIT_ATTENTION == ret) && first) { if (--op->max_uas > 0) pr2serr("Unit attention, continuing (w)\n"); else { pr2serr("Unit attention, too many (w)\n"); break; } } else if ((SG_LIB_CAT_ABORTED_COMMAND == ret) && first) { if (--op->max_aborted > 0) pr2serr("Aborted command, continuing (w)\n"); else { pr2serr("Aborted command, too many (w)\n"); break; } } else if (ret < 0) break; else if (retries_tmp > 0) { pr2serr(">>> retrying pt write: starting lba=%" PRId64 " [0x%" PRIx64 "] blocks=%d\n", to_block, (uint64_t)to_block, blocks); --retries_tmp; ++op->num_retries; if (op->wr_unrecovered_errs > 0) --op->wr_unrecovered_errs; } else break; first = 0; } return ret; } /* This function performs a "trim" on a pt device. In the SCSI command set * this is either done with the UNMAP command or WRITE SAME command. This * function uses WRITE SAME(16) with the unmap bit set. In Linux libata * translates this to the ATA DATA SET MANAGEMENT command with the trim * field set. Returns 0 on success. */ int pt_write_same16(struct opts_t * op, const unsigned char * buff, int bs, int blocks, int64_t start_block) { int k, ret, res, sense_cat, vt; uint64_t llba; uint32_t unum; unsigned char wsCmdBlk[16]; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp = op->odip->ptvp; int sg_fd = op->odip->fd; memset(wsCmdBlk, 0, sizeof(wsCmdBlk)); wsCmdBlk[0] = 0x93; /* WRITE SAME(16) opcode */ /* set UNMAP; clear wrprotect, anchor, pbdata, lbdata */ wsCmdBlk[1] = 0x8; llba = start_block; for (k = 7; k >= 0; --k) { wsCmdBlk[2 + k] = (llba & 0xff); llba >>= 8; } unum = blocks; for (k = 3; k >= 0; --k) { wsCmdBlk[10 + k] = (unum & 0xff); unum >>= 8; } if (op->verbose > 2) { pr2serr(" WRITE SAME(16) cdb: "); for (k = 0; k < (int)sizeof(wsCmdBlk); ++k) pr2serr("%02x ", wsCmdBlk[k]); pr2serr("\n"); if (op->verbose > 4) pr2serr(" Data-out buffer length=%d\n", bs); } if (NULL == ptvp) { pr2serr("pt_write_same16: ptvp NULL?\n"); return -1; } clear_scsi_pt_obj(ptvp); set_scsi_pt_cdb(ptvp, wsCmdBlk, sizeof(wsCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, buff, bs); vt = ((op->verbose > 1) ? (op->verbose - 1) : 0); while (((res = do_scsi_pt(ptvp, sg_fd, WRITE_SAME16_TIMEOUT, vt)) < 0) && (-EINTR == res)) ++op->interrupted_retries; /* resubmit if interrupted system call */ ret = sg_cmds_process_resp(ptvp, "Write same(16)", res, 0, sense_b, 1 /*noisy */, vt, &sense_cat); if (-1 == ret) ; else if (-2 == ret) { switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; case SG_LIB_CAT_MEDIUM_HARD: { int valid, slen; uint64_t ull = 0; slen = get_scsi_pt_sense_len(ptvp); valid = sg_get_sense_info_fld(sense_b, slen, &ull); if (valid) pr2serr("Medium or hardware error starting at lba=%" PRIu64 " [0x%" PRIx64 "]\n", ull, ull); } ret = sense_cat; break; default: ret = -1; break; } } else ret = 0; return ret; } void pt_sync_cache(int fd) { int res; res = sg_ll_sync_cache_10(fd, 0, 0, 0, 0, 0, 1, 0); if (SG_LIB_CAT_UNIT_ATTENTION == res) { pr2serr("Unit attention (out, sync cache), continuing\n"); res = sg_ll_sync_cache_10(fd, 0, 0, 0, 0, 0, 1, 0); } if (0 != res) pr2serr("Unable to do SCSI synchronize cache\n"); } static int pt_tpc_process_res(int cp_ret, int sense_cat, const unsigned char * sense_b, int sense_len) { int ret, sb_ok; if (-1 == cp_ret) ret = -1; else if (-2 == cp_ret) { struct sg_scsi_sense_hdr ssh; sb_ok = sg_scsi_normalize_sense(sense_b, sense_len, &ssh); switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_UNIT_ATTENTION: case SG_LIB_CAT_ABORTED_COMMAND: ret = sense_cat; break; case SG_LIB_CAT_ILLEGAL_REQ: if (sb_ok) { if ((ASC_GENERAL_0 == ssh.asc) && (ASQ_OP_IN_PROGRESS == ssh.ascq)) ret = DDPT_CAT_OP_IN_PROGRESS; else if (ASC_3PC_GEN == ssh.asc) { if (ASQ_TARGET_UNDERRUN == ssh.ascq) ret = DDPT_CAT_TARGET_UNDERRUN; else if (ASQ_TARGET_OVERRUN == ssh.ascq) ret = DDPT_CAT_TARGET_OVERRUN; else ret = sense_cat; } else if (ASC_PARAM_LST_LEN_ERR == ssh.asc) ret = DDPT_CAT_PARAM_LST_LEN_ERR; else if (ASC_INVALID_PARAM == ssh.asc) { if (ASQ_INVALID_FLD_IN_PARAM == ssh.ascq) ret = DDPT_CAT_INVALID_FLD_IN_PARAM; else if (ASQ_TOO_MANY_SEGS_IN_PARAM == ssh.ascq) ret = DDPT_CAT_TOO_MANY_SEGS_IN_PARAM; else ret = sense_cat; } else if (ASC_INSUFF_RES == ssh.asc) { if (ASQ_INSUFF_RES_CREATE_ROD == ssh.ascq) ret = DDPT_CAT_INSUFF_RES_CREATE_ROD; else if (ASQ_INSUFF_RES_CREATE_RODTOK == ssh.ascq) ret = DDPT_CAT_INSUFF_RES_CREATE_RODTOK; else ret = sense_cat; } else if (ASC_INVALID_TOKOP == ssh.asc) ret = DDPT_CAT_TOKOP_BASE + ssh.ascq; else ret = sense_cat; } else ret = sense_cat; break; case SG_LIB_CAT_SENSE: if (sb_ok) { if (SPC_SK_DATA_PROTECT == ssh.sense_key) ret = DDPT_CAT_SK_DATA_PROTECT; else if (SPC_SK_COPY_ABORTED == ssh.sense_key) ret = DDPT_CAT_SK_COPY_ABORTED; else ret = sense_cat; } else ret = -1; break; case SG_LIB_CAT_RECOVERED: case SG_LIB_CAT_NO_SENSE: ret = 0; break; default: ret = -1; break; } } else ret = 0; return ret; } /* Handles various service actions associated with opcode 0x83 which is * called THIRD PARTY COPY OUT. These include the EXTENDED COPY(LID1 and * LID4), POPULATE TOKEN and WRITE USING TOKEN commands. * Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> opcode 0x83 not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int pt_3party_copy_out(int sg_fd, int sa, uint32_t list_id, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int vb, int err_vb) { int k, res, ret, has_lid, sense_cat, tmout; unsigned char xcopyCmdBlk[DDPT_TPC_OUT_CMDLEN] = {DDPT_TPC_OUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; char cname[80]; if (vb < 0) vb = 0; if (err_vb < 0) err_vb = 0; sg_get_opcode_sa_name(DDPT_TPC_OUT_CMD, sa, 0, sizeof(cname), cname); xcopyCmdBlk[1] = (unsigned char)(sa & 0x1f); switch (sa) { case 0x0: /* XCOPY(LID1) */ case 0x1: /* XCOPY(LID4) */ xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff); xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff); xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff); xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff); has_lid = 0; break; case 0x10: /* POPULATE TOKEN (SBC-3) */ case 0x11: /* WRITE USING TOKEN (SBC-3) */ xcopyCmdBlk[6] = (unsigned char)((list_id >> 24) & 0xff); xcopyCmdBlk[7] = (unsigned char)((list_id >> 16) & 0xff); xcopyCmdBlk[8] = (unsigned char)((list_id >> 8) & 0xff); xcopyCmdBlk[9] = (unsigned char)(list_id & 0xff); has_lid = 1; xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff); xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff); xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff); xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff); xcopyCmdBlk[14] = (unsigned char)(group_num & 0x1f); break; case 0x1c: /* COPY OPERATION ABORT */ xcopyCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff); xcopyCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff); xcopyCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff); xcopyCmdBlk[5] = (unsigned char)(list_id & 0xff); has_lid = 1; break; default: pr2serr("pt_3party_copy_out: unknown service action 0x%x\n", sa); return -1; } tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT; if (vb) { if ((vb > 1) || (param_len <= 0)) { pr2serr(" %s cmd : ", cname); for (k = 0; k < DDPT_TPC_OUT_CMDLEN; ++k) pr2serr("%02x ", xcopyCmdBlk[k]); pr2serr("\n"); } else if (has_lid) pr2serr(" %s for list_id=%" PRIu32 "\n", cname, list_id); if (paramp && param_len) { if (vb > 1) { if (param_len <= 16) { pr2serr(" %s parameter list:\n", cname); dStrHexErr((const char *)paramp, param_len, -1); } else { pr2serr(" %s, first 16 of %d byte parameter list:\n", cname, param_len); dStrHexErr((const char *)paramp, 16, -1); } } } } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { pr2serr("%s: out of memory\n", cname); return -1; } set_scsi_pt_cdb(ptvp, xcopyCmdBlk, sizeof(xcopyCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); res = do_scsi_pt(ptvp, sg_fd, tmout, vb); ret = sg_cmds_process_resp(ptvp, cname, res, 0, sense_b, noisy, ((err_vb > 0) ? err_vb : 0), &sense_cat); if ((-1 == ret) && (SCSI_PT_RESULT_STATUS == get_scsi_pt_result_category(ptvp)) && (SAM_STAT_RESERVATION_CONFLICT == get_scsi_pt_status_response(ptvp))) ret = DDPT_CAT_RESERVATION_CONFLICT; else ret = pt_tpc_process_res(ret, sense_cat, sense_b, get_scsi_pt_sense_len(ptvp)); destruct_scsi_pt_obj(ptvp); return ret; } int pt_3party_copy_in(int sg_fd, int sa, uint32_t list_id, int timeout_secs, void * resp, int mx_resp_len, int noisy, int vb, int err_vb) { int k, res, ret, sense_cat, tmout; unsigned char rcvcopyresCmdBlk[DDPT_TPC_IN_CMDLEN] = {DDPT_TPC_IN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; struct sg_pt_base * ptvp; char cname[64]; if (vb < 0) vb = 0; if (err_vb < 0) err_vb = 0; sg_get_opcode_sa_name(DDPT_TPC_IN_CMD, sa, 0, (int)sizeof(cname), cname); rcvcopyresCmdBlk[1] = (unsigned char)(sa & 0x1f); if (sa <= 4) /* LID1 variants */ rcvcopyresCmdBlk[2] = (unsigned char)(list_id); else if ((sa >= 5) && (sa <= 7)) { /* LID4 variants */ rcvcopyresCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff); rcvcopyresCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff); rcvcopyresCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff); rcvcopyresCmdBlk[5] = (unsigned char)(list_id & 0xff); } rcvcopyresCmdBlk[10] = (unsigned char)((mx_resp_len >> 24) & 0xff); rcvcopyresCmdBlk[11] = (unsigned char)((mx_resp_len >> 16) & 0xff); rcvcopyresCmdBlk[12] = (unsigned char)((mx_resp_len >> 8) & 0xff); rcvcopyresCmdBlk[13] = (unsigned char)(mx_resp_len & 0xff); tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT; if (vb > 1) { pr2serr(" %s cmd: ", cname); for (k = 0; k < DDPT_TPC_IN_CMDLEN; ++k) pr2serr("%02x ", rcvcopyresCmdBlk[k]); pr2serr("\n"); } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { pr2serr("%s: out of memory\n", cname); return -1; } set_scsi_pt_cdb(ptvp, rcvcopyresCmdBlk, sizeof(rcvcopyresCmdBlk)); set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); res = do_scsi_pt(ptvp, sg_fd, tmout, vb); ret = sg_cmds_process_resp(ptvp, cname, res, mx_resp_len, sense_b, noisy, ((err_vb > 0) ? err_vb : 0), &sense_cat); if ((-1 == ret) && (SCSI_PT_RESULT_STATUS == get_scsi_pt_result_category(ptvp)) && (SAM_STAT_RESERVATION_CONFLICT == get_scsi_pt_status_response(ptvp))) ret = DDPT_CAT_RESERVATION_CONFLICT; else ret = pt_tpc_process_res(ret, sense_cat, sense_b, get_scsi_pt_sense_len(ptvp)); destruct_scsi_pt_obj(ptvp); return ret; } ddpt-0.94/src/ddptctl.c0000644000175000017500000010604712320426132013771 0ustar douggdougg/* * Copyright (c) 2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* ddpt is a utility program for copying files. It broadly follows the syntax * and semantics of the "dd" program found in Unix. ddpt is specialised for * "files" that represent storage devices, especially those that understand * the SCSI command set accessed via a pass-through. */ /* * This utility, ddptctl, is an auxiliary to do related tasks for ddpt. * That way ddpt can concentrate on copy (or partial copy) operations. */ /* Need _GNU_SOURCE for O_DIRECT */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #define __STDC_LIMIT_MACROS 1 /* for UINT64_MAX, UINT32_MAX, etc */ #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include /* N.B. config.h must precede anything that depends on HAVE_* */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ddpt.h" const char * ddptctl_version_str = "0.94 20140407 [svn: r277]"; #ifdef SG_LIB_LINUX #include #include #include #include #include /* */ #include /* For tape ioctls */ #ifndef MTWEOFI #define MTWEOFI 35 /* write an end-of-file record (mark) in immediate mode */ #endif #ifdef HAVE_FALLOCATE #include #ifndef FALLOC_FL_KEEP_SIZE #define FALLOC_FL_KEEP_SIZE 0x01 /* from lk 3.1 linux/falloc.h */ #endif #endif #endif /* SG_LIB_LINUX */ #ifdef SG_LIB_FREEBSD #include #include #include #include #endif #ifdef SG_LIB_SOLARIS #include #include #endif #ifdef SG_LIB_WIN32 #ifndef SG_LIB_MINGW /* cygwin */ #include #endif #endif #include "sg_lib.h" #include "sg_cmds_basic.h" #define DEF_3PC_OUT_TIMEOUT (10 * 60) /* is 10 minutes enough? */ #define DEF_3PC_IN_TIMEOUT 60 /* these should be fast */ #define DEF_ROD_TOK_FILE "ddptctl_rod_tok.bin" static struct scat_gath_elem fixed_sgl[MAX_FIXED_SGL_ELEMS]; static struct option long_options[] = { {"abort", no_argument, 0, 'A'}, {"all_toks", no_argument, 0, 'a'}, {"block", no_argument, 0, 'b'}, {"del_tkn", no_argument, 0, 'D'}, {"help", no_argument, 0, 'h'}, {"info", no_argument, 0, 'i'}, {"immed", no_argument, 0, 'I'}, {"list_id", required_argument, 0, 'l'}, {"oir", required_argument, 0, 'O'}, {"poll", no_argument, 0, 'p'}, {"pt", required_argument, 0, 'P'}, {"receive", no_argument, 0, 'R'}, {"rtf", required_argument, 0, 'r'}, {"rtype", required_argument, 0, 't'}, {"timeout", required_argument, 0, 'T'}, {"size", no_argument, 0, 's'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"wut", required_argument, 0, 'w'}, {0, 0, 0, 0}, }; static void usage() { pr2serr("Usage: " "ddptctl [--abort] [--all_toks] [--block] [--del_tkn] [--help] " "[-immed]\n" " [--info] [--list_id=LID] [--oir=OIR] [--poll] " "[--pt=GL]\n" " [--receive] [--rtf=RTF] [rtype=RTYPE] [--size]\n" " [--timeout=ITO[,CMD]] [--verbose] [--version] " "[--wut=SL]\n" " [DEVICE]\n" " where:\n" " --abort|-A call COPY OPERATION ABORT command\n" " --all_toks|-a call REPORT ALL ROD TOKENS command\n" " --block|-B treat as block DEVICE (def: use " "SCSI commands)\n" " --del_tkn|-D set DEL_TKN bit in WUT command\n" " --help|-h print out usage message\n" " --immed|-I set IMMED bit in PT or WUT, exit " "prior to\n" " data transfer completion (then use " "--poll)\n" " --info|-i provide information on DEVICE or " "RTF\n" " --list_id=LID|-l LID LID is list identifier used with " "PT, WUT,\n" " RRTI or COPY OPERATION ABORT (def: " "257)\n" " --oir=OIR|-O OIR Offset In ROD (def: 0), used by WUT\n" " --poll|-p call RRTI periodically until " "completed\n" " --pt=GL|-P GL call PT with gather list GL. GL's " "format is\n" " LBA1,NUM1[,LBA2,NUM2...]\n" " --receive|-R call RRTI once\n" " --rtf=RTF|-r RTF ROD Token file for analysis (--info); " "output by\n" " -pt=, --poll or --receive; input to " "--wut=\n" " --rtype=RTYPE|-t RTYPE ROD type (def: RTV cleared in " "PT command)\n" " --size|-s get size of DEVICE (def: with SCSI " "commands)\n" " --timeout=ITO[,CMD] | -T ITO[,CMD]\n" " ITO is inactivity timeout (def: 0), " "CMD is\n" " command timeout (def: 600); units: " "seconds\n" " --verbose|-v increase verbosity\n" " --version|-V print version string and exit\n" " --wut=SL|-w SL call WUT with scatter list SL. SL's " "format same\n" " as GL\n\n" "ddptctl is a ddpt helper utility, mainly for ODX, a subset of " "xcopy(LID4).\nPT refers to the POPULATE TOKEN command, WUT to " "the WRITE USING TOKEN\ncommand and RRTI to the RECEIVE ROD " "TOKEN INFORMATION command. If\nthe ODX_RTF_LEN environment " "variable is present, the ROD's size is\nappended to the ROD " "Token placed in the RTF file.\n" ); } static int odx_rt_info(const struct opts_t * op) { int res, fd, err, m, prot_en, p_type, lbppbe, vendor, desig_type; int all_0, all_1, k, num, bp_chunk; int target_dev_desc = 0; int got_rtf_len = 0; int a_err = 0; uint64_t bc; uint32_t rod_t, bs; uint16_t rtl; unsigned char uc; unsigned char rth[520]; char b[128]; struct stat st; if ('\0' == op->rtf[0]) { pr2serr("odx_rt_info: expected ROD Token filename (rtf=RTF)\n"); return SG_LIB_FILE_ERROR; } if ((fd = open(op->rtf, O_RDONLY)) < 0) { err = errno; pr2serr("could not open '%s' for reading: %s\n", op->rtf, safe_strerror(err)); return SG_LIB_FILE_ERROR; } if (fstat(fd, &st) < 0) { perror("fstat() on rtf"); return SG_LIB_FILE_ERROR; } res = st.st_size % 512; if (res > 0) { res = st.st_size % 520; if (res > 0) { pr2serr("rtf size is %d bytes, not a multiple of 512 or 520 " "bytes, so exit\n", (int)st.st_size); return SG_LIB_FILE_ERROR; } ++got_rtf_len; } bp_chunk = got_rtf_len ? 520 : 512; num = st.st_size / bp_chunk; if (num > 1) printf("Decoding file with %d ROD Tokens:\n", num); for (k = 0; k < num; ++k) { res = read(fd, rth, bp_chunk); if (res < 0) { err = errno; pr2serr("could not read '%s': %s\n", op->rtf, safe_strerror(err)); close(fd); return SG_LIB_FILE_ERROR; } if (res < bp_chunk) { pr2serr("unable to read %d bytes from '%s', only got %d bytes\n", bp_chunk, op->rtf, res); pr2serr("... it is unlikely file '%s' contains a ROD Token\n", op->rtf); close(fd); return SG_LIB_FILE_ERROR; } if (op->verbose > 3) { pr2serr("Hex dump of chunk %d from rtf file:\n", bp_chunk); dStrHexErr((const char *)rth, bp_chunk, 1); } if (num > 1) printf("%s Decoding information from ROD Token %d\n", ((k > 0) ? "\n" : ""), k); else printf("Decoding information from ROD Token:\n"); rod_t = (rth[0] << 24) + (rth[1] << 16) + (rth[2] << 8) + rth[3]; printf(" ROD type: %s\n", rod_type_str(rod_t, b, sizeof(b))); if (rod_t >= 0xfffffff0) { printf(" Since ROD type is vendor specific, the following may " "not be relevant\n"); vendor = 1; } else { vendor = 0; target_dev_desc = (RODT_ACCESS_ON_REF == rod_t) || (RODT_PIT_DEF == rod_t) || (RODT_PIT_VULN == rod_t) || (RODT_PIT_PERS == rod_t); } rtl = (rth[6] << 8) + rth[7]; if (rtl < ODX_ROD_TOK_LEN_FLD) { pr2serr(">>> ROD Token length field is too short, should be at " "least\n %d bytes (0x%x), got 0x%" PRIx16 "\n", ODX_ROD_TOK_LEN_FLD, ODX_ROD_TOK_LEN_FLD, rtl); if (! vendor) { a_err = SG_LIB_CAT_OTHER; goto skip_to_num_bytes; } } printf(" Copy manager ROD Token identifier: %s\n", rt_cm_id_str(rth, rtl + 8, b, sizeof(b))); printf(" Creator Logical Unit descriptor:\n"); /* should make smaller version of following that outputs to stdout */ if (0xe4 != rth[16]) { pr2serr(">>> Expected Identification descriptor (0xe4) got 0x%x\n", rth[16]); if (! vendor) { a_err = SG_LIB_CAT_OTHER; goto skip_to_num_bytes; } } printf(" Peripheral Device type: 0x%x\n", rth[17] & 0x1f); printf(" Relative initiator port identifier: 0x%x\n", (rth[18] << 8) + rth[19]); desig_type = rth[20 + 1] & 0xf; if ((0x2 == desig_type) || (0x3 == desig_type)) decode_designation_descriptor(rth + 20, 32 - 4, 0, op->verbose); else printf(" Expected designator type of EUI-64 or NAA, got " "0x%x\n", desig_type); /* A 16 byte integer worth of bytes! Seems like overkill. */ /* Look for all 0s or all 1s in the top 8 bytes */ all_0 = (0x0 == rth[48]); if (all_0) all_1 = 0; else if (0xff == rth[48]) all_1 = 1; else { all_1 = 0; printf(" Number of bytes represented: strange, bypass\n"); goto skip_to_bytes_rep; } for (m = 1; m < 8; m++) { uc = rth[48 + m]; if (! (((0xff == uc) && all_1) || ((0 == uc) && all_0))) break; } if (m < 8) { printf(" Number of bytes represented: strange, bypass\n"); goto skip_to_bytes_rep; } bc = 0; for (m = 0; m < 8; m++) { if (m > 0) bc <<= 8; bc |= rth[56 + m]; } if ((UINT64_MAX == bc) && all_1) printf(" Number of bytes represented: unknown or too large\n"); else if (all_0) printf(" Number of bytes represented: %" PRIu64 " [0x%" PRIx64 "]\n", bc, bc); else printf(" Number of bytes represented: strange (top 8 bytes " "0xff)\n"); skip_to_bytes_rep: bs = ((rth[96] << 24) + (rth[97] << 16) + (rth[98] << 8) + rth[99]); if (0 == bs) { printf(" Device type specific data (for disk) has block size of " "0; unlikely so skip\n"); goto skip_to_target_dev_desc; } printf(" Assume pdt=0 (e.g. disk) and decode device type specific " "data:\n"); printf(" block size: %" PRIu32 " [0x%" PRIx32 "] bytes\n", bs, bs); prot_en = !!(rth[100] & 0x1); p_type = ((rth[100] >> 1) & 0x7); printf(" Protection: prot_en=%d, p_type=%d, p_i_exponent=%d", prot_en, p_type, ((rth[101] >> 4) & 0xf)); if (prot_en) printf(" [type %d protection]\n", p_type + 1); else printf("\n"); printf(" Logical block provisioning: lbpme=%d, lbprz=%d\n", !!(rth[102] & 0x80), !!(rth[102] & 0x40)); lbppbe = rth[102] & 0xf; printf(" Logical blocks per physical block exponent=%d\n", lbppbe); if (lbppbe > 0) printf(" [so physical block length=%" PRIu32 " bytes]\n", bs * (1 << lbppbe)); printf(" Lowest aligned logical block address=%d\n", ((rth[102] & 0x3f) << 8) + rth[103]); skip_to_target_dev_desc: if (target_dev_desc) { desig_type = rth[128 + 1] & 0xf; if ((0x2 == desig_type) || (0x3 == desig_type) || (0x8 == desig_type) || op->verbose) { printf(" Target device descriptor:\n"); decode_designation_descriptor(rth + 128, 128 - 4, 0, op->verbose); } else printf(" Target device descriptor: unexpected designator " "type [0x%x]\n", desig_type); } skip_to_num_bytes: if (got_rtf_len) { for (m = 0, bc = 0; m < 8; ++m) { if (m > 0) bc <<= 8; bc += rth[512 + m]; } printf(" Number of bytes represented: %" PRIu64 " [0x%" PRIx64 "] (appended to token)\n", bc, bc); } } close(fd); return a_err; } static int do_copy_abort(struct opts_t * op) { return pt_3party_copy_out(op->idip->fd, SA_COPY_ABORT, op->list_id, DEF_GROUP_NUM, DEF_3PC_OUT_TIMEOUT, NULL, 0, 1, op->verbose, op->verbose); } static int report_all_toks(struct opts_t * op, struct dev_info_t * dip) { int res, fd; unsigned int len; unsigned char rsp[2048]; fd = dip->fd; res = pt_3party_copy_in(fd, SA_ALL_ROD_TOKS, op->list_id, DEF_3PC_IN_TIMEOUT, rsp, sizeof(rsp), 1, op->verbose, op->verbose); if (res) return res; len = ((rsp[0] << 24) | (rsp[1] << 16) | (rsp[2] << 8) | rsp[3]) + 4; if (len > sizeof(rsp)) { pr2serr(" ROD Tokens too long for internal buffer, output " "truncated\n"); len = sizeof(rsp); } if (op->verbose > 2) { pr2serr("\nReport all ROD tokens response in hex:\n"); dStrHexErr((const char *)rsp, len, 1); } // Hmmm, not supported on HP 3 PAR (and not required for ODX) return 0; } static int write_to_rtf(struct opts_t * op, const struct rrti_resp_t * rp) { int res, len, err; const char * cp; if (op->rtf_fd < 0) { cp = DEF_ROD_TOK_FILE; strncpy(op->rtf, cp, INOUTF_SZ - 1); pr2serr("no --rtf=RTF given (or RTF broken) so writing ROD Token " "to %s\n", cp); res = open_rtf(op); if (res) return SG_LIB_FILE_ERROR; } else cp = op->rtf; len = (rp->rt_len > 512) ? 512 : rp->rt_len; res = write(op->rtf_fd, rp->rod_tok, len); if (res < 0) { err = errno; pr2serr("%s: unable to write to file: %s [%s]\n", __func__, cp, safe_strerror(err)); return SG_LIB_FILE_ERROR; } if (res < len) { pr2serr("%s: short write to file: %s, wanted %d, got %d\n", __func__, cp, len, res); return SG_LIB_CAT_OTHER; } return 0; } /* Returns the number of times 'ch' is found in string 's' given the * string's length. */ static int num_chs_in_str(const char * s, int slen, int ch) { int res = 0; while (--slen >= 0) { if (ch == s[slen]) ++res; } return res; } static int do_sgl(struct opts_t * op, const char * opt, const char * buf) { int k, len, res, got; len = (int)strlen(buf); if ((('-' == buf[0]) && (1 == len)) || ((len > 1) && ('@' == buf[0]))) { res = file_to_sgl(((len > 1) ? (buf + 1) : buf), fixed_sgl, &got, MAX_FIXED_SGL_ELEMS); if (res) { pr2serr("bad argument to '%s'\n", opt); return SG_LIB_SYNTAX_ERROR; } } else if (num_chs_in_str(buf, len, ',') > 0) { res = cl_to_sgl(buf, fixed_sgl, &got, MAX_FIXED_SGL_ELEMS); if (res) { pr2serr("bad argument to '%s'\n", opt); return SG_LIB_SYNTAX_ERROR; } } else { pr2serr("bad argument to '%s', need at least one LBA,NUM pair\n", opt); return SG_LIB_SYNTAX_ERROR; } op->in_sgl = fixed_sgl; op->in_sgl_elems = got; op->out_sgl = fixed_sgl; op->out_sgl_elems = got; if (op->verbose > 3) { pr2serr("scatter-gather list (%d elements):\n", op->in_sgl_elems); for (k = 0; k < op->in_sgl_elems; ++k) pr2serr(" lba: 0x%" PRIx64 ", number: 0x%" PRIx32 "\n", op->in_sgl[k].lba, op->in_sgl[k].num); } return 0; } int main(int argc, char * argv[]) { int c, k, n, fd, flags, blk_sz, cont, err; uint32_t delay; int64_t i64, num_blks; uint64_t tc; int req_abort = 0; int req_all_toks = 0; int do_block = 0; int do_info = 0; int do_poll = 0; int req_pt = 0; int do_receive = 0; int do_size = 0; int req_wut = 0; int ret = 0; struct opts_t ops; struct flags_t iflag, oflag; struct dev_info_t ids, ods, o2ds; struct sg_simple_inquiry_resp sir; struct rrti_resp_t rrti_rsp; struct opts_t * op; char * np; const char * sglp = NULL; char b[80]; char bb[80]; unsigned char rt[512]; state_init(&ops, &iflag, &oflag, &ids, &ods, &o2ds); op = &ops; memset(&sir, 0, sizeof(sir)); memset(&rrti_rsp, 0, sizeof(rrti_rsp)); while (1) { int option_index = 0; c = getopt_long(argc, argv, "AaBDhiIl:O:pP:r:Rst:T:vVw:", long_options, &option_index); if (c == -1) break; switch (c) { case 'A': ++req_abort; break; case 'a': ++req_all_toks; break; case 'B': ++do_block; break; case 'D': ++op->oflagp->del_tkn; break; case 'h': case '?': usage(); return 0; case 'i': ++do_info; break; case 'I': ++op->iflagp->immed; ++op->oflagp->immed; break; case 'l': i64 = sg_get_llnum(optarg); if (-1 == i64) { pr2serr("bad argument to 'list_id='\n"); return SG_LIB_SYNTAX_ERROR; } if (i64 > UINT32_MAX) { pr2serr("argument to 'list_id=' too big for 32 bits\n"); return SG_LIB_SYNTAX_ERROR; } op->list_id = (uint32_t)i64; op->list_id_given = 1; break; case 'O': op->offset_in_rod = sg_get_llnum(optarg); if (-1LL == op->offset_in_rod) { pr2serr("bad argument to '--oir='\n"); return SG_LIB_SYNTAX_ERROR; } break; case 'p': ++do_poll; break; case 'P': /* takes gather list as argument */ if (req_pt) { pr2serr("Using two --pt=GL options is contradictory\n"); return SG_LIB_SYNTAX_ERROR; } ++req_pt; sglp = optarg; break; case 'r': if (op->rtf[0]) { pr2serr("Can only use --rtf=RTF once for ROD Token " "filename\n"); return SG_LIB_SYNTAX_ERROR; } if (optarg && (0 == strlen(optarg))) { pr2serr("--rtf= needs a non-blank argument (a filename)\n"); return SG_LIB_SYNTAX_ERROR; } strncpy(op->rtf, optarg, INOUTF_SZ - 1); break; case 'R': ++do_receive; break; case 's': ++do_size; break; case 't': if (0 == strncmp("pit-def", optarg, 7)) op->rod_type = RODT_PIT_DEF; else if (0 == strncmp("pit-vuln", optarg, 8)) op->rod_type = RODT_PIT_VULN; else if (0 == strncmp("pit-pers", optarg, 8)) op->rod_type = RODT_PIT_PERS; else if (0 == strncmp("pit-any", optarg, 7)) op->rod_type = RODT_PIT_ANY; else if (0 == strncmp("zero", optarg, 4)) op->rod_type = RODT_BLK_ZERO; else { i64 = sg_get_llnum(optarg); if (-1 == i64) { pr2serr("bad argument to '--rtype='; can give (hex) " "number, 'pit-def', 'pit-vuln',\n"); pr2serr("'pit-pers', 'pit-any' or 'zero'\n"); return SG_LIB_SYNTAX_ERROR; } if (i64 > UINT32_MAX) { pr2serr("'rtype=' argument exceeds 32 bits\n"); return SG_LIB_SYNTAX_ERROR; } op->rod_type = (uint32_t)i64; } ++op->rod_type_given; break; case 'T': n = sg_get_num(optarg); if (-1 == n) { pr2serr("bad argument to '--timeout='\n"); return SG_LIB_SYNTAX_ERROR; } op->inactivity_to = n; np = strchr(optarg, ','); if (np) { op->timeout_xcopy = sg_get_num(++np); if (-1 == op->timeout_xcopy) { pr2serr("bad argument to '--timeout=ok,xxx'\n"); return SG_LIB_SYNTAX_ERROR; } } break; case 'v': ++op->verbose; break; case 'V': pr2serr("version: %s\n", ddptctl_version_str); return 0; case 'w': /* takes scatter list as argument */ if (req_wut) { pr2serr("Using two --wut=SL options is contradictory\n"); return SG_LIB_SYNTAX_ERROR; } ++req_wut; sglp = optarg; break; default: pr2serr("unrecognised option code 0x%x ??\n", c); usage(); return SG_LIB_SYNTAX_ERROR; } } if (optind < argc) { if ('\0' == op->idip->fn[0]) { strncpy(op->idip->fn, argv[optind], INOUTF_SZ - 1); strncpy(op->odip->fn, argv[optind], INOUTF_SZ - 1); ++optind; } if (optind < argc) { for (; optind < argc; ++optind) pr2serr("Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if ('\0' == op->idip->fn[0]) { if (! op->rtf[0]) { pr2serr("missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } } op->odx_request = ODX_REQ_NONE; k = 0; if (req_abort) ++k; if (req_all_toks) ++k; if (do_poll) { ++k; op->odx_request = ODX_READ_INTO_RODS; } if (req_pt) { ++k; op->odx_request = ODX_READ_INTO_RODS; } if (do_receive) { ++k; op->odx_request = ODX_READ_INTO_RODS; } if (req_wut) { ++k; op->odx_request = ODX_WRITE_FROM_RODS; } if (k > 1) { pr2serr("Can only have one of --abort, --all_toks, --poll, --pt=, " "--receive and --wut=\n"); return SG_LIB_SYNTAX_ERROR; } if (do_info && (1 == k)) { pr2serr("--info cannot be used with an ODX command option (e.g. " "--pt=)\n"); return SG_LIB_SYNTAX_ERROR; } if (1 == k) { if ('\0' == op->idip->fn[0]) { pr2serr("need a DEVICE (e.g. /dev/sg3) to send command to\n"); return SG_LIB_SYNTAX_ERROR; } if (! (req_all_toks || op->list_id_given)) op->list_id = DEF_LID4_LID; } if (op->rtf[0]) { if (do_info) { if (op->idip->fn[0]) pr2serr("Ignore device name [%s] and decode RTF\n", op->idip->fn); return odx_rt_info(op); } else if ('\0' == op->idip->fn[0]) return odx_rt_info(op); } /* If present, this will cause the ROD's size to be appended to the * corresponding ROD Token placed in the RTF file (big endian, 8 byte) */ np = getenv(ODX_RTF_LEN); if (np) ++op->rtf_len_add; if (req_pt || req_wut) { ret = do_sgl(op, (req_pt ? "--pt=" : "--wut="), sglp); if (ret) return ret; } op->idip->d_type = do_block ? FT_BLOCK : FT_PT; if (op->idip->d_type & FT_PT) { fd = pt_open_if(op, &sir); if (-1 == fd) { ret = SG_LIB_FILE_ERROR; goto clean_up; } else if (fd < -1) { ret = SG_LIB_CAT_OTHER; goto clean_up; } op->idip->fd = fd; op->odip->fd = fd; } else if (op->idip->d_type & FT_BLOCK) { flags = O_RDONLY; fd = open(op->idip->fn, flags); if (fd < 0) { pr2serr("could not open %s for reading: %s\n", op->idip->fn, safe_strerror(errno)); ret = SG_LIB_FILE_ERROR; goto clean_up; } op->idip->fd = fd; op->odip->fd = fd; } else { pr2serr("expecting to open a file but nothing found\n"); ret = SG_LIB_CAT_OTHER; goto clean_up; } if (op->odx_request != ODX_REQ_NONE) { if (('\0' == op->rtf[0]) && (ODX_WRITE_FROM_RODS == op->odx_request) && (RODT_BLK_ZERO != op->rod_type)) { pr2serr("--wut= needs ROD token file but no --rtf=RTF\n"); ret = SG_LIB_FILE_ERROR; goto clean_up; } ret = open_rtf(op); if (ret) { ret = SG_LIB_FILE_ERROR; goto clean_up; } } if (req_abort) { ret = do_copy_abort(op); if (ret) goto clean_up; } else if (req_all_toks) { ret = report_all_toks(op, op->idip); if (ret) goto clean_up; } else if (do_poll) { do { ret = do_rrti(op, DDPT_ARG_IN, &rrti_rsp, op->verbose); if (ret) goto clean_up; cont = ((rrti_rsp.cstat >= 0x10) && (rrti_rsp.cstat <= 0x12)); if (cont) { delay = rrti_rsp.esu_del; if ((delay < 0xfffffffe) && (delay > 0)) { if (op->verbose > 1) pr2serr("using copy manager recommended delay of %" PRIu32 " milliseconds\n", delay); } else { delay = DEF_ODX_POLL_DELAY_MS; if (op->verbose > 1) pr2serr("using default for poll delay\n"); } if (delay) sleep_ms(delay); } } while (cont); sg_get_opcode_sa_name(THIRD_PARTY_COPY_OUT_CMD, rrti_rsp.for_sa, 0, (int)sizeof(b), b); printf("RRTI for %s: %s\n", b, cpy_op_status_str(rrti_rsp.cstat, bb, sizeof(bb))); printf(" transfer count of %" PRIu64 " [0x%" PRIx64 "]\n", rrti_rsp.tc, rrti_rsp.tc); if ((SA_POP_TOK == rrti_rsp.for_sa) && (rrti_rsp.rt_len > 0)) { ret = write_to_rtf(op, &rrti_rsp); if (ret) goto clean_up; } } else if (req_pt) { op->odx_request = ODX_READ_INTO_RODS; num_blks = count_sgl_blocks(op->in_sgl, op->in_sgl_elems); if ((ret = do_pop_tok(op, 0, num_blks, 0, op->verbose))) goto clean_up; else if (op->iflagp->immed) goto clean_up; if ((ret = process_after_poptok(op, &tc, op->verbose))) goto clean_up; printf("PT completes with a transfer count of %" PRIu64 " [0x%" PRIx64 "]\n", tc, tc); if (op->rtf_fd < 0) { /* ROD Token not sent to file, so ... */ /* dummy up rrti_rsp object and write to DEF_ROD_TOK_FILE */ rrti_rsp.rt_len = 512; get_local_rod_tok(rrti_rsp.rod_tok, rrti_rsp.rt_len); ret = write_to_rtf(op, &rrti_rsp); if (ret) goto clean_up; } goto clean_up; } else if (do_receive) { ret = do_rrti(op, DDPT_ARG_IN, &rrti_rsp, op->verbose); if (ret) goto clean_up; sg_get_opcode_sa_name(THIRD_PARTY_COPY_OUT_CMD, rrti_rsp.for_sa, 0, (int)sizeof(b), b); printf("RRTI for %s: %s\n", b, cpy_op_status_str(rrti_rsp.cstat, bb, sizeof(bb))); printf(" transfer count of %" PRIu64 " [0x%" PRIx64 "]\n", rrti_rsp.tc, rrti_rsp.tc); if ((SA_POP_TOK == rrti_rsp.for_sa) && (rrti_rsp.rt_len > 0)) { ret = write_to_rtf(op, &rrti_rsp); if (ret) goto clean_up; } } else if (req_wut) { op->odx_request = ODX_WRITE_FROM_RODS; memset(rt, 0, sizeof(rt)); if (RODT_BLK_ZERO == op->rod_type) { if (op->verbose > 1) pr2serr(" configure for block device zero ROD Token\n"); rt[0] = (unsigned char)((RODT_BLK_ZERO >> 24) & 0xff); rt[1] = (unsigned char)((RODT_BLK_ZERO >> 16) & 0xff); rt[2] = (unsigned char)((RODT_BLK_ZERO >> 8) & 0xff); rt[3] = (unsigned char)(RODT_BLK_ZERO & 0xff); rt[6] = (unsigned char)((ODX_ROD_TOK_LEN_FLD >> 8) & 0xff); rt[7] = (unsigned char)(ODX_ROD_TOK_LEN_FLD & 0xff); } else { ret = read(op->rtf_fd, rt, sizeof(rt)); if (ret < 0) { err = errno; pr2serr("could not read '%s': %s\n", op->rtf, safe_strerror(err)); goto clean_up; } if (ret < (int)sizeof(rt)) pr2serr("unable to read %d bytes from '%s', only got %d " "bytes\n", (int)sizeof(rt), op->rtf, ret); } num_blks = count_sgl_blocks(op->out_sgl, op->out_sgl_elems); if ((ret = do_wut(op, rt, 0, num_blks, op->offset_in_rod, 1 /* assume more left */, 0, op->verbose))) goto clean_up; else if (op->oflagp->immed) goto clean_up; if ((ret = process_after_wut(op, &tc, op->verbose))) goto clean_up; printf("WUT completes with a transfer count of %" PRIu64 " [0x%" PRIx64 "]\n", tc, tc); } else if (do_info || do_size) { if (op->idip->d_type & FT_PT) { ret = pt_read_capacity(op, DDPT_ARG_IN, &num_blks, &blk_sz); if (ret) { if (SG_LIB_CAT_UNIT_ATTENTION == ret) { if (op->verbose) pr2serr("Unit attention (readcap), continuing\n"); ret = pt_read_capacity(op, DDPT_ARG_IN, &num_blks, &blk_sz); if (ret) { if (0 == sir.peripheral_type) pr2serr("read capacity failed, perhaps because " "non-disk device [pdt=%d]\n", sir.peripheral_type); goto clean_up; } } } print_blk_sizes(op->idip->fn, "readcap", num_blks, blk_sz, 0); if (do_info) { if (0x8 & sir.byte_5) { printf("3PC (third party copy) bit set in standard " "INQUIRY response\n"); printf(" Third Party Copy VPD page:\n"); print_3pc_vpd(op, 0); } else { printf("3PC (third party copy) bit clear in standard " "INQUIRY response\n"); printf(" so %s [pdt=0x%x] does not seem to support " "XCOPY\n", op->idip->fn, sir.peripheral_type); } } } else if (op->idip->d_type & FT_BLOCK) { ret = get_blkdev_capacity(op, DDPT_ARG_IN, &num_blks, &blk_sz); if (ret) goto clean_up; print_blk_sizes(op->idip->fn, "block", num_blks, blk_sz, 0); } else { num_blks = 0; blk_sz = 0; printf("unable to print capacity information about device\n"); } } else printf("Has something been forgotten\n"); clean_up: if ((req_pt || req_wut) && op->iflagp->immed && (0 == ret)) pr2serr("Started ODX %s command in immediate mode.\nUser may need " "--list_id=%" PRIu32 " on following invocation with " "--receive or\n--poll for completion\n", (req_pt ? "Populate Token" : "Write Using Token"), op->list_id); if (op->idip->fd >= 0) { if (op->idip->d_type & FT_PT) pt_close(op->idip->fd); else if (op->idip->d_type & FT_BLOCK) close(op->idip->fd); } if (op->rtf_fd >= 0) close(op->rtf_fd); if (ret) { if (ret > 0) print_exit_status_msg("Exit status", ret, 0); else if (ret < 0) { pr2serr("Some error occurred\n"); ret = 1; } } return ret; } ddpt-0.94/src/ddpt.h0000644000175000017500000004671112316716027013306 0ustar douggdougg#ifndef DDPT_H #define DDPT_H /* This is a C header file for the ddpt utility. See ddpt.c and ddpt.8 * for more information. */ #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef __cplusplus extern "C" { #endif #ifdef SG_LIB_WIN32 #include #endif #ifdef SG_LIB_FREEBSD #ifndef SIGINFO /* hack to undo hiding by _XOPEN_SOURCE and _GNU_SOURCE */ #define SIGINFO 29 #endif #endif #ifdef SG_LIB_WIN32 #ifdef SG_LIB_MINGW #define SIGPIPE 13 #define SIGQUIT 3 #define SIGUSR1 25 #endif #endif /* Borrow signal handling from dd (src/dd.c in coreutils-8.13) */ /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is present. */ #ifndef SA_NOCLDSTOP # define SA_NOCLDSTOP 0 # define sigprocmask(How, Set, Oset) /* empty */ # define sigset_t int # if ! HAVE_SIGINTERRUPT # define siginterrupt(sig, flag) /* empty */ # endif #endif /* NonStop circa 2011 lacks SA_RESETHAND; see Bug#9076. */ #ifndef SA_RESETHAND # define SA_RESETHAND 0 #endif #ifndef SIGINFO # define SIGINFO SIGUSR1 #endif /* end of borrow from dd signal handling defines */ #define STR_SZ 1024 #define INOUTF_SZ 512 #define EBUFF_SZ 512 #define DEF_BLOCK_SIZE 512 #define DEF_BPT_LT8 8192 /* BPT when IBS < 8 */ #define DEF_BPT_LT64 1024 /* BPT when IBS < 64 */ #define DEF_BPT_LT1024 128 /* BPT when IBS < 1024 */ #define DEF_BPT_LT8192 16 /* BPT when IBS < 8192 */ #define DEF_BPT_LT32768 4 /* BPT when IBS < 32768 */ #define DEF_BPT_GE32768 1 /* BPT when IBS >= 32768 */ #define MAX_XC_BPT 65535 /* BPT maximum for xcopy(LID1) */ #define MAX_XC_BPT_POW2 32768 /* BPT maximum that is power of 2 */ #define DEF_SCSI_CDBSZ 10 #define MAX_SCSI_CDBSZ 32 #define VPD_DEVICE_ID 0x83 #define VPD_3PARTY_COPY 0x8f #define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ #define READ_CAP_REPLY_LEN 8 #define RCAP16_REPLY_LEN 32 #define DEF_RW_TIMEOUT 60 /* 60 seconds for READ and WRITE */ #define WRITE_SAME16_TIMEOUT 180 /* 3 minutes */ #define DEF_GROUP_NUM 0 #define DEF_LID4_LID 257 /* just above the LID1 highest of 255 */ #define DEF_LID4_WR_LID 258 #ifdef SG_LIB_LINUX #ifndef RAW_MAJOR #define RAW_MAJOR 255 /*unlikey value */ #endif #define DEV_NULL_MINOR_NUM 3 #endif #define SG_LIB_FLOCK_ERR 90 /* File type categories */ #define FT_OTHER 1 /* unknown (unable to identify) */ #define FT_PT 2 /* SCSI commands can be sent via a pass-through */ #define FT_REG 4 /* a normal (regular) file */ #define FT_DEV_NULL 8 /* either "/dev/null" or "." as filename */ #define FT_TAPE 16 /* tape style device */ #define FT_BLOCK 32 /* block device */ #define FT_FIFO 64 /* fifo (named or unnamed pipe (stdout)) */ #define FT_CHAR 128 /* char dev, doesn't fit another category */ #define FT_ERROR 256 /* couldn't "stat" file */ /* ODX type requested */ #define ODX_REQ_NONE 0 /* some other type of copy */ #define ODX_READ_INTO_RODS 1 /* POPULATE TOKENs (PTs): disk->rods */ #define ODX_WRITE_FROM_RODS 2 /* WRITE USING TOKENs (WUTs): rods->disk */ #define ODX_COPY 3 /* odx disk->disk or zero->disk */ /* ROD Types used by ODX */ #define RODT_CM_INTERNAL 0x0 #define RODT_ACCESS_ON_REF 0x10000 #define RODT_PIT_DEF 0x800000 #define RODT_PIT_VULN 0x800001 #define RODT_PIT_PERS 0x800002 #define RODT_PIT_ANY 0x80ffff #define RODT_BLK_ZERO 0xffff0001 /* If O_DIRECT or O_SYNC not supported then define harmlessly */ #ifndef O_DIRECT #define O_DIRECT 0 #endif #ifndef O_SYNC #define O_SYNC 0 #endif #ifndef O_NONBLOCK #define O_NONBLOCK 0 #endif #define DDPT_ARG_IN 0 #define DDPT_ARG_OUT 1 #define DDPT_ARG_OUT2 2 #define MIN_RESERVED_SIZE 8192 #define MAX_UNIT_ATTENTIONS 10 #define MAX_ABORTED_CMDS 16 #define DELAY_COPY_SEGMENT 0 #define DELAY_WRITE 1 #define REASON_TAPE_SHORT_READ 1024 /* leave_reason indication */ /* Following used for sense_key=aborted_command, asc=0x10, ascq=* which * contains errors associated with protection fields */ #ifndef SG_LIB_CAT_PROTECTION #define SG_LIB_CAT_PROTECTION 40 #define SG_LIB_CAT_PROTECTION_WITH_INFO 41 #endif #define DDPT_CAT_RESERVATION_CONFLICT 30 #define DDPT_CAT_PARAM_LST_LEN_ERR 50 #define DDPT_CAT_INVALID_FLD_IN_PARAM 51 #define DDPT_CAT_TOO_MANY_SEGS_IN_PARAM 52 #define DDPT_CAT_TARGET_UNDERRUN 53 #define DDPT_CAT_TARGET_OVERRUN 54 #define DDPT_CAT_OP_IN_PROGRESS 55 #define DDPT_CAT_INSUFF_RES_CREATE_ROD 56 #define DDPT_CAT_INSUFF_RES_CREATE_RODTOK 57 #define DDPT_CAT_CMDS_CLEARED_BY_DEV_SVR 58 #define DDPT_CAT_TOKOP_BASE 70 /* assume less than 20 above this */ #define DDPT_CAT_SK_DATA_PROTECT 7 /* same as sense key code */ #define DDPT_CAT_SK_COPY_ABORTED 10 /* same as sense key code */ #define XCOPY_TO_SRC "XCOPY_TO_SRC" #define XCOPY_TO_DST "XCOPY_TO_DST" #define DEF_XCOPY_SRC0_DST1 1 #define ODX_RTF_LEN "ODX_RTF_LEN" /* append 8 byte ROD size to token */ /* ODX: length field inside ROD Token constant, implies 512 byte ROD Token */ #define ODX_ROD_TOK_LEN_FLD 504 /* 0x1f8 */ #define DEF_ODX_POLL_DELAY_MS 500 /* In SPC-4 the cdb opcodes have more generic names */ #define THIRD_PARTY_COPY_OUT_CMD 0x83 #define THIRD_PARTY_COPY_IN_CMD 0x84 /* Third party copy IN (opcode 0x84) and OUT (opcode 0x83) command service * actions */ #define SA_XCOPY_LID1 0x0 /* OUT, originate */ #define SA_XCOPY_LID4 0x1 /* OUT, originate */ #define SA_POP_TOK 0x10 /* OUT, originate */ #define SA_WR_USING_TOK 0x11 /* OUT, originate */ #define SA_COPY_ABORT 0x1C /* OUT, abort */ #define SA_COPY_STATUS_LID1 0x0 /* IN, retrieve */ #define SA_COPY_DATA_LID1 0x1 /* IN, retrieve */ #define SA_COPY_OP_PARAMS 0x3 /* IN, retrieve */ #define SA_COPY_FAIL_DETAILS 0x4 /* IN, retrieve */ #define SA_COPY_STATUS_LID4 0x5 /* IN, retrieve */ #define SA_COPY_DATA_LID4 0x6 /* IN, retrieve */ #define SA_ROD_TOK_INFO 0x7 /* IN, retrieve */ #define SA_ALL_ROD_TOKS 0x8 /* IN, retrieve */ #define MAX_FIXED_SGL_ELEMS 128 /* same for gl and sl; MS max is 64 */ struct scat_gath_elem { uint64_t lba; /* of first block */ uint32_t num; /* of blocks */ }; struct block_rodtok_vpd { uint16_t max_range_desc; uint32_t max_inactivity_to; uint32_t def_inactivity_to; uint32_t max_tok_xfer_size; uint32_t optimal_xfer_count; }; /* One instance for arguments to iflag= , another instance for oflag= * conv= arguments are mapped to flag arguments. * General or for disk unless otherwise marked. */ struct flags_t { int append; int block; /* only for pt, non blocking default */ int cat; /* xcopy(lid1) related */ int cdbsz; int coe; int dc; /* xcopy(lid1) related */ int del_tkn; /* xcopy(odx) related */ int direct; int dpo; int errblk; int excl; int fdatasync; int flock; int force; int fsync; int fua; int fua_nv; int ignoreew; /* tape */ int immed; /* xcopy(odx) related */ int nocache; int no_del_tkn; /* xcopy(odx) related */ int nofm; /* tape */ int nopad; int norcap; int nowrite; int odx; /* xcopy(LID4), sbc-3's POPULATE TOKEN++ */ int pad; /* used for xcopy(lid1) or tape */ int prealloc; int pt; /* use pass-through to inject SCSI commands */ int resume; int rarc; int retries; int rtf_len; int self; int sparing; int sparse; int ssync; int strunc; int sync; int trunc; int wsame16; int xcopy; /* xcopy(LID1) */ }; /* one instance per file/device: if, of and of2 */ struct dev_info_t { int d_type; /* one of FT_* values */ int d_type_hold; int fd; #ifdef SG_LIB_WIN32 HANDLE fh; #endif int pdt; int prot_type; /* from RCAP(16) or 0 */ int p_i_exp; /* protection intervals exponent */ unsigned long xc_min_bytes; unsigned long xc_max_bytes; char fn[INOUTF_SZ]; struct block_rodtok_vpd * odxp; struct sg_pt_base * ptvp; }; /* command line options and most other state */ /* The _given fields indicate whether option was given or is a default */ struct opts_t { /* command line related variables */ int64_t skip; int64_t seek; int count_given; int bs_given; /* 1 implies bs= option given on command line */ int delay; /* intra copy segment delay in milliseconds */ int wdelay; /* delay prior to each write in copy segment */ int subsequent_wdelay; /* so no delay before first write */ int ibs; int ibs_pi; /* if (protect) ibs_pi = ibs+pi_len else ibs_pi=ibs */ int ibs_given; int obs; int obs_pi; /* if (protect) obs_pi = obs+pi_len else obs_pi=obs */ int obs_given; int bpt_i; /* blocks (of input) per transfer */ int bpt_given; int obpch; /* output blocks per check, granularity of sparse, * sparing and trim checks for zeros */ int id_usage; /* xcopy(LID1) List identifier usage, init to -1 */ int interrupt_io; /* [intio=0|1] if 0, mask SIGINFO++ during IO */ uint32_t list_id; /* xcopy(LID1) and odx related */ int list_id_given; int outf_given; int prio; /* xcopy(LID1) related */ int rdprotect; int wrprotect; int cdbsz_given; int coe_limit; int coe_count; int verbose; int quiet; int do_help; int do_time; int has_xcopy; /* --xcopy (LID1): iflag=xcopy or oflag=xcopy */ int odx_request; /* ODX_REQ_NONE==0 for no ODX */ int has_odx; /* --odx: equivalent to iflag=odx or oflag=odx */ uint32_t inactivity_to; /* ODX: timeout in seconds */ uint32_t rod_type; /* ODX: ROD type */ int rod_type_given; int64_t offset_in_rod; /* ODX: units are obs bytes */ int timeout_xcopy; /* xcopy(LID1) and ODX */ int in_sgl_elems; /* xcopy, odx */ int out_sgl_elems; /* xcopy, odx */ int rtf_fd; /* ODX: rtf's file descriptor (init: -1) */ int rtf_len_add; /* append 64 bit ROD byte size to token */ int rtf_append; /* if rtf is regular file: open(O_APPEND) */ char rtf[INOUTF_SZ]; /* ODX: ROD token filename */ struct scat_gath_elem * in_sgl; /* xcopy, odx: alternative to skip= * and count= */ struct scat_gath_elem * out_sgl; /* xcopy, odx: alternative to seek= * and count= */ struct flags_t * iflagp; struct dev_info_t * idip; struct flags_t * oflagp; struct dev_info_t * odip; struct dev_info_t * o2dip; /* working variables and statistics */ int64_t dd_count; /* -1 for not specified, 0 for no blocks to copy */ int64_t in_full; int64_t out_full; int64_t out_sparse; /* used for sparse, sparing + trim */ int64_t lowest_unrecovered; /* on reads */ int64_t highest_unrecovered; /* on reads */ int64_t num_xcopy; /* xcopy(LID1) */ int in_partial; int max_aborted; int max_uas; int out_partial; int out_sparse_active; int out_sparing_active; int out_sparse_partial; int out_trim_active; int recovered_errs; /* on reads */ int unrecovered_errs; /* on reads */ int wr_recovered_errs; int wr_unrecovered_errs; int xc_cat; int xc_dc; int status_none; int trim_errs; int read_tape_numbytes; int last_tape_read_len; /* Length of previous tape read */ unsigned int consec_same_len_reads; int num_retries; int sum_of_resids; int interrupted_retries; int err_to_report; int reading_fifo; int read1_or_transfer; /* 1 when of=/dev/null or similar */ int ibs_hold; unsigned char * wrkBuff; unsigned char * wrkPos; unsigned char * wrkBuff2; unsigned char * wrkPos2; unsigned char * zeros_buff; #ifdef HAVE_POSIX_FADVISE off_t lowest_skip; off_t lowest_seek; #endif #if SA_NOCLDSTOP sigset_t caught_signals; sigset_t orig_mask; #endif #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) int start_tm_valid; struct timespec start_tm; #elif defined(HAVE_GETTIMEOFDAY) int start_tm_valid; struct timeval start_tm; #endif FILE * errblk_fp; int wscan; /* only used on Windows, for scanning devices */ }; /* state of working variables within do_copy() */ /* permits do_copy() to be broken up into lots of helpers */ struct cp_state_t { int64_t if_filepos; int64_t of_filepos; int icbpt; int ocbpt; int bytes_read; int bytes_of; int bytes_of2; int leave_after_write; int leave_reason; /* ==0 for no error (e.g. EOF) */ int partial_write_bytes; }; struct val_str_t { int num; const char * name; }; /* This data is from the parameter data found in data-in of RRTI command */ struct rrti_resp_t { uint8_t for_sa; /* response to service action */ uint8_t cstat; /* copy operation status */ uint8_t xc_cstatus; /* extended copy completion status */ uint8_t sense_len; /* (parameter data, actual) sense data length */ uint32_t esu_del; /* estimated status update delay (ms) */ uint64_t tc; /* transfer count (blocks) */ uint32_t rt_len; /* might differ from 512, 0 if no ROD token */ unsigned char rod_tok[512]; /* (perhaps truncate to) ODX ROD Token */ }; struct sg_simple_inquiry_resp; /* Functions declared below are shared by different compilation units */ /* defined in ddpt.c */ /* No global function defined in ddpt.c apart from main() */ /* defined in ddpt_com.c */ #ifdef __GNUC__ int pr2serr(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); #else int pr2serr(const char * fmt, ...); #endif void sleep_ms(int millisecs); void state_init(struct opts_t * op, struct flags_t * ifp, struct flags_t * ofp, struct dev_info_t * idip, struct dev_info_t * odip, struct dev_info_t * o2dip); void print_stats(const char * str, struct opts_t * op, int who); int dd_filetype(const char * filename, int verbose); char * dd_filetype_str(int ft, char * buff, int max_bufflen, const char * fname); void calc_duration_init(struct opts_t * op); void calc_duration_throughput(const char * leadin, int contin, struct opts_t * op); void print_blk_sizes(const char * fname, const char * access_typ, int64_t num_blks, int blk_sz, int to_stderr); void zero_coe_limit_count(struct opts_t * op); int get_blkdev_capacity(struct opts_t * op, int which_arg, int64_t * num_blks, int * blk_sz); void errblk_open(struct opts_t * op); void errblk_put(uint64_t lba, struct opts_t * op); void errblk_put_range(uint64_t lba, int num, struct opts_t * op); void errblk_close(struct opts_t * op); #ifdef SG_LIB_LINUX void print_tape_summary(struct opts_t * op, int res, const char * str); void print_tape_pos(const char * prefix, const char * postfix, struct opts_t * op); #endif void install_signal_handlers(struct opts_t * op); void signals_process_delay(struct opts_t * op, int delay_type); void decode_designation_descriptor(const unsigned char * ucp, int len_less_4, int to_stderr, int verb); int coe_process_eio(struct opts_t * op, int64_t skip); char * rod_type_str(uint32_t rt, char * b, int b_mlen); char * rt_cm_id_str(const unsigned char * rtp, int rt_len, char * b, int b_mlen); void print_exit_status_msg(const char * prefix, int exit_stat, int to_stderr); int cl_to_sgl(const char * inp, struct scat_gath_elem * sgl_arr, int * arr_len, int max_arr_len); int file_to_sgl(const char * file_name, struct scat_gath_elem * sgl_arr, int * arr_len, int max_arr_len); /* defined in ddpt_pt.c */ void * pt_construct_obj(void); void pt_destruct_obj(void * vp); int pt_open_if(struct opts_t * op, struct sg_simple_inquiry_resp * sirp); int pt_open_of(struct opts_t * op, struct sg_simple_inquiry_resp * sirp); void pt_close(int fd); int pt_read_capacity(struct opts_t * op, int in0_out1, int64_t * num_blks, int * blk_sz); int pt_read(struct opts_t * op, int in0_out1, unsigned char * buff, int blocks, int * blks_readp); int pt_write(struct opts_t * op, const unsigned char * buff, int blocks, int64_t to_block); int pt_write_same16(struct opts_t * op, const unsigned char * buff, int bs, int blocks, int64_t start_block); void pt_sync_cache(int fd); int pt_3party_copy_out(int sg_fd, int sa, uint32_t list_id, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose, int err_vb); int pt_3party_copy_in(int sg_fd, int sa, uint32_t list_id, int timeout_secs, void * resp, int mx_resp_len, int noisy, int verbose, int err_vb); /* defined in ddpt_xcopy.c */ int open_rtf(struct opts_t * op); const char * cpy_op_status_str(int cos, char * b, int blen); uint64_t count_sgl_blocks(const struct scat_gath_elem * sglp, int elems); int print_3pc_vpd(struct opts_t * op, int to_stderr); int do_xcopy_lid1(struct opts_t * op); int do_pop_tok(struct opts_t * op, uint64_t blk_off, uint32_t num_blks, int walk_list_id, int vb_a); int do_rrti(struct opts_t * op, int in0_out1, struct rrti_resp_t * rrp, int verb); void get_local_rod_tok(unsigned char * tokp, int max_tok_len); int process_after_poptok(struct opts_t * op, uint64_t * tcp, int vb_a); int do_wut(struct opts_t * op, unsigned char * tokp, uint64_t blk_off, uint32_t num_blks, uint64_t oir, int more_left, int walk_list_id, int vb_a); int process_after_wut(struct opts_t * op, uint64_t * tcp, int vb_a); int do_odx(struct opts_t * op); /* defined in ddpt_cl.c */ int cl_process(struct opts_t * op, int argc, char * argv[], const char * version_str); void ddpt_usage(int help); #ifdef SG_LIB_WIN32 /* defined in ddpt_win32.c */ int win32_dd_filetype(const char * fn, int verbose); int win32_get_blkdev_capacity(struct opts_t * optsp, int which_arg, int64_t * num_blks, int * blk_sz); void win32_adjust_fns_pt(struct opts_t * optsp); int win32_open_if(struct opts_t * optsp, int flags, int verbose); int win32_open_of(struct opts_t * optsp, int flags, int verbose); int win32_set_file_pos(struct opts_t * optsp, int if0_of1, int64_t pos, int verbose); int win32_block_read(struct opts_t * optsp, unsigned char * bp, int num_bytes, int verbose); int win32_block_read_from_of(struct opts_t * optsp, unsigned char * bp, int num_bytes, int verbose); int win32_block_write(struct opts_t * optsp, const unsigned char * bp, int num_bytes, int verbose); int win32_cp_read_block(struct opts_t * optsp, struct cp_state_t * csp, unsigned char * wrkPos, int * ifull_extrap, int verbose); void win32_sleep_ms(int millisecs); int sg_do_wscan(char letter, int do_scan, int verb); #ifndef HAVE_SYSCONF size_t win32_pagesize(void); #endif #endif /* SG_LIB_WIN32 */ #ifdef __cplusplus } #endif #endif ddpt-0.94/src/ddpt_xcopy.c0000644000175000017500000027455612320426132014523 0ustar douggdougg/* * Copyright (c) 2013-2014 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This file contains SCSI Extended copy command helper functions for ddpt. */ /* Was needed for posix_fadvise() */ /* #define _XOPEN_SOURCE 600 */ /* Need _GNU_SOURCE for O_DIRECT */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #define __STDC_FORMAT_MACROS 1 #include #include #include /* N.B. config.h must precede anything that depends on HAVE_* */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ddpt.h" /* includes */ #include "sg_lib.h" #include "sg_cmds_basic.h" #define DEF_3PC_OUT_TIMEOUT (10 * 60) /* is 10 minutes enough? */ #define DEF_3PC_IN_TIMEOUT 60 /* these should be fast */ /* Target descriptor variety */ #define TD_FC_WWPN 1 #define TD_FC_PORT 2 #define TD_FC_WWPN_AND_PORT 4 #define TD_SPI 8 #define TD_VPD 16 #define TD_IPV4 32 #define TD_ALIAS 64 #define TD_RDMA 128 #define TD_FW 256 #define TD_SAS 512 #define TD_IPV6 1024 #define TD_IP_COPY_SERVICE 2048 #define TD_ROD 4096 #define MAX_IN_PROGRESS 10 #define LOCAL_ROD_TOKEN_SIZE 1024 static unsigned char local_rod_token[LOCAL_ROD_TOKEN_SIZE]; static const char * rec_copy_op_params_str = "Receive copy operating " "parameters"; static struct val_str_t xcopy4_cpy_op_status[] = { {0x1, "Operation completed without errors"}, {0x2, "Operation completed with errors"}, {0x3, "Operation completed without errors but with partial ROD token " "usage"}, {0x4, "Operation completed without errors but with residual data"}, {0x10, "Operation in progress, foreground or background unknown"}, {0x11, "Operation in progress in foreground"}, {0x12, "Operation in progress in background"}, {0x60, "Operation terminated"}, {0x0, NULL}, }; static int simplified_dt(const struct dev_info_t * dip) { int d_type = dip->d_type; switch (d_type) { case FT_BLOCK: case FT_TAPE: case FT_REG: case FT_DEV_NULL: case FT_FIFO: case FT_ERROR: return d_type; default: if (FT_PT & d_type) { if ((0 == dip->pdt) || (0xe == dip->pdt)) /* D-A or RBC */ return FT_BLOCK; else if (0x1 == dip->pdt) return FT_TAPE; } return FT_OTHER; } } static int seg_desc_from_d_type(int in_dt, int in_off, int out_dt, int out_off) { int desc_type = -1; switch (in_dt) { case FT_BLOCK: switch (out_dt) { case FT_TAPE: if (out_off) break; if (in_off) desc_type = 0x8; else desc_type = 0; break; case FT_BLOCK: if (in_off || out_off) desc_type = 0xA; else desc_type = 2; break; default: break; } break; case FT_TAPE: if (in_off) break; switch (out_dt) { case FT_TAPE: if (!out_off) { desc_type = 3; break; } break; case FT_BLOCK: if (out_off) desc_type = 9; else desc_type = 3; break; case FT_DEV_NULL: desc_type = 6; break; default: break; } break; default: break; } return desc_type; } static int scsi_encode_seg_desc(struct opts_t * op, unsigned char *seg_desc, int seg_desc_type, int64_t num_blk, uint64_t src_lba, uint64_t dst_lba) { int seg_desc_len = 0; seg_desc[0] = seg_desc_type; seg_desc[1] = (op->xc_dc << 1) | op->xc_cat; if (seg_desc_type == 0x02) { seg_desc_len = 0x18; seg_desc[4] = 0; seg_desc[5] = 0; /* Source target index */ seg_desc[7] = 1; /* Destination target index */ seg_desc[10] = (num_blk >> 8) & 0xff; seg_desc[11] = num_blk & 0xff; seg_desc[12] = (src_lba >> 56) & 0xff; seg_desc[13] = (src_lba >> 48) & 0xff; seg_desc[14] = (src_lba >> 40) & 0xff; seg_desc[15] = (src_lba >> 32) & 0xff; seg_desc[16] = (src_lba >> 24) & 0xff; seg_desc[17] = (src_lba >> 16) & 0xff; seg_desc[18] = (src_lba >> 8) & 0xff; seg_desc[19] = src_lba & 0xff; seg_desc[20] = (dst_lba >> 56) & 0xff; seg_desc[21] = (dst_lba >> 48) & 0xff; seg_desc[22] = (dst_lba >> 40) & 0xff; seg_desc[23] = (dst_lba >> 32) & 0xff; seg_desc[24] = (dst_lba >> 24) & 0xff; seg_desc[25] = (dst_lba >> 16) & 0xff; seg_desc[26] = (dst_lba >> 8) & 0xff; seg_desc[27] = dst_lba & 0xff; } seg_desc[2] = (seg_desc_len >> 8) & 0xFF; seg_desc[3] = seg_desc_len & 0xFF; return seg_desc_len + 4; } static int a_xcopy_lid1_cmd(struct opts_t * op, unsigned char *src_desc, int src_desc_len, unsigned char *dst_desc, int dst_desc_len, int seg_desc_type, int64_t num_blk) { unsigned char xcopyBuff[256]; int desc_offset = 16; int seg_desc_len, verb, err_vb, fd, tmout; uint64_t src_lba = op->skip; uint64_t dst_lba = op->seek; fd = (op->iflagp->xcopy) ? op->idip->fd : op->odip->fd; verb = (op->verbose > 1) ? (op->verbose - 2) : 0; if (op->verbose > 0) err_vb = (verb > 1) ? verb : 1; else err_vb = 0; memset(xcopyBuff, 0, 256); xcopyBuff[0] = op->list_id; xcopyBuff[1] = (op->id_usage << 3) | op->prio; xcopyBuff[2] = 0; xcopyBuff[3] = src_desc_len + dst_desc_len; /* Two target descriptors */ memcpy(xcopyBuff + desc_offset, src_desc, src_desc_len); desc_offset += src_desc_len; memcpy(xcopyBuff + desc_offset, dst_desc, dst_desc_len); desc_offset += dst_desc_len; seg_desc_len = scsi_encode_seg_desc(op, xcopyBuff + desc_offset, seg_desc_type, num_blk, src_lba, dst_lba); xcopyBuff[11] = seg_desc_len; /* One segment descriptor */ desc_offset += seg_desc_len; tmout = (op->timeout_xcopy < 1) ? DEF_3PC_OUT_TIMEOUT : op->timeout_xcopy; if (verb) pr2serr("xcopy(LID1) cmd; src_lba=0x%" PRIx64 ", num_blks=%" PRId64 "\n", src_lba, num_blk); return pt_3party_copy_out(fd, SA_XCOPY_LID1, op->list_id, DEF_GROUP_NUM, tmout, xcopyBuff, desc_offset, 1, verb, err_vb); } /* Returns target descriptor variety encoded into an int. There may be * more than one, OR-ed together. A return value of zero or less is * considered as an error. */ static int scsi_operating_parameter(struct opts_t * op, int is_dest) { int res, fd, ftype, pdt, snlid, verb; unsigned char rcBuff[256]; unsigned int rcBuffLen = 256, len, n, td_list = 0; unsigned long num, max_target_num, max_segment_num, max_segment_len; unsigned long max_desc_len, max_inline_data, held_data_limit; int valid = 0; struct dev_info_t * dip; verb = (op->verbose ? (op->verbose - 1) : 0); dip = is_dest ? op->odip : op->idip; fd = dip->fd; ftype = dip->d_type; if (FT_PT & ftype) { pdt = dip->pdt; if ((0 == pdt) || (0xe == pdt)) /* direct-access or RBC */ ftype |= FT_BLOCK; else if (0x1 == pdt) ftype |= FT_TAPE; } else if (FT_FIFO & ftype) ftype |= FT_REG; if (FT_REG & ftype) { pr2serr("%s: not expecting a regular file here: %s\n", __func__, dip->fn); return -SG_LIB_FILE_ERROR; } /* Third Party Copy IN command; sa: RECEIVE COPY OPERATING PARAMETERS */ res = pt_3party_copy_in(fd, SA_COPY_OP_PARAMS, 0, DEF_3PC_IN_TIMEOUT, rcBuff, rcBuffLen, 1, verb, op->verbose); if (0 != res) return -res; len = ((rcBuff[0] << 24) | (rcBuff[1] << 16) | (rcBuff[2] << 8) | rcBuff[3]) + 4; if (len > rcBuffLen) { pr2serr(" <verbose > 2) { pr2serr("\nOutput %s response in hex:\n", rec_copy_op_params_str); dStrHexErr((const char *)rcBuff, len, 1); } snlid = rcBuff[4] & 0x1; max_target_num = rcBuff[8] << 8 | rcBuff[9]; max_segment_num = rcBuff[10] << 8 | rcBuff[11]; max_desc_len = rcBuff[12] << 24 | rcBuff[13] << 16 | rcBuff[14] << 8 | rcBuff[15]; max_segment_len = rcBuff[16] << 24 | rcBuff[17] << 16 | rcBuff[18] << 8 | rcBuff[19]; dip->xc_max_bytes = max_segment_len ? max_segment_len : ULONG_MAX; max_inline_data = rcBuff[20] << 24 | rcBuff[21] << 16 | rcBuff[22] << 8 | rcBuff[23]; if (op->verbose) { pr2serr(" >> %s, %sput [%s]:\n", rec_copy_op_params_str, (is_dest ? "out" : "in"), dip->fn); pr2serr(" Support No List IDentifier (SNLID): %d\n", snlid); pr2serr(" Maximum target descriptor count: %lu\n", max_target_num); pr2serr(" Maximum segment descriptor count: %lu\n", max_segment_num); pr2serr(" Maximum descriptor list length: %lu\n", max_desc_len); pr2serr(" Maximum segment length: %lu\n", max_segment_len); pr2serr(" Maximum inline data length: %lu\n", max_inline_data); } held_data_limit = rcBuff[24] << 24 | rcBuff[25] << 16 | rcBuff[26] << 8 | rcBuff[27]; if (op->id_usage < 0) { if (! held_data_limit) op->id_usage = 2; else op->id_usage = 0; } if (op->verbose) { pr2serr(" Held data limit: %lu (list_id_usage: %d)\n", held_data_limit, op->id_usage); num = rcBuff[28] << 24 | rcBuff[29] << 16 | rcBuff[30] << 8 | rcBuff[31]; pr2serr(" Maximum stream device transfer size: %lu\n", num); pr2serr(" Maximum concurrent copies: %u\n", rcBuff[36]); pr2serr(" Data segment granularity: %u bytes\n", 1 << rcBuff[37]); pr2serr(" Inline data granularity: %u bytes\n", 1 << rcBuff[38]); pr2serr(" Held data granularity: %u bytes\n", 1 << rcBuff[39]); pr2serr(" Implemented descriptor list:\n"); } dip->xc_min_bytes = 1 << rcBuff[37]; for (n = 0; n < rcBuff[43]; n++) { switch(rcBuff[44 + n]) { case 0x00: /* copy block to stream device */ if (!is_dest && (ftype & FT_BLOCK)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy Block to Stream device\n"); break; case 0x01: /* copy stream to block device */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_BLOCK)) valid++; if (op->verbose) pr2serr(" Copy Stream to Block device\n"); break; case 0x02: /* copy block to block device */ if (!is_dest && (ftype & FT_BLOCK)) valid++; if (is_dest && (ftype & FT_BLOCK)) valid++; if (op->verbose) pr2serr(" Copy Block to Block device\n"); break; case 0x03: /* copy stream to stream device */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy Stream to Stream device\n"); break; case 0x04: /* copy inline data to stream device */ if (!is_dest && (ftype & FT_REG)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy inline data to Stream device\n"); break; case 0x05: /* copy embedded data to stream device */ if (!is_dest && (ftype & FT_REG)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy embedded data to Stream device\n"); break; case 0x06: /* Read from stream device and discard */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_DEV_NULL)) valid++; if (op->verbose) pr2serr(" Read from stream device and discard\n"); break; case 0x07: /* Verify block or stream device operation */ if (!is_dest && (ftype & (FT_TAPE | FT_BLOCK))) valid++; if (is_dest && (ftype & (FT_TAPE | FT_BLOCK))) valid++; if (op->verbose) pr2serr(" Verify block or stream device operation\n"); break; case 0x08: /* copy block device with offset to stream device */ if (!is_dest && (ftype & FT_BLOCK)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy block device with offset to stream " "device\n"); break; case 0x09: /* copy stream device to block device with offset */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_BLOCK)) valid++; if (op->verbose) pr2serr(" Copy stream device to block device with " "offset\n"); break; case 0x0a: /* copy block device with offset to block device with * offset */ if (!is_dest && (ftype & FT_BLOCK)) valid++; if (is_dest && (ftype & FT_BLOCK)) valid++; if (op->verbose) pr2serr(" Copy block device with offset to block " "device with offset\n"); break; case 0x0b: /* copy block device to stream device and hold data */ if (!is_dest && (ftype & FT_BLOCK)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy block device to stream device and hold " "data\n"); break; case 0x0c: /* copy stream device to block device and hold data */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_BLOCK)) valid++; if (op->verbose) pr2serr(" Copy stream device to block device and hold " "data\n"); break; case 0x0d: /* copy block device to block device and hold data */ if (!is_dest && (ftype & FT_BLOCK)) valid++; if (is_dest && (ftype & FT_BLOCK)) valid++; if (op->verbose) pr2serr(" Copy block device to block device and hold " "data\n"); break; case 0x0e: /* copy stream device to stream device and hold data */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_TAPE)) valid++; if (op->verbose) pr2serr(" Copy block device to block device and hold " "data\n"); break; case 0x0f: /* read from stream device and hold data */ if (!is_dest && (ftype & FT_TAPE)) valid++; if (is_dest && (ftype & FT_DEV_NULL)) valid++; if (op->verbose) pr2serr(" Read from stream device and hold data\n"); break; case 0xe0: /* FC N_Port_Name */ if (op->verbose) pr2serr(" FC N_Port_Name target descriptor\n"); td_list |= TD_FC_WWPN; break; case 0xe1: /* FC Port_ID */ if (op->verbose) pr2serr(" FC Port_ID target descriptor\n"); td_list |= TD_FC_PORT; break; case 0xe2: /* FC N_Port_ID with N_Port_Name checking */ if (op->verbose) pr2serr(" FC N_Port_ID with N_Port_Name target " "descriptor\n"); td_list |= TD_FC_WWPN_AND_PORT; break; case 0xe3: /* Parallel Interface T_L */ if (op->verbose) pr2serr(" SPI T_L target descriptor\n"); td_list |= TD_SPI; break; case 0xe4: /* identification descriptor */ if (op->verbose) pr2serr(" Identification target descriptor\n"); td_list |= TD_VPD; break; case 0xe5: /* IPv4 */ if (op->verbose) pr2serr(" IPv4 target descriptor\n"); td_list |= TD_IPV4; break; case 0xe6: /* Alias */ if (op->verbose) pr2serr(" Alias target descriptor\n"); td_list |= TD_ALIAS; break; case 0xe7: /* RDMA */ if (op->verbose) pr2serr(" RDMA target descriptor\n"); td_list |= TD_RDMA; break; case 0xe8: /* FireWire */ if (op->verbose) pr2serr(" IEEE 1394 target descriptor\n"); td_list |= TD_FW; break; case 0xe9: /* SAS */ if (op->verbose) pr2serr(" SAS target descriptor\n"); td_list |= TD_SAS; break; case 0xea: /* IPv6 */ if (op->verbose) pr2serr(" IPv6 target descriptor\n"); td_list |= TD_IPV6; break; case 0xeb: /* IP Copy Service */ if (op->verbose) pr2serr(" IP Copy Service target descriptor\n"); td_list |= TD_IP_COPY_SERVICE; break; case 0xfe: /* ROD */ if (op->verbose) pr2serr(" ROD target descriptor\n"); td_list |= TD_ROD; break; default: pr2serr(">> Unhandled target descriptor 0x%02x\n", rcBuff[44 + n]); break; } } if (!valid) { pr2serr(">> no matching target descriptor supported\n"); td_list = 0; } return td_list; } /* build xcopy(lid1) CSCD descriptor using device id VPD page */ static int desc_from_vpd_id(struct opts_t * op, unsigned char *desc, int desc_len, int is_dest) { int fd, res, u, i_len, assoc, desig, verb; unsigned char rcBuff[256], *ucp, *best = NULL; unsigned int len = 254; unsigned int block_size; int off = -1; int best_len = 0; int f_desig = 0; struct flags_t * flp; struct dev_info_t * dip; verb = (op->verbose ? (op->verbose - 1) : 0); dip = is_dest ? op->odip : op->idip; fd = dip->fd; flp = is_dest ? op->oflagp : op->iflagp; block_size = is_dest ? op->obs : op->ibs; memset(rcBuff, 0xff, len); res = sg_ll_inquiry(fd, 0, 1, VPD_DEVICE_ID, rcBuff, 4, 1, verb); if (0 != res) { if (SG_LIB_CAT_ILLEGAL_REQ == res) pr2serr("Device identification VPD page not found [%s]\n", dip->fn); else pr2serr("VPD inquiry failed with %d [%s] , try again with " "'-vv'\n", res, dip->fn); return res; } else if (rcBuff[1] != VPD_DEVICE_ID) { pr2serr("invalid VPD response\n"); return SG_LIB_CAT_MALFORMED; } len = ((rcBuff[2] << 8) + rcBuff[3]) + 4; res = sg_ll_inquiry(fd, 0, 1, VPD_DEVICE_ID, rcBuff, len, 1, verb); if (0 != res) { pr2serr("VPD inquiry failed with %d\n", res); return res; } else if (rcBuff[1] != VPD_DEVICE_ID) { pr2serr("invalid VPD response\n"); return SG_LIB_CAT_MALFORMED; } if (op->verbose > 2) { pr2serr("Output VPD_DEVICE_ID (0x83) page in hex:\n"); dStrHexErr((const char *)rcBuff, len, 1); } while ((u = sg_vpd_dev_id_iter(rcBuff + 4, len - 4, &off, 0, -1, -1)) == 0) { ucp = rcBuff + 4 + off; i_len = ucp[3]; if (((unsigned int)off + i_len + 4) > len) { pr2serr(" VPD page error: designator length %d longer than\n" " remaining response length=%d\n", i_len, (len - off)); return SG_LIB_CAT_MALFORMED; } assoc = ((ucp[1] >> 4) & 0x3); desig = (ucp[1] & 0xf); if (op->verbose > 2) pr2serr(" Desc %d: assoc %u desig %u len %d\n", off, assoc, desig, i_len); /* Descriptor must be less than 16 bytes */ if (i_len > 16) continue; if (desig == 3) { best = ucp; best_len = i_len; break; } if (desig == 2) { if (!best || f_desig < 2) { best = ucp; best_len = i_len; f_desig = 2; } } else if (desig == 1) { if (!best || f_desig == 0) { best = ucp; best_len = i_len; f_desig = desig; } } else if (desig == 0) { if (!best) { best = ucp; best_len = i_len; f_desig = desig; } } } if (best) { if (op->verbose) decode_designation_descriptor(best, best_len, 1, op->verbose); if (best_len + 4 < desc_len) { memset(desc, 0, 32); desc[0] = 0xe4; memcpy(desc + 4, best, best_len + 4); desc[4] &= 0x1f; desc[28] = flp->pad << 2; desc[29] = (block_size >> 16) & 0xff; desc[30] = (block_size >> 8) & 0xff; desc[31] = block_size & 0xff; if (op->verbose > 3) { pr2serr("Descriptor in hex (bs %d):\n", block_size); dStrHexErr((const char *)desc, 32, 1); } return 32; } return best_len + 8; } return 0; } /* Called from main() in ddpt.c . Returns 0 on success or a positive * errno value if problems. This is for a xcopy(LID1) disk->disk copy. */ int do_xcopy_lid1(struct opts_t * op) { int res, ibpt, obpt, bs_same, max_bpt, blocks, oblocks; int src_desc_len, dst_desc_len, seg_desc_type; unsigned char src_desc[256]; unsigned char dst_desc[256]; const struct flags_t * ifp = op->iflagp; const struct flags_t * ofp = op->oflagp; const struct dev_info_t * idip = op->idip; const struct dev_info_t * odip = op->odip; if (op->list_id_given && (op->list_id > UCHAR_MAX)) { pr2serr("list_id for xcopy(LID1) cannot exceed 255\n"); return SG_LIB_SYNTAX_ERROR; } if (op->id_usage == 3) { /* list_id usage disabled */ if (op->list_id_given && (0 != op->list_id)) { pr2serr("list_id disabled by id_usage flag\n"); return SG_LIB_SYNTAX_ERROR; } else op->list_id = 0; } res = scsi_operating_parameter(op, 0); if (SG_LIB_CAT_UNIT_ATTENTION == -res) res = scsi_operating_parameter(op, 0); if (res < 0) { if (-res == SG_LIB_CAT_INVALID_OP) { pr2serr("%s command not supported on %s\n", rec_copy_op_params_str, idip->fn); return EINVAL; } else if (-res == SG_LIB_CAT_NOT_READY) pr2serr("%s failed on %s - not ready\n", rec_copy_op_params_str, idip->fn); else { pr2serr("Unable to %s on %s\n", rec_copy_op_params_str, idip->fn); return -res; } } else if (res == 0) return SG_LIB_CAT_INVALID_OP; if (res & TD_VPD) { if (op->verbose) pr2serr(" >> using VPD identification for source %s\n", op->idip->fn); src_desc_len = desc_from_vpd_id(op, src_desc, sizeof(src_desc), 0); if (src_desc_len > (int)sizeof(src_desc)) { pr2serr("source descriptor too large (%d bytes)\n", res); return SG_LIB_CAT_MALFORMED; } } else return SG_LIB_CAT_INVALID_OP; res = scsi_operating_parameter(op, 1); if (res < 0) { if (SG_LIB_CAT_UNIT_ATTENTION == -res) { pr2serr("Unit attention (%s), continuing\n", rec_copy_op_params_str); res = scsi_operating_parameter(op, 1); } else { if (-res == SG_LIB_CAT_INVALID_OP) { pr2serr("%s command not supported on %s\n", rec_copy_op_params_str, odip->fn); return EINVAL; } else if (-res == SG_LIB_CAT_NOT_READY) pr2serr("%s failed on %s - not ready\n", rec_copy_op_params_str, odip->fn); else { pr2serr("Unable to %s on %s\n", rec_copy_op_params_str, odip->fn); return -res; } } } else if (res == 0) return SG_LIB_CAT_INVALID_OP; if (res & TD_VPD) { if (op->verbose) pr2serr(" >> using VPD identification for destination %s\n", odip->fn); dst_desc_len = desc_from_vpd_id(op, dst_desc, sizeof(dst_desc), 1); if (dst_desc_len > (int)sizeof(dst_desc)) { pr2serr("destination descriptor too large (%d bytes)\n", res); return SG_LIB_CAT_MALFORMED; } } else return SG_LIB_CAT_INVALID_OP; bs_same = (op->ibs == op->obs); max_bpt = bs_same ? MAX_XC_BPT : MAX_XC_BPT_POW2; /* Beware, xc_max_bytes may be ULONG_MAX hence unsigned long division */ if (op->bpt_given) { ibpt = op->bpt_i; ibpt = (ibpt > max_bpt) ? max_bpt : ibpt; obpt = bs_same ? ibpt : ((op->ibs * op->bpt_i) / op->obs); if (ifp->dc || ofp->dc) { if ((unsigned long)obpt * op->obs > odip->xc_max_bytes) { pr2serr("bpt too large (max %ld blocks)\n", odip->xc_max_bytes / op->obs); return SG_LIB_SYNTAX_ERROR; } } else { if ((unsigned long)ibpt * op->ibs > idip->xc_max_bytes) { pr2serr("bpt too large (max %ld blocks)\n", idip->xc_max_bytes / op->ibs); return SG_LIB_SYNTAX_ERROR; } } } else { unsigned long r; if (ifp->dc || ofp->dc) { r = odip->xc_max_bytes / (unsigned long)op->obs; obpt = (r > INT_MAX) ? INT_MAX : (int)r; ibpt = bs_same ? obpt : ((op->obs * obpt) / op->ibs); ibpt = (ibpt > max_bpt) ? max_bpt : ibpt; obpt = bs_same ? ibpt : ((op->ibs * ibpt) / op->obs); } else { r = idip->xc_max_bytes / (unsigned long)op->ibs; ibpt = (r > (unsigned long)max_bpt) ? max_bpt : (int)r; obpt = bs_same ? ibpt : ((op->ibs * ibpt) / op->obs); } } if (op->verbose > 1) pr2serr("do_xcopy_lid1: xcopy->%s will use ibpt=%d, obpt=%d\n", (ifp->xcopy ? idip->fn : odip->fn), ibpt, obpt); seg_desc_type = seg_desc_from_d_type(simplified_dt(op->idip), 0, simplified_dt(op->odip), 0); res = 0; while (op->dd_count > 0) { blocks = (op->dd_count > ibpt) ? ibpt : op->dd_count; oblocks = bs_same ? blocks : ((op->ibs * blocks) / op->obs); res = a_xcopy_lid1_cmd(op, src_desc, src_desc_len, dst_desc, dst_desc_len, seg_desc_type, blocks); if (res != 0) { if ((op->verbose > 0) && (op->verbose < 3)) { pr2serr("a_xcopy_lid1_cmd: "); switch (res) { case SG_LIB_CAT_INVALID_OP: pr2serr("invalid opcode\n"); break; case SG_LIB_CAT_ILLEGAL_REQ: pr2serr("illegal request\n"); break; case SG_LIB_CAT_UNIT_ATTENTION: pr2serr("unit attention\n"); break; case SG_LIB_CAT_NOT_READY: pr2serr("not ready\n"); break; case SG_LIB_CAT_ABORTED_COMMAND: pr2serr("aborted command\n"); break; default: pr2serr("unknown result=%d\n", res); break; } pr2serr(" use 'verbose=3' (or '-vvv') for more " "information\n"); } break; } op->in_full += blocks; op->out_full += oblocks; op->skip += blocks; op->seek += oblocks; op->num_xcopy++; op->dd_count -= blocks; if (op->dd_count > 0) signals_process_delay(op, DELAY_COPY_SEGMENT); } return res; } /* vvvvvvvvv ODX [SBC-3's POPULATE TOKEN + WRITE USING TOKEN] vvvvvvv */ int open_rtf(struct opts_t * op) { int res, fd, must_exist, r_w1, flags; struct stat a_st; if (op->rtf_fd >= 0) { pr2serr("%s: rtf already open\n", __func__ ); return -1; } must_exist = 0; switch (op->odx_request) { case ODX_COPY: if (RODT_BLK_ZERO == op->rod_type) { if (op->verbose) pr2serr("ignoring rtf %s since token is fixed\n", op->rtf); return 0; } r_w1 = 1; break; case ODX_READ_INTO_RODS: r_w1 = 1; break; case ODX_WRITE_FROM_RODS: r_w1 = 0; must_exist = 1; break; default: r_w1 = 1; break; } if (! op->rtf[0]) return must_exist ? -1 : 0; res = stat(op->rtf, &a_st); if (res < 0) { if (ENOENT == errno) { if (must_exist) { pr2serr("%s not found but rtf required\n", op->rtf); return -1; } } else { perror("rtf"); return -1; } fd = creat(op->rtf, 0644); if (fd < 0) { perror(op->rtf); return -1; } op->rtf_fd = fd; return 0; } if (S_ISDIR(a_st.st_mode)) { pr2serr("%s: %s is a directory, expected a file\n", __func__, op->rtf); return -1; } if (S_ISBLK(a_st.st_mode) || S_ISCHR(a_st.st_mode)) { pr2serr("%s: %s is a block or char device, unexpected\n", __func__, op->rtf); return -1; } flags = (r_w1 ? O_WRONLY : O_RDONLY); if (S_ISREG(a_st.st_mode) && r_w1) flags |= (op->rtf_append ? O_APPEND : O_TRUNC); fd = open(op->rtf, flags); if (fd < 0) { perror(op->rtf); return -1; } op->rtf_fd = fd; return 0; } const char * cpy_op_status_str(int cos, char * b, int blen) { const struct val_str_t * vsp; const char * p = NULL; for (vsp = xcopy4_cpy_op_status; vsp->name; ++vsp) { if (cos == vsp->num) { p = vsp->name; break; } } if (p) snprintf(b, blen, "%s", p); else snprintf(b, blen, "copy operation status 0x%x not found\n", cos); return b; } /* This is xcopy(LID4) related: "ROD" == Representation Of Data * Used by VPD_3PARTY_COPY */ static void decode_rod_descriptor(const unsigned char * buff, int len) { const unsigned char * ucp = buff; int k, bump, j; uint64_t ull; for (k = 0; k < len; k += bump, ucp += bump) { bump = (ucp[2] << 8) + ucp[3]; switch (ucp[0]) { case 0: /* Block ROD device type specific descriptor */ pr2serr(" Optimal block ROD length granularity: %d\n", (ucp[6] << 8) + ucp[7]); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[8 + j]; } pr2serr(" Maximum Bytes in block ROD: %" PRIu64 "\n", ull); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[16 + j]; } pr2serr(" Optimal Bytes in block ROD transfer: %" PRIu64 "\n", ull); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[24 + j]; } pr2serr(" Optimal Bytes to token per segment: %" PRIu64 "\n", ull); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[32 + j]; } pr2serr(" Optimal Bytes from token per segment: %" PRIu64 "\n", ull); break; case 1: /* Stream ROD device type specific descriptor */ ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[8 + j]; } pr2serr(" Maximum Bytes in stream ROD: %" PRIu64 "\n", ull); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[16 + j]; } pr2serr(" Optimal Bytes in stream ROD transfer: %" PRIu64 "\n", ull); break; case 3: /* Copy manager ROD device type specific descriptor */ ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[8 + j]; } pr2serr(" Maximum Bytes in processor ROD: %" PRIu64 "\n", ull); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[16 + j]; } pr2serr(" Optimal Bytes in processor ROD transfer: %" PRIu64 "\n", ull); break; default: pr2serr(" Unhandled descriptor (format %d, device type " "%d)\n", ucp[0] >> 5, ucp[0] & 0x1F); break; } } } /* VPD_3PARTY_COPY [3PC, third party copy] */ static void decode_3party_copy_vpd(unsigned char * buff, int len, int to_stderr, int verbose) { int j, k, bump, desc_type, desc_len, sa_len; unsigned int u; const unsigned char * ucp; uint64_t ull; char b[80]; int (*print_p)(const char *, ...); print_p = to_stderr ? pr2serr : printf; if (len < 4) { print_p("Third-party Copy VPD page length too short=%d\n", len); return; } len -= 4; ucp = buff + 4; for (k = 0; k < len; k += bump, ucp += bump) { desc_type = (ucp[0] << 8) + ucp[1]; desc_len = (ucp[2] << 8) + ucp[3]; if (verbose) print_p("Descriptor type=%d, len=%d\n", desc_type, desc_len); bump = 4 + desc_len; if ((k + bump) > len) { print_p("Third-party Copy VPD page, short descriptor length=%d, " "left=%d\n", bump, (len - k)); return; } if (0 == desc_len) continue; switch (desc_type) { case 0x0000: /* Required if POPULATE TOKEN (or friend) used */ print_p(" Block Device ROD Token Limits:\n"); print_p(" Maximum Range Descriptors: %d\n", (ucp[10] << 8) + ucp[11]); u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) | ucp[15]; print_p(" Maximum Inactivity Timeout: %u seconds\n", u); u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) | ucp[19]; print_p(" Default Inactivity Timeout: %u seconds\n", u); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[20 + j]; } print_p(" Maximum Token Transfer Size: %" PRIu64 "\n", ull); ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[28 + j]; } print_p(" Optimal Transfer Count: %" PRIu64 "\n", ull); break; case 0x0001: /* Mandatory (SPC-4) */ print_p(" Supported Commands:\n"); j = 0; while (j < ucp[4]) { sa_len = ucp[6 + j]; for (k = 0; k < sa_len; k++) { sg_get_opcode_sa_name(ucp[5 + j], ucp[7 + j + k], 0, sizeof(b), b); print_p(" %s\n", b); } j += sa_len; } break; case 0x0004: print_p(" Parameter Data:\n"); print_p(" Maximum CSCD Descriptor Count: %d\n", (ucp[8] << 8) + ucp[9]); print_p(" Maximum Segment Descriptor Count: %d\n", (ucp[10] << 8) + ucp[11]); u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) | ucp[15]; print_p(" Maximum Descriptor List Length: %u\n", u); u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) | ucp[19]; print_p(" Maximum Inline Data Length: %u\n", u); break; case 0x0008: print_p(" Supported Descriptors:\n"); for (j = 0; j < ucp[4]; j++) { print_p(" 0x%x\n", ucp[5 + j]); } break; case 0x000C: print_p(" Supported CSCD IDs:\n"); for (j = 0; j < (ucp[4] << 8) + ucp[5]; j += 2) { u = (ucp[6 + j] << 8) | ucp[7 + j]; print_p(" 0x%04x\n", u); } break; case 0x0106: print_p(" ROD Token Features:\n"); print_p(" Remote Tokens: %d\n", ucp[4] & 0x0f); u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) | ucp[19]; print_p(" Minimum Token Lifetime: %u seconds\n", u); u = (ucp[20] << 24) | (ucp[21] << 16) | (ucp[22] << 8) | ucp[23]; print_p(" Maximum Token Lifetime: %u seconds\n", u); u = (ucp[24] << 24) | (ucp[25] << 16) | (ucp[26] << 8) | ucp[27]; print_p(" Maximum Token inactivity timeout: %d\n", u); decode_rod_descriptor(&ucp[48], (ucp[46] << 8) + ucp[47]); break; case 0x0108: print_p(" Supported ROD Token and ROD Types:\n"); for (j = 0; j < (ucp[6] << 8) + ucp[7]; j+= 64) { u = (ucp[8 + j] << 24) | (ucp[8 + j + 1] << 16) | (ucp[8 + j + 2] << 8) | ucp[8 + j + 3]; print_p(" ROD Type %u:\n", u); print_p(" Internal: %s\n", ucp[8 + j + 4] & 0x80 ? "yes" : "no"); print_p(" Token In: %s\n", ucp[8 + j + 4] & 0x02 ? "yes" : "no"); print_p(" Token Out: %s\n", ucp[8 + j + 4] & 0x01 ? "yes" : "no"); print_p(" Preference: %d\n", (ucp[8 + j + 6] << 8) + ucp[8 + j + 7]); } break; case 0x8001: /* Mandatory (SPC-4) */ print_p(" General Copy Operations:\n"); u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7]; print_p(" Total Concurrent Copies: %u\n", u); u = (ucp[8] << 24) | (ucp[9] << 16) | (ucp[10] << 8) | ucp[11]; print_p(" Maximum Identified Concurrent Copies: %u\n", u); u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) | ucp[15]; print_p(" Maximum Segment Length: %u\n", u); ull = (1 << ucp[16]); print_p(" Data Segment Granularity: %" PRIu64 "\n", ull); ull = (1 << ucp[17]); print_p(" Inline Data Granularity: %" PRIu64 "\n", ull); break; case 0x9101: print_p(" Stream Copy Operations:\n"); u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7]; print_p(" Maximum Stream Device Transfer Size: %u\n", u); break; case 0xC001: print_p(" Held Data:\n"); u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7]; print_p(" Held Data Limit: %u\n", u); ull = (1 << ucp[8]); print_p(" Held Data Granularity: %" PRIu64 "\n", ull); break; default: print_p("Unexpected type=%d\n", desc_type); dStrHexErr((const char *)ucp, bump, 1); break; } } } /* Note this function passes back a malloc-ed buffer if it returns 0 and * fixed_b != *alloc_bp which caller should free. Returns 0 on success. */ static int fetch_3pc_vpd(int fd, const char * fn, unsigned char * fixed_b, int fixed_blen, unsigned char ** alloc_bp, int verb) { int res, len; unsigned char * rp; rp = fixed_b; if (alloc_bp) *alloc_bp = fixed_b; res = sg_ll_inquiry(fd, 0, 1, VPD_3PARTY_COPY, rp, fixed_blen, 1, verb); if (res) { if (SG_LIB_CAT_ILLEGAL_REQ == res) { if (fn) pr2serr("Third Party Copy VPD page not found [%s]\n", fn); else pr2serr("Third Party Copy VPD page not found\n"); } else pr2serr("Third Party Copy VPD inquiry failed with %d, try again " "with '-vv'\n", res); return res; } else if (rp[1] != VPD_3PARTY_COPY) { pr2serr("invalid 3PARTY_COPY VPD response\n"); return SG_LIB_CAT_MALFORMED; } len = ((rp[2] << 8) + rp[3]) + 4; if (len > fixed_blen) { rp = (unsigned char *)malloc(len); if (NULL == rp) { pr2serr("Not enough user memory for %s\n", __func__); return SG_LIB_CAT_OTHER; } if (alloc_bp) *alloc_bp = rp; res = sg_ll_inquiry(fd, 0, 1, VPD_3PARTY_COPY, rp, len, 1, verb); if (res) { pr2serr("3PARTY_COPY VPD inquiry failed with %d\n", res); if (fixed_b != rp) free(rp); return res; } } return 0; } static int get_3pc_vpd_blkdev_lims(struct opts_t * op, struct dev_info_t * dip) { unsigned char rBuff[256]; unsigned char * rp; unsigned char * ucp; int res, verb, n, len, bump, desc_type, desc_len, k, j; int found = 0; uint32_t max_ito = 0; uint64_t ull; verb = (op->verbose ? (op->verbose - 1) : 0); rp = rBuff; n = (int)sizeof(rBuff); res = fetch_3pc_vpd(dip->fd, dip->fn, rBuff, n, &rp, verb); if (res) return res; len = ((rp[2] << 8) + rp[3]) + 4; len -= 4; ucp = rp + 4; for (k = 0; k < len; k += bump, ucp += bump) { desc_type = (ucp[0] << 8) + ucp[1]; desc_len = (ucp[2] << 8) + ucp[3]; if (op->verbose > 4) pr2serr("Descriptor type=%d, len=%d\n", desc_type, desc_len); bump = 4 + desc_len; if ((k + bump) > len) { pr2serr("3PARTY_COPY Copy VPD page, short descriptor length=%d, " "left=%d\n", bump, (len - k)); if (rBuff != rp) free(rp); return SG_LIB_CAT_OTHER; } if (0 == desc_len) continue; switch (desc_type) { case 0x0000: /* Block Device ROD Token Limits */ ++found; if (op->verbose > 3) { pr2serr("3PARTY_COPY Copy VPD, Block Device ROD Token " "Limits descriptor:\n"); dStrHexErr((const char *)ucp, desc_len, 1); } if (desc_len < 32) { pr2serr("3PARTY_COPY Copy VPD, Block Device ROD Token " "Limits descriptor, too short, want 32 got %d\n", desc_len); break; } dip->odxp->max_range_desc = (ucp[10] << 8) + ucp[11]; max_ito = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) | ucp[15]; dip->odxp->max_inactivity_to = max_ito; dip->odxp->def_inactivity_to = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) | ucp[19]; ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[20 + j]; } dip->odxp->max_tok_xfer_size = ull; ull = 0; for (j = 0; j < 8; j++) { if (j > 0) ull <<= 8; ull |= ucp[28 + j]; } dip->odxp->optimal_xfer_count = ull; break; default: break; } } if (rBuff != rp) free(rp); if (! found) { pr2serr("Did not find Block Device ROD Token Limits descriptor in " "3PARTY_COPY Copy VPD page\n"); return SG_LIB_CAT_OTHER; } if ((max_ito > 0) && (op->inactivity_to > max_ito)) { pr2serr("Block Device ROD Token Limits: maximum inactivity timeout " "(%" PRIu32 ") exceeded\n", max_ito); if (! op->iflagp->force) { pr2serr("... exiting; can override with 'force' flag\n"); return SG_LIB_CAT_OTHER; } } return 0; } int print_3pc_vpd(struct opts_t * op, int to_stderr) { unsigned char rBuff[256]; unsigned char * rp; int res, verb, len; verb = (op->verbose ? (op->verbose - 1) : 0); res = fetch_3pc_vpd(op->idip->fd, NULL, rBuff, (int)sizeof(rBuff), &rp, verb); if (res) return res; len = ((rp[2] << 8) + rp[3]) + 4; decode_3party_copy_vpd(rp, len, to_stderr, verb); if (rBuff != rp) free(rp); return res; } uint64_t count_sgl_blocks(const struct scat_gath_elem * sglp, int elems) { int k; uint64_t num; for (k = 0, num = 0; k < elems; ++k, ++sglp) num += sglp->num; return num; } /* Return maximum number of blocks from the available num_blks that are * available in the scatter gather list, given several constraints. First * bypass blk_off blocks in the list. Then check that elems and * max_descriptors is not exceeded. If max_descriptors is 0 then it is not * constraining. The return value is always <= num_blks. */ static uint64_t count_restricted_sgl_blocks(const struct scat_gath_elem * sglp, int elems, uint64_t blk_off, uint32_t num_blks, uint32_t max_descriptors) { int k, j, md; uint64_t res; if ((0 == max_descriptors) || (max_descriptors > INT_MAX)) md = INT_MAX; else md = (int)max_descriptors; for (k = 0; k < elems; ++k, ++sglp) { if ((uint64_t)sglp->num > blk_off) break; blk_off -= sglp->num; } if (k >= elems) return 0; for (j = 0, res = 0; (k < elems) && (j < md) && (res < (uint64_t)num_blks); ++k, ++j, ++sglp) { if (0 == j) res = (uint64_t)sglp->num - blk_off; else res += (uint64_t)sglp->num; } return (res < (uint64_t)num_blks) ? res : (uint64_t)num_blks; } /* Do POPULATE_TOKEN command, returns 0 on success */ int do_pop_tok(struct opts_t * op, uint64_t blk_off, uint32_t num_blks, int walk_list_id, int vb_a) { int res, k, j, n, len, fd, tmout, sz_bdrd, elems, pl_sz, err_vb; uint64_t lba, sg0_off; uint32_t num; const struct scat_gath_elem * sglp; unsigned char * pl; if (vb_a) pr2serr("%s: blk_off=%" PRIu64 ", num_blks=%" PRIu32 "\n", __func__, blk_off, num_blks); if (op->verbose == vb_a) err_vb = op->verbose; else if (op->verbose > 0) err_vb = (vb_a > 0) ? vb_a : 1; else err_vb = 0; fd = op->idip->fd; if (op->in_sgl) { sg0_off = blk_off; for (k = 0, sglp = op->in_sgl; k < op->in_sgl_elems; ++k, ++sglp) { if ((uint64_t)sglp->num >= sg0_off) break; sg0_off -= sglp->num; } if (k >= op->in_sgl_elems) { pr2serr("%s: exhausted sgl_elems [%d], miscalculation\n", __func__, op->in_sgl_elems); return SG_LIB_CAT_MALFORMED; } /* remain sg elements is worst case, might use less */ elems = op->in_sgl_elems - k; pl_sz = 16 + (16 * elems); } else { sg0_off = 0; /* compilers should be smarter */ sglp = NULL; elems = 1; pl_sz = 32; } pl = (unsigned char *)malloc(pl_sz); if (NULL == pl) { pr2serr("Not enough user memory for %s\n", __func__); return SG_LIB_CAT_OTHER; } memset(pl, 0, pl_sz); if (op->rod_type_given) { pl[2] = 0x2; /* RTV bit */ pl[8] = (unsigned char)((op->rod_type >> 24) & 0xff); pl[9] = (unsigned char)((op->rod_type >> 16) & 0xff); pl[10] = (unsigned char)((op->rod_type >> 8) & 0xff); pl[11] = (unsigned char)(op->rod_type & 0xff); } if (op->iflagp->immed) pl[2] |= 0x1; /* IMMED bit */ /* if inactivity_to=0 then cm takes default in TPC VPD page */ pl[4] = (unsigned char)((op->inactivity_to >> 24) & 0xff); pl[5] = (unsigned char)((op->inactivity_to >> 16) & 0xff); pl[6] = (unsigned char)((op->inactivity_to >> 8) & 0xff); pl[7] = (unsigned char)(op->inactivity_to & 0xff); if (sglp) { lba = sglp->lba + sg0_off; num = sglp->num - sg0_off; for (k = 0, n = 15; k < elems; ++k, num_blks -= num, ++sglp) { if (k > 0) { lba = sglp->lba; num = sglp->num; } if (num > num_blks) num = num_blks; if (vb_a) pr2serr(" lba=0x%" PRIx64 ", num=%" PRIu32 ", k=%d\n", lba, num, k); pl[++n] = (unsigned char)((lba >> 56) & 0xff); pl[++n] = (unsigned char)((lba >> 48) & 0xff); pl[++n] = (unsigned char)((lba >> 40) & 0xff); pl[++n] = (unsigned char)((lba >> 32) & 0xff); pl[++n] = (unsigned char)((lba >> 24) & 0xff); pl[++n] = (unsigned char)((lba >> 16) & 0xff); pl[++n] = (unsigned char)((lba >> 8) & 0xff); pl[++n] = (unsigned char)(lba & 0xff); pl[++n] = (unsigned char)((num >> 24) & 0xff); pl[++n] = (unsigned char)((num >> 16) & 0xff); pl[++n] = (unsigned char)((num >> 8) & 0xff); pl[++n] = (unsigned char)(num & 0xff); n += 4; } sz_bdrd = k * 16; pl[14] = (unsigned char)((sz_bdrd >> 8) & 0xff); pl[15] = (unsigned char)(sz_bdrd & 0xff); len = n + 1; } else { /* assume count= and possibly skip= given */ sz_bdrd = 16; /* single element */ pl[14] = (unsigned char)((sz_bdrd >> 8) & 0xff); pl[15] = (unsigned char)(sz_bdrd & 0xff); lba = op->skip + blk_off; if (vb_a) pr2serr(" lba=0x%" PRIx64 ", num_blks=%" PRIu32 "\n", lba, num_blks); pl[16] = (unsigned char)((lba >> 56) & 0xff); pl[17] = (unsigned char)((lba >> 48) & 0xff); pl[18] = (unsigned char)((lba >> 40) & 0xff); pl[19] = (unsigned char)((lba >> 32) & 0xff); pl[20] = (unsigned char)((lba >> 24) & 0xff); pl[21] = (unsigned char)((lba >> 16) & 0xff); pl[22] = (unsigned char)((lba >> 8) & 0xff); pl[23] = (unsigned char)(lba & 0xff); pl[24] = (unsigned char)((num_blks >> 24) & 0xff); pl[25] = (unsigned char)((num_blks >> 16) & 0xff); pl[26] = (unsigned char)((num_blks >> 8) & 0xff); pl[27] = (unsigned char)(num_blks & 0xff); len = 32; } n = len - 2; pl[0] = (unsigned char)((n >> 8) & 0xff); pl[1] = (unsigned char)(n & 0xff); tmout = (op->timeout_xcopy < 1) ? DEF_3PC_OUT_TIMEOUT : op->timeout_xcopy; res = pt_3party_copy_out(fd, SA_POP_TOK, op->list_id, DEF_GROUP_NUM, tmout, pl, len, 1, vb_a - 1, err_vb); if ((DDPT_CAT_OP_IN_PROGRESS == res) && walk_list_id) { for (j = 0; j < MAX_IN_PROGRESS; ++j) { res = pt_3party_copy_out(fd, SA_POP_TOK, ++op->list_id, DEF_GROUP_NUM, tmout, pl, len, 1, vb_a - 1, err_vb); if (DDPT_CAT_OP_IN_PROGRESS != res) break; } if (MAX_IN_PROGRESS == j) { if (vb_a) pr2serr("%s: too many list_id_s 'in progress'\n", __func__); } } free(pl); return res; } int do_rrti(struct opts_t * op, int in0_out1, struct rrti_resp_t * rrp, int verb) { int j, res, fd, off, err_vb; uint32_t len, rtdl; unsigned char rsp[1024]; char b[400]; char bb[80]; const char * cp; /* want to suppress 'pass-through requested n bytes ...' messages with * 'ddpt verbose=2 ...' */ err_vb = op->verbose; if ((verb != op->verbose) && (err_vb > 1)) --err_vb; fd = in0_out1 ? op->odip->fd : op->idip->fd; res = pt_3party_copy_in(fd, SA_ROD_TOK_INFO, op->list_id, DEF_3PC_IN_TIMEOUT, rsp, sizeof(rsp), 1, verb, err_vb); if (res) return res; len = ((rsp[0] << 24) | (rsp[1] << 16) | (rsp[2] << 8) | rsp[3]) + 4; if (len > sizeof(rsp)) { pr2serr("RRTI: ROD Token info too long for internal buffer, output " "truncated\n"); len = sizeof(rsp); } if (verb > 1) { pr2serr("\nRRTI response in hex:\n"); dStrHexErr((const char *)rsp, len, 1); } if (NULL == rrp) return 0; rrp->for_sa = 0x1f & rsp[4]; switch(rrp->for_sa) { case SA_POP_TOK: cp = "RRTI for PT"; break; case SA_WR_USING_TOK: cp = "RRTI for WUT"; break; case SA_XCOPY_LID1: cp = "RRTI for XCOPY(LID1)"; break; case SA_XCOPY_LID4: cp = "RRTI for XCOPY(LID4)"; break; default: cp = "RRTI for unknown originating xcopy command"; break; } if (verb > 1) pr2serr("%s\n", cp); rrp->cstat = 0x7f & rsp[5]; rrp->xc_cstatus = rsp[12]; rrp->sense_len = rsp[14]; rrp->esu_del = (rsp[8] << 24) | (rsp[9] << 16) | (rsp[10] << 8) | rsp[11]; if (verb) pr2serr("%s: %s\n", cp, cpy_op_status_str(rrp->cstat, b, sizeof(b))); rrp->tc = 0; for (j = 0; j < 8; j++) { if (j > 0) rrp->tc <<= 8; rrp->tc |= rsp[16 + j]; } if (rrp->sense_len > 0) { snprintf(bb, sizeof(bb), "%s: sense data", cp); sg_get_sense_str(bb, rsp + 32, rrp->sense_len, verb, sizeof(b), b); pr2serr("%s\n", b); } off = 32 + rsp[13]; rtdl = (rsp[off] << 24) | (rsp[off + 1] << 16) | (rsp[off + 2] << 8) | rsp[off + 3]; rrp->rt_len = (rtdl > 2) ? rtdl - 2 : 0; if (rtdl > 2) memcpy(rrp->rod_tok, rsp + off + 6, ((rrp->rt_len > 512) ? 512 : rrp->rt_len)); return 0; } int process_after_poptok(struct opts_t * op, uint64_t * tcp, int vb_a) { int res, k, len, vb_b, err, cont; uint64_t rod_sz; uint32_t delay; struct rrti_resp_t r; char b[400]; unsigned char uc[8]; if (op->verbose == vb_a) vb_b = op->verbose; else vb_b = (vb_a > 0) ? (vb_a - 1) : 0; do { res = do_rrti(op, DDPT_ARG_IN, &r, vb_b); if (res) return res; if (SA_POP_TOK != r.for_sa) { sg_get_opcode_sa_name(THIRD_PARTY_COPY_OUT_CMD, r.for_sa, 0, sizeof(b), b); pr2serr("Receive ROD Token info expected response for Populate " "Token\n but got response for %s\n", b); } cont = ((r.cstat >= 0x10) && (r.cstat <= 0x12)); if (cont) { delay = r.esu_del; if ((delay < 0xfffffffe) && (delay > 0)) { if (vb_b > 1) pr2serr("using copy manager recommended delay of %" PRIu32 " milliseconds\n", delay); } else { delay = DEF_ODX_POLL_DELAY_MS; if (vb_b > 1) pr2serr("using default for poll delay\n"); } if (delay) sleep_ms(delay); } } while (cont); if ((! ((0x1 == r.cstat) || (0x3 == r.cstat))) || (vb_b > 1)) pr2serr("RRTI for PT: %s\n", cpy_op_status_str(r.cstat, b, sizeof(b))); if (vb_a) pr2serr("RRTI for PT: Transfer count=%" PRIu64 " [0x%" PRIx64 "]\n", r.tc, r.tc); if (tcp) *tcp = r.tc; if (r.rt_len > 0) { len = (r.rt_len > 512) ? 512 : r.rt_len; if (vb_a) { pr2serr("RRTI for PT: copy manager ROD Token id: %s", rt_cm_id_str(r.rod_tok, r.rt_len, b, sizeof(b))); if (512 == r.rt_len) pr2serr("\n"); else pr2serr(" [rt_len=%" PRIu32 "d]\n", r.rt_len); } if (op->rtf_fd >= 0) { /* write ROD Token to RTF */ res = write(op->rtf_fd, r.rod_tok, len); if (res < 0) { err = errno; pr2serr("%s: unable to write to file: %s [%s]\n", __func__, op->rtf, safe_strerror(err)); return SG_LIB_FILE_ERROR; } if (res < len) { pr2serr("%s: short write to file: %s, wanted %d, got %d\n", __func__, op->rtf, len, res); return SG_LIB_CAT_OTHER; } if (op->rtf_len_add) { rod_sz = r.tc * op->ibs; for (k = 7; k >= 0; --k, rod_sz >>= 8) uc[k] = rod_sz & 0xff; res = write(op->rtf_fd, uc, 8); if (res < 0) { err = errno; pr2serr("%s: unable to write length to file: %s [%s]\n", __func__, op->rtf, safe_strerror(err)); return SG_LIB_FILE_ERROR; } } } /* write ROD Token to static, in any case; could be a copy */ if (len > LOCAL_ROD_TOKEN_SIZE) { pr2serr("%s: ROD token too large for static storage, try " "'rtf=RTF'\n", __func__); return SG_LIB_CAT_OTHER; } memcpy(local_rod_token, r.rod_tok, len); } return 0; } void get_local_rod_tok(unsigned char * tokp, int max_tok_len) { int len; if (tokp && (max_tok_len > 0)) { len = (max_tok_len > 512) ? 512 : max_tok_len; memcpy(tokp, local_rod_token, len); } } /* Do WRITE USING TOKEN command, returns 0 on success */ int do_wut(struct opts_t * op, unsigned char * tokp, uint64_t blk_off, uint32_t num_blks, uint64_t oir, int more_left, int walk_list_id, int vb_a) { int len, k, j, n, fd, res, tmout, sz_bdrd, elems, pl_sz, rodt_blk_zero; int err_vb = 0; struct flags_t * flp; uint64_t lba, sg0_off; uint32_t num; const struct scat_gath_elem * sglp; unsigned char * pl; // unsigned char rt[512]; if (op->verbose == vb_a) err_vb = op->verbose; else if (op->verbose > 0) err_vb = (vb_a > 0) ? vb_a : 1; if (vb_a) pr2serr("%s: enter; blk_off=%" PRIu64 ", num_blks=%" PRIu32 ", " " oir=0x%" PRIx64 "\n", __func__, blk_off, num_blks, oir); fd = op->odip->fd; flp = op->oflagp; rodt_blk_zero = (RODT_BLK_ZERO == op->rod_type); if (op->out_sgl) { sglp = op->out_sgl; for (k = 0, sg0_off = blk_off; k < op->out_sgl_elems; ++k, ++sglp) { if ((uint64_t)sglp->num >= sg0_off) break; sg0_off -= sglp->num; } if (k >= op->out_sgl_elems) { pr2serr("%s: exhausted sgl_elems [%d], miscalculation\n", __func__, op->out_sgl_elems); return SG_LIB_CAT_MALFORMED; } /* remain sg elements is worst case, might use less */ elems = op->out_sgl_elems - k; pl_sz = 540 + (16 * elems); } else { sg0_off = 0; /* compilers should be smarter */ sglp = NULL; elems = 1; pl_sz = 540 + 16; } pl = (unsigned char *)malloc(pl_sz); if (NULL == pl) { pr2serr("Not enough user memory for %s\n", __func__); return SG_LIB_CAT_OTHER; } memset(pl, 0, pl_sz); if (! rodt_blk_zero) { if (flp->del_tkn) /* only from ddptctl */ pl[2] = 0x2; /* DEL_TKN bit */ else if ((! more_left) && (! flp->no_del_tkn)) pl[2] = 0x2; /* last write from ROD which may hold more */ } if (flp->immed) pl[2] |= 0x1; /* IMMED bit */ if (oir) { /* Offset in ROD field */ pl[8] = (unsigned char)((oir >> 56) & 0xff); pl[9] = (unsigned char)((oir >> 48) & 0xff); pl[10] = (unsigned char)((oir >> 40) & 0xff); pl[11] = (unsigned char)((oir >> 32) & 0xff); pl[12] = (unsigned char)((oir >> 24) & 0xff); pl[13] = (unsigned char)((oir >> 16) & 0xff); pl[14] = (unsigned char)((oir >> 8) & 0xff); pl[15] = (unsigned char)(oir & 0xff); } memcpy(pl + 16, tokp, 512); if (sglp) { lba = sglp->lba + sg0_off; num = sglp->num - sg0_off; for (k = 0, n = 535; k < elems; ++k, num_blks -= num, ++sglp) { if (k > 0) { lba = sglp->lba; num = sglp->num; } if (num > num_blks) num = num_blks; if (vb_a) pr2serr(" lba=0x%" PRIx64 ", num=%" PRIu32 ", k=%d\n", lba, num, k); pl[++n] = (unsigned char)((lba >> 56) & 0xff); pl[++n] = (unsigned char)((lba >> 48) & 0xff); pl[++n] = (unsigned char)((lba >> 40) & 0xff); pl[++n] = (unsigned char)((lba >> 32) & 0xff); pl[++n] = (unsigned char)((lba >> 24) & 0xff); pl[++n] = (unsigned char)((lba >> 16) & 0xff); pl[++n] = (unsigned char)((lba >> 8) & 0xff); pl[++n] = (unsigned char)(lba & 0xff); pl[++n] = (unsigned char)((num >> 24) & 0xff); pl[++n] = (unsigned char)((num >> 16) & 0xff); pl[++n] = (unsigned char)((num >> 8) & 0xff); pl[++n] = (unsigned char)(num & 0xff); n += 4; } sz_bdrd = 16 * k; pl[534] = (unsigned char)((sz_bdrd >> 8) & 0xff); pl[535] = (unsigned char)(sz_bdrd & 0xff); } else { sz_bdrd = 16; /* single element */ pl[534] = (unsigned char)((sz_bdrd >> 8) & 0xff); pl[535] = (unsigned char)(sz_bdrd & 0xff); lba = op->seek + blk_off; if (vb_a) pr2serr(" lba=0x%" PRIx64 ", num_blks=%" PRIu32 "\n", lba, num_blks); pl[536] = (unsigned char)((lba >> 56) & 0xff); pl[537] = (unsigned char)((lba >> 48) & 0xff); pl[538] = (unsigned char)((lba >> 40) & 0xff); pl[539] = (unsigned char)((lba >> 32) & 0xff); pl[540] = (unsigned char)((lba >> 24) & 0xff); pl[541] = (unsigned char)((lba >> 16) & 0xff); pl[542] = (unsigned char)((lba >> 8) & 0xff); pl[543] = (unsigned char)(lba & 0xff); pl[544] = (unsigned char)((num_blks >> 24) & 0xff); pl[545] = (unsigned char)((num_blks >> 16) & 0xff); pl[546] = (unsigned char)((num_blks >> 8) & 0xff); pl[547] = (unsigned char)(num_blks & 0xff); } len = 536 + sz_bdrd; n = len - 2; pl[0] = (unsigned char)((n >> 8) & 0xff); pl[1] = (unsigned char)(n & 0xff); fd = op->odip->fd; tmout = (op->timeout_xcopy < 1) ? DEF_3PC_OUT_TIMEOUT : op->timeout_xcopy; res = pt_3party_copy_out(fd, SA_WR_USING_TOK, op->list_id, DEF_GROUP_NUM, tmout, pl, len, 1, vb_a - 1, err_vb); if ((DDPT_CAT_OP_IN_PROGRESS == res) && walk_list_id) { for (j = 0; j < MAX_IN_PROGRESS; ++j) { res = pt_3party_copy_out(fd, SA_WR_USING_TOK, ++op->list_id, DEF_GROUP_NUM, tmout, pl, len, 1, vb_a - 1, err_vb); if (DDPT_CAT_OP_IN_PROGRESS != res) break; } if (MAX_IN_PROGRESS == j) { if (vb_a) pr2serr("%s: too many list_id_s 'in progress'\n", __func__); } } free(pl); return res; } int process_after_wut(struct opts_t * op, uint64_t * tcp, int vb_a) { int res, cont, vb_b; uint32_t delay; struct rrti_resp_t r; char b[80]; if (op->verbose == vb_a) vb_b = op->verbose; else vb_b = (vb_a > 0) ? (vb_a - 1) : 0; do { res = do_rrti(op, DDPT_ARG_OUT, &r, vb_b); if (res) return res; if (SA_WR_USING_TOK != r.for_sa) { sg_get_opcode_sa_name(THIRD_PARTY_COPY_OUT_CMD, r.for_sa, 0, sizeof(b), b); pr2serr("Receive ROD Token info expected response for Write " "Using Token\n but got response for %s\n", b); } cont = ((r.cstat >= 0x10) && (r.cstat <= 0x12)); if (cont) { delay = r.esu_del; if ((delay < 0xfffffffe) && (delay > 0)) { if (vb_b > 1) pr2serr("using copy manager recommended delay of %" PRIu32 " milliseconds\n", delay); } else { delay = DEF_ODX_POLL_DELAY_MS; if (vb_b > 1) pr2serr("using default for poll delay\n"); } if (delay) sleep_ms(delay); } } while (cont); if ((! ((0x1 == r.cstat) || (0x3 == r.cstat))) || (vb_b > 1)) pr2serr("RRTI for WUT: %s\n", cpy_op_status_str(r.cstat, b, sizeof(b))); if (tcp) *tcp = r.tc; if (vb_a) pr2serr("RRTI for WUT: Transfer count=%" PRIu64 " [0x%" PRIx64 "]\n", r.tc, r.tc); return 0; } #if 0 static int odx_check_sgl(struct opts_t * op, uint64_t num_blks, int in0_out1) { uint32_t allowed_descs; struct dev_info_t * dip = in0_out1 ? op->odip : op->idip; struct flags_t * flp = in0_out1 ? op->oflagp : op->iflagp; uint32_t num_elems = in0_out1 ? op->out_sgl_elems : op->in_sgl_elems; const char * sgl_nm = in0_out1 ? "scatter" : "gather"; if ((op->dd_count >= 0) && ((uint64_t)op->dd_count != num_blks)) { pr2serr("%s: count= value not equal to the sum of %s " "nums\n", __func__, sgl_nm); return SG_LIB_SYNTAX_ERROR; } if ((! flp->force) && dip->odxp) { allowed_descs = dip->odxp->max_range_desc; if ((allowed_descs > 0) && (num_elems > allowed_descs)) { pr2serr("%s: number of %s list elements exceeds what the " "Block Device ROD\nToken Limits descriptor in the 3PC " "VPD page permits (%d).\nCan try '%cflag=force'\n", __func__, sgl_nm, allowed_descs, (in0_out1 ? 'o' : 'i')); return SG_LIB_CAT_OTHER; } } return 0; } #endif static int fetch_read_cap(struct opts_t * op, int in0_out1, int64_t * num_blks, int * blk_sz) { int res; int bs = in0_out1 ? op->obs : op->ibs; struct dev_info_t * dip = in0_out1 ? op->odip : op->idip; struct flags_t * flagp = in0_out1 ? op->oflagp : op->iflagp; const char * oip = in0_out1 ? "o" : "i"; if ((res = pt_read_capacity(op, in0_out1, num_blks, blk_sz))) { if (SG_LIB_CAT_UNIT_ATTENTION == res) { pr2serr("Unit attention (readcap(%s)), continuing\n", oip); res = pt_read_capacity(op, in0_out1, num_blks, blk_sz); } if (res) return res; } if (op->verbose) { print_blk_sizes(dip->fn, "readcap", *num_blks, *blk_sz, 1); if (dip->prot_type > 0) pr2serr(" reports Protection_type=%d, p_i_exp=%d\n", dip->prot_type, dip->p_i_exp); } if ((*num_blks > 0) && (*blk_sz != bs)) { pr2serr(">> warning: %s block size confusion: %sbs=%d, device " "claims=%d\n", dip->fn, oip, bs, *blk_sz); if (0 == flagp->force) { pr2serr(">> abort copy, use %sflag=force to override\n", oip); return -1; } } return 0; } /* This is called when rod_type=zero which implies the input is a dummy * (require 'if=/dev/null') and we want to write block of zeros to the * destination. Returns 0 when successful. */ static int odx_full_zero_copy(struct opts_t * op) { int k, got_count, res, out_blk_sz, out_num_elems, vb3; struct dev_info_t * odip = op->odip; uint64_t out_blk_off, num, tc; int64_t out_num_blks, v; vb3 = (op->verbose > 1) ? (op->verbose - 2) : 0; k = dd_filetype(op->idip->fn, op->verbose); got_count = (op->dd_count > 0); if (FT_DEV_NULL != k) { pr2serr("For single WUT version of ODX write blocks of zeros, " "don't give if=IFILE option\n"); pr2serr("For full copy version of ODX write blocks of zeros, " "give if=/dev/null or equivalent\n"); return SG_LIB_SYNTAX_ERROR; } res = fetch_read_cap(op, DDPT_ARG_OUT, &out_num_blks, &out_blk_sz); if (res) return res; v = out_num_blks; if (op->out_sgl) { /* scatter list */ out_num_elems = op->out_sgl_elems; out_num_blks = count_sgl_blocks(op->out_sgl, out_num_elems); } else { /* no scatter list */ out_num_elems = 1; out_num_blks = got_count ? op->dd_count : 0; } if (0 == op->dd_count) { if (op->verbose) pr2serr("%s: enough checks, count=0 given so exit\n", __func__); return 0; } if ((op->dd_count < 0) && (0 == out_num_blks)) { if (1 == op->verbose) pr2serr("%s: zero the lot after scaling for seek=\n", __func__); v -= op->seek; if (v < 0) { pr2serr("%s: seek exceeds out device size\n", __func__); return SG_LIB_SYNTAX_ERROR; } out_num_blks = v; } out_blk_off = 0; op->dd_count = out_num_blks; /* Build fixed format ROD Token Block Zero; specified by SBC-3 */ memset(local_rod_token, 0, sizeof(local_rod_token)); local_rod_token[0] = (unsigned char)((RODT_BLK_ZERO >> 24) & 0xff); local_rod_token[1] = (unsigned char)((RODT_BLK_ZERO >> 16) & 0xff); local_rod_token[2] = (unsigned char)((RODT_BLK_ZERO >> 8) & 0xff); local_rod_token[3] = (unsigned char)(RODT_BLK_ZERO & 0xff); local_rod_token[6] = (unsigned char)((ODX_ROD_TOK_LEN_FLD >> 8) & 0xff); local_rod_token[7] = (unsigned char)(ODX_ROD_TOK_LEN_FLD & 0xff); if (op->verbose > 1) pr2serr("%s: about to zero %" PRIi64 " blocks\n", __func__, out_num_blks); for (k = 0; out_num_blks > 0; out_num_blks -= num, ++k) { num = out_num_blks; if ((op->obpch > 0) && ((uint64_t)op->obpch < num)) num = op->obpch; /* in this case BPT refers to OFILE */ if ((odip->odxp->max_tok_xfer_size > 0) && (num > odip->odxp->max_tok_xfer_size)) num = odip->odxp->max_tok_xfer_size; if (op->out_sgl) num = count_restricted_sgl_blocks(op->out_sgl, out_num_elems, out_blk_off, num, odip->odxp->max_range_desc); if ((res = do_wut(op, local_rod_token, out_blk_off, num, 0, 0, ! op->list_id_given, vb3))) return res; if ((res = process_after_wut(op, &tc, vb3))) return res; if (tc != num) { pr2serr("%s: number requested differs from transfer count\n", __func__); // ouch, think about this one } op->out_full += tc; out_blk_off += num; op->dd_count -= tc; } return 0; } /* This function is designed to be the reading or input ise of a network * copy. Returns 0 on success. */ static int odx_read_into_rods(struct opts_t * op) { int k, res, in_blk_sz, got_count, in_num_elems, vb3; uint64_t in_blk_off, num, tc_i; int64_t in_num_blks, u; struct dev_info_t * idip = op->idip; vb3 = (op->verbose > 1) ? (op->verbose - 2) : 0; got_count = (op->dd_count > 0); /* need to know block size of input and output */ res = fetch_read_cap(op, DDPT_ARG_IN, &in_num_blks, &in_blk_sz); if (res) return res; u = in_num_blks; if (op->in_sgl) { /* gather list */ in_num_elems = op->in_sgl_elems; in_num_blks = count_sgl_blocks(op->in_sgl, in_num_elems); if (got_count && (in_num_blks != op->dd_count)) { pr2serr("%s: count= value not equal to the sum of gather nums\n", __func__); return SG_LIB_CAT_OTHER; } } else { in_num_elems = 1; in_num_blks = got_count ? op->dd_count : 0; } if (0 == op->dd_count) { if (op->verbose) pr2serr("%s: enough checks, count=0 given so exit\n", __func__); return 0; } if ((op->dd_count < 0) && (0 == in_num_blks)) { if (op->verbose > 1) pr2serr("%s: read the lot after scaling for skip=\n", __func__); u -= op->skip; if (u < 0) { pr2serr("%s: skip exceeds input device size\n", __func__); return SG_LIB_SYNTAX_ERROR; } in_num_blks = u; } in_blk_off = 0; op->dd_count = in_num_blks; if (op->verbose > 1) pr2serr("%s: about to read %" PRIi64 " blocks\n", __func__, in_num_blks); /* read using PT[,PT...] sequence; output separate ROD Token for each */ for (k = 0; in_num_blks > 0; in_num_blks -= num, ++k) { if (k > 0) signals_process_delay(op, DELAY_COPY_SEGMENT); num = in_num_blks; if (op->bpt_given && ((uint64_t)op->bpt_i < num)) num = op->bpt_i; if ((idip->odxp->max_tok_xfer_size > 0) && (num > idip->odxp->max_tok_xfer_size)) num = idip->odxp->max_tok_xfer_size; if (op->in_sgl) num = count_restricted_sgl_blocks(op->in_sgl, in_num_elems, in_blk_off, num, idip->odxp->max_range_desc); if (op->verbose > 2) pr2serr("%s: k=%d, in_blk_off=0x%" PRIx64 ", i_num=%" PRIu64 "\n", __func__, k, in_blk_off, num); if ((res = do_pop_tok(op, in_blk_off, num, ! op->list_id_given, vb3))) return res; if ((res = process_after_poptok(op, &tc_i, vb3))) return res; if (tc_i != num) { pr2serr("%s: number requested (in) differs from transfer " "count\n", __func__); // ouch, think about this one } op->in_full += tc_i; in_blk_off += tc_i; op->dd_count -= tc_i; } return 0; } /* This function is designed to copy large amounts (terabytes) with * potentially different block sizes on input and output. Returns * 0 on success. */ static int odx_write_from_rods(struct opts_t * op) { int k, res, n, off, out_blk_sz; int got_count, out_num_elems, err, vb3; uint64_t out_blk_off, num, o_num, r_o_num, oir, tc_o; int64_t out_num_blks, v; struct dev_info_t * odip = op->odip; unsigned char rt[520]; vb3 = (op->verbose > 1) ? (op->verbose - 2) : 0; got_count = (op->dd_count > 0); res = fetch_read_cap(op, DDPT_ARG_OUT, &out_num_blks, &out_blk_sz); if (res) return res; v = out_num_blks; if (op->out_sgl) { /* scatter list */ out_num_elems = op->out_sgl_elems; out_num_blks = count_sgl_blocks(op->out_sgl, out_num_elems); } else { /* no scatter list */ out_num_elems = 1; out_num_blks = got_count ? op->dd_count : 0; } if (0 == op->dd_count) { if (op->verbose) pr2serr("%s: enough checks, count=0 given so exit\n", __func__); return 0; } if ((op->dd_count < 0) && (0 == out_num_blks)) { if (op->verbose > 1) pr2serr("%s: write the lot after scaling for seek=\n", __func__); v -= op->seek; if (v < 0) { pr2serr("%s: seek exceeds out device size\n", __func__); return SG_LIB_SYNTAX_ERROR; } out_num_blks = v; } out_blk_off = 0; op->dd_count = out_num_blks; if (op->verbose > 1) pr2serr("%s: about to write %" PRIi64 " blocks (seen from output)\n", __func__, out_num_blks); /* copy using PT, WUT, [WUT, ...], PT, WUT, [WUT, ...] sequence */ for (k = 0; out_num_blks > 0; out_num_blks -= num, ++k) { if (k > 0) signals_process_delay(op, DELAY_COPY_SEGMENT); memset(rt, 0, sizeof(rt)); n = op->rtf_len_add ? 520 : 512; res = read(op->rtf_fd, rt, n); if (res < 0) { err = errno; pr2serr("%s: could not read '%s': %s\n", __func__, op->rtf, safe_strerror(err)); return SG_LIB_FILE_ERROR; } if (0 == res) { if (op->verbose) pr2serr("%s: there are no more tokens to read from RTF or, \n" "if it is a pipe or socket, the other end closed " " it\n", __func__); break; } if (res < n) { pr2serr("%s: unable to read %d bytes from '%s', only got %d " "bytes\n", __func__, (int)sizeof(rt), op->rtf, res); pr2serr(" try to continue\n"); } if (op->rtf_len_add) off = 512; else { /* 'number of bytes represented' is a 16 byte integer! It starts * at offset 48 and may not be present so its contents might be * random. If any of the top 8 bytes are non-zero, give up. */ for (n = 0; n < 8; ++n) { if (0x0 != rt[48 + n]) break; } if (n < 8) { pr2serr("%s: wild 'bytes represented' field in ROD Token so " "give up.\n Try again with conv=rtf_len\n", __func__); return SG_LIB_CAT_OTHER; } off = 56; } for (n = 0, num = 0; n < 8; ++n) { if (n > 0) num <<= 8; num += rt[off + n]; } o_num = num / (unsigned int)op->obs; if (o_num > 0xffffffffffLL) { pr2serr("%s: ROD size seems too large (%" PRIu64 " blocks " "each %d bytes)\nTry again with conv=rtf_len\n", __func__, o_num, op->obs); return SG_LIB_CAT_OTHER; } if (0 == o_num) { pr2serr("%s: ROD size is less than 1 block (%d bytes). Try " "again with conv=rtf_len\n", __func__, op->obs); return SG_LIB_CAT_OTHER; } num = o_num; for (oir = 0; o_num > 0; oir += r_o_num, o_num -= r_o_num) { /* output dev might be more constrained than input, so multiple * WUT calls (latter ones using offset in ROD) may be needed */ if (k > 0) signals_process_delay(op, DELAY_WRITE); r_o_num = o_num; if (op->bpt_given) { /* take either bpt argument since input is a ROD */ if ((op->obpch > 0) && ((uint64_t)op->obpch < r_o_num)) r_o_num = op->obpch; else if ((op->bpt_i > 0) && ((uint64_t)op->bpt_i < r_o_num)) r_o_num = op->bpt_i; } if ((odip->odxp->max_tok_xfer_size > 0) && (r_o_num > odip->odxp->max_tok_xfer_size)) r_o_num = odip->odxp->max_tok_xfer_size; if (op->out_sgl) r_o_num = count_restricted_sgl_blocks(op->out_sgl, out_num_elems, out_blk_off, r_o_num, odip->odxp->max_range_desc); res = do_wut(op, rt, out_blk_off, r_o_num, oir, (r_o_num < o_num), ! op->list_id_given, vb3); if (res) return res; if ((res = process_after_wut(op, &tc_o, vb3))) return res; if (tc_o != r_o_num) { pr2serr("%s: number requested (out) differs from transfer " "count\n", __func__); // ouch, could have over-drained ROD } op->out_full += tc_o; out_blk_off += tc_o; op->dd_count -= tc_o; } } return 0; } /* This function is designed to copy large amounts (terabytes) with * potentially different block sizes on input and output. Returns * 0 on success. */ static int odx_full_copy(struct opts_t * op) { int k, res, ok, in_blk_sz, out_blk_sz, oneto1, in_mult, out_mult; int got_count, in_num_elems, out_num_elems, vb3; uint64_t in_blk_off, out_blk_off, num, o_num, r_o_num, oir, tc_i, tc_o; int64_t in_num_blks, out_num_blks, u, uu, v, vv; struct dev_info_t * idip = op->idip; struct dev_info_t * odip = op->odip; vb3 = (op->verbose > 1) ? (op->verbose - 2) : 0; got_count = (op->dd_count > 0); /* need to know block size of input and output */ res = fetch_read_cap(op, DDPT_ARG_IN, &in_num_blks, &in_blk_sz); if (res) return res; u = in_num_blks; res = fetch_read_cap(op, DDPT_ARG_OUT, &out_num_blks, &out_blk_sz); if (res) return res; v = out_num_blks; oneto1 = (in_blk_sz == out_blk_sz); in_mult = 0; /* so (in_blk_sz < out_blk_sz) */ out_mult = 0; if (! oneto1) { out_mult = in_blk_sz / out_blk_sz; if (out_mult > 0) ok = (in_blk_sz == (out_mult * out_blk_sz)); else { in_mult = out_blk_sz / in_blk_sz; ok = (out_blk_sz == (in_mult * in_blk_sz)); } if (! ok) { pr2serr("%s: only accept different block sizes if one is a " "multiple of the other.\n input block size=%d and " "output block size=%d\n", __func__, in_blk_sz, out_blk_sz); return SG_LIB_CAT_OTHER; } } if (op->in_sgl) { /* gather list */ in_num_elems = op->in_sgl_elems; in_num_blks = count_sgl_blocks(op->in_sgl, in_num_elems); if (got_count && (in_num_blks != op->dd_count)) { pr2serr("%s: count= value not equal to the sum of gather nums\n", __func__); return SG_LIB_CAT_OTHER; } } else { in_num_elems = 1; in_num_blks = got_count ? op->dd_count : 0; } if (op->out_sgl) { /* scatter list */ out_num_elems = op->out_sgl_elems; out_num_blks = count_sgl_blocks(op->out_sgl, out_num_elems); if (oneto1) { if(got_count && (out_num_blks != op->dd_count)) { pr2serr("%s: count= value not equal to the sum of scatter " "nums\n", __func__); return SG_LIB_SYNTAX_ERROR; } if (out_num_blks != in_num_blks) { pr2serr("%s: number of blocks in gather list differ from " "scatter list\n", __func__); if (op->iflagp->force || op->oflagp->force) pr2serr("... continuing due to force flag\n"); else { pr2serr("... can be overridden with force flag\n"); return SG_LIB_SYNTAX_ERROR; } } } else { /* unequal block size */ u = out_blk_sz * out_num_blks; if (op->in_sgl && (u != (in_blk_sz * in_num_blks))) { pr2serr("%s: number of blocks in both lists need to reflect " "the same number of bytes, but don't\n", __func__); return SG_LIB_SYNTAX_ERROR; } if (got_count && (u != (in_blk_sz * in_num_blks))) { pr2serr("%s: number of scatter blocks and count need to " "reflect the same number of bytes, but don't\n", __func__); return SG_LIB_SYNTAX_ERROR; } } } else { /* no scatter list */ out_num_elems = 1; if (got_count) { if (oneto1) out_num_blks = op->dd_count; else if (in_mult) out_num_blks = op->dd_count * out_blk_sz / in_blk_sz; else out_num_blks = op->dd_count * in_blk_sz / out_blk_sz; } else out_num_blks = 0; } if (0 == op->dd_count) { if (op->verbose) pr2serr("%s: enough checks, count=0 given so exit\n", __func__); return 0; } if ((op->dd_count < 0) && (0 == in_num_blks) && (0 == out_num_blks)) { if (op->verbose > 1) pr2serr("%s: copy the lot after scaling for skip= and seek=\n", __func__); u -= op->skip; v -= op->seek; if (u < 0) { pr2serr("%s: skip exceeds input device size\n", __func__); return SG_LIB_SYNTAX_ERROR; } if (v < 0) { pr2serr("%s: seek exceeds out device size\n", __func__); return SG_LIB_SYNTAX_ERROR; } if (oneto1) { in_num_blks = (u < v) ? u : v; out_num_blks = in_num_blks; } else { uu = u * in_blk_sz; vv = v * out_blk_sz; if (uu == vv) { in_num_blks = u; out_num_blks = v; } else if (uu < vv) { in_num_blks = u; out_num_blks = uu / out_blk_sz; } else { in_num_blks = vv / in_blk_sz; out_num_blks = v; } } } in_blk_off = 0; out_blk_off = 0; op->dd_count = in_num_blks; if (op->verbose > 1) pr2serr("%s: about to copy %" PRIi64 " blocks (seen from input)\n", __func__, in_num_blks); /* copy using PT, WUT, [WUT, ...], PT, WUT, [WUT, ...] sequence */ for (k = 0; in_num_blks > 0; in_num_blks -= num, ++k) { if (k > 0) signals_process_delay(op, DELAY_COPY_SEGMENT); num = in_num_blks; if (op->bpt_given && ((uint64_t)op->bpt_i < num)) num = op->bpt_i; if ((idip->odxp->max_tok_xfer_size > 0) && (num > idip->odxp->max_tok_xfer_size)) num = idip->odxp->max_tok_xfer_size; if (op->in_sgl) num = count_restricted_sgl_blocks(op->in_sgl, in_num_elems, in_blk_off, num, idip->odxp->max_range_desc); if (! oneto1) { if (in_mult) { o_num = num / in_mult; num = o_num * in_mult; if (0 == num) { if (in_num_blks < in_mult) { pr2serr("%s: unable to copy trailing blocks due to " "block size mismatch\n", __func__); return 0; } else { pr2serr("%s: block size mismatch problem, perhaps " "BPT value too small\n", __func__); return SG_LIB_SYNTAX_ERROR; } } } else /* out_mult must be >= 2 */ o_num = num * out_mult; } else o_num = num; if (op->verbose > 2) pr2serr("%s: k=%d, in_blk_off=0x%" PRIx64 ", i_num=%" PRIu64 ", " "out_blk_off=0x%" PRIx64 ", o_num=%" PRIu64 "\n", __func__, k, in_blk_off, num, out_blk_off, o_num); if ((res = do_pop_tok(op, in_blk_off, num, ! op->list_id_given, vb3))) return res; if ((res = process_after_poptok(op, &tc_i, vb3))) return res; if (tc_i != num) { pr2serr("%s: number requested (in) differs from transfer " "count\n", __func__); // ouch, think about this one } op->in_full += tc_i; in_blk_off += tc_i; for (oir = 0; o_num > 0; oir += r_o_num, o_num -= r_o_num) { /* output dev might be more constrained than input, so multiple * WUT calls (latter ones using offset in ROD) may be needed */ if (k > 0) signals_process_delay(op, DELAY_WRITE); r_o_num = o_num; if ((op->obpch > 0) && ((uint64_t)op->obpch < r_o_num)) r_o_num = op->obpch; if ((odip->odxp->max_tok_xfer_size > 0) && (r_o_num > odip->odxp->max_tok_xfer_size)) r_o_num = odip->odxp->max_tok_xfer_size; if (op->out_sgl) r_o_num = count_restricted_sgl_blocks(op->out_sgl, out_num_elems, out_blk_off, r_o_num, odip->odxp->max_range_desc); res = do_wut(op, local_rod_token, out_blk_off, r_o_num, oir, (r_o_num < o_num), ! op->list_id_given, vb3); if (res) return res; if ((res = process_after_wut(op, &tc_o, vb3))) return res; if (tc_o != r_o_num) { pr2serr("%s: number requested (out) differs from transfer " "count\n", __func__); // ouch, could have over-drained ROD } op->out_full += tc_o; out_blk_off += tc_o; } op->dd_count -= tc_i; } return 0; } static int odx_setup_and_run(struct opts_t * op, int * whop) { int fd, res, req; struct dev_info_t * dip; if (whop) *whop = 0; req = op->odx_request; if (! op->list_id_given) op->list_id = (ODX_WRITE_FROM_RODS == req) ? DEF_LID4_WR_LID : DEF_LID4_LID; if ((ODX_READ_INTO_RODS == req) || ((ODX_COPY == req) && (RODT_BLK_ZERO != op->rod_type))) { fd = pt_open_if(op, NULL); if (-1 == fd) return SG_LIB_FILE_ERROR; else if (fd < -1) return SG_LIB_CAT_OTHER; dip = op->idip; dip->fd = fd; dip->odxp = (struct block_rodtok_vpd *)malloc(sizeof(*dip->odxp)); if (NULL == dip->odxp) { pr2serr("Not enough user memory for %s\n", __func__); return SG_LIB_CAT_OTHER; } memset(dip->odxp, 0, sizeof(*dip->odxp)); res = get_3pc_vpd_blkdev_lims(op, dip); if (res && (op->iflagp->force < 2)) return res; } if ((ODX_WRITE_FROM_RODS == req) || (ODX_COPY == req)) { fd = pt_open_of(op, NULL); if (-1 == fd) return SG_LIB_FILE_ERROR; else if (fd < -1) return SG_LIB_CAT_OTHER; dip = op->odip; dip->fd = fd; dip->odxp = (struct block_rodtok_vpd *)malloc(sizeof(*dip->odxp)); if (NULL == dip->odxp) { pr2serr("Not enough user memory for %s 2\n", __func__); return SG_LIB_CAT_OTHER; } memset(dip->odxp, 0, sizeof(*dip->odxp)); res = get_3pc_vpd_blkdev_lims(op, dip); if (res && (op->oflagp->force < 2)) return res; } if (ODX_READ_INTO_RODS == req) { if (whop) *whop = 1; res = odx_read_into_rods(op); if (res) return res; } else if (ODX_WRITE_FROM_RODS == req) { if (whop) *whop = 2; res = odx_write_from_rods(op); if (res) return res; } else if (ODX_COPY == req) { if (op->rod_type_given && (RODT_BLK_ZERO == op->rod_type)) { if (whop) *whop = 2; return odx_full_zero_copy(op); } else return odx_full_copy(op); } return 0; } /* Called from main() in ddpt.c . Returns 0 on success or a positive * errno value if problems. This is for ODX which is a subset of * xcopy(LID4) for disk->disk, disk->held and held-> disk copies. */ int do_odx(struct opts_t * op) { int ret, who; if (op->iflagp->append || op->oflagp->append) ++op->rtf_append; if (op->iflagp->rtf_len || op->oflagp->rtf_len) ++op->rtf_len_add; if (op->rtf[0]) { ret = open_rtf(op); if (ret) { ret = SG_LIB_FILE_ERROR; goto the_end; } } if (op->do_time) calc_duration_init(op); ret = odx_setup_and_run(op, &who); if (0 == op->status_none) print_stats("", op, who); if (op->do_time) calc_duration_throughput("", 0, op); if (op->rtf_fd >= 0) { close(op->rtf_fd); op->rtf_fd = -1; } the_end: return ret; } ddpt-0.94/config.h.in0000644000175000017500000000452612230536230013423 0ustar douggdougg/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the `fallocate' function. */ #undef HAVE_FALLOCATE /* Define to 1 if you have the `fdatasync' function. */ #undef HAVE_FDATASYNC /* Define to 1 if you have the `fsync' function. */ #undef HAVE_FSYNC /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_BSG_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_KDEV_T_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TYPES_H /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP /* Define to 1 if you have the `posix_fadvise' function. */ #undef HAVE_POSIX_FADVISE /* Define to 1 if you have the `posix_fallocate' function. */ #undef HAVE_POSIX_FALLOCATE /* Define to 1 if you have the `posix_memalign' function. */ #undef HAVE_POSIX_MEMALIGN /* Define to 1 if you have the `siginterrupt' function. */ #undef HAVE_SIGINTERRUPT /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* ignore linux bsg */ #undef IGNORE_LINUX_BSG /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* ddpt Build Host */ #undef SG_LIB_BUILD_HOST /* ddpt on FreeBSD */ #undef SG_LIB_FREEBSD /* assume ddpt on linux */ #undef SG_LIB_LINUX /* also MinGW environment */ #undef SG_LIB_MINGW /* ddpt on Solaris */ #undef SG_LIB_SOLARIS /* ddpt on Win32 */ #undef SG_LIB_WIN32 /* full SCSI sense strings */ #undef SG_SCSI_STRINGS /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* allow large buffers, aligned? */ #undef WIN32_SPT_DIRECT ddpt-0.94/aclocal.m40000644000175000017500000011701412234471250013241 0ustar douggdougg# generated automatically by aclocal 1.13.3 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.13' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.13.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.13.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # -*- Autoconf -*- # Obsolete and "removed" macros, that must however still report explicit # error messages when used, to smooth transition. # # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. AC_DEFUN([AM_CONFIG_HEADER], [AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl AC_CONFIG_HEADERS($@)]) AC_DEFUN([AM_PROG_CC_STDC], [AC_PROG_CC am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should simply use the 'AC][_PROG_CC' macro instead. Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'.])]) AC_DEFUN([AM_C_PROTOTYPES], [AC_FATAL([automatic de-ANSI-fication support has been removed])]) AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR ddpt-0.94/debian/0000755000175000017500000000000012320426231012612 5ustar douggdouggddpt-0.94/debian/changelog0000644000175000017500000000155512320426132014472 0ustar douggdouggddpt (0.94-0.1) unstable; urgency=low * see ChangeLog -- Douglas Gilbert Mon, 07 Apr 2014 01:00:00 -0400 ddpt (0.93-0.1) unstable; urgency=low * see ChangeLog -- Douglas Gilbert Wed, 13 Nov 2013 21:00:00 -0500 ddpt (0.92-0.1) unstable; urgency=low * ddpt -- Douglas Gilbert Thu, 17 Feb 2011 11:00:00 -0500 ddpt (0.91-1) unstable; urgency=low * New upstream release * Changed compat level from 4 to 8 * Updated Standards-Version to 3.9.1 -- Tomas Fasth Wed, 01 Dec 2010 00:51:01 +0000 ddpt (0.91-0.1) unstable; urgency=low * ddpt -- Douglas Gilbert Fri, 13 Aug 2010 18:00:00 -0400 ddpt (0.90-0.1) unstable; urgency=low * ddpt initial version -- Douglas Gilbert Sat, 08 May 2010 18:00:00 -0400 ddpt-0.94/debian/compat0000644000175000017500000000000211502217272014014 0ustar douggdougg7 ddpt-0.94/debian/control0000644000175000017500000000131212270047422014217 0ustar douggdouggSource: ddpt Section: admin Priority: optional Maintainer: Tomas Fasth Build-Depends: cdbs (>= 0.4.15), debhelper (>= 4.0.0), autotools-dev Standards-Version: 3.9.1 Package: ddpt Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Copies disks, partitions and files. Copies files. Is specialized for cases where the source and/or destination is a storage device. Optionally can use a pass-through interface to issue SCSI READ and WRITE commands. Various sparse file and device handling options. Similar to and an extension of the Unix dd command. Also supports two variants of SCSI copy offload: xcopy(LID1) and the disk->disk subset of xcopy(LID4) known as ODX. ddpt-0.94/debian/rules0000755000175000017500000000031611104200157013666 0ustar douggdougg#!/usr/bin/make -f include /usr/share/cdbs/1/rules/buildcore.mk include /usr/share/cdbs/1/class/autotools.mk include /usr/share/cdbs/1/rules/debhelper.mk #include /usr/share/cdbs/1/rules/simple-patchsys.mk ddpt-0.94/debian/copyright0000644000175000017500000000242011527261361014554 0ustar douggdouggThis package was debianized by Tue, 4 Nov 2008 23:59:59 -0500. It was downloaded from http://sg.danny.cz/sg/p/ddpt-0.91.tgz Copyright Holder: Douglas Gilbert License: Redistribution and use in source and binary forms, with or without modification, are permitted under the terms of the BSD License. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software is copyright(c) 2008-2011 by Douglas Gilbert On Debian systems, the complete text of the BSD License can be found in `/usr/share/common-licenses/BSD'. ddpt-0.94/debian/docs0000644000175000017500000000012111444165776013503 0ustar douggdouggAUTHORS COPYING CREDITS INSTALL NEWS README ChangeLog TODO doc/ddpt_examples.txt ddpt-0.94/ddpt.spec0000644000175000017500000000343612320426132013205 0ustar douggdougg%define name ddpt %define version 0.94 %define release 1 Summary: Copy files (like dd) especially SCSI/storage devices Name: %{name} Version: %{version} Release: %{release} License: FreeBSD Group: Utilities/System URL: http://sg.danny.cz/sg/ddpt.html Source0: http://sg.danny.cz/sg/p/%{name}-%{version}.tgz BuildRoot: %{_tmppath}/%{name}-%{version}-root Packager: Douglas Gilbert %description ddpt is yet another variant of the Unix dd command used to copy files. This variant is specialized for moving data to, from or between storage devices. If requested, SCSI commands can be sent to read or write data. SCSI commands are sent via a pass-through interface. Also supports two variants of SCSI copy offload: xcopy(LID1) and the disk->disk subset of xcopy(LID4) known as ODX. %prep %setup -q %build %configure %install if [ "$RPM_BUILD_ROOT" != "/" ]; then rm -rf $RPM_BUILD_ROOT fi make install \ DESTDIR=$RPM_BUILD_ROOT %clean if [ "$RPM_BUILD_ROOT" != "/" ]; then rm -rf $RPM_BUILD_ROOT fi %files %defattr(-,root,root) %doc ChangeLog INSTALL README CREDITS AUTHORS COPYING %attr(0755,root,root) %{_bindir}/* # >> should that be %attr(0755,root,root) %{_sbindir}/* ?? %{_mandir}/man8/* %changelog * Mon Apr 07 2014 - dgilbert at interlog dot com - add ODX (subset xcopy(LID4)) support * ddpt-0.94 * Wed Nov 13 2013 - dgilbert at interlog dot com - allow tape device in non-pt mode; rework signal handling, xcopy * ddpt-0.93 * Thu Feb 17 2011 - dgilbert at interlog dot com - warn about pt on block partitions, coe on reg,blk in * ddpt-0.92 * Fri Aug 13 2010 - dgilbert at interlog dot com - extend bpt=BPT to bpt=BPT[,OBPC], resume and trim flags * ddpt-0.91 * Sat May 08 2010 - dgilbert at interlog dot com - initial version * ddpt-0.90 ddpt-0.94/AUTHORS0000644000175000017500000000005711104213063012436 0ustar douggdouggDouglas Gilbert ddpt-0.94/doc/0000755000175000017500000000000012320426231012135 5ustar douggdouggddpt-0.94/doc/ddpt.80000644000175000017500000021657512320426132013201 0ustar douggdougg.TH DDPT "8" "April 2014" "ddpt\-0.94" DDPT .SH NAME ddpt \- copies data between files and storage devices. Support for devices that understand the SCSI command set. .SH SYNOPSIS .B ddpt [\fIbpt=BPT[,OBPC]\fR] [\fIbs=BS\fR] [\fIcdbsz=\fR{6|10|12|16|32}] [\fIcoe=\fR{0|1}] [\fIcoe_limit=CL\fR] [\fIconv=CONVS\fR] [\fIcount=COUNT\fR] [\fIdelay=MS[,W_MS]\fR] [\fIibs=IBS\fR] [\fIid_usage=LIU\fR] \fIif=IFILE\fR [\fIiflag=FLAGS\fR] [\fIintio=\fR{0|1}] [\fIiseek=SKIP\fR] [\fIito=ITO\fR] [\fIlist_id=LID\fR] [\fIobs=OBS\fR] [\fIof=OFILE\fR] [\fIof2=OFILE2\fR] [\fIoflag=FLAGS\fR] [\fIoseek=SEEK\fR] [\fIprio=PRIO\fR] [\fIprotect=RDP[,WRP]\fR] [\fIretries=RETR\fR] [\fIrtf=RTF\fR] [\fIrtype=RTYPE\fR] [\fIseek=SEEK\fR] [\fIskip=SKIP\fR] [\fIstatus=STAT\fR] [\fIto=TO\fR] [\fIverbose=VERB\fR] [\fI\-\-help\fR] [\fI\-\-odx\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-wscan\fR] [\fI\-\-xcopy\fR] .PP For comparison here is the synopsis for GNU's dd command: .PP .B dd [\fIbs=BS\fR] [\fIcbs=CBS\fR] [\fIconv=CONVS\fR] [\fIcount=COUNT\fR] [\fIibs=IBS\fR] [\fIif=IFILE\fR] [\fIiflag=FLAGS\fR] [\fIobs=OBS\fR] [\fIof=OFILE\fR] [\fIoflag=FLAGS\fR] [\fIseek=SEEK\fR] [\fIskip=SKIP\fR] [\fIstatus=STAT\fR] [\fI\-\-help\fR] [\fI\-\-version\fR] .SH DESCRIPTION .\" Add any additional description here .PP Copies data between files or simply reads data from a file. This utility is specialized for "files" that are storage devices, especially those that can use the SCSI command sets (e.g. SATA and SAS disks). It can issue SCSI commands in pass\-through ("pt") mode. Similar syntax and semantics to the Unix .B dd(1) command. .PP For comparison, the SYNOPSIS section above shows both the .B ddpt command line options followed by GNU's .B dd(1) command line options. Broadly speaking ddpt can be considered a super\-set of dd. See the section on DD DIFFERENCES for significant differences between ddpt and dd. .PP This utility either does direct copies, based on read\-write sequences, or offloaded copies. In an offloaded copy the data being copied does not necessarily pass through the memory of the the machine originating the copy operation; this can save a significant amount of time and lessen CPU usage. .PP When doing a direct copy, this utility breaks the copy into segments since computer RAM is typically a scarce resource. First it reads in \fIBPT*IBS\fR bytes from \fIIFILE\fR (or less if near the end of the copy) into a copy buffer. In the absence of the various options and conditions that bypass the write operation, the copy buffer is then written out to \fIOFILE\fR. The copy process continues working its way along \fIIFILE\fR and \fIOFILE\fR until either \fICOUNT\fR is exhausted, an end of file is detected, or an error occurs. If \fIIBS\fR and \fIOBS\fR are different, ddpt restricts the value of \fIOBS\fR such that the copy buffer is an integral number of output blocks (i.e. (((\fIIBS * BPT\fR) % \fIOBS\fR) == 0) ). In the following descriptions, "segment" refers to all or part of a copy buffer. .PP The term "pt device" is used for a pass\-through device to which SCSI commands like READ(10), WRITE(10) or POPULATE TOKEN may be sent. A pt device may only be able to process SCSI commands in which case the "pt" flag is assumed. The ability to recognize such a pt only device may vary depending on the operating system (e.g. in Linux /dev/sg2 and /dev/bsg/3:0:1:0 are recognized). However if a device can process either normal UNIX read()/ write() calls or pass\-through SCSI commands then the default is to use UNIX read()/write() calls. That default can be overridden by using the "pt" flag (e.g. "if=/dev/sdc iflag=pt"). When pt access is specified any partition information is .B ignored. So "if=/dev/sdc2 iflag=pt skip=3" will start at logical block address 3 of '/dev/sdc'. As a protection measure ddpt will only accept that if the force flag is also given (i.e. 'iflag=pt,force'). .PP This utility supports two types of offloaded copies. Both are based on the EXTENDED COPY (XCOPY or xcopy) family of SCSI commands. The first uses the XCOPY(LID1) command to do a disk to disk copy. LID1 stands for List IDentifier length of 1 byte and the command is described in the SPC\-4 drafts and the earlier SPC\-3 and SPC\-2 standards. Recent SPC\-4 drafts have added the XCOPY(LID4) sub\-family of copy offloaded commands. There is a subset of XCOPY(LID4), specialized for offloaded disk to disk copies, that is known by the market name: ODX. In the descriptions below "xcopy" refers to copies based on XCOPY(LID1) while "odx" refers to either full or partial ODX copies. See the XCOPY and ODX sections below for more information. .SH OPTIONS The dd\-like options with the name=value syntax are listed first, sorted by name. Following that, options starting with "\-" are listed. .TP \fBbpt\fR=\fIBPT[,OBPC]\fR where \fIBPT\fR is Blocks Per Transfer. A direct copy is made up of multiple transfers, each first reading \fIBPT\fR input blocks (i.e. \fIBPT * IBS\fR bytes) from \fIIFILE\fR into the copy buffer and then from that copy buffer writing \fI(BPT * IBS) / OBS\fR output blocks to \fIOFILE\fR. This continues until the copy is finished, with the last transfer being potentially shorter. The default \fIBPT\fR value varies depending on \fIIBS\fR. When \fIIBS\fR < 8, \fIBPT\fR is 8192; when \fIIBS\fR < 64, \fIBPT\fR is 1024; when \fIIBS\fR < 1024, \fIBPT\fR is 128; when \fIIBS\fR < 8192, \fIBPT\fR is 16; when \fIIBS\fR < 32768, \fIBPT\fR is 4; else \fIBPT\fR defaults to 1. If \fIBPT\fR is given as 0 it is treated as the default value. For "bs=512", \fIBPT\fR defaults to 128 so that 64 KiB (or less) is read from \fIIFILE\fR into the copy buffer. This option is treated differently in ODX and is typically only needed for testing; see ODX section. .br The optional \fIOBPC\fR (Output Blocks Per Check) argument controls controls the granularity of sparse writes, write sparing and trim checks. The default granularity is the size of the copy buffer (i.e. \fIBPT * IBS\fR bytes). That can be reduced by specifying \fIOBPC\fR. The finest granularity is when \fIOBPC\fR is 1 which implies the unit of each check is \fIOBS\fR bytes. When \fIOBPC\fR is 0, or not given, the default granularity is used. Large \fIOBPC\fR values are rounded down so that \fIOBPC*OBS\fR does not exceed the size of the copy buffer. .br odx: may be used to limit the data represented by each ROD. Mainly for testing. .TP \fBbs\fR=\fIBS\fR where \fIBS\fR is the \fIIFILE\fR and \fIOFILE\fR block size in bytes. Conflicts with either the "ibs=" or "obs=" options. The value of \fIBS\fR is placed in \fIIBS\fR and \fIOBS\fR. If \fIIFILE\fR or \fIOFILE\fR is a "pt" device then \fIBS\fR .B must be the logical block size of the device. See the DD DIFFERENCES section below. The default is 512 bytes; note that newer disks use 4096 byte blocks with perhaps larger block sizes coming in the future. CD/DVD/BD media use a logical block size of 2048 bytes. .TP \fBcdbsz\fR={6|10|12|16|32} size of SCSI READ and/or WRITE commands issued to pt devices. The default is 10 byte SCSI command blocks unless calculations indicate that a 4 byte block number may be exceeded or \fIBPT\fR is greater than 16 bits (i.e. more than 65535 blocks), in which case it defaults to 16 byte SCSI commands. .TP \fBcoe\fR={0|1} set to 1 for continue on error. Applies to errors on input and output for pt devices but only on input from block devices or regular files. Errors on other files will stop ddpt. Default is 0 which implies stop on any error. See the 'coe' flag for more information. .TP \fBcoe_limit\fR=\fICL\fR where \fICL\fR is the maximum number of consecutive bad blocks stepped over due to "coe=1" on reads before the copy terminates. The default is 0 which is implies no limit. This option is meant to stop the copy soon after unrecorded media is detected while still offering "continue on error" capability for infrequent, randomly distributed errors. .TP \fBconv\fR=\fICONVS\fR see the CONVERSIONS section below. .TP \fBcount\fR=\fICOUNT\fR copy \fICOUNT\fR input blocks from \fIIFILE\fR to \fIOFILE\fR. If this option is not given (or \fICOUNT\fR is '\-1') then the \fICOUNT\fR may be deduced from either \fIIFILE\fR or \fIOFILE\fR. See the COUNT section below. .br odx: if a gather list is given to \fIskip=SKIP\fR or a scatter list is given to \fIseek=SEEK\fR then typically \fIcount=COUNT\fR should not be supplied. This is because a scatter gather list implies a transfer count. If both are given then ddpt will exit if they are unequal, the force option can be used to override this action. .TP \fBdelay\fR=\fIMS[,W_MS]\fR after each segment is copied (typically every (\fIIBS\fR * \fIBPT\fR) bytes) a delay (sleep) of \fIMS\fR milliseconds is performed. The default value for \fIMS\fR is 0 which implies no delay. If \fIW_MS\fR is given and greater than 0 (its default value) then there is an additional delay of \fIW_MS\fR milliseconds associated with each actual write operation that is performed. If \fIMS\fR is greater than 0 then there is not a delay before the first copy segment (or after the last); if \fIW_MS\fR is greater than 0 then there is not a delay before the first write segment. These delays can be used for a bandwidth limiting. .br odx: the \fIMS\fR delay is implemented in the same fashion after each ROD is copied, apart from the last. If \fIW_MS\fR is greater than 0 then that delay occurs before each WUT command, apart from the first. .TP \fBibs\fR=\fIIBS\fR where \fIIBS\fR is the \fIIFILE\fR block size in bytes. The default value is \fIBS\fR or its default (512). Conflicts the "bs=" option (i.e. giving both "bs=512 ibs=512" is considered a syntax error). .TP \fBid_usage\fR=\fILIU\fR xcopy: SCSI EXTENDED COPY parameter list LIST ID USAGE field is set to \fILIU\fR. The default value is 0 or 2 . \fILIU\fR can be a number between 0 and 3 inclusive or a string. The strings can be either: 'hold' for 0, 'discard' for 2 or 'disable' for 3. .TP \fBif\fR=\fIIFILE\fR read from \fIIFILE\fR. This option must be given (apart from one odx case). If \fIIFILE\fR is '\-' then stdin is read. Starts reading at the beginning of \fIIFILE\fR unless \fISKIP\fR is given. .br odx: the \fIrtf=RTF\fR option may replace the \fIif=IFILE\fR option as input. See the ODX section. .TP \fBiflag\fR=\fIFLAGS\fR where \fIFLAGS\fR is a comma separated list of one or more flags outlined in the FLAGS section below. These flags are associated with \fIIFILE\fR and are mostly ignored when \fIIFILE\fR is stdin. .TP \fBintio\fR={0|1} set to 1 for allow signals (SIGINT, SIGPIPE and SIGUSR1 (or SIGINFO)) to be received during IO from \fIIFILE\fR or IO to \fIOFILE\fR or \fIOFILE2\fR. Default is 0 which causes these signals to be masked during IO operations with a check for signals prior each IO. As long as IO operations don't lock up (e.g. SCSI READ and WRITE commands) the default is the safer option. Even if IO operations do lock up it is best to let the kernel take care of that. .TP \fBiseek\fR=\fISKIP\fR start reading \fISKIP\fR blocks (each of \fIIBS\fR bytes) from the start of \fIIFILE\fR. Default is block 0 (i.e. start of file). This option is a synonym for \fIskip=SKIP\fR, see its description. .TP \fBito\fR=\fIITO\fR odx: \fIITO\fR is the inactivity timeout whose units are seconds. The default value is 0 which means the copy manager will take the default inactivity timeout value from the Block Device ROD Token Limits descriptor in the Third Party Copy VPD page. \fIITO\fR is ignored if it it exceeds the maximum inactivity timeout value in the same descriptor (unless the force flag is given). .TP \fBlist_id\fR=\fILID\fR \fILID\fR is the xcopy LIST IDENTIFIER field. It is used to associate an originating xcopy command with follow\-up commands such as RECEIVE ROD TOKEN INFORMATION. If given, the \fILID\fR should not clash with any other xcopy \fILID\fR currently in use on this I_T nexus. .br xcopy: \fILID\fR is a 1 byte (8 bit) value whose default value is 1 or, if id_usage=disable, 0 . \fILID\fR must not exceed 255. .br odx: \fILID\fR is a 4 byte (32 bit) value whose default value is 257 (i.e. 0x101) and, if a second default is needed, 258 (0x102) is used. If a clash is detected on the default list identifier value then the next higher value is tried (stopping after 10 attempts). .TP \fBobs\fR=\fIOBS\fR where \fIOBS\fR is the \fIOFILE\fR block size in bytes. The default value is \fIBS\fR or its default (512). Conflicts the "bs=" option (e.g. giving both "bs=512 obs=512" is considered a syntax error). If \fIOBS\fR is given then it has the following restriction: the integer expression (((\fIIBS\fR * \fIBPT\fR) % \fIOBS\fR) == 0) must be true. Stated another way: the copy buffer size must be an integral multiple of \fIOBS\fR. If \fIof2=OFILE2\fR is given then \fIOBS\fR is its block size as well. .TP \fBof\fR=\fIOFILE\fR write to \fIOFILE\fR. The default value is /dev/null . If \fIOFILE\fR is '\-' then writes to stdout. If \fIOFILE\fR is /dev/null then no actual writes are performed. If \fIOFILE\fR is '.' (period) then it is treated the same way as /dev/null . If \fIOFILE\fR exists then it is _not_ truncated unless "oflag=trunc" is given. See section on DD DIFFERENCES. .br odx: if this option (\fIof=OFILE\fR) is not given and the \fIrtf=RTF\fR option is given then the \fIRTF\fR file may be thought of as receiving the output in the form of one or more ROD Tokens. See the ODX section. .TP \fBof2\fR=\fIOFILE2\fR write output to \fIOFILE2\fR. The default action is not to do this additional write (i.e. when this option is not given). \fIOFILE2\fR is assumed to be a regular file or a fifo (i.e. a named pipe). \fIOFILE2\fR is opened for writing and is created if necessary. If \fIOFILE2\fR is a fifo (named pipe) then some other command should be consuming that data (e.g. 'md5sum OFILE2'), otherwise this utility will block. The write to \fIOFILE2\fR occurs before the write to \fIOFILE\fR and prior to sparse writing and write sparing logic. So everything read is written to \fIOFILE2\fR. .TP \fBoflag\fR=\fIFLAGS\fR where \fIFLAGS\fR is a comma separated list of one or more flags outlined in the FLAGS section. These flags are associated with \fIOFILE\fR and are ignored when \fIOFILE\fR is /dev/null, '.' (period), or stdout. .TP \fBoseek\fR=\fISEEK\fR start writing \fISEEK\fR blocks (each of \fIOBS\fR bytes) from the start of \fIOFILE\fR. Default is block 0 (i.e. start of file). This option is a synonym for \fIseek=SEEK\fR, see its description. .TP \fBprio\fR=\fIPRIO\fR xcopy: SCSI EXTENDED COPY parameter list PRIORITY field is set to \fIPRIO\fR. The default value is 1 . .TP \fBprotect\fR=\fIRDP[,WRP]\fR where \fIRDP\fR is the RDPROTECT field in SCSI READ commands and \fIWRP\fR is the WRPROTECT field in SCSI WRITE commands. The default value for both is 0 which implies no additional protection information will be transferred. Both \fIRDP\fR and \fIWRP\fR can be from 0 to 7. If \fIRDP\fR is greater than 0 then \fIIFILE\fR must be a pt device. If \fIWRP\fR is greater than 0 then \fIOFILE\fR must be a pt device. See the PROTECTION INFORMATION section below. .TP \fBretries\fR=\fIRETR\fR sometimes retries at the host are useful, for example when there is a transport error. When \fIRETR\fR is greater than zero then SCSI READs and WRITEs are retried on error, \fIRETR\fR times. Default value is zero. Only applies to errors on pt devices. .TP \fBrtf\fR=\fIRTF\fR odx: where \fIRTF\fR is a filename. One or more ROD tokens are written to \fIRTF\fR during a read to tokens variant or a full copy variant. One or more ROD tokens are read from \fIRTF\fR during a write from token variant. This option is not required on a full copy variant. ROD Tokens are 512 bytes long and an extra 8 byte (big\-endian) integer containing the 'number of bytes represented' is placed after each ROD Token if rtf_len is given. .TP \fBrtype\fR=\fIRTYPE\fR odx: where \fIRTYPE\fR is the ROD Type. The default value (0) indicates that the copy manager (in the source) decides. \fIRTYPE\fR can be a decimal number, a hex number (prefixed by 0x or with a "h" appended) or one of "pit\-def", "pit\-vuln", "pit\-pers", "pit\-any" or "zero". The final truncated word can be spelt out (e.g. "pit\-vulnerable"). The "pit\-" prefix is a shortening of "point in time" copy. The "zero" causes a special Block device zero Token to be created. .TP \fBseek\fR=\fISEEK\fR start writing \fISEEK\fR blocks (each of \fIOBS\fR bytes) from the start of \fIOFILE\fR. Default is block 0 (i.e. start of file). The \fISEEK\fR value may exceed the number of \fIOBS\fR\-sized blocks in \fIOFILE\fR. .br odx: \fISEEK\fR can be a scatter list: comma separated, in the form seek=A1,N1[,A2,N2...] . The scatter list may alternatively be read from a file using this form: seek=@ or read from stdin using this form: seek=\- (or seek=@\-) . A and N are decimal (optionally with a suffix multiplier) unless a hex indication is given. Hex values are indicated by either a leading "0x" or a trailing "h". The address (i.e. A) is a 64 bit unsigned integer while the number of blocks (i.e. N) is a 32 bit integer. Thus for a block size of 512 bytes, a single scatter gather list element cannot exceed 4 TB ((2**32 \- 1) * 512). Note that \fICOUNT\fR is a 64 bit unsigned integer and thus does not have this restriction. There can be no more than 128 scatter list elements. .TP \fBskip\fR=\fISKIP\fR start reading \fISKIP\fR blocks (each of \fIIBS\fR bytes) from the start of \fIIFILE\fR. Default is block 0 (i.e. start of file). The \fISKIP\fR value must be less than the number of \fIIBS\fR\-sized blocks in \fIIFILE\fR. .br odx: \fISKIP\fR can be a gather list: comma separated, in the form skip=A1,N1[,A2,N2...] . The gather list may alternatively be read from a file using this form: skip=@ or read from stdin using this form: skip=\- . See the odx section of the \fIseek=SEEK\fR option for further details. .TP \fBstatus\fR=\fISTAT\fR the \fISTAT\fR value of 'noxfer' suppresses the throughput speed and the copy time reporting at the end of the copy. A \fISTAT\fR value of 'none' additionally suppresses the records in and out reporting after the copy. So 'status=none' makes ddpt act like a traditional Unix command in which "no news is good news". The default action of ddpt is to show the throughput (in megabytes per second) and the time taken to do the copy after the "records in" and "records out" lines at the end of the copy. As a convenience the value 'null' is accepted for \fISTAT\fR and does nothing. .TP \fBto\fR=\fITO\fR odx, xcopy: where \fITO\fR is am xcopy originating command timeout in seconds. The default value is 0 which is converted internally to 600 seconds (10 minutes). Best to set this timeout value well above the expected copy time. In a odx full copy this timeout is applied to both the POPULATE TOKEN and WRITE USING TOKEN commands. .TP \fBverbose\fR=\fIVERB\fR as \fIVERB\fR increases so does the amount of debug reporting sent to stderr. Default value is zero which yields the minimum amount of debug reporting. A value of 1 reports extra information that is not repetitive. A value 2 reports cdbs and responses for SCSI commands that are not repetitive (i.e. other that READ and WRITE). Error processing is not considered repetitive. Values of 3 and 4 yield reporting for all SCSI commands, plus Unix read() and write() calls, so there can be a lot of output. If \fIVERB\fR is "\-1" then reporting that would have been sent to stderr is redirected to /dev/null essentially throwing it away. .TP \fB\-h\fR, \fB\-\-help\fR reports usage message then exits. .TP \fB\-o\fR, \fB\-\-odx\fR indicates to this utility that one of the four odx variants is requested. See ODX section. .TP \fB\-v\fR, \fB\-\-verbose\fR equivalent of \fIverbose=1\fR. If \fI\-\-verbose\fR appears twice then that is equivalent to \fIverbose=2\fR. Also \fI\-vv\fR is equivalent to \fIverbose=2\fR. .TP \fB\-V\fR, \fB\-\-version\fR reports version number information then exits. .TP \fB\-w\fR, \fB\-\-wscan\fR this option is available in Windows only. It lists storage device names and the corresponding volumes, if any. When used twice it adds the "bus type" of the closest transport (e.g. a SATA disk in a USB connected enclosure has bus type USB). When used three times a SCSI adapter scan is added. When used four times only a SCSI adapter scan is shown. See EXAMPLES section below and the README.win32 file. .TP \fB\-x\fR, \fB\-\-xcopy\fR this option will attempt to call the SCSI EXTENDED COPY(LID1) command. In the absence of another indication the xcopy command will be sent to the destination (i.e. \fIOFILE\fR). See the section on ENVIRONMENT VARIABLES below. .SH COUNT When the \fIcount=COUNT\fR option is not given (or \fICOUNT\fR is '\-1') then an attempt is made to deduce \fICOUNT\fR as follows. .PP When both or either \fIIFILE\fR and \fIOFILE\fR are block devices, then the minimum size, expressed in units of input blocks, is used. When both or either \fIIFILE\fR and \fIOFILE\fR are pass\-through devices, then the minimum size, expressed in units of input blocks, is used. .PP If a regular file is used as input, its size, expressed in units of input blocks (and rounded up if necessary) is used. Note that the rounding up of the deduced \fICOUNT\fR may result in a partial read of the last input block and a corresponding partial write to \fIOFILE\fR if it is a regular file. After a regular file to regular file copy the length of \fIOFILE\fR will be the same as \fIIFILE\fR unless \fIOFILE\fR existed and its length was already greater than that of \fIIFILE\fR. To get a copy like the standard Unix cp command, use oflag=trunc with ddpt. .PP The size of pt devices is deduced from the SCSI READ CAPACITY command. Block device sizes (or their partition sizes) are obtained from the operating system, if available. .PP If \fIskip=SKIP\fR or \fIskip=SEEK\fR are given and the \fICOUNT\fR is deduced (i.e. not explicitly given) then that size is scaled back so that the copy will not overrun the file or device. .PP If \fICOUNT\fR is not given and \fIIFILE\fR is a fifo (and stdin is treated as a fifo) then \fIIFILE\fR is read until an EOF is detected. If \fICOUNT\fR is not given and \fIIFILE\fR is a /dev/zero (or equivalent) then zeros are read until an error occurs (e.g. file system full). .PP If \fICOUNT\fR is not given and cannot be deduced then an error message is issued and no copy takes place. .SH CONVERSIONS One or more conversions can be given to the "conv=" option. If more than one is given, they should be comma separated. ddpt does not perform the traditional dd conversions (e.g. ASCII to EBCDIC). Recently added conversions inherited from GNU's dd overlap somewhat with the some of ddpt flags. .TP fdatasync equivalent to "oflag=fdatasync". Flushes data associated with the \fIOFILE\fR to storage at the end of the copy. This conversion is for compatibility with GNU's dd. .TP fsync equivalent to "oflag=fsync". Flushes data and meta\-data associated with the \fIOFILE\fR to storage at the end of the copy. This conversion .TP no_del_tkn equivalent to "oflag=no_del_tkn". .TP noerror this conversion is very close to "iflag=coe" and is treated as such. See the "coe" flag. Note that an error on a block device or regular file \fIOFILE\fR will stop the copy. .TP notrunc this conversion is accepted for compatibility with dd and ignored since the default action of this utility is not to truncate \fIOFILE\fR. .TP null has no affect, just a placeholder. .TP resume See "resume" in the FLAGS sections for more information. .TP rtf_len equivalent to "oflag=rtf_len". .TP sparing See "sparing" in the FLAGS sections for more information. .TP sparse FreeBSD's dd supports "conv=sparse" and now GNU's dd does as well so the same syntax is supported in ddpt. See "sparse" in the FLAGS sections for more information. .TP sync is ignored by ddpt. With dd it means supply zero fill (rather than skip) and is typically used like this "conv=noerror,sync" to have the same functionality as ddpt's "iflag=coe". .TP trunc if \fIOFILE\fR is a regular file then truncate it prior to starting the copy. See "trunc" in the FLAGS section. .SH FLAGS A list of flags and their meanings follow. The flag name is followed by one or two indications in square brackets. The first indication is either "[i]", "[o]" or "[io]" indicating this flag is active for the \fIIFILE\fR, \fIOFILE\fR or both the \fIIFILE\fR and the \fIOFILE\fR. The second indication contains some combination of "reg", "blk" "pt", "odx", or "xcopy". These indicate whether the flag applies to a regular file, a block device (accessed via Unix read() and write() commands, a pass\-through device, an ODX offloaded copy or a XCOPY(LID1) offloaded copy respectively. Other special file types that are sometimes referred to are "fifo" and "tape". .TP append [o] [reg], [io] [odx] causes the O_APPEND flag to be added to the open of \fIOFILE\fR. For regular files this will lead to data being appended to the end of any existing data. Conflicts the \fIseek=SEEK\fR option. The default action of this utility is to overwrite any existing data from the beginning of \fIOFILE\fR or, if \fISEEK\fR is given, starting at block \fISEEK\fR. Note that attempting to 'append' to a device file (e.g. a disk) will usually be ignored or may cause an error to be reported. .br odx: if the \fIrtf=RTF\fR option is given, \fIRTF\fR exists, is a regular file and this utility wants to write to \fIRTF\fR then new ROD Tokens are appended to \fIRTF\fR. The default action is to truncate \fIRTF\fR before new ROD Tokens are written to it. .TP block [io] [pt] pass\-through file opens are non\-blocking by default and may report the pt device is busy. Use this flag to open blocking so utility may wait until another process locking (or with an exclusive open) is complete before continuing. .TP cat [io] [xcopy] xcopy: set CAT (residual data handling) bit in EXTENDED COPY(LID1) parameter list segment descriptor header. May appear in either flag list when xcopy is being used. Works with the PAD bit for handling residual data on the destination side. See the XCOPY section below. .TP coe [io] [pt], [i] [reg,blk] continue on error. 'iflag=coe oflag=coe' and 'coe=1' are equivalent. Errors occurring on output regular or block files will stop ddpt. Error messages are sent to stderr. This flag is similar to 'conv=noerror,sync' in the .B dd(1) utility. Unrecovered errors are counted and reported in the summary at the end of the copy. .IP This paragraph concerns coe on pt devices. A medium, hardware or blank check error during a read operation will will cause the following: first re\-read blocks prior to the bad block, then try to recover the bad block (supplying zeros if that fails), and finally re\-read the blocks after the bad block. A medium, hardware or blank check error while writing is reported but otherwise ignored. SCSI disks may automatically try and remap faulty sectors (see the AWRE and ARRE in the read write error recovery mode page (the sdparm utility can access these attributes)). If bad LBAs are reported by the pass\-through then the LBA of the lowest and highest bad block is also reported. .IP This paragraph concerns coe on input regular files and block devices. When a EIO or EREMOTEIO error is detected on a normal segment read then the segment is re\-read one block (i.e. \fIIBS\fR bytes) at a time. Any block that yields a EIO or EREMOTEIO error is replaced by zeros. Any other error, a short read or an end of file will terminate the copy, usually after the data that has been read is written to the output file. .TP dc [io] [blk,pt] xcopy: set DC (destination counter) bit in EXTENDED COPY(LID1) parameter list segment descriptor header. May appear in either flag list when xcopy is being used. .TP direct [io] [reg,blk] causes the O_DIRECT flag to be added to the open of \fIIFILE\fR and/or \fIOFILE\fR. This flag requires some memory alignment on IO. Hence user memory buffers are aligned to the page size. May have no effect on pt devices. This flag will bypass caching/buffering normally done by block layer. Beware of data coherency issues if the same locations have been recently accessed via the block layer in its normal mode (i.e. non\-direct). See open(2) man page. .TP dpo [io] [pt] set the DPO bit (disable page out) in SCSI READ and WRITE commands. Not supported for 6 byte cdb variants of READ and WRITE. Indicates that data is unlikely to be required to stay in device (e.g. disk) cache. May speed media copy and/or cause a media copy to have less impact on other device users. .TP errblk [i] [pt] [experimental] attempts to create or append to a file called "errblk.txt" in the current directory the logical block addresses of blocks that cannot be read. The first (appended) line is "# start ". That is followed by the LBAs in hex (and prefixed with "0x") of any block that cannot be read, one LBA per line. If the sense data does not correctly identify the LBA of the first error in the range it was asked to read then a LBA range is reported in the form of the lowest and the highest LBA in the range separated by a "\-". At the end of the copy a line with "# stop " is appended to "errblk.txt". Typically used with "coe". .TP excl [io] [reg,blk] causes the O_EXCL flag to be added to the open of \fIIFILE\fR and/or \fIOFILE\fR. See open(2) man page. .TP fdatasync [o] [reg,blk] Flushes data associated with the \fIOFILE\fR to storage at the end of the copy. .TP flock [io] [reg,blk,pt] after opening the associated file (i.e. \fIIFILE\fR and/or \fIOFILE\fR) an attempt is made to get an advisory exclusive lock with the flock() system call. The flock arguments are "FLOCK_EX | FLOCK_NB" which will cause the lock to be taken if available else a "temporarily unavailable" error is generated. An exit status of 90 is produced in the latter case and no copy is done. See flock(2) man page. .TP force [io] [pt] [xcopy,odx] override difference between given block size and the block size found by the SCSI READ CAPACITY command. Use the given block size. Without this flag the copy would not be performed. pt access to what appears to be a block partition is aborted in version 0.92; that can be overridden by the force flag. For related reasons the 'norcap' flag requires this flag when applied to a block device accessed via pt. .br xcopy and odx: various limits imposed by associated VPD pages or the RECEIVE COPY OPERATING PARAMETERS command can be overridden (i.e. exceeded) if this flag is given. Note that the copy manager will probably object. .TP fsync [o] [reg,blk] Flushes data and metadata (describing the file) associated with the \fIOFILE\fR to storage at the end of the copy. .TP fua [io] [pt] causes the FUA (force unit access) bit to be set in SCSI READ and/or WRITE commands. The 6 byte variants of the SCSI READ and WRITE commands do not support the FUA bit. .TP fua_nv [io] [pt] causes the FUA_NV (force unit access non\-volatile cache) bit to be set in SCSI READ and/or WRITE commands. This only has an effect with pt devices. The 6 byte variants of the SCSI READ and WRITE commands do not support the FUA_NV bit. The FUA_NV bit was made obsolete in SBC\-3 revision 35d. .TP ignoreew [o] [tape] ignore the early warning indication (of end of tape) when writing to tape. See TAPE section. .TP immed [io] [odx] sets the IMMED bit in the POPULATE TOKEN (when [i]) or WRITE USING TOKEN (when [o]) command. That command should return status promptly after starting the data transfer. The RECEIVE ROD TOKEN INFORMATION command is then used to poll for completion. SCSI command timeouts should not be exceeded, even for very large RODs, if this flag is used. .TP nocache [io] [reg,blk] use posix_fadvise(POSIX_FADV_DONTNEED) to advise corresponding file there is no need to fill the file buffer with recently read or written blocks. If used with "iflag=" it will increase the read ahead on \fIIFILE\fR. .TP no_del_tkn [o] [odx] will clear the DEL_TKN bit on the last WRITE USING TOKEN command of each ROD Token in a odx full copy. In a large odx full copy several ROD Tokens may be used (one after the other). The default action is to set the DEL_TKN bit on the last WUT command of each ROD. Either way it should not make much difference because the copy manager deletes a ROD Token after a copy is completed. The copy manager will also delete/invalidate a ROD Token if the inactivity timeout is reached. .TP nofm [o] [tape] no File Mark (FM) on close when writing to tape. See TAPE section. .TP nopad [o] [tape] when the block to be written to a tape drive contains less than \fIOBS\fR bytes, then this option causes the partial block to be written as is. The default action for a tape in this case is to pad the block. See TAPE section. .TP norcap [io] [pt] do not perform SCSI READ CAPACITY command on the corresponding pt device. If used on block device accessed via pt then 'force' flag is also required. This is to warn about using pt access on what may be a block device partition. .TP nowrite [o] [reg,blk,pt] bypass writes to \fIOFILE\fR. The "records out" count is not incremented. \fIOFILE\fR is still opened but "oflag=trunc" if given is ignored. Also the ftruncate call associated with the sparse flag is ignored (i.e. bypassed). Commands such as trim and SCSI SYNCHRONIZE CACHE are still sent. .TP null [io] has no affect, just a placeholder. .TP odx [io] [odx] indicates to this utility that one of the four variants of an odx copy is requested. Using any of the \fI\-\-odx\fR, \fIrtf=RTF\fR or \fIrtype=RTYPE\fR options also indicates that odx is requested. See the ODX section. .TP pad [o] [reg,blk,pt], [io] [xcopy] when the block to be written (typically the last block) contains less than \fIOBS\fR bytes, then this option causes the block to be padded with zeros (i.e. bytes of binary zero). The default action for a regular file and a fifo is to do a partial write. The default action of a block and a pt device is to ignore the partial write. The default action of a tape is to pad, so this flag is not needed (see the nopad flag). .br xcopy: sets the PAD bit in the CSCD descriptor of the associated \fIIFILE\fR or \fIOFILE\fR. Is associated with residual data handling and works together with the cat flag. See the XCOPY section below. .TP prealloc [o] [reg] use the fallocate() call prior to starting a copy to set \fIOFILE\fR to its expected size. .TP pt [io] [blk,pt] causes a device to be accessed in "pt" mode. In "pt" mode SCSI READ and WRITE commands are sent to access blocks rather than standard UNIX read() and write() commands. The "pt" mode may be implicit if the device is only capable of passing through SCSI commands (e.g. the /dev/sg* and some /dev/bsg/* devices in Linux). This flag is needed for device nodes that can be accessed both via standard UNIX read() and write() commands as well as SCSI commands. Such devices default standard UNIX read() and write() commands in the absence of this flag. .TP rarc [i] [pt] bit set in READ(10, 12, 16 and 32) to suppress RAID rebuild functions when a bad (or recovered after difficulties) block is detected. .TP resume [o] [reg] when a copy is interrupted (e.g. with Control\-C from the keyboard) then using the same invocation again with the addition of "oflag=resume" will attempt to restart the copy from the point of the interrupt (or just before that point). It is harmless to use "oflag=resume" when \fIOFILE\fR doesn't exist or is zero length. If the length of \fIOFILE\fR is greater than or equal to the length implied by a ddpt invocation that includes "oflag=resume" then no further data is copied. .TP self [io] [pt] used together with trim flag to do a self trim (trim of segments of a pt device that contain all zeros). If \fIOFILE\fR is not given, then it is set to the same as \fIIFILE\fR. If \fISEEK\fR is not given it set to the same value as \fISKIP\fR (possibly adjusted if \fIIBS\fR and \fIOBS\fR are different). Implicitly sets "nowrite" flag. .TP sparing [o] [reg,blk,pt] during the copy each \fIIBS\fR * \fIBPT\fR byte segment is read from \fIIFILE\fR into a buffer. Then, instead of writing that buffer to \fIOFILE\fR, the corresponding segment is read from \fIOFILE\fR into another buffer. If the two buffers are different, the former buffer is written to the \fIOFILE\fR. If the two buffers compare equal then the write to \fIOFILE\fR is not performed. Write sparing is useful when a write operation is significantly slower than a read. Under some conditions flash memory devices have slow writes plus an upper limit on the number of times the same cell can be rewritten. The granularity of the comparison can be reduced from the default \fIIBS\fR * \fIBPT\fR byte segment with the the \fIOBPC\fR value given to the "bpt=" option. The finest granularity is when \fIOBPC\fR is 1 which implies \fIOBS\fR bytes. .TP sparse [o] [reg,blk,pt] after each \fIIBS\fR * \fIBPT\fR byte segment is read from \fIIFILE\fR, it is checked to see if it is all zeros. If so, that segment is not written to \fIOFILE\fR. See the section on SPARSE WRITES below. The granularity of the zero comparison can be reduced from the default \fIIBS\fR * \fIBPT\fR byte segment with the \fIOBPC\fR value given to the "bpt=" option. .TP ssync [o] [pt] if \fIOFILE\fR is in "pt" mode then the SCSI SYNCHRONIZE CACHE command is sent to \fIOFILE\fR at the end of the copy. .TP strunc [o] [reg] perform a sparse copy with a ftruncate system call to extend the length of the \fIOFILE\fR if required. See the sparse flag and the section on SPARSE WRITES below. .TP sync [io] [reg,blk] causes the O_SYNC flag to be added to the open of \fIIFILE\fR and/or \fIOFILE\fR. See open(2) man page. .TP rtf_len [io] [odx] odx: with the 'read to tokens' variant, after 512 bytes of each ROD Token are written to \fIIRTF\fR an additional 8 byte (big endian) integer is written. That integer is the number of bytes the associated ROD represents. The draft standards say for standard ROD types the ROD Token holds this value. However vendor specific ROD types may be used or the vendors may choose not to comply. Either way the 'write from tokens' variant needs to know the size of the ROD it is writing from. .TP trim [io] [pt] [experimental] similar logic to the "sparse" option. However instead of skipping segments that are full of zeros a "trim" command is sent to \fIOFILE\fR. Usually set as an oflag argument but for self trim can be used as an iflag argument (e.g. "iflag=self,trim"). Depending on the usage this may require the device to support "deterministic read zero after trim". See the TRIM, UNMAP AND WRITE SAME section below. .TP trunc [o] [reg] if \fIOFILE\fR is a regular file then it is truncated prior to starting the copy. If \fISEEK\fR is not given or 0 then \fIOFILE\fR is truncated to zero length; when \fISEEK\fR is larger than zero the truncation takes place at file byte pointer \fISEEK*OBS\fR. Ignored if "oflag=append". Conflicts with "oflag=sparing". .TP unmap [io] [pt] same as the trim flag. .TP xcopy [io] [pt] invoke SCSI XCOPY(LID1) logic and send the XCOPY command to the either \fIIFILE\fR or \fIOFILE\fR depending on which flag this called. If both are given (i.e. an invocation including 'iflag=xcopy oflag=xcopy') then send the XCOPY(LID1) to \fIOFILE\fR. .SH XCOPY This section describes XCOPY(LID1) support with this utility. For ODX support (XCOPY(LID4) subset) see the ODX section. .PP A device (logical unit (LU)) that supports XCOPY operations should set the 3PC field (3PC stands for Third Party Copy) in its standard INQUIRY response. That is not checked when this utility does an xcopy operation but if it fails, that is one thing that the user may want to check. .PP If the xcopy starts and fails while underway, then 'sg_copy_results \-s' may be useful to view the copy status. It might also be used from a different process with the same I_T nexus (i.e. the same machine) to check status during an xcopy operation. .PP The \fIpad\fR and \fIcat\fR flags control the handling of residual data. As the data can be specified either in terms of source or target block size and both might have different block sizes residual data is likely to happen in these cases. If both block sizes are identical these bits have no effect as residual data will not occur. .PP If neither of these flags are set, the EXTENDED COPY command will be aborted with additional sense 'UNEXPECTED INEXACT SEGMENT'. .PP If only the \fIcat\fR flag is set the residual data will be retained and made available for subsequent segment descriptors. Residual data will be discarded for the last segment descriptor. .PP If the \fIpad\fR flag is set for the source descriptor only, any residual data for both source or destination will be discarded. .PP If the \fIpad\fR flag is set for the target descriptor only any residual source data will be handled as if the \fIcat\fR flag is set, but any residual destination data will be padded to make a whole block transfer. .PP If the \fIpad\fR flag is set for both source and target any residual source data will be discarded, and any residual destination data will be padded. .PP There is a web page discussing ddpt, XCOPY and ODX at http://sg.danny.cz/sg/ddpt_xcopy_odx.html .SH ODX This section describes ODX support (an XCOPY(LID4) subset) for this utility. ODX descriptions use the following command name abbreviations: PT for the POPULATE TOKEN command, RRTI for the READ ROD TOKEN INFORMATION command, and WUT for the WRITE USING TOKEN command. .PP A device (logical unit (LU)) that supports ODX operations is required to set the 3PC field (3PC stands for Third Party Copy) in its standard INQUIRY response and support the Third Party Copy VPD page. If this utility generates errors noting the absence of these then the device in question probably does not support ODX. .PP There a four variants of ODX supported by ddpt: .br \fBfull copy\fR : ddpt \-\-odx if=/dev/sg3 bs=512 of=/dev/sg4 .br \fBzero output blocks\fR : ddpt if=/dev/null rtype=zero bs=512 of=/dev/sg4 .br \fBread to tokens\fR : ddpt if=/dev/sg3 bs=512 skip=@gath.lst rtf=a.rt .br \fBwrite from tokens\fR : ddpt rtf=a.rt bs=512 of=/dev/sg4 seek=@scat.lst .PP The full copy will call PT and WUT commands repeatedly until the copy is complete. More precisely the full copy will make the largest single call to PT allowed by the input's Third Party Copy VPD page (and, if given, allowed by the \fIBPT\fR argument in the \fIbpt=BPT[,OBPC]\fR option). Then one or more WUT calls are made to write out from the ROD created by the PT step. The largest single WUT call is constrained by the output's Third Party Copy VPD page (and, if given, allowed by the \fIOBPC\fR argument in the \fIbpt=BPT[,OBPC]\fR option). This sequence continues until the requested copy is complete. .PP The zero output blocks variant is a special case of the full copy in which only WUT calls are made. ODX defines a special ROD Token to zero blocks. That special ROD Token has a fixed pattern (shown in SBC\-3) and does not need to be created by a PT command like normal ROD Tokens. .PP The read to tokens and the write from tokens variants are designed to be the read (input) and write (output) sides respectively of a network copy. Each can run on different machines by sending the \fIRTF\fR file from the machine doing the read to the machine doing the write. The read to tokens will make one or more PT calls and output the resulting ROD Tokens to the \fIRTF\fR file. \fIRTF\fR might be a regular file or a named pipe. .PP All four variants can have the immed flag set. Then the PT and/or WUT commands are issued with the IMMED bit set and the RRTI command is used to poll for completion. The delay between the polls is as suggested by the RRTI command (or if no suggestion is made, 500 milliseconds). Either iflag=immed, oflag=immed or both can be given but are only effective if the corresponding \fIIFILE\fR or \fIOFILE\fR sends a PT or WUT command. .PP Typically there is no need to give the \fIlist_id=LID\fR option. If this option is not given then 257 is chosen. If that is busy then 258 is tried. That continues until a usable \fILID\fR is found or 10 \fILID\fRs have been tried. In the latter case ddpt exits with status of 55 (operation in progress). If the user gives \fIlist_id=LID\fR option and \fILID\fR is busy then ddpt exits with exit status 55. .PP If the block size of the input and output are different (i.e. \fIIBS\fR is not equal to \fIOBS\fR) then one must be a multiple of the other. So an input block size of 512 bytes and an output block size of 4096 bytes (or vice versa) is acceptable. .PP The four ODX variants are distinguished as follows: if \fIOFILE\fR is a pass\-through device, if=/dev/null (or equivalent) and rtype=zero then the zero output blocks variant is selected. If both \fIIFILE\fR and \fIOFILE\fR are pass\-through devices and there is some indication of an ODX request (e.g. the \fI\-\-odx\fR option), then the full copy variant is selected. The read to tokens and the write from token variants are indicated by the absence of either a \fIof=OFILE\fR or a \fIif=IFILE\fR option, respectively, plus the presence of a \fIrtf=RTF\fR option. .PP The helper utility ddptctl contains options to issue a single PT, RRTI, WUT or COPY OPERATION ABORT command. It can also issue a series of polling RRTI commands. It can decode information in ROD Tokens (which is not as informative as it should be) and print the number of blocks and block size of a disk, plus protection information if available. See ddptctl. .PP There is a web page discussing ddpt, XCOPY and ODX at http://sg.danny.cz/sg/ddpt_xcopy_odx.html .SH SPARSE WRITES Bypassing writes of blocks full of zeros can save a lot of IO. However with regular files, bypassed writes at the end of the copy can lead to an \fIOFILE\fR which is shorter than it would have been without sparse writes. This can lead to integrity checking programs like md5sum and sha1sum generating different values. .PP This utility has two ways of handling this file length problem: writing the last block (even if it is full of zeros) or using the ftruncate system call. A third approach is to ignore the problem (i.e. leaving \fIOFILE\fR shorter). The ftruncate approach is used when "oflag=strunc" while the last block is written when "oflag=sparse". To ignore the file length issue use "oflag=sparse,sparse". Note that if \fIOFILE\fR's length is already correct or longer than required, no action is taken. .PP The support for sparse writing of regular files may depend on the OS, the file system and the settings of \fIOFILE\fR. POSIX makes few guarantees when the ftruncate system call is used to extend a file's length, as may occur when "oflag=strunc". Further, primitive file systems like VFAT may not accept sparse writes or simulate the effect by writing blocks of zeros. The latter approach will defeat any sparse writing performance gain. .SH TRIM, UNMAP AND WRITE SAME This is a new storage feature often associated with Solid State Disks (SSDs) or disk arrays with "thin provisioning". In the ATA command set (ACS\-2) the relevant command is DATA SET MANAGEMENT with the TRIM bit set. In the SCSI command set (SBC\-3) it is either the UNMAP or WRITE SAME command. Note there is no TRIM command however the term is frequently used in the technical press. .PP Trim is a way of telling a storage device that blocks are no longer needed. Keeping the pool of unwritten blocks large is important for the write performance of SSDs and the thrifty use of real storage in thin provisioned arrays. Currently file systems in recent OSes may issue trims associated with file deletes. The trim option in ddpt may be useful when a partition or a whole SSD is to be "deleted". Note that ddpt is bypassing file systems in that it only offers trim on pass\-through (pt) devices. .PP This utility issues SCSI commands to pt devices and for "trim" currently issues a SCSI WRITE SAME(16) command with the UNMAP bit set. If the pt device is a SSD with a ATA interface then recent versions of Linux will translate the SCSI WRITE SAME to the ATA DATA SET MANAGEMENT command with the TRIM bit set. The maximum size of each "trim" command sent is the size of the copy buffer (i.e. \fIIBS\fR * \fIBPT\fR bytes). And that maximum can be reduced with the \fIOBPC\fR argument of the "bpt=" option. .PP The trim can be used various ways. One way is a copy where the copy buffer (or some part of it) is checked for zeros as is done by the sparse oflag. When a zero segment is found, a trim "command" is sent to the \fIOFILE\fR. For example: .PP ddpt if=dsk.img bs=512 of=/dev/sdc oflag=pt,trim .PP The copy buffer is 64 KiB (since \fIBPT\fR and \fIOBPC\fR default to 128 when "bs=512") and it is checked for all zeros. If it is all zeros then a trim command is sent to the corresponding location of /dev/sdc which is accessed via the pt interface. If it is not all zeros then a SCSI WRITE command is sent. Another way is to trim all or part of a disk. To trim a whole disk (i.e. deleting all its data): .PP ddpt if=/dev/zero bs=512 of=/dev/sdc oflag=pt,trim .PP A third way is to "self\-trim" which is to only trim those parts of a disk that contain segments full of zeros: .PP ddpt if=/dev/sdc skip=0x2300 bs=512 iflag=pt,self,trim count=0x1234f0 .PP The "self" oflag automatically sets up the output side of the copy to send trim commands (if required) back the the same device (i.e. /dev/sdc). If this example was self\-trimming a partition then the partition would start at LBA 0x2300 and be 0x1234f0 blocks long. .PP Some random product examples: the Intel X25\-M G2 SSDs have trim with recent firmware and they do deterministic read zero after trim. The Seagate Pulsar SSD has an ATA interface which supports the deterministic reads of zero after the DATA SET MANAGEMENT command with the TRIM option. .SH DD DIFFERENCES dd defaults "if=" and "of=" to stdin and stdout respectively. This follows Unix filter conventions. However since dd and ddpt are often used to read binary data for timing purposes, having to supply "of=/dev/null" can be easily forgotten. Without it dd will typically spew binary data on the console. So ddpt has changed its defaults: the "if=\fIIFILE\fR" is now mandatory for direct copies and to read from stdin "if=\-" can be used; "of=\fIOFILE\fR" remains optional but its default changes to "/dev/null" (or "NUL" in Windows). To send output to stdout ddpt accepts "of=\-". .PP dd truncates \fIOFILE\fR unless "conv=notrunc" is given. When dd truncates, it truncates to zero length unless \fISEEK\fR is greater than zero. ddpt does not truncate \fIOFILE\fR by default. If \fIOFILE\fR exists it will be overwritten. The overwrite starts at block zero unless \fISEEK\fR or "oflag=append" is given. If \fIOFILE\fR is a regular file then "oflag=trunc" (or "conv=trunc") will truncate \fIOFILE\fR prior to the copy. .PP Numeric arguments to ddpt can be given in hexadecimal, either with a leading "0x" or "0X" or with a trailing "h". Note that dd accepts "0x123" but interprets it as "0 * 123" (i.e. zero). ddpt will also interpret "x" as multiplies unless the left operand is zero (e.g. "0x123"). So both dd and ddpt will interpret "skip=2x123" as "skip=246". .PP Terabyte size disks make it impractical to copy all the data into a buffer before writing it out. Therefore both dd and ddpt read a relatively small amount of data into a copy (or transfer) buffer then write it out to the destination, repeating this process until the \fICOUNT\fR is exhausted. .PP A major difference in ddpt is the addition of \fIBPT\fR to control the size of the copy buffer. With dd, \fIIBS\fR is the size of the copy buffer and the unit of \fISKIP\fR and \fICOUNT\fR. With ddpt, \fIIBS\fR * \fIBPT\fR is the size of the copy buffer and \fIIBS\fR is the unit of \fISKIP\fR and \fICOUNT\fR. This allows ddpt to have its \fIIBS\fR set to the logical block size of \fIIFILE\fR without unduly restricting the size of the copy buffer. And setting \fIIBS\fR (and \fIOBS\fR for \fIOFILE\fR) accurately is required when the pass\-through interface is used since with the SCSI READ and WRITE commands the logical block size is implicit. .PP The way dd handles its copy buffer (outlined in SUSv4 description of dd) is relatively complex, especially when \fIIBS\fR and \fIOBS\fR are different sizes. The restriction that ddpt places on \fIIBS\fR and \fIOBS\fR ( i.e. (((\fIIBS * BPT\fR) % \fIOBS\fR) == 0) ) means that a single copy buffer can be used since its size is a multiple of both \fIIBS\fR and \fIOBS\fR. Being able to precisely define the copy buffer size in ddpt makes sparse writing, write sparing and trim operations simpler to define and the user to control. .PP ddpt does not support dd's "cbs=" option (conversion block size). If the "cbs=" option is given to ddpt then it is ignored. .PP ddpt adds two types of disk to disk, offloaded copies: XCOPY(LID1) first introduced in SPC\-2 (standardized in 2001), and ODX which is a subset of XCOPY(LID4) first introduced in SPC\-4 draft (revision 34, 2012). .SH PROTECTION INFORMATION This section is about protection information which is typically an extra 8 bytes associated with each logical block. Those 8 byte are divided into 3 fields: logical block guard (16 bit (2 byte) CRC), logical block application tag (2 bytes) and the logical block reference tag (4 bytes). The acronym DIF is sometimes used for protection information. .PP The feature to read and/or write protection information by using the \fIprotect=RDP[,WRP]\fR option is currently experimental. It should be used with care and may not "play well" with some other features such as write sparing and sparse writing. It should be used to copy user data plus the associated protection information to or from a regular file. It could also be used for a device to device copy assuming the "pt" interface is used for both. Also only modern SCSI disks support protection information. .PP When \fIRDP\fR or \fIWRP\fR is greater than 0 then a copy with associated protection information is active. In this state \fIIBS\fR and \fIOBS\fR must be the same and equal to the logical block size of the device(s) formatted with protection information. If a SCSI disk with 512 byte logical block size has protection information then the actual number of bytes transferred for each logical block is typically 520 bytes. For such a disk \fIBS=512\fR is required even when additional protection information is being transferred. .SH MULTIPLIERS By default numeric arguments to options are assumed to be decimal. Almost all numeric arguments to options (e.g. \fICOUNT\fR in the \fIcount=COUNT\fR option) may include one of these multiplicative suffixes: c C *1; w W *2; b B *512; k K KiB *1,024; KB *1,000; m M MiB *1,048,576; MB *1,000,000 . This pattern continues for "G", "T" and "P". The latter two suffixes can only be used for 64 bit values. Some numeric arguments are limited to 32 bit values (e.g. \fIBS\fRin the \fIbs=BS\fR option). Also a suffix of the form "x" multiplies the leading number by ; however the combinations "0x" and "0X" are treated differently, see the next paragraph. These multiplicative suffixes are compatible with GNU's dd command (since 2002) which claims compliance with the SI and with IEC 60027\-2 standards. .PP Alternatively numerical values can be given in hexadecimal indicated by either a leading "0x" or "0X", or by a trailing "h" or "H". When hex numbers are given, suffix multipliers cannot be used. .PP If a numeric argument is required to fit in 32 bits and is too large then an error is reported. Usually negative numbers are not permitted but "count=-1" is a special case and means "all available"; "verbose=-1" is another special case. .SH NOTES A partial write is a write to the \fIOFILE\fR of less than \fIOBS\fR bytes. This typically occurs at the end of a copy. dd can do partial writes. ddpt does partial writes to regular files and fifos (including stdout). However ddpt ignores partial writes when \fIOFILE\fR is a block device or a pt device. When ddpt ignores a partial write, it sends a warning to the console (stderr). .PP At the end of the copy two lines are reported to the console: .br + records in .br + records out .PP The "records in" line is the number of full input blocks (each of \fIIBS\fR bytes) that have been read plus the number of partial blocks ( usually less than \fIIBS\fR bytes) that have been read. Following the lead of dd when 'iflag=coe' is active a block that cannot be read (and has zeros substituted for its output) is regarded as a partial read. The "records out" line is the number of full output blocks (each of \fIOBS\fR bytes) that have been written plus the number of partial blocks (usually less than \fIOBS\fR bytes) that have been written. .PP Block devices (e.g. /dev/sda and /dev/hda) can be given for \fIIFILE\fR. If neither 'iflag=direct' nor 'iflag=pt' is given then normal block IO involving buffering and caching is performed. If 'iflag=direct' is given then the buffering and caching is bypassed (this is applicable to both SCSI devices and ATA disks). When 'iflag=pt' is given SCSI commands are sent to the device which bypasses most of the actions performed by the block layer. The same applies for block devices given for \fIOFILE\fR. .PP .PP All informative, warning and error reports are sent to stderr so that dd's output file can be stdout and remain unpolluted. If no options are given, then no copying (nor reading) takes place and a brief message is sent to stderr inviting the user to invoke ddpt again but with '\-\-help' option to get the usage message. .PP Disk partition information can often be found with .B fdisk(8) [the "\-ul" argument is useful in this respect]. Also .B parted(8) can be used like this: 'parted /dev/sda unit s print' . .PP For pt devices this utility issues SCSI READ and WRITE (SBC) commands which are appropriate for disks and reading from CD/DVD/BD drives. Those commands are not formatted correctly for tape drives so ddpt cannot be used on tape drives via a pt device. If the largest block address of the requested transfer exceeds a 32 bit block number (i.e 0xffffffff) then a warning is issued and the pt device is accessed via SCSI READ(16) and WRITE(16) commands. .PP .B The attributes of a block device (e.g. partitions) are ignored when the .B pt flag is used. Hence the whole device is read (rather than just the second partition) by this invocation: .PP ddpt if=/dev/sdb2 iflag=pt of=t bs=512 .PP Assuming /dev/sdb and /dev/sg2 refer to the same device, then after the following two invocations, the contents of the files "t", "tt" and "ttt" should be same: .PP ddpt if=/dev/sdb of=tt bs=512 .PP ddpt if=/dev/sg2 of=ttt bs=512 .PP The SCSI READ(32) and WRITE(32) commands are restricted to media that is formatted with protection type 2. This is a T10 restriction. .SH SIGNALS The signal handling has been borrowed from GNU's dd: SIGINT, SIGQUIT and SIGPIPE report the number of remaining blocks to be transferred and the records in + out counts; then they have their default action. SIGUSR1 (or SIGINFO) causes the same information to be output and the copy continues. All output caused by signals is sent to stderr. .PP Like GNU's dd, ddpt respects the signal disposition of "ignored" (SIG_IGN) set by the shell, script or other program that invokes ddpt. So in that case it will ignore such signals. Further dd ignores SIGUSR1 if the environment variable POSIXLY_CORRECT is set because POSIX defines dd will only act on SIGINFO (and Linux has no such signal); ddpt ignores the POSIXLY_CORRECT environment variable. As recommended by Susv3, ddpt does not expect the signal (blocking) mask to be blocking SIGUSR1 (SIGINFO), SIGINT or SIGPIPE on entry. .PP Unix system calls that do IO can be interrupted by signal processing, typically returning an EINTR error number. The dd utility (and many other Unix utilities) restart the IO operation that was interrupted. While this will work most of the time for disk IO it is problematic for tape drives because the implicit position pointer on the tape may have moved. So the default (i.e. "intio=0") in this utility is to mask those signals during IO operations and only check them prior to starting an IO operation. Most low level IO (e.g. using SCSI command to write to a disk) will timeout if there is a low level error. However NFS (the Network File System) will potentially wait for a long time (e.g. expecting a network problem will soon be fixed) and in this case using "intio=1" may be best. .SH TAPE There is support for copies to and from tape drives in Linux. Only the st driver device names can be used (e.g. /dev/st0 and /dev/nst2). Hence use of Linux pass\-through device names (e.g. /dev/sg2) for tape drives is not supported. On Debian\-based distributions, it is suggested that the mt\-st package is installed as it provides a more fully\-featured version of the "mt" tape control program. .PP Tape drives can operate in fixed\- or variable\-length block modes. In variable\-block mode, each write to the tape writes a single block of that size. In fixed\-block mode, each write to the tape must be a multiple of the previously\-selected block size. .PP The block size/mode can be set with the mt command prior to invoking ddpt. For example: .br # mt \-f /dev/nst0 setblk 0 .br sets variable\-block mode, and .br # mt \-f /dev/nst0 setblk 32768 .br sets fixed\-block mode with block size 32768 bytes. .PP Note that some tape drives support only fixed\-block mode, and possibly even only one block size. (For example, QIC\-150 tapes use a fixed block size of 512 bytes.) There may also be restrictions on the block size, e.g. it may have to be even. .PP When using ddpt to write to tape, if the final read from the input is less than \fIOBS\fR, it is padded to \fIOBS\fR bytes before writing to tape to ensure that all blocks of the tape file are the same length. Having a shorter final block would fail if the drive is in fixed\-block mode, and could create interchange problems. It is common to expect all blocks in a file on tape to be the same length. However, to tell ddpt to not pad the final block, use 'oflag=nopad'. .PP The st tape driver normally writes a filemark when the file (e.g. /dev/nst0) is closed. To not have the filemark written, use 'oflag=nofm'. One use case for that might be if using ddpt several times in succession to append more data to the same file on tape. In that case it is probably desirable to write the filemark at the end of the sequence. So either omit 'oflag=nofm' on the last ddpt invocation, or manually write a filemark using mt after ddpt exits: .br # mt \-f /dev/nst0 weof 1 .PP For reading from an unknown tape where the block size(s) is not known, read in variable\-block mode specifying a large \fIIBS\fR. The st driver returns a smaller amount of data if the size of the block read is smaller. Thus a command like: .br # ddpt if=/dev/nst0 of=output.bin bs=262144 .br should read the file from tape regardless of the block size used (assuming no blocks are larger than 256KB). ddpt's verbose option will display what the actual block size(s) is. .SH ENVIRONMENT VARIABLES If the command line invocation of an xcopy does not explicitly (and unambiguously) indicate whether the XCOPY SCSI command should be sent to \fIIFILE\fR (i.e. the source) or \fIOFILE\fR (i.e. the destination) then a check is made for the presence of the XCOPY_TO_SRC and XCOPY_TO_DST environment variables. If either one exists (but not both) then it indicates where the SCSI XCOPY command will be sent. By default the XCOPY command is sent to \fIOFILE\fR. .PP The ODX write from tokens variant is very complex to implement if the amount of data held in each ROD is not known. The value should be found in the "number of bytes represented" field in the ROD Token but that is not well supported yet by vendors. So for such case that number can be appended as a big endian 8 byte integer following each ROD Token in the \fIRTF\fR file. The \fIconv=rtf_len\fR will cause that length to be appended. Specifying that option on each read to tokens and write from tokens invocation can be a nuisance. Setting the environment variable ODX_RTF_LEN will cause this utility to act as if the \fIconv=rtf_len\fR option has been given. .SH EXIT STATUS To aid scripts that call ddpt, the exit status is set to indicate success (0) or failure (1 or more). Note that some of the lower values correspond to the SCSI sense key values. The exit status values are: .TP .B 0 success .TP .B 1 syntax error. Either illegal command line options, options with bad arguments or a combination of options that is not permitted. .TP .B 2 the device reports that it is not ready for the operation requested. The device may be in the process of becoming ready (e.g. spinning up but not at speed) so the utility may work after a wait. .TP .B 3 the device reports a medium or hardware error (or a blank check). For example an attempt to read a corrupted block on a disk will yield this value. .TP .B 5 the device reports an "illegal request" with an additional sense code other than "invalid operation code". This is often a supported command with a field set requesting an unsupported capability. .TP .B 6 the device reports a "unit attention" condition. This usually indicates that something unrelated to the requested command has occurred (e.g. a device reset) potentially before the current SCSI command was sent. The requested command has not been executed by the device. Note that unit attention conditions are usually only reported once by a device. .TP .B 9 the device reports an illegal request with an additional sense code of "invalid operation code" which means that it doesn't support the requested command. .TP .B 11 the device reports an aborted command. In some cases aborted commands can be retried immediately (e.g. if the transport aborted the command due to congestion). .TP .B 15 the utility is unable to open, close or use the given \fIIFILE\fR or \fIOFILE\fR. The given file name could be incorrect or there may be permission problems. Adding the \fI\-v\fR option may give more information. .TP .B 20 the device reports it has a check condition but "no sense". It is unlikely that this value will occur as an exit status. .TP .B 21 the device reports a "recovered error". The requested command was successful. Most likely a utility will report a recovered error to stderr and continue, probably leaving the utility with an exit status of 0 . .TP .B 33 the command sent to device has timed out. This occurs in Linux only; in other ports a command timeout will appear as a transport (or OS) error. .TP .B 51 a command received 'illegal field in parameter list'. This may occur with an odx copy if some combination of parameters is illegal or not supported (e.g. iflag=immed) .TP .B 55 a command received 'operation in progress'. This may occur with an odx copy when the given \fILID\fR is already being used by another process (e.g. also using odx) on the same machine. Choose another \fILID\fR. .TP .B 70 a command received 'invalid token operation, cause not reportable'. This may occur with an odx operation when the given ROD Token is invalid. One reason for that may be the inactivity timeout has been reached and the copy manager has cancelled the ROD Token. .TP .B 71-89 these status values provide more information than exit status 70. See SPC\-4 ASC and ASCQ assignments (currently in Annex F.2), specifically the entries for asc=23h . For example exit status 72 corresponds to asc=23h, ascq=2h which implies the odx copy manager does not support copies between LUs in different targets. That is optional; an odx copy manager is required to support copies between LUs (that are block devices) in the same target. .TP .B 90 the flock flag has been given on a device and some other process holds the advisory exclusive lock. .TP .B 97 the response to a SCSI command failed sanity checks. .TP .B 98 the device reports it has a check condition but the error doesn't fit into any of the above categories. .TP .B 99 any errors that can't be categorized into values 1 to 98 may yield this value. This includes transport and operating system errors after the command has been sent to the device. .SH EXAMPLES The examples in this page use Linux device names. For suitable device names in other supported Operating Systems see this web page: http://sg.danny.cz/sg/device_name.html . The sg3_utils(8) man page in the sg3_utils package also covers device naming. .PP ddpt usage looks quite similar to dd: .PP ddpt if=/dev/sg0 of=t bs=512 count=1MB .PP This will copy 1 million 512 byte blocks from the device associated with /dev/sg0 (which should have 512 byte blocks) to a file called t. Assuming /dev/sda and /dev/sg0 are the same device then the above is equivalent to: .PP dd if=/dev/sda iflag=direct of=t bs=512 count=1000000 .PP although dd's speed may improve if bs was larger and count was suitably reduced. The use of the 'iflag=direct' option bypasses the buffering and caching that is usually done on a block device. .PP The dd command's bs argument can be thought of as roughly equivalent to ddpt's bs*bpt . dd almost assumes buffering on a block device and will work as long as bs is a multiple of the actual logical block size. Since ddpt can work at a lower level in some cases the bs argument must be a disk's actual logical block size. Thus the bpt argument was introduced to make the copy more efficient. So these two invocations are roughly equivalent: .PP dd if=/dev/sda of=t bs=8k count=64 .br ddpt if=/dev/sda of=t bs=512 bpt=16 count=1k .PP In both cases the total number of bytes moved is bs*count . And that will be done by reading 8k (8192 bytes) into a buffer then writing out that buffer to the file t. The read write sequence continues until the count is complete or an error occurs. .PP The 'of2=' option can save time when the input would otherwise need to be read twice. For example, to copy data and take a md5sum of it without needing to re\-read the data: .PP mkfifo fif .br md5sum fif & .br ddpt if=/dev/sg3 iflag=coe of=sg3.img oflag=sparse of2=fif bs=512 .PP This will image /dev/sg3 (e.g. an unmounted disk) and place the contents in the (sparse) file sg3.img . Without re\-reading the data it will also perform a md5sum calculation on the image. .PP Now we use sparse writing logic to get some idea of how many blocks on a disk are full of zeros. After a SCSI FORMAT UNIT command or an ATA SECURITY ERASE command a disk may be all zeros. .PP ddpt if=/dev/sdc bs=512 oflag=sparse .PP Since no "of=" option is given, output goes to /dev/null so nothing is actually written so the "records out" will be zero. However there will be a count of "records in" and "bypassed records out". If /dev/sdc is full of zeros then "records in" and "bypassed records out" will be the same. Since the "bpt=" option is not given it defaults to "bpt=128,128" so the copy buffer will be 64 KiB and the sparse check for zeros will be done with 64 KiB (128 block) granularity. .PP For examples of the trim and self,trim options see the section above on TRIM, UNMAP AND WRITE SAME. .PP Following is an example run on a Windows OS using the '\-\-wscan' option which shows the available device names (e.g. PD1) and the associated volume name(s): .PP ddpt \-w .br PD0 [C] FUJITSU MHY2160BH 0000 .br PD1 [DF] WD 2500BEV External 1.05 WD\-WXE90 .br CDROM0 [E] MATSHITA DVD/CDRW UJDA775 CB03 .PP So, for example, volumes D: and F: reside on PhysicalDisk1 (abbreviated to "PD1") which is manufactured by WD (Western Digital). .PP Further examples can be found on this web page: http://sg.danny.cz/sg/ddpt.html . There is a text file containing examples called ddpt_examples.txt in the "doc" directory of this package's distribution tarball. .SH AUTHORS Written by Doug Gilbert .SH "REPORTING BUGS" Report bugs to . .SH COPYRIGHT Copyright \(co 2008\-2014 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. .SH "SEE ALSO" This utility has a companion/helper utility called .B ddptctl(8) .br There is a web page discussing ddpt at http://sg.danny.cz/sg/ddpt.html .PP The lmbench package contains .B lmdd which is also interesting. For moving data to and from tapes see .B dt which is found at http://www.scsifaq.org/RMiller_Tools/index.html .PP To change mode parameters that effect a SCSI device's caching and error recovery see .B sdparm(sdparm) .PP To verify the data on the media or to verify it against some other copy of the data see .B sg_verify(sg3_utils) .PP To scan and repair disk partitions see TestDisk (testdisk). .PP Additional references: .B dd(1), open(2), flock(2), sg_xcopy,sg_copy_results, .B sg_dd(sg3_utils) ddpt-0.94/doc/Makefile.am0000644000175000017500000000003612302272606014175 0ustar douggdougg man_MANS = ddpt.8 ddptctl.8 ddpt-0.94/doc/Makefile.in0000644000175000017500000003371512302272606014220 0ustar douggdougg# Makefile.in generated by automake 1.13.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man8dir = $(mandir)/man8 am__installdirs = "$(DESTDIR)$(man8dir)" NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SGUTILS_LIBS = @SGUTILS_LIBS@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ os_deps = @os_deps@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ rt_libs = @rt_libs@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man_MANS = ddpt.8 ddptctl.8 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: for dir in "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am uninstall-man \ uninstall-man8 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ddpt-0.94/doc/ddptctl.80000644000175000017500000003657612320426132013705 0ustar douggdougg.TH DDPTCTL "8" "April 2014" "ddpt\-0.94" DDPT .SH NAME ddptctl \- helper/auxiliary utility for ddpt .SH SYNOPSIS .B ddptctl [\fI\-\-abort\fR] [\fI\-\-all_toks\fR] [\fI\-\-block\fR] [\fI\-\-del_tkn\fR] [\fI\-\-help\fR] [\fI\-\-immed\fR] [\fI\-\-info\fR] [\fI\-\-list_id=LID\fR] [\fI\-\-oir=OIR\fR] [\fI\-\-poll\fR] [\fI\-\-pt=GL\fR] [\fI\-\-receive\fR] [\fI\-\-rtf=RTF\fR] [\fI\-\-rtype=RTYPE\fR] [\fI\-\-size\fR] [\fI\-\-timeout=ITO[,CMD]\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-wut=SL\fR] [\fIDEVICE\fR] .SH DESCRIPTION .\" Add any additional description here .PP This utility is a helper/auxiliary for the ddpt utility which copies data between or within SCSI devices (logical units). While ddpt's command line syntax is modelled on that of the POSIX dd command, this utility has a more standard Unix command line syntax with both short and long variants of each option. .PP The T10 committee defines a family of SCSI commands for offloaded copy. The central (but not the only) command is EXTENDED COPY often shortened to XCOPY or xcopy. There are now two generations of xcopy, the older one is given the suffix "LID1" and the newer one: "LID4". There is a subset of XCOPY(LID4) that supports disk to disk copies and is based on the SBC\-3 commands: POPULATE TOKEN (PT) and WRITE USING TOKEN (WUT). ODX is a market name that has become associated with this subset. This utility can issue PT, WUT and related commands, read the Third Party Copy VPD page and perform several other housekeeping tasks. .PP The xcopy family of commands are described in the SPC\-4 and SBC\-3 documents found at http://www.t10.org . .SH OPTIONS Arguments to long options are mandatory for short options as well. .TP \fB\-A\fR, \fB\-\-abort\fR this option will issue the COPY OPERATION ABORT command with the \fILID\fR given in the \fI\-\-list_id=LID\fR option. If the \fI\-\-list_id=LID\fR option is not given then its default \fILID\fR (257) is used. If there is an xcopy operation ongoing on this I\-T nexus (i.e. issued by this machine to any LU sharing the same target) using that \fILID\fR then the copy is aborted. Note there is a sense key (COPY ABORTED) indicating some but not all data has been copied due to this action. .TP \fB\-a\fR, \fB\-\-all_toks\fR send the REPORT ALL ROD TOKENS SCSI command to \fIDEVICE\fR and decode the response. An ODX implementation is not required to support this command. .TP \fB\-B\fR, \fB\-\-block\fR treat \fIDEVICE\fR as a block device when checking its \fI\-\-size\fR. The default action of this utility is to treat \fIDEVICE\fR as a SCSI pass\-through device. .TP \fB\-D\fR, \fB\-\-del_tkn\fR set the DEL_TKN bit in a WUT command (default: clear the DEL_TKN bit). Since an ODX copy manager deletes the ROD Token after is has been fully copied from (once), this option is typically not needed. It may be useful for long\-lived ROD Tokens that have only been partially written from (or not used at all) and are no longer needed. .br To delete an unused ROD Token a degenerate scatter list seems to be acceptable (e.g. '\-\-wut=0,0 \-\-del_tkn'). .TP \fB\-h\fR, \fB\-\-help\fR outputs the usage message summarizing command line options then exits. .TP \fB\-I\fR, \fB\-\-immed\fR set the IMMED bit in the PT or WUT command. When given the PT and WUT commands return promptly before the data transfer is complete; then this utility exits. The user should then invoke the utility again with the \fI\-\-poll\fR option and the same \fILID\fR and \fIDEVICE\fR to await completion and receive the final transfer count. The default action of PT and WUT (i.e. without this option) is to wait for completion (i.e. all data transferred or an error occurs) before exiting this utility. .TP \fB\-i\fR, \fB\-\-info\fR when the \fIDEVICE\fR argument is given then check its Third Party Copy VPD page and print out anything found. Also check if the 3PC bit is set in the standard INQUIRY response. .br If the \fIDEVICE\fR argument is not given and the \fI\-\-rtf=RTF\fR option is given then decode part of the ROD Token held in the \fI\-\-RTF\fR file. SPC\-4 defines some parts of a ROD Token that can be decoded but does not require the copy manager to set these fields; so many fields may appear as zeros. A \fI\-\-RTF\fR file that has been generated by the ddpt utility may contain multiple ROD Tokens, each optionally followed by an 8 byte "number of bytes represented" integer. They are all decoded, based on \fI\-\-RTF\fR file length which should either be a multiple of 512 or 520 bytes. .TP \fB\-l\fR, \fB\-\-list_id\fR=\fILID\fR \fILID\fR is a list identifier which is used to associate an originating xcopy command (e.g. PT or WUT) with a follow\-up command that retrieves information or aborts the operation. T10 requires active \fILID\fRs to be unique on a given I\-T nexus. An I\-T nexus is the current machine (more precisely a HBA if a machine has two or more) and a specific target which will contain one or more logical units (LUs) of which \fIDEVICE\fR is one. If the \fIDEVICE\fR's copy manager feels that rather complex condition has not been met then an error is generated with sense data that decodes to "operation in progress". Rather than try to work out who is doing what elsewhere, try another \fILID\fR value. .br The default value for \fILID\fR is 257. .TP \fB\-O\fR, \fB\-\-oir\fR=\fIOIR\fR \fIOIR\fR is the Offset In ROD, a field in the WUT command. It may be be used together with the \fI\-\-wut=SL\fR option. Its default value is 0 and its units are the logical block size of \fIDEVICE\fR. .TP \fB\-p\fR, \fB\-\-poll\fR send RECEIVE ROD TOKEN INFORMATION SCSI commands (RRTIs) to the \fIDEVICE\fR using the \fILID\fR (i.e. from the \fI\-\-list_id=LID\fR option). If a copy status is received indicating the operation is ongoing, then this SCSI command is sent periodically (as suggested by the previous RRTI command or 500 milliseconds) until some other copy status is detected. If the \fI\-\-list_id=LID\fR option is not given then a \fILID\fR of 257 is assumed. .br If the originating xcopy command was POPULATE TOKEN and the RRTI command indicates that it has completed successfully then the associated ROD Token (returned in the RRTI response) is written to the \fIRTF\fR file. If the \fI\-\-rtf=RTF\fR option is not given then the ROD token is written to a file called ddptctl_rod_tok.bin in the current directory. .TP \fB\-P\fR, \fB\-\-pt\fR=\fIGL\fR send a POPULATE TOKEN (PT) command with the given gather list. The format of \fIGL\fR is given in the NOTES section. If used without the \fI\-\-immed\fR option then this utility, after the PT command finishes successfully, will call the RRTI command. When the RRTI command finishes, potentially with a new ROD Token, this utility will exit. Prior to that exit, if a new ROD Token is available and the \fI\-\-rtf=RTF\fR option is given then that ROD Token is written to the \fIRTF\fR file. If the \fI\-\-rtf=RTF\fR option is not given then the ROD token is written to a file called ddptctl_rod_tok.bin in the current directory. .br If the \fI\-\-immed\fR option is given this utility will exit after the PT command finishes. To complete the operation this utility should be invoked again with the \fI\-\-poll\fR option and the same \fIDEVICE\fR. .TP \fB\-R\fR, \fB\-\-receive\fR send the RECEIVE ROD TOKEN INFORMATION SCSI command (RRTI) to the \fIDEVICE\fR using the \fILID\fR (i.e. from the \fI\-\-list_id=LID\fR option). If the \fI\-\-list_id=LID\fR option is not given then a \fILID\fR of 257 is assumed. .br If the originating xcopy command was POPULATE TOKEN and the RRTI command indicates that it has completed successfully then the associated ROD Token (returned in the RRTI response) is written to the \fIRTF\fR file. If the \fI\-\-rtf=RTF\fR option is not given then the ROD token is written to a file called ddptctl_rod_tok.bin in the current directory. .TP \fB\-r\fR, \fB\-\-rtf\fR=\fIRTF\fR when \fIRTF\fR is a file containing an ODX ROD Token or the name of a file the ROD Token is to be written to. A ROD Token used by ODX is 512 bytes long. If the \fIRTF\fR file was produced by the ddpt utility then it might contain multiple ROD Tokens, each optionally followed by an 8 byte integer containing the "number of bytes represented" by the preceding ROD Token. .br If an \fIRTF\fR file with multiple ROD Tokens is given to this utility with \fI\-\-wut=SL\fR then only the first ROD Token is used. If an \fIRTF\fR file is being decoded (i.e. no \fIDEVICE\fR argument given) then all ROD Tokens are decoded. .TP \fB\-t\fR, \fB\-\-rtype\fR=\fIRTYPE\fR where \fIRTYPE\fR is the ROD Type, a field in the PT command (apart from "zero"). The default value (0) indicates that the copy manager (in the \fIDEVICE\fR) decides. \fIRTYPE\fR can be a decimal number, a hex number (prefixed by 0x or with a "h" appended) or one of "pit\-def", "pit\-vuln", "pit\-pers", "pit\-any" or "zero". The final truncated word can be spelt out (e.g. "pit\-vulnerable"). The "pit\-" lead\-in stands for "point in time" copy. .br The "zero" is a special case and is not given to a PT command. Instead it causes a special Block Device Zero Token to be created that can be used with the \fI\-\-wut=SL\fR option to write blocks of zeros to the given \fIDEVICE\fR. .TP \fB\-s\fR, \fB\-\-size\fR prints the number of blocks and the size of each block for the given \fIDEVICE\fR. Protection information is printed if available. By default uses the pass\-through interface and the READ CAPACITY command to obtain this information. If the \fI\-\-block\fR option is given then the block layer in the OS is query for size information (and protection information is not reported). .TP \fB\-T\fR, \fB\-\-timeout\fR=\fIITO[,CMD]\fR where \fIITO\fR is the inactivity timeout (units: seconds) given to the PT command. The default is 0 in which case the copy manager uses its own default which is shown in the Third party Copy VPD page. .br \fICMD\fR is the SCSI command timeout (units: seconds) applied to SCSI commands issued by this utility; default is 0 which is translated to 600 seconds for originating xcopy commands (e.g. PT and WUT) and 60 seconds for other commands. Best not to trigger command timeouts. .TP \fB\-v\fR, \fB\-\-verbose\fR increase the level of verbosity, (i.e. debug output). .TP \fB\-V\fR, \fB\-\-version\fR print the version string and then exit. .TP \fB\-w\fR, \fB\-\-wut\fR=\fISL\fR send a WRITE USING TOKEN (WUT) command with the given scatter list. The format of \fISL\fR is given in the NOTES section. This option requires the \fI\-\-rtf=RTF\fR option to supply the ROD Token. If used without the \fI\-\-immed\fR option then after the WUT command finishes successfully this utility will call the RRTI command. When the RRTI command finishes this utility will exit. .br If the \fI\-\-immed\fR option is given this utility will exit after the WUT command finishes. To complete the operation this utility should be invoked again with the \fI\-\-poll\fR option and the same \fIDEVICE\fR. .SH NOTES The scatter gather list given to the \fI\-\-pt=GL\fR and \fI\-\-wut=SL\fR options in the simplest case contains a pair a numbers, separated by a comma. The first number is the starting LBA and the second number is the number of blocks (no bigger than 32 bits) to read to or write from that starting LBA. Another pair of numbers can appear after that forming the second element of a scatter gather list. Starting LBAs can be in any order but T10 prohibits any logical block appearing more than once in a scatter gather list. .PP Scatter gather lists can be placed in a file or read from stdin. A file name referring to a file containing a scatter gather list must follow the "@" character (e.g. \-\-pt=@my_sgl.txt"). Reading a list from stdin is indicated by "@\-" or "\-" (e.g. "\-\-pt=\-"). Scatter gather lists in a file have a looser format and can take spaces and tabs as well as a comma as separators. Anything from and including a "#" on a line is ignored. .PP Both the PT and WUT commands are issued "as is" without checking the Third Party Copy VPD page. The copy manager may well reject these commands (with exit status 51: invalid field in parameter list) if the maximum range descriptors field or the maximum token transfer size field are exceeded. .PP There is a web page discussing ddptctl and ddpt, XCOPY and ODX at http://sg.danny.cz/sg/ddpt_xcopy_odx.html .SH EXIT STATUS The exit status of ddptctl is 0 when it is successful. Otherwise the exit status for this utility is the same as that for ddpt. See the EXIT STATUS section in the ddpt man page. .SH EXAMPLES First issue a PT command without the \fI\-\-immed\fR option so RRTI is called to complete the operation: .PP # ddptctl \-\-pt=0x0,10k,20k,5k \-\-rtf=aa.rt /dev/sdb .br PT completes with a transfer count of 15360 [0x3c00] .PP The transfer count (10k + 5k == 15360) indicates the operation was successful and the ROD Token is in the aa.rt file. Now use that ROD Token to write to the same locations on /dev/sdc: .PP # ddptctl \-\-rtf=aa.rt \-\-wut=0x0,10k,20k,5k /dev/sdc .br WUT completes with a transfer count of 15360 [0x3c00] .PP So the copy was successful. Now taking a closer look at the ROD token: .PP # ddptctl \-\-info --rtf=aa.rt .br Decoding information from ROD Token: .br ROD type: point in time copy - default [0x800000] .br Copy manager ROD Token identifier: 0x520000710000000c .br Creator Logical Unit descriptor: .br Peripheral Device type: 0x0 .br Relative initiator port identifier: 0x0 .br designator_type: NAA, code_set: Binary .br associated with the addressed logical unit .br 0x60002ac0000000000000000c00009502 .br Number of bytes represented: 0 [0x0] .br Device type specific data (for disk) has block size of 0; unlikely so skip .br Target device descriptor: unexpected designator type [0x0] .PP T10 does not require implementations to supply much of the above (only the ROD type and the token length) so expect to see some empty fields. .PP To see information about /dev/sdb relevant to ODX, try: .PP # ddptctl --info /dev/sdb .br /dev/sdb [readcap]: num_blks=209715200 [0xc800000], blk_size=512, 107 GB .br 3PC (third party copy) bit set in standard INQUIRY response .br Third Party Copy VPD page: .br Block Device ROD Token Limits: .br Maximum Range Descriptors: 8 .br Maximum Inactivity Timeout: 60 seconds .br Default Inactivity Timeout: 30 seconds .br Maximum Token Transfer Size: 524288 .br Optimal Transfer Count: 524288 .PP That maximum token transfer size [524288 blocks each 512 bytes gives 256 MB] is the largest size a ROD Token created by /dev/sdb can hold. Use that and show the \fI\-\-immed\fR option on the destination: .PP # ddptctl --pt=0x0,0x80000 --rtf=aa.rt /dev/sdb .br PT completes with a transfer count of 524288 [0x80000] .PP # ddptctl --rtf=aa.rt --wut=0x0,0x80000 --immed /dev/sdc .br Started ODX Write Using Token command in immediate mode. .br User may need --list_id=257 on following invocation with --receive or .br --poll for completion .PP # ddptctl --poll --rtf=aa.rt /dev/sdc .br RRTI for Write using token: Operation completed without errors .br transfer count of 524288 [0x80000] .PP To copy larger amounts and/or with a larger number of scatter gather elements (than 8 "range descriptors") use one of the four ODX variants in the ddpt utility. .SH AUTHORS Written by Douglas Gilbert. .SH "REPORTING BUGS" Report bugs to . .SH COPYRIGHT Copyright \(co 2014 Douglas Gilbert .br This software is distributed under a FreeBSD license. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. .SH "SEE ALSO" .B ddpt ddpt-0.94/doc/ddpt_examples.txt0000644000175000017500000003241612320426132015535 0ustar douggdougg# ddpt examples # ============= # Lines that start with "#", like this one, are comments. # Lines that start with "$" are commands entered by the user. Some # long commands are split over several lines with a trailing "\" # on all but the last line of the command. # Other non-blank lines are command output. Command output is shown # in only some cases. # dd "standard" regular file to regular file copy. 'stat -c %s ' # is a way of getting a file's length, in bytes. $ stat -c %s src 6915 $ dd if=src of=dst 13+1 records in 13+1 records out 6915 bytes (6.9 kB) copied, 0.000128857 s, 53.7 MB/s # Now lets look at the ddpt equivalent. So we try the same options but # the dst2 file exists and it is relatively large. $ stat -c %s dst2 524800 $ ddpt if=src of=dst2 Assume block size of 512 bytes for both input and output 13+1 records in 13+1 records out time to transfer data: 0.000121 secs at 59.24 MB/sec $ stat -c %s dst 524800 # ddpt does not truncate dst2, it overwrites it. So if dst2's file length # is longer than src's file length then the output file needs to be # truncated: $ ddpt if=src of=dst2 oflag=trunc Assume block size of 512 bytes for both input and output 13+1 records in 13+1 records out time to transfer data: 0.000243 secs at 29.50 MB/sec $ stat -c %s dst2 6915 # So now src is the same length as dst and dst2. And they all contain the # same data. The ddpt benefit of not truncating the output file by default # is with write sparing and the resume capability. # Sometimes it may be useful to preserve permissions and timestamps # of the src file. After the copy (by ddpt or dd) call these: $ chmod --reference=src dst2 $ touch --reference=src dst2 # and to preserve the src's ACL (Access Control List): $ getfacl src | setfacl --set-file=- dst2 # Both dd and ddpt default to a block size of 512 bytes (bs=512) as they # are designed to move disk data which up until recent times typically # had a block size of 512 bytes. However for copying regular (normal) # files bs=1 would be a clearer choice. dd is relatively inefficient when # bs=1 but ddpt should be faster. So we can do this: $ ddpt if=src bs=1 of=dst2 oflag=trunc 6915+0 records in 6915+0 records out time to transfer data: 0.000134 secs at 51.60 MB/sec # Notice that "records in" and "records out" are byte counts since "bs=1" # if the src file is large then $ dd if=src of=dst # can be quite inefficient because dd reads BS (argument to "bs=") or # IBS bytes at a time, then writes them to dst and continues until # all of src has been read (or the COUNT is exhausted). So something # like this is often suggested: $ dd if=src of=dst bs=64k # ddpt reads BPT*IBS bytes at a time from src before writing them to # dst2. The default value of BPT varies depending on IBS; for IBS=512 # BPT defaults to 128. So for 512 byte blocks ddpt reads in chunks of # 64 KB. Hence this invocation of ddpt remains quite efficient: $ ddpt if=src ibs=512 of=dst2 oflag=trunc obs=1 # The advantage of keeping the IBS value low (and specifically equal to # the logical block size for block devices) is that the SKIP and COUNT # arguments are in units of IBS bytes: $ ddpt if=/dev/sda skip=0x4215cc bs=512 of=dst2.img count=1234560 # There is no need to worry about short reads on a block device # so giving BS sets both IBS and OBS to the same value. So now # SKIP and COUNT are in 512 byte units (so SKIP is a Logical Block # Address (LBA)). Notice that SKIP is given in hexadecimal (dd only # accepts decimal arguments). Since the "bpt=" option is not given # BPT defaults to 128 and each read into the copy buffer is # 128*512 = 64 KB. The dd equivalent: $ dd if=/dev/sda skip=4330956 bs=512 of=dst.img count=1234560 # will be slow since dd will read 512 bytes, write 512 bytes at a time. # Changing to "bs=64k" looks like it will help but now SKIP and COUNT # need to be divided by 128. However the SKIP value is not divisible by # 128. An efficient solution is not pretty. # When block sizes differ between the input and output devices, ddpt may # zero pad the last copy segment so an integral number of OBS sized blocks # are written. With this example the output (sent to stderr) is shown: $ ddpt if=/dev/sda ibs=512 of=/dev/sdc obs=4096 count=9 9+0 records in 2+0 records out time to transfer data: 0.000045 secs at 102.40 MB/sec # The COUNT implies a copy of 9*512 = 4608 bytes. That spills into the # second record (block) of /dev/sdc because its logical block size is 4096 # bytes. ddpt pads with zeros which is what the last 3542 bytes of the # second block of /dev/sdc will contain after the copy. # Sparse writes can be used to count the number of blocks that contain # all zeros. sda1 is a half full 73 GB partition (on a SSD) and we check # for zero blocks 40 GB from its start and for a length of 5 GB: $ ddpt if=/dev/sda1 skip=80m bs=512 oflag=sparse count=10m Output file not specified so no copy, just reading input 10485760+0 records in 0+0 records out 5672704 bypassed records out time to read data: 20.583461 secs at 260.83 MB/sec # Actually a copy buffer (64 KB) at a time is being checked for all # zeros so that count understates the true value. By setting OBPC to # 1, each block will be checked at a (slight) cost in execution time: $ ddpt if=/dev/sda1 skip=80m bs=512 oflag=sparse count=10m bpt=128,1 Output file not specified so no copy, just reading input 10485760+0 records in 0+0 records out 6317217 bypassed records out time to read data: 20.575803 secs at 260.92 MB/sec # Zero filled blocks are listed as "bypassed records out" (even though # nothing is actually written). When the granularity of the check for # zeros is 64 KB then 5672704 zero blocks are found. When the granularity # of the check is reduced to 512 bytes then 6317217 zero blocks are found. # As an example of write sparing, assume the regular file t exists # and tt doesn't. Lets say the length of t is 524897 bytes: $ ddpt if=t bs=512 of=tt oflag=sparing 1025+1 records in 1025+1 records out 0 bypassed records out time to transfer data: 0.001061 secs at 495.11 MB/sec # Now repeating the operation with oflag=sparing still set: $ ddpt if=t bs=512 of=tt oflag=sparing 1025+1 records in 0+0 records out 1025+1 bypassed records out time to transfer data: 0.001680 secs at 312.69 MB/sec # Since t and tt should now contain the same data write sparing # has been able to bypass all writes to tt. # # The "time to transfer" line in the output can be removed by # the addition of the status=noxfer option: $ ddpt if=t bs=512 of=tt oflag=sparing status=noxfer 1025+1 records in 0+0 records out 1025+1 bypassed records out # Imaging disks and partitions to a regular file can take a long # time. Sometimes the copy must be interrupted or there is # some failure (say power) which stops the copy. In such cases # oflag=resume may be helpful. In the case shown below a small # partition is being copied to a regular file and it is # interrupted with ^C from the keyboard: $ ddpt if=/dev/sda2 of=sda2.bin bs=512 ^CInterrupted by signal SIGINT, remaining block count=1409601 662784+0 records in 662784+0 records out time to transfer data: 5.226487 secs at 64.93 MB/sec To resume, invoke with same arguments plus oflag=resume # Taking the advice from the last line: $ ddpt if=/dev/sda2 of=sda2.bin bs=512 oflag=resume resume adjusting skip=662784, seek=662784, and count=1409601 1409601+0 records in 1409601+0 records out time to transfer data: 10.543506 secs at 68.45 MB/sec # By checking the size of sda2.bin the resume logic has adjusted # the skip, seek and count options to complete the rest of the # copy. If the copy was finished then making the same invocation # is harmless: $ ddpt if=/dev/sda2 of=sda2.bin bs=512 oflag=resume resume finds copy complete, exiting # And if sda2.bin was empty on did not exist then a full copy # would occur. # ddpt supports a trim operation on the output file when it is # accessed via the pt interface. Some SSDs support the trim # operation (also known as unmap) with "deterministic read # zero after trim". ddpt treats a trim like sparse, however # instead of bypassing a segment of zeros a trim command is sent. # In SCSI parlance trim is a WRITE SAME with the UNMAP bit set. $ ddpt if=/dev/sdb1 bs=512 of=/dev/sg1 seek=73899000 oflag=trim 18314037+0 records in 16970165+0 records out 1343872 trimmed records out time to transfer data: 174.057264 secs at 53.87 MB/sec # To trim (zero) a large portion of a SSD use /dev/zero as the # input file. This will zero from logical block 73899000 until # the end of /dev/sg1 which is a SSD: $ ddpt if=/dev/zero bs=512 of=/dev/sg1 seek=73899000 oflag=trim Progress report: remaining block count=38895160 43507456+0 records in 0+0 records out 43507328 trimmed records out time to transfer data so far: 405.905942 secs at 54.88 MB/sec continuing ... 82402488+0 records in 0+0 records out 82402488 trimmed records out time to transfer data: 768.067647 secs at 54.93 MB/sec # Notice the "Progress report:" line and the indented lines # following it. What happened here was a SIGUSR1 signal was sent # to the process running ddpt with a 'kill -s SIGUSR1 ' # command. The of a running ddpt can be found with the 'ps ax' # command. The progress report finished with "continuing ..." # line. The un-indented lines at the end of the output were # placed there at the completion of the ddpt copy. # self trim describes the technique of reading a block device # (accessed via a pt interface) and checking for segments of # zeros (64 KB of zeros in the first case). Segments full of # zeros are "trimmed". # In Linux /dev/sg* and /dev/bsg/* are pt devices. $ ddpt if=/dev/sg0 bs=512 skip=130045952 iflag=self,trim # The bpt option can be used to both increase the size of the # copy segment and reduce granularity on trim check to 1 output # block (i.e. 512 bytes at a time). This may result in a lot more # small "trim" commands being issued. $ ddpt if=/dev/sg0 bs=512 skip=130045952 iflag=self,trim bpt=1024,1 # the self flag does some option juggling and transforms the previous # invocation into: $ ddpt if=/dev/sg0 bs=512 skip=130045952 of=/dev/sg0 seek=130045952 \ oflag=trim,nowrite bpt=1024,1 # which is now a "copy" back to the same file. Nasty things happen if # SKIP and SEEK are not the same. Best to stick with the simpler # "iflag=self,trim" form and avoid the pitfalls of replicated arguments. # If some command line arithmetic is required (e.g. with the skip, seek # and/or count arguments) then the bash shell offers the "$(( ))" syntax. # It is basically integer arithmetic, probably up to 64 bits precision, # with hex number accepted (leading 0x) but without multiplier suffixes # (e.g. $((1M + 1)) is not accepted). See the "ARITHMETIC EVALUATION" # section in the bash man page. $ ddpt if=/dev/sg1 skip=$((0xfff + 1)) count=1 # xcopy is an abbreviation of the SCSI EXTENDED COPY command and facility. # There are two variants: "LID1" (List Identifier length of 1 byte) # and "LID4". xcopy is a performance win when disks (LUs) are remote or # disks have better bandwidth to a storage switch (e.g. a SAS expander) # than they do to server machines. Some xcopy implementations use the term # "remote copy". This example copies the contents of /dev/sdc to /dev/sdd $ ddpt if=/dev/sdc iflag=xcopy bs=512 of=/dev/sdd 204800+0 records in 204800+0 records out 4 xcopy commands done time to transfer data: 0.162026 secs at 647.17 MB/sec # In this case the EXTENDED COPY command is sent to /dev/sdc . To send that # command to the destination (i.e. /dev/sdd) instead then replace # "iflag=xcopy" with "oflag=xcopy". If the above fails add "verbose=1" and # ramp that up to 5 to see what is happening "in the weeds". # Logically the resulting state of the destination should be the same # whether or not the xcopy facility is used. The difference should be in the # performance, with the xcopy version being faster, possibly much faster, # with essentially no load on the machine issuing the xcopy. # A subset of xcopy(LID4) that does disk to disk, token based copies and has # the market name ODX is supported. A full disk to disk copy looks like this: $ ddpt --odx if=/dev/sg3 of=/dev/sg4 bs=512 20971520+0 records in 20971520+0 records out time to transfer data: 38.994866 secs at 275.35 MB/sec # ODX also has a facility to zero out blocks: $ ddpt rtype=zero if=/dev/null of=/dev/sg4 bs=512 20971520+0 records out time to transfer data: 25.348843 secs at 423.59 MB/sec # The ROD type of "zero" has a special, static ROD Token associated with it. # Network copies can be done by exposing a ROD Token (512 bytes long) or a # sequence of them. In the following example both mach_a and mach_b can "see" # the same storage array. One of that array's targets contains two LUs: # /dev/sg3 and /dev/sg4. In the first step, one or more RODs are populated # with 1m blocks starting at LBA 0x1234 from /dev/sg3. Those ROD Tokens are # passed back to mach_a which places them in a file called "my.tk". A # network copy ("scp") is used to copy "my.tk" to mach_b. mach_b then uses # those 1m blocks of data represented by the ROD Tokens in "my.tk" to write # to /dev/sg4, starting at LBA 0 (since no seek= option is given): mach_a $ ddpt if=/dev/sg3 bs=512 skip=0x1234,1m rtf=my.tk 1048576+0 records in time to transfer data: 0.002217 secs at 242160.99 MB/sec mach_a $ scp -p my.tk user@mach_b:/tmp mach_b $ ddpt rtf=/tmp/my.tk bs=512 of=/dev/sg4 count=1m 1048576+0 records out time to transfer data: 0.747828 secs at 717.91 MB/sec # Douglas Gilbert 20140407 ddpt-0.94/configure0000755000175000017500000052334012270047422013313 0ustar douggdougg#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for ddpt 0.94. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: dgilbert@interlog.com about your system, including any $0: error possibly output before this message. Then install $0: a modern shell, or manually run the script under such a $0: shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ddpt' PACKAGE_TARNAME='ddpt' PACKAGE_VERSION='0.94' PACKAGE_STRING='ddpt 0.94' PACKAGE_BUGREPORT='dgilbert@interlog.com' PACKAGE_URL='' ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS HAVE_SGUTILS_FALSE HAVE_SGUTILS_TRUE SGUTILS_LIBS OS_WIN32_CYGWIN_FALSE OS_WIN32_CYGWIN_TRUE OS_WIN32_MINGW_FALSE OS_WIN32_MINGW_TRUE OS_SOLARIS_FALSE OS_SOLARIS_TRUE OS_LINUX_FALSE OS_LINUX_TRUE OS_FREEBSD_FALSE OS_FREEBSD_TRUE os_libs os_deps host_os host_vendor host_cpu host build_os build_vendor build_cpu build rt_libs EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking enable_linuxbsg enable_libsgutils enable_scsistrings ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures ddpt 0.94 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/ddpt] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of ddpt 0.94:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-linuxbsg ignore linux bsg (sgv4) if present --disable-libsgutils ignore libsgutils if present --disable-scsistrings Disable full SCSI sense strings Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF ddpt configure 0.94 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by ddpt $as_me 0.94, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.13' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='ddpt' VERSION='0.94' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE ac_config_headers="$ac_config_headers config.h" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi # AC_PROG_CXX # check for headers ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in linux/types.h linux/bsg.h linux/kdev_t.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_LINUX_TYPES_H # include #endif " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in posix_fadvise do : ac_fn_c_check_func "$LINENO" "posix_fadvise" "ac_cv_func_posix_fadvise" if test "x$ac_cv_func_posix_fadvise" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSIX_FADVISE 1 _ACEOF fi done for ac_func in fsync do : ac_fn_c_check_func "$LINENO" "fsync" "ac_cv_func_fsync" if test "x$ac_cv_func_fsync" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FSYNC 1 _ACEOF fi done for ac_func in fdatasync do : ac_fn_c_check_func "$LINENO" "fdatasync" "ac_cv_func_fdatasync" if test "x$ac_cv_func_fdatasync" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FDATASYNC 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 $as_echo_n "checking for clock_gettime in -lrt... " >&6; } if ${ac_cv_lib_rt_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_clock_gettime=yes else ac_cv_lib_rt_clock_gettime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 $as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : rt_libs='-lrt' else rt_libs='' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 $as_echo_n "checking for clock_gettime in -lrt... " >&6; } if ${ac_cv_lib_rt_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_clock_gettime=yes else ac_cv_lib_rt_clock_gettime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 $as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi for ac_func in clock_gettime do : ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" if test "x$ac_cv_func_clock_gettime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CLOCK_GETTIME 1 _ACEOF fi done for ac_func in gettimeofday do : ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETTIMEOFDAY 1 _ACEOF fi done for ac_func in nanosleep do : ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep" if test "x$ac_cv_func_nanosleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NANOSLEEP 1 _ACEOF fi done for ac_func in siginterrupt do : ac_fn_c_check_func "$LINENO" "siginterrupt" "ac_cv_func_siginterrupt" if test "x$ac_cv_func_siginterrupt" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIGINTERRUPT 1 _ACEOF fi done for ac_func in fallocate do : ac_fn_c_check_func "$LINENO" "fallocate" "ac_cv_func_fallocate" if test "x$ac_cv_func_fallocate" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FALLOCATE 1 _ACEOF fi done for ac_func in posix_fallocate do : ac_fn_c_check_func "$LINENO" "posix_fallocate" "ac_cv_func_posix_fallocate" if test "x$ac_cv_func_posix_fallocate" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSIX_FALLOCATE 1 _ACEOF fi done for ac_func in posix_memalign do : ac_fn_c_check_func "$LINENO" "posix_memalign" "ac_cv_func_posix_memalign" if test "x$ac_cv_func_posix_memalign" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSIX_MEMALIGN 1 _ACEOF fi done for ac_func in sysconf do : ac_fn_c_check_func "$LINENO" "sysconf" "ac_cv_func_sysconf" if test "x$ac_cv_func_sysconf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYSCONF 1 _ACEOF fi done # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac cat >>confdefs.h <<_ACEOF #define SG_LIB_BUILD_HOST "${host}" _ACEOF case "${host}" in *-*-linux-gnu*) os_deps='sg_pt_linux.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_LINUX 1 _ACEOF os_libs='' ;; *-*-linux*) os_deps='sg_pt_linux.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_LINUX 1 _ACEOF os_libs='' ;; *-*-freebsd*|*-*-kfreebsd*-gnu*) os_deps='sg_pt_freebsd.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_FREEBSD 1 _ACEOF os_libs='-lcam' ;; *-*-solaris*) os_deps='sg_pt_solaris.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_SOLARIS 1 _ACEOF os_libs='' ;; *-*-cygwin*) os_deps='sg_pt_win32.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_WIN32 1 _ACEOF cat >>confdefs.h <<_ACEOF #define WIN32_SPT_DIRECT 1 _ACEOF os_libs='' ;; *-*-mingw*) os_deps='sg_pt_win32.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_WIN32 1 _ACEOF cat >>confdefs.h <<_ACEOF #define WIN32_SPT_DIRECT 1 _ACEOF cat >>confdefs.h <<_ACEOF #define SG_LIB_MINGW 1 _ACEOF os_libs='' ;; *) os_deps='sg_pt_linux.o' cat >>confdefs.h <<_ACEOF #define SG_LIB_LINUX 1 _ACEOF os_libs='' ;; esac # Define platform-specific symbol. if echo $host_os | grep 'freebsd' > /dev/null; then OS_FREEBSD_TRUE= OS_FREEBSD_FALSE='#' else OS_FREEBSD_TRUE='#' OS_FREEBSD_FALSE= fi if echo $host_os | grep '^linux' > /dev/null; then OS_LINUX_TRUE= OS_LINUX_FALSE='#' else OS_LINUX_TRUE='#' OS_LINUX_FALSE= fi if echo $host_os | grep '^solaris' > /dev/null; then OS_SOLARIS_TRUE= OS_SOLARIS_FALSE='#' else OS_SOLARIS_TRUE='#' OS_SOLARIS_FALSE= fi if echo $host_os | grep '^mingw' > /dev/null; then OS_WIN32_MINGW_TRUE= OS_WIN32_MINGW_FALSE='#' else OS_WIN32_MINGW_TRUE='#' OS_WIN32_MINGW_FALSE= fi if echo $host_os | grep '^cygwin' > /dev/null; then OS_WIN32_CYGWIN_TRUE= OS_WIN32_CYGWIN_FALSE='#' else OS_WIN32_CYGWIN_TRUE='#' OS_WIN32_CYGWIN_FALSE= fi # Check whether --enable-linuxbsg was given. if test "${enable_linuxbsg+set}" = set; then : enableval=$enable_linuxbsg; cat >>confdefs.h <<_ACEOF #define IGNORE_LINUX_BSG 1 _ACEOF fi # Check whether --enable-libsgutils was given. if test "${enable_libsgutils+set}" = set; then : enableval=$enable_libsgutils; have_sgutils=no else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sg_ll_inquiry in -lsgutils2" >&5 $as_echo_n "checking for sg_ll_inquiry in -lsgutils2... " >&6; } if ${ac_cv_lib_sgutils2_sg_ll_inquiry+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsgutils2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sg_ll_inquiry (); int main () { return sg_ll_inquiry (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sgutils2_sg_ll_inquiry=yes else ac_cv_lib_sgutils2_sg_ll_inquiry=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sgutils2_sg_ll_inquiry" >&5 $as_echo "$ac_cv_lib_sgutils2_sg_ll_inquiry" >&6; } if test "x$ac_cv_lib_sgutils2_sg_ll_inquiry" = xyes; then : SGUTILS_LIBS="-lsgutils2"; have_sgutils=yes else have_sgutils=no fi fi if test x"$have_sgutils" = xyes; then HAVE_SGUTILS_TRUE= HAVE_SGUTILS_FALSE='#' else HAVE_SGUTILS_TRUE='#' HAVE_SGUTILS_FALSE= fi # Check whether --enable-scsistrings was given. if test "${enable_scsistrings+set}" = set; then : enableval=$enable_scsistrings; else cat >>confdefs.h <<_ACEOF #define SG_SCSI_STRINGS 1 _ACEOF fi # AC_PROG_LIBTOOL ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OS_FREEBSD_TRUE}" && test -z "${OS_FREEBSD_FALSE}"; then as_fn_error $? "conditional \"OS_FREEBSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OS_LINUX_TRUE}" && test -z "${OS_LINUX_FALSE}"; then as_fn_error $? "conditional \"OS_LINUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OS_SOLARIS_TRUE}" && test -z "${OS_SOLARIS_FALSE}"; then as_fn_error $? "conditional \"OS_SOLARIS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OS_WIN32_MINGW_TRUE}" && test -z "${OS_WIN32_MINGW_FALSE}"; then as_fn_error $? "conditional \"OS_WIN32_MINGW\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OS_WIN32_CYGWIN_TRUE}" && test -z "${OS_WIN32_CYGWIN_FALSE}"; then as_fn_error $? "conditional \"OS_WIN32_CYGWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SGUTILS_TRUE}" && test -z "${HAVE_SGUTILS_FALSE}"; then as_fn_error $? "conditional \"HAVE_SGUTILS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by ddpt $as_me 0.94, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ ddpt config.status 0.94 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ddpt-0.94/CREDITS0000644000175000017500000000147412237573203012427 0ustar douggdouggThe author of ddpt would like to thank the following people who have made contributions: Mark Knibbs defined write sparing and sparse writing. [20081212] defined granularity control for sparing+sparse; oflag=resume; lazy seeks; trim and self-trim. [20100730] implemented prealloc flag (fallocate()) [20111227] delay [20131021]; implemented much of the tape support and wrote documentation [20131105] Peter Allworth original dd clone design used by sg3_utils's dd variants (e.g. sg_dd). The sg_dd linux utility has been generalized to become this utility (ddpt). [20081212] Thomas Glanzmann help testing xcopy [20131021] Doug Gilbert 7th November 2013 ddpt-0.94/NEWS0000644000175000017500000000004511446031070012067 0ustar douggdouggSee the ChangeLog and README* files. ddpt-0.94/configure.ac0000644000175000017500000000674412270047422013676 0ustar douggdouggAC_INIT(ddpt, 0.94, dgilbert@interlog.com) AM_INIT_AUTOMAKE AM_MAINTAINER_MODE AM_CONFIG_HEADER(config.h) AC_PROG_CC # AC_PROG_CXX AC_PROG_INSTALL # check for headers AC_HEADER_STDC AC_CHECK_HEADERS([linux/types.h linux/bsg.h linux/kdev_t.h], [], [], [[#ifdef HAVE_LINUX_TYPES_H # include #endif ]]) AC_CHECK_FUNCS(posix_fadvise) AC_CHECK_FUNCS(fsync) AC_CHECK_FUNCS(fdatasync) AC_CHECK_LIB(rt, clock_gettime, AC_SUBST([rt_libs], ['-lrt']), AC_SUBST([rt_libs], [''])) AC_CHECK_LIB(rt, clock_gettime) AC_CHECK_FUNCS(clock_gettime) AC_CHECK_FUNCS(gettimeofday) AC_CHECK_FUNCS(nanosleep) AC_CHECK_FUNCS(siginterrupt) AC_CHECK_FUNCS(fallocate) AC_CHECK_FUNCS(posix_fallocate) AC_CHECK_FUNCS(posix_memalign) AC_CHECK_FUNCS(sysconf) AC_CANONICAL_HOST AC_DEFINE_UNQUOTED(SG_LIB_BUILD_HOST, "${host}", [ddpt Build Host]) case "${host}" in *-*-linux-gnu*) AC_SUBST([os_deps], ['sg_pt_linux.o']) AC_DEFINE_UNQUOTED(SG_LIB_LINUX, 1, [ddpt on linux]) AC_SUBST([os_libs], ['']) ;; *-*-linux*) AC_SUBST([os_deps], ['sg_pt_linux.o']) AC_DEFINE_UNQUOTED(SG_LIB_LINUX, 1, [ddpt on linux]) AC_SUBST([os_libs], ['']) ;; *-*-freebsd*|*-*-kfreebsd*-gnu*) AC_SUBST([os_deps], ['sg_pt_freebsd.o']) AC_DEFINE_UNQUOTED(SG_LIB_FREEBSD, 1, [ddpt on FreeBSD]) AC_SUBST([os_libs], ['-lcam']);; *-*-solaris*) AC_SUBST([os_deps], ['sg_pt_solaris.o']) AC_DEFINE_UNQUOTED(SG_LIB_SOLARIS, 1, [ddpt on Solaris]) AC_SUBST([os_libs], ['']);; *-*-cygwin*) AC_SUBST([os_deps], ['sg_pt_win32.o']) AC_DEFINE_UNQUOTED(SG_LIB_WIN32, 1, [ddpt on Win32]) AC_DEFINE_UNQUOTED(WIN32_SPT_DIRECT, 1, [allow large buffers, aligned?]) AC_SUBST([os_libs], ['']) ;; *-*-mingw*) AC_SUBST([os_deps], ['sg_pt_win32.o']) AC_DEFINE_UNQUOTED(SG_LIB_WIN32, 1, [ddpt on Win32]) AC_DEFINE_UNQUOTED(WIN32_SPT_DIRECT, 1, [allow large buffers, aligned?]) AC_DEFINE_UNQUOTED(SG_LIB_MINGW, 1, [also MinGW environment]) AC_SUBST([os_libs], ['']) ;; *) AC_SUBST([os_deps], ['sg_pt_linux.o']) AC_DEFINE_UNQUOTED(SG_LIB_LINUX, 1, [assume ddpt on linux]) AC_SUBST([os_libs], ['']) ;; esac # Define platform-specific symbol. AM_CONDITIONAL(OS_FREEBSD, [echo $host_os | grep 'freebsd' > /dev/null]) AM_CONDITIONAL(OS_LINUX, [echo $host_os | grep '^linux' > /dev/null]) AM_CONDITIONAL(OS_SOLARIS, [echo $host_os | grep '^solaris' > /dev/null]) AM_CONDITIONAL(OS_WIN32_MINGW, [echo $host_os | grep '^mingw' > /dev/null]) AM_CONDITIONAL(OS_WIN32_CYGWIN, [echo $host_os | grep '^cygwin' > /dev/null]) AC_ARG_ENABLE([linuxbsg], AC_HELP_STRING([--disable-linuxbsg], [ignore linux bsg (sgv4) if present]), [AC_DEFINE_UNQUOTED(IGNORE_LINUX_BSG, 1, [ignore linux bsg], )], []) AC_ARG_ENABLE([libsgutils], AC_HELP_STRING([--disable-libsgutils], [ignore libsgutils if present]), [have_sgutils=no], [AC_CHECK_LIB(sgutils2, sg_ll_inquiry, [SGUTILS_LIBS="-lsgutils2"; have_sgutils=yes], have_sgutils=no)]) AC_SUBST(SGUTILS_LIBS) AM_CONDITIONAL(HAVE_SGUTILS, test x"$have_sgutils" = xyes) AC_ARG_ENABLE([scsistrings], [AS_HELP_STRING([--disable-scsistrings], [Disable full SCSI sense strings])], [], [AC_DEFINE_UNQUOTED(SG_SCSI_STRINGS, 1, [full SCSI sense strings], )]) # AC_PROG_LIBTOOL AC_OUTPUT(Makefile src/Makefile doc/Makefile) ddpt-0.94/include/0000755000175000017500000000000012320426231013013 5ustar douggdouggddpt-0.94/include/sg_cmds_basic.h0000644000175000017500000003054612302271066015760 0ustar douggdougg#ifndef SG_CMDS_BASIC_H #define SG_CMDS_BASIC_H /* * Copyright (c) 2004-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* * Error, warning and verbose output is sent to the file pointed to by * sg_warnings_strm which is declared in sg_lib.h and can be set with * the sg_set_warnings_strm() function. If not given sg_warnings_strm * defaults to stderr. * If 'noisy' and 'verbose' are both zero then following functions should * not output anything to sg_warnings_strm. If 'noisy' is non-zero and * 'verbose' is zero then Unit Attention, Recovered, Medium and Hardware * errors (sense keys) send output to sg_warnings_strm. Increasing values * of 'verbose' send increasing amounts of (debug) output to * sg_warnings_strm. */ #ifdef __cplusplus extern "C" { #endif /* Invokes a SCSI INQUIRY command and yields the response * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other errors */ int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI LOG SELECT command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Log Select not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, * -1 -> other failure */ int sg_ll_log_select(int sg_fd, int pcr, int sp, int pc, int pg_code, int subpg_code, unsigned char * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI LOG SENSE command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Log Sense not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code, int subpg_code, int paramp, unsigned char * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI MODE SENSE (6) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code, int sub_pg_code, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command (SPC-3) * prevent==0 allows removal, prevent==1 prevents removal ... * Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> command not supported * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy, int verbose); /* Invokes a SCSI READ CAPACITY (10) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_UNIT_ATTENTION * -> perhaps media changed, SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI READ CAPACITY (16) command. Returns 0 -> success, * SG_LIB_CAT_UNIT_ATTENTION -> media changed??, SG_LIB_CAT_INVALID_OP * -> cdb not supported, SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_readcap_16(int sg_fd, int pmi, uint64_t llba, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI REPORT LUNS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Luns not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ int sg_ll_report_luns(int sg_fd, int select_report, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI REQUEST SENSE command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Request Sense not supported??, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI START STOP UNIT command (SBC + MMC). * Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Start stop unit not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure * SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and * format_layer_number(mmc) fields. They also overlap on the noflush(sbc) * and fl(mmc) one bit field. This is the cause of the awkardly named * pc_mod__fl_num and noflush__fl arguments to this function. */ int sg_ll_start_stop_unit(int sg_fd, int immed, int pc_mod__fl_num, int power_cond, int noflush__fl, int loej, int start, int noisy, int verbose); /* Invokes a SCSI SYNCHRONIZE CACHE (10) command. Return of 0 -> success, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_INVALID_OP -> cdb not supported, * SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group, unsigned int lba, unsigned int count, int noisy, int verbose); /* Invokes a SCSI TEST UNIT READY command. * 'pack_id' is just for diagnostics, safe to set to 0. * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other failure */ int sg_ll_test_unit_ready(int sg_fd, int pack_id, int noisy, int verbose); /* Invokes a SCSI TEST UNIT READY command. * 'pack_id' is just for diagnostics, safe to set to 0. * Looks for progress indicator if 'progress' non-NULL; * if found writes value [0..65535] else write -1. * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> * device not ready, -1 -> other failure */ int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress, int noisy, int verbose); struct sg_simple_inquiry_resp { unsigned char peripheral_qualifier; unsigned char peripheral_type; unsigned char rmb; unsigned char version; /* as per recent drafts: whole of byte 2 */ unsigned char byte_3; unsigned char byte_5; unsigned char byte_6; unsigned char byte_7; char vendor[9]; char product[17]; char revision[5]; }; /* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response. * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other errors */ int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data, int noisy, int verbose); /* MODE SENSE commands yield a response that has block descriptors followed * by mode pages. In most cases users are interested in the first mode page. * This function returns the (byte) offset of the start of the first mode * page. Set mode_sense_6 to 1 for MODE SENSE (6) and 0 for MODE SENSE (10). * Returns >= 0 is successful or -1 if failure. If there is a failure * a message is written to err_buff. */ int sg_mode_page_offset(const unsigned char * resp, int resp_len, int mode_sense_6, char * err_buff, int err_buff_len); /* Fetches current, changeable, default and/or saveable modes pages as * indicated by pcontrol_arr for given pg_code and sub_pg_code. If * mode6==0 then use MODE SENSE (10) else use MODE SENSE (6). If * flexible set and mode data length seems wrong then try and * fix (compensating hack for bad device or driver). pcontrol_arr * should have 4 elements for output of current, changeable, default * and saved values respectively. Each element should be NULL or * at least mx_mpage_len bytes long. * Return of 0 -> overall success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, * SG_LIB_CAT_MALFORMED -> bad response, -1 -> other failure. * If success_mask pointer is not NULL then first zeros it. Then set bits * 0, 1, 2 and/or 3 if the current, changeable, default and saved values * respectively have been fetched. If error on current page * then stops and returns that error; otherwise continues if an error is * detected but returns the first error encountered. */ int sg_get_mode_page_controls(int sg_fd, int mode6, int pg_code, int sub_pg_code, int dbd, int flexible, int mx_mpage_len, int * success_mask, void * pcontrol_arr[], int * reported_len, int verbose); /* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. Implementation calls scsi_pt_open_device(). */ int sg_cmds_open_device(const char * device_name, int read_only, int verbose); /* Returns file descriptor >= 0 if successful. If error in Unix returns negated errno. Implementation calls scsi_pt_open_flags(). */ int sg_cmds_open_flags(const char * device_name, int flags, int verbose); /* Returns 0 if successful. If error in Unix returns negated errno. Implementation calls scsi_pt_close_device(). */ int sg_cmds_close_device(int device_fd); const char * sg_cmds_version(); struct sg_pt_base; /* This is a helper function used by sg_cmds_* implementations after the * call to the pass-through. pt_res is returned from do_scsi_pt(). If valid * sense data is found it is decoded and output to sg_warnings_strm (def: * stderr); depending on the 'noisy' and 'verbose' settings. Returns -2 for * sense data (may not be fatal), -1 for failed, 0, or a positive number. If * 'mx_di_len > 0' then asks pass-through for resid and returns * (mx_di_len - resid); otherwise returns 0. So for data-in it should return * the actual number of bytes received. For data-out (to device) or no data * call with 'mx_di_len' set to 0 or less. If -2 returned then sense category * output via 'o_sense_cat' pointer (if not NULL). Note that several sense * categories also have data in bytes received; -2 is still returned. */ int sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, int pt_res, int mx_di_len, const unsigned char * sense_b, int noisy, int verbose, int * o_sense_cat); #ifdef __cplusplus } #endif #endif ddpt-0.94/include/sg_linux_inc.h0000644000175000017500000000367010671112741015660 0ustar douggdougg#ifndef SG_LINUX_INC_H #define SG_LINUX_INC_H #ifdef SG_KERNEL_INCLUDES #define __user typedef unsigned char u8; #include "/usr/src/linux/include/scsi/sg.h" #include "/usr/src/linux/include/scsi/scsi.h" #else #ifdef SG_TRICK_GNU_INCLUDES #include #include #else #include #include #endif #endif #ifdef BLKGETSIZE64 #ifndef u64 #include /* C99 header for exact integer types */ typedef uint64_t u64; /* problems with BLKGETSIZE64 ioctl in lk 2.4 */ #endif #endif /* Getting the correct include files for the sg interface can be an ordeal. In a perfect world, one would just write: #include #include This would include the files found in the /usr/include/scsi directory. Those files are maintained with the GNU library which may or may not agree with the kernel and version of sg driver that is running. Any many cases this will not matter. However in some it might, for example glibc 2.1's include files match the sg driver found in the lk 2.2 series. Hence if glibc 2.1 is used with lk 2.4 then the additional sg v3 interface will not be visible. If this is a problem then defining SG_KERNEL_INCLUDES will access the kernel supplied header files (assuming they are in the normal place). The GNU library maintainers and various kernel people don't like this approach (but it does work). The technique selected by defining SG_TRICK_GNU_INCLUDES worked (and was used) prior to glibc 2.2 . Prior to that version /usr/include/linux was a symbolic link to /usr/src/linux/include/linux . There are other approaches if this include "mixup" causes pain. These would involve include files being copied or symbolic links being introduced. Sorry about the inconvenience. Typically neither SG_KERNEL_INCLUDES nor SG_TRICK_GNU_INCLUDES is defined. dpg 20010415, 20030522 */ #endif ddpt-0.94/include/sg_cmds_mmc.h0000644000175000017500000000376212207377272015465 0ustar douggdougg#ifndef SG_CMDS_MMC_H #define SG_CMDS_MMC_H /* * Copyright (c) 2008-2013 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #ifdef __cplusplus extern "C" { #endif /* Invokes a SCSI GET CONFIGURATION command (MMC-3...6). * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI GET PERFORMANCE command (MMC-3...6). * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_get_performance(int sg_fd, int data_type, unsigned int starting_lba, int max_num_desc, int type, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI SET CD SPEED command (MMC). * Return of 0 -> success, SG_LIB_CAT_INVALID_OP -> command not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed, int drv_write_speed, int noisy, int verbose); /* Invokes a SCSI SET STREAMING command (MMC). Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Set Streaming not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_NOT_READY -> device not ready, * -1 -> other failure */ int sg_ll_set_streaming(int sg_fd, int type, void * paramp, int param_len, int noisy, int verbose); #ifdef __cplusplus } #endif #endif ddpt-0.94/include/Makefile.am0000644000175000017500000000142212156455364015066 0ustar douggdougg scsiincludedir = $(includedir)/scsi scsiinclude_HEADERS = \ sg_lib.h \ sg_lib_data.h \ sg_cmds.h \ sg_cmds_basic.h \ sg_cmds_extra.h \ sg_cmds_mmc.h \ sg_pt.h if OS_LINUX scsiinclude_HEADERS += \ sg_linux_inc.h \ sg_io_linux.h noinst_HEADERS = \ sg_pt_win32.h endif if OS_WIN32_MINGW scsiinclude_HEADERS += sg_pt_win32.h noinst_HEADERS = \ sg_linux_inc.h \ sg_io_linux.h endif if OS_WIN32_CYGWIN scsiinclude_HEADERS += sg_pt_win32.h noinst_HEADERS = \ sg_linux_inc.h \ sg_io_linux.h endif if OS_FREEBSD noinst_HEADERS = \ sg_linux_inc.h \ sg_io_linux.h \ sg_pt_win32.h endif if OS_SOLARIS noinst_HEADERS = \ sg_linux_inc.h \ sg_io_linux.h \ sg_pt_win32.h endif if OS_OSF noinst_HEADERS = \ sg_linux_inc.h \ sg_io_linux.h \ sg_pt_win32.h endif ddpt-0.94/include/Makefile.in0000644000175000017500000004205012234470316015070 0ustar douggdougg# Makefile.in generated by automake 1.13.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @OS_LINUX_TRUE@am__append_1 = \ @OS_LINUX_TRUE@ sg_linux_inc.h \ @OS_LINUX_TRUE@ sg_io_linux.h @OS_WIN32_MINGW_TRUE@am__append_2 = sg_pt_win32.h @OS_WIN32_CYGWIN_TRUE@am__append_3 = sg_pt_win32.h subdir = include DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(am__noinst_HEADERS_DIST) $(am__scsiinclude_HEADERS_DIST) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__noinst_HEADERS_DIST = sg_linux_inc.h sg_io_linux.h sg_pt_win32.h am__scsiinclude_HEADERS_DIST = sg_lib.h sg_lib_data.h sg_cmds.h \ sg_cmds_basic.h sg_cmds_extra.h sg_cmds_mmc.h sg_pt.h \ sg_linux_inc.h sg_io_linux.h sg_pt_win32.h am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(scsiincludedir)" HEADERS = $(noinst_HEADERS) $(scsiinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETOPT_O_FILES = @GETOPT_O_FILES@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ scsiincludedir = $(includedir)/scsi scsiinclude_HEADERS = sg_lib.h sg_lib_data.h sg_cmds.h sg_cmds_basic.h \ sg_cmds_extra.h sg_cmds_mmc.h sg_pt.h $(am__append_1) \ $(am__append_2) $(am__append_3) @OS_FREEBSD_TRUE@noinst_HEADERS = \ @OS_FREEBSD_TRUE@ sg_linux_inc.h \ @OS_FREEBSD_TRUE@ sg_io_linux.h \ @OS_FREEBSD_TRUE@ sg_pt_win32.h @OS_LINUX_TRUE@noinst_HEADERS = \ @OS_LINUX_TRUE@ sg_pt_win32.h @OS_OSF_TRUE@noinst_HEADERS = \ @OS_OSF_TRUE@ sg_linux_inc.h \ @OS_OSF_TRUE@ sg_io_linux.h \ @OS_OSF_TRUE@ sg_pt_win32.h @OS_SOLARIS_TRUE@noinst_HEADERS = \ @OS_SOLARIS_TRUE@ sg_linux_inc.h \ @OS_SOLARIS_TRUE@ sg_io_linux.h \ @OS_SOLARIS_TRUE@ sg_pt_win32.h @OS_WIN32_CYGWIN_TRUE@noinst_HEADERS = \ @OS_WIN32_CYGWIN_TRUE@ sg_linux_inc.h \ @OS_WIN32_CYGWIN_TRUE@ sg_io_linux.h @OS_WIN32_MINGW_TRUE@noinst_HEADERS = \ @OS_WIN32_MINGW_TRUE@ sg_linux_inc.h \ @OS_WIN32_MINGW_TRUE@ sg_io_linux.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu include/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-scsiincludeHEADERS: $(scsiinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(scsiinclude_HEADERS)'; test -n "$(scsiincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(scsiincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(scsiincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(scsiincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(scsiincludedir)" || exit $$?; \ done uninstall-scsiincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(scsiinclude_HEADERS)'; test -n "$(scsiincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(scsiincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(scsiincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-scsiincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-scsiincludeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am \ install-scsiincludeHEADERS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-scsiincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ddpt-0.94/include/sg_lib_data.h0000644000175000017500000000560012164452524015427 0ustar douggdougg#ifndef SG_LIB_DATA_H #define SG_LIB_DATA_H /* * Copyright (c) 2007-2012 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* * This header file contains some structure declarations and array name * declarations which are defined in the sg_lib_data.c . * Typically this header does not need to be exposed to users of the * sg_lib interface declared in sg_libs.h . */ #include #ifdef __cplusplus extern "C" { #endif /* Commands with service actions that change the command name */ #define SG_MAINTENANCE_IN 0xa3 #define SG_MAINTENANCE_OUT 0xa4 #define SG_PERSISTENT_RESERVE_IN 0x5e #define SG_PERSISTENT_RESERVE_OUT 0x5f #define SG_EXTENDED_COPY 0x83 /* since spc4r34 called: Third party copy out */ #define SG_RECEIVE_COPY 0x84 /* since spc4r34 called: Third party copy in */ #define SG_SERVICE_ACTION_IN_12 0xab #define SG_SERVICE_ACTION_OUT_12 0xa9 #define SG_SERVICE_ACTION_BIDI 0x9d #define SG_SERVICE_ACTION_IN_16 0x9e #define SG_SERVICE_ACTION_OUT_16 0x9f #define SG_READ_BUFFER 0x3c #define SG_WRITE_BUFFER 0x3b #define SG_VARIABLE_LENGTH_CMD 0x7f struct sg_lib_value_name_t { int value; int peri_dev_type; /* 0 -> SPC and/or PDT_DISK, >0 -> PDT */ const char * name; }; struct sg_lib_asc_ascq_t { unsigned char asc; /* additional sense code */ unsigned char ascq; /* additional sense code qualifier */ const char * text; }; struct sg_lib_asc_ascq_range_t { unsigned char asc; /* additional sense code (ASC) */ unsigned char ascq_min; /* ASCQ minimum in range */ unsigned char ascq_max; /* ASCQ maximum in range */ const char * text; }; extern const char * sg_lib_version_str; extern struct sg_lib_value_name_t sg_lib_normal_opcodes[]; extern struct sg_lib_value_name_t sg_lib_read_buff_arr[]; extern struct sg_lib_value_name_t sg_lib_write_buff_arr[]; extern struct sg_lib_value_name_t sg_lib_maint_in_arr[]; extern struct sg_lib_value_name_t sg_lib_maint_out_arr[]; extern struct sg_lib_value_name_t sg_lib_pr_in_arr[]; extern struct sg_lib_value_name_t sg_lib_pr_out_arr[]; extern struct sg_lib_value_name_t sg_lib_serv_in12_arr[]; extern struct sg_lib_value_name_t sg_lib_serv_out12_arr[]; extern struct sg_lib_value_name_t sg_lib_serv_in16_arr[]; extern struct sg_lib_value_name_t sg_lib_serv_out16_arr[]; extern struct sg_lib_value_name_t sg_lib_serv_bidi_arr[]; extern struct sg_lib_value_name_t sg_lib_xcopy_sa_arr[]; extern struct sg_lib_value_name_t sg_lib_rec_copy_sa_arr[]; extern struct sg_lib_value_name_t sg_lib_variable_length_arr[]; extern struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[]; extern struct sg_lib_asc_ascq_t sg_lib_asc_ascq[]; extern const char * sg_lib_sense_key_desc[]; extern const char * sg_lib_pdt_strs[]; extern const char * sg_lib_transport_proto_strs[]; #ifdef __cplusplus } #endif #endif ddpt-0.94/include/sg_pt.h0000644000175000017500000001404012207377272014315 0ustar douggdougg#ifndef SG_PT_H #define SG_PT_H /* * Copyright (c) 2005-2011 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #include #ifdef __cplusplus extern "C" { #endif /* This declaration hides the fact that each implementation has its own * structure "derived" (using a C++ term) from this one. It compiles * because 'struct sg_pt_base' is only referenced (by pointer: 'objp') * in this interface. An instance of this structure represents the * context of one SCSI command. */ struct sg_pt_base; /* The format of the version string is like this: "2.01 20090201". * The leading digit will be incremented if this interface changes * in a way that may impact backward compatibility. */ const char * scsi_pt_version(); /* Returns >= 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_open_device(const char * device_name, int read_only, int verbose); /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed * together. Returns valid file descriptor( >= 0 ) if successful, otherwise * returns -1 or a negated errno. * In Win32 O_EXCL translated to equivalent. */ int scsi_pt_open_flags(const char * device_name, int flags, int verbose); /* Returns 0 if successful. If error in Unix returns negated errno. */ int scsi_pt_close_device(int device_fd); /* Creates an object that can be used to issue one or more SCSI commands * (or task management functions). Returns NULL if problem. * Once this object has been created it should be destroyed with * destruct_scsi_pt_obj() when it is no longer needed. */ struct sg_pt_base * construct_scsi_pt_obj(void); /* Clear state information held in *objp . This allows this object to be * used to issue more than one SCSI command. */ void clear_scsi_pt_obj(struct sg_pt_base * objp); /* Set the CDB (command descriptor block) */ void set_scsi_pt_cdb(struct sg_pt_base * objp, const unsigned char * cdb, int cdb_len); /* Set the sense buffer and the maximum length that it can handle */ void set_scsi_pt_sense(struct sg_pt_base * objp, unsigned char * sense, int max_sense_len); /* Set a pointer and length to be used for data transferred from device */ void set_scsi_pt_data_in(struct sg_pt_base * objp, /* from device */ unsigned char * dxferp, int dxfer_len); /* Set a pointer and length to be used for data transferred to device */ void set_scsi_pt_data_out(struct sg_pt_base * objp, /* to device */ const unsigned char * dxferp, int dxfer_len); /* The following "set_"s implementations may be dummies */ void set_scsi_pt_packet_id(struct sg_pt_base * objp, int pack_id); void set_scsi_pt_tag(struct sg_pt_base * objp, uint64_t tag); void set_scsi_pt_task_management(struct sg_pt_base * objp, int tmf_code); void set_scsi_pt_task_attr(struct sg_pt_base * objp, int attribute, int priority); /* Following is a guard which is defined when set_scsi_pt_flags() is * present. Older versions of this library may not have this function. */ #define SCSI_PT_FLAGS_FUNCTION 1 /* If neither QUEUE_AT_HEAD nor QUEUE_AT_TAIL are given, or both * are given, use the pass-through default. */ #define SCSI_PT_FLAGS_QUEUE_AT_TAIL 0x10 #define SCSI_PT_FLAGS_QUEUE_AT_HEAD 0x20 /* Set (potentially OS dependant) flags for pass-through mechanism. * Apart from contradictions, flags can be OR-ed together. */ void set_scsi_pt_flags(struct sg_pt_base * objp, int flags); #define SCSI_PT_DO_START_OK 0 #define SCSI_PT_DO_BAD_PARAMS 1 #define SCSI_PT_DO_TIMEOUT 2 /* If OS error prior to or during command submission then returns negated * error value (e.g. Unix '-errno'). This includes interrupted system calls * (e.g. by a signal) in which case -EINTR would be returned. Note that * system call errors also can be fetched with get_scsi_pt_os_err(). * Return 0 if okay (i.e. at the very least: command sent). Positive * return values are errors (see SCSI_PT_DO_* defines). */ int do_scsi_pt(struct sg_pt_base * objp, int fd, int timeout_secs, int verbose); #define SCSI_PT_RESULT_GOOD 0 #define SCSI_PT_RESULT_STATUS 1 /* other than GOOD and CHECK CONDITION */ #define SCSI_PT_RESULT_SENSE 2 #define SCSI_PT_RESULT_TRANSPORT_ERR 3 #define SCSI_PT_RESULT_OS_ERR 4 /* highest numbered applicable category returned */ int get_scsi_pt_result_category(const struct sg_pt_base * objp); /* If not available return 0 */ int get_scsi_pt_resid(const struct sg_pt_base * objp); /* Returns SCSI status value (from device that received the command). */ int get_scsi_pt_status_response(const struct sg_pt_base * objp); /* Actual sense length returned. If sense data is present but actual sense length is not known, return 'max_sense_len' */ int get_scsi_pt_sense_len(const struct sg_pt_base * objp); /* If not available return 0 */ int get_scsi_pt_os_err(const struct sg_pt_base * objp); char * get_scsi_pt_os_err_str(const struct sg_pt_base * objp, int max_b_len, char * b); /* If not available return 0 */ int get_scsi_pt_transport_err(const struct sg_pt_base * objp); char * get_scsi_pt_transport_err_str(const struct sg_pt_base * objp, int max_b_len, char * b); /* If not available return -1 */ int get_scsi_pt_duration_ms(const struct sg_pt_base * objp); /* Should be invoked once per objp after other processing is complete in * order to clean up resources. For ever successful construct_scsi_pt_obj() * call there should be one destruct_scsi_pt_obj(). */ void destruct_scsi_pt_obj(struct sg_pt_base * objp); #ifdef SG_LIB_WIN32 #define SG_LIB_WIN32_DIRECT 1 /* Request SPT direct interface when state_direct is 1, state_direct set * to 0 for the SPT indirect interface. Default setting selected by build * (i.e. library compile time) and is usually indirect. */ void scsi_pt_win32_direct(int state_direct); /* Returns current SPT interface state, 1 for direct, 0 for indirect */ int scsi_pt_win32_spt_state(void); #endif #ifdef __cplusplus } #endif #endif ddpt-0.94/include/sg_lib.h0000644000175000017500000004404612313347140014436 0ustar douggdougg#ifndef SG_LIB_H #define SG_LIB_H /* * Copyright (c) 2004-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* * * On 5th October 2004 a FreeBSD license was added to this file. * The intention is to keep this file and the related sg_lib.c file * as open source and encourage their unencumbered use. * * Current version number is in the sg_lib.c file and can be accessed * with the sg_lib_version() function. */ /* * This header file contains defines and function declarations that may * be useful to applications that communicate with devices that use a * SCSI command set. These command sets have names like SPC-4, SBC-3, * SSC-3, SES-2 and draft standards defining them can be found at * http://www.t10.org . Virtually all devices in the Linux SCSI subsystem * utilize SCSI command sets. Many devices in other Linux device subsystems * utilize SCSI command sets either natively or via emulation (e.g. a * parallel ATA disk in a USB enclosure). */ #include #include #ifdef __cplusplus extern "C" { #endif /* SCSI Peripheral Device Types (PDT) [5 bit field] */ #define PDT_DISK 0x0 /* direct access block device (disk) */ #define PDT_TAPE 0x1 /* sequential access device (magnetic tape) */ #define PDT_PRINTER 0x2 /* printer device (see SSC-1) */ #define PDT_PROCESSOR 0x3 /* processor device (e.g. SAFTE device) */ #define PDT_WO 0x4 /* write once device (some optical disks) */ #define PDT_MMC 0x5 /* CD/DVD/BD (multi-media) */ #define PDT_SCANNER 0x6 /* obsolete */ #define PDT_OPTICAL 0x7 /* optical memory device (some optical disks) */ #define PDT_MCHANGER 0x8 /* media changer device (e.g. tape robot) */ #define PDT_COMMS 0x9 /* communications device (obsolete) */ #define PDT_SAC 0xc /* storage array controller device */ #define PDT_SES 0xd /* SCSI Enclosure Services (SES) device */ #define PDT_RBC 0xe /* Reduced Block Commands (simplified PDT_DISK) */ #define PDT_OCRW 0xf /* optical card read/write device */ #define PDT_BCC 0x10 /* bridge controller commands */ #define PDT_OSD 0x11 /* Object Storage Device (OSD) */ #define PDT_ADC 0x12 /* Automation/drive commands (ADC) */ #define PDT_SMD 0x13 /* Security Manager Device (SMD) */ #define PDT_ZBC 0x14 /* Zoned Block Commands (ZBC) */ #define PDT_WLUN 0x1e /* Well known logical unit (WLUN) */ #define PDT_UNKNOWN 0x1f /* Unknown or no device type */ #ifndef SAM_STAT_GOOD /* The SCSI status codes as found in SAM-4 at www.t10.org */ #define SAM_STAT_GOOD 0x0 #define SAM_STAT_CHECK_CONDITION 0x2 #define SAM_STAT_CONDITION_MET 0x4 #define SAM_STAT_BUSY 0x8 #define SAM_STAT_INTERMEDIATE 0x10 /* obsolete in SAM-4 */ #define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14 /* obsolete in SAM-4 */ #define SAM_STAT_RESERVATION_CONFLICT 0x18 #define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */ #define SAM_STAT_TASK_SET_FULL 0x28 #define SAM_STAT_ACA_ACTIVE 0x30 #define SAM_STAT_TASK_ABORTED 0x40 #endif /* The SCSI sense key codes as found in SPC-4 at www.t10.org */ #define SPC_SK_NO_SENSE 0x0 #define SPC_SK_RECOVERED_ERROR 0x1 #define SPC_SK_NOT_READY 0x2 #define SPC_SK_MEDIUM_ERROR 0x3 #define SPC_SK_HARDWARE_ERROR 0x4 #define SPC_SK_ILLEGAL_REQUEST 0x5 #define SPC_SK_UNIT_ATTENTION 0x6 #define SPC_SK_DATA_PROTECT 0x7 #define SPC_SK_BLANK_CHECK 0x8 #define SPC_SK_VENDOR_SPECIFIC 0x9 #define SPC_SK_COPY_ABORTED 0xa #define SPC_SK_ABORTED_COMMAND 0xb #define SPC_SK_RESERVED 0xc #define SPC_SK_VOLUME_OVERFLOW 0xd #define SPC_SK_MISCOMPARE 0xe #define SPC_SK_COMPLETED 0xf /* Transport protocol identifiers or just Protocol identifiers */ #define TPROTO_FCP 0 #define TPROTO_SPI 1 #define TPROTO_SSA 2 #define TPROTO_1394 3 #define TPROTO_SRP 4 #define TPROTO_ISCSI 5 #define TPROTO_SAS 6 #define TPROTO_ADT 7 #define TPROTO_ATA 8 #define TPROTO_UAS 9 /* USB attached SCSI */ #define TPROTO_SOP 0xa /* SCSI over PCIe */ #define TPROTO_NONE 0xf /* The format of the version string is like this: "1.87 20130731" */ const char * sg_lib_version(); /* Returns length of SCSI command given the opcode (first byte). * Yields the wrong answer for variable length commands (opcode=0x7f) * and potentially some vendor specific commands. */ int sg_get_command_size(unsigned char cdb_byte0); /* Command name given pointer to the cdb. Certain command names * depend on peripheral type (give 0 if unknown). Places command * name into buff and will write no more than buff_len bytes. */ void sg_get_command_name(const unsigned char * cdbp, int peri_type, int buff_len, char * buff); /* Command name given only the first byte (byte 0) of a cdb and * peripheral type. */ void sg_get_opcode_name(unsigned char cdb_byte0, int peri_type, int buff_len, char * buff); /* Command name given opcode (byte 0), service action and peripheral type. * If no service action give 0, if unknown peripheral type give 0. */ void sg_get_opcode_sa_name(unsigned char cdb_byte0, int service_action, int peri_type, int buff_len, char * buff); /* Fetch scsi status string. */ void sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff); /* This is a slightly stretched SCSI sense "descriptor" format header. * The addition is to allow the 0x70 and 0x71 response codes. The idea * is to place the salient data of both "fixed" and "descriptor" sense * format into one structure to ease application processing. * The original sense buffer should be kept around for those cases * in which more information is required (e.g. the LBA of a MEDIUM ERROR). */ struct sg_scsi_sense_hdr { unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */ unsigned char sense_key; unsigned char asc; unsigned char ascq; unsigned char byte4; unsigned char byte5; unsigned char byte6; unsigned char additional_length; }; /* Maps the salient data from a sense buffer which is in either fixed or * descriptor format into a structure mimicking a descriptor format * header (i.e. the first 8 bytes of sense descriptor format). * If zero response code returns 0. Otherwise returns 1 and if 'sshp' is * non-NULL then zero all fields and then set the appropriate fields in * that structure. sshp::additional_length is always 0 for response * codes 0x70 and 0x71 (fixed format). */ int sg_scsi_normalize_sense(const unsigned char * sensep, int sense_len, struct sg_scsi_sense_hdr * sshp); /* Attempt to find the first SCSI sense data descriptor that matches the * given 'desc_type'. If found return pointer to start of sense data * descriptor; otherwise (including fixed format sense data) returns NULL. */ const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len, int desc_type); /* Get sense key from sense buffer. If successful returns a sense key value * between 0 and 15. If sense buffer cannot be decode, returns -1 . */ int sg_get_sense_key(const unsigned char * sensep, int sense_len); /* Yield string associated with sense_key value. Returns 'buff'. */ char * sg_get_sense_key_str(int sense_key, int buff_len, char * buff); /* Yield string associated with ASC/ASCQ values. Returns 'buff'. */ char * sg_get_asc_ascq_str(int asc, int ascq, int buff_len, char * buff); /* Returns 1 if valid bit set, 0 if valid bit clear. Irrespective the * information field is written out via 'info_outp' (except when it is * NULL). Handles both fixed and descriptor sense formats. */ int sg_get_sense_info_fld(const unsigned char * sensep, int sb_len, uint64_t * info_outp); /* Returns 1 if any of the 3 bits (i.e. FILEMARK, EOM or ILI) are set. * In descriptor format if the stream commands descriptor not found * then returns 0. Writes 1 or 0 corresponding to these bits to the * last three arguments if they are non-NULL. */ int sg_get_sense_filemark_eom_ili(const unsigned char * sensep, int sb_len, int * filemark_p, int * eom_p, int * ili_p); /* Returns 1 if SKSV is set and sense key is NO_SENSE or NOT_READY. Also * returns 1 if progress indication sense data descriptor found. Places * progress field from sense data where progress_outp points. If progress * field is not available returns 0. Handles both fixed and descriptor * sense formats. N.B. App should multiply by 100 and divide by 65536 * to get percentage completion from given value. */ int sg_get_sense_progress_fld(const unsigned char * sensep, int sb_len, int * progress_outp); /* Closely related to sg_print_sense(). Puts decoded sense data in 'buff'. * Usually multiline with multiple '\n' including one trailing. If * 'raw_sinfo' set appends sense buffer in hex. */ void sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer, int sb_len, int raw_sinfo, int buff_len, char * buff); /* Yield string associated with peripheral device type (pdt). Returns * 'buff'. If 'pdt' out of range yields "bad pdt" string. */ char * sg_get_pdt_str(int pdt, int buff_len, char * buff); /* Yield string associated with transport protocol identifier (tpi). Returns * 'buff'. If 'tpi' out of range yields "bad tpi" string. */ char * sg_get_trans_proto_str(int tpi, int buff_len, char * buff); extern FILE * sg_warnings_strm; void sg_set_warnings_strm(FILE * warnings_strm); /* The following "print" functions send ACSII to 'sg_warnings_strm' file * descriptor (default value is stderr) */ void sg_print_command(const unsigned char * command); void sg_print_sense(const char * leadin, const unsigned char * sense_buffer, int sb_len, int raw_info); void sg_print_scsi_status(int scsi_status); /* Utilities can use these process status values for syntax errors and * file (device node) problems (e.g. not found or permissions). */ #define SG_LIB_SYNTAX_ERROR 1 #define SG_LIB_FILE_ERROR 15 /* The sg_err_category_sense() function returns one of the following. * These may be used as process status values (on exit). Notice that * some of the lower values correspond to SCSI sense key values. */ #define SG_LIB_CAT_CLEAN 0 /* No errors or other information */ /* Value 1 left unused for utilities to use SG_LIB_SYNTAX_ERROR */ #define SG_LIB_CAT_NOT_READY 2 /* interpreted from sense buffer */ /* [sk,asc,ascq: 0x2,*,*] */ #define SG_LIB_CAT_MEDIUM_HARD 3 /* medium or hardware error, blank check */ /* [sk,asc,ascq: 0x3/0x4/0x8,*,*] */ #define SG_LIB_CAT_ILLEGAL_REQ 5 /* Illegal request (other than invalid */ /* opcode): [sk,asc,ascq: 0x5,*,*] */ #define SG_LIB_CAT_UNIT_ATTENTION 6 /* interpreted from sense buffer */ /* [sk,asc,ascq: 0x6,*,*] */ /* was SG_LIB_CAT_MEDIA_CHANGED earlier [sk,asc,ascq: 0x6,0x28,*] */ #define SG_LIB_CAT_INVALID_OP 9 /* (Illegal request,) Invalid opcode: */ /* [sk,asc,ascq: 0x5,0x20,0x0] */ #define SG_LIB_CAT_ABORTED_COMMAND 11 /* interpreted from sense buffer */ /* [sk,asc,ascq: 0xb,*,*] */ #define SG_LIB_CAT_MISCOMPARE 14 /* interpreted from sense buffer */ /* [sk,asc,ascq: 0xe,*,*] */ #define SG_LIB_CAT_NO_SENSE 20 /* sense data with key of "no sense" */ /* [sk,asc,ascq: 0x0,*,*] */ #define SG_LIB_CAT_RECOVERED 21 /* Successful command after recovered err */ /* [sk,asc,ascq: 0x1,*,*] */ #define SG_LIB_CAT_MALFORMED 97 /* Response to SCSI command malformed */ #define SG_LIB_CAT_SENSE 98 /* Something else is in the sense buffer */ #define SG_LIB_CAT_OTHER 99 /* Some other error/warning has occurred */ /* (e.g. a transport or driver error) */ /* Returns a SG_LIB_CAT_* value. If cannot decode sense_buffer or a less * common sense key then return SG_LIB_CAT_SENSE .*/ int sg_err_category_sense(const unsigned char * sense_buffer, int sb_len); /* Here are some additional sense data categories that are not returned * by sg_err_category_sense() but are returned by some related functions. */ #define SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO 17 /* Illegal request (other than */ /* invalid opcode) plus 'info' field: */ /* [sk,asc,ascq: 0x5,*,*] */ #define SG_LIB_CAT_MEDIUM_HARD_WITH_INFO 18 /* medium or hardware error */ /* sense key plus 'info' field: */ /* [sk,asc,ascq: 0x3/0x4,*,*] */ #define SG_LIB_CAT_TIMEOUT 33 /* Iterates to next designation descriptor in the device identification * VPD page. The 'initial_desig_desc' should point to start of first * descriptor with 'page_len' being the number of valid bytes in that * and following descriptors. To start, 'off' should point to a negative * value, thereafter it should point to the value yielded by the previous * call. If 0 returned then 'initial_desig_desc + *off' should be a valid * descriptor; returns -1 if normal end condition and -2 for an abnormal * termination. Matches association, designator_type and/or code_set when * any of those values are greater than or equal to zero. */ int sg_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len, int * off, int m_assoc, int m_desig_type, int m_code_set); /* <<< General purpose (i.e. not SCSI specific) utility functions >>> */ /* Always returns valid string even if errnum is wild (or library problem). * If errnum is negative, flip its sign. */ char * safe_strerror(int errnum); /* Print (to stdout) 'str' of bytes in hex, 16 bytes per line optionally * followed at the right hand side of the line with an ASCII interpretation. * Each line is prefixed with an address, starting at 0 for str[0]..str[15]. * All output numbers are in hex. 'no_ascii' allows for 3 output types: * > 0 each line has address then up to 16 ASCII-hex bytes * = 0 in addition, the bytes are listed in ASCII to the right * < 0 only the ASCII-hex bytes are listed (i.e. without address) */ void dStrHex(const char* str, int len, int no_ascii); /* Print (to sg_warnings_strm (stderr)) 'str' of bytes in hex, 16 bytes per * line optionally followed at right by its ASCII interpretation. Same * logic as dStrHex() with different output stream (i.e. stderr). */ void dStrHexErr(const char* str, int len, int no_ascii); /* Read 'len' bytes from 'str' and output as ASCII-Hex bytes (space * separated) to 'b' not to exceed 'b_len' characters. Each line * starts with 'leadin' (NULL for no leadin) and there are 16 bytes * per line with an extra space between the 8th and 9th bytes. 'format' * is unused, set to 0 . */ void dStrHexStr(const char* str, int len, const char * leadin, int format, int b_len, char * b); /* Returns 1 when executed on big endian machine; else returns 0. * Useful for displaying ATA identify words (which need swapping on a * big endian machine). */ int sg_is_big_endian(); /* Extract character sequence from ATA words as in the model string * in a IDENTIFY DEVICE response. Returns number of characters * written to 'ochars' before 0 character is found or 'num' words * are processed. */ int sg_ata_get_chars(const unsigned short * word_arr, int start_word, int num_words, int is_big_endian, char * ochars); /* Print (to stdout) 16 bit 'words' in hex, 8 words per line optionally * followed at the right hand side of the line with an ASCII interpretation * (pairs of ASCII characters in big endian order (upper first)). * Each line is prefixed with an address, starting at 0. * All output numbers are in hex. 'no_ascii' allows for 3 output types: * > 0 each line has address then up to 8 ASCII-hex words * = 0 in addition, the words are listed in ASCII pairs to the right * = -1 only the ASCII-hex words are listed (i.e. without address) * = -2 only the ASCII-hex words, formatted for "hdparm --Istdin" * < -2 same as -1 * If 'swapb' non-zero then bytes in each word swapped. Needs to be set * for ATA IDENTIFY DEVICE response on big-endian machines. */ void dWordHex(const unsigned short* words, int num, int no_ascii, int swapb); /* If the number in 'buf' can not be decoded or the multiplier is unknown * then -1 is returned. Accepts a hex prefix (0x or 0X) or a 'h' (or 'H') * suffix. Otherwise a decimal multiplier suffix may be given. Recognised * multipliers: c C *1; w W *2; b B *512; k K KiB *1,024; * KB *1,000; m M MiB *1,048,576; MB *1,000,000; g G GiB *1,073,741,824; * GB *1,000,000,000 and x which multiplies by . Ignore leading * spaces and tabs; accept comma, space, tab and hash as terminator. */ int sg_get_num(const char * buf); /* If the number in 'buf' can not be decoded then -1 is returned. Accepts a * hex prefix (0x or 0X) or a 'h' (or 'H') suffix; otherwise decimal is * assumed. Does not accept multipliers. Accept a comma (","), a whitespace * or newline as terminator. */ int sg_get_num_nomult(const char * buf); /* If the number in 'buf' can not be decoded or the multiplier is unknown * then -1LL is returned. Accepts a hex prefix (0x or 0X) or a 'h' (or 'H') * suffix. Otherwise a decimal multiplier suffix may be given. In addition * to supporting the multipliers of sg_get_num(), this function supports: * t T TiB *(2**40); TB *(10**12); p P PiB *(2**50); PB *(10**15) . * Ignore leading spaces and tabs; accept comma, space, tab and hash as * terminator. */ int64_t sg_get_llnum(const char * buf); /* <<< Architectural support functions [is there a better place?] >>> */ /* Non Unix OSes distinguish between text and binary files. * Set text mode on fd. Does nothing in Unix. Returns negative number on * failure. */ int sg_set_text_mode(int fd); /* Set binary mode on fd. Does nothing in Unix. Returns negative number on * failure. */ int sg_set_binary_mode(int fd); #ifdef __cplusplus } #endif #endif ddpt-0.94/include/sg_pt_win32.h0000644000175000017500000001107612061626602015335 0ustar douggdougg#ifndef SG_PT_WIN32_H #define SG_PT_WIN32_H /* * The information in this file was obtained from scsi-wnt.h by * Richard Stemmer, rs@epost.de . He in turn gives credit to * Jay A. Key (for scsipt.c). * The plscsi program (by Pat LaVarre ) has * also been used as a reference. * Much of the information in this header can also be obtained * from msdn.microsoft.com . * Updated for cygwin version 1.7.17 changes 20121026 */ #include #define SCSI_MAX_SENSE_LEN 64 #define SCSI_MAX_CDB_LEN 16 #define SCSI_MAX_INDIRECT_DATA 16384 typedef struct { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; ULONG_PTR DataBufferOffset; /* was ULONG; problem in 64 bit */ ULONG SenseInfoOffset; UCHAR Cdb[SCSI_MAX_CDB_LEN]; } SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; typedef struct { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; ULONG SenseInfoOffset; UCHAR Cdb[SCSI_MAX_CDB_LEN]; } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; typedef struct { SCSI_PASS_THROUGH spt; /* plscsi shows a follow on 16 bytes allowing 32 byte cdb */ ULONG Filler; UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; UCHAR ucDataBuf[SCSI_MAX_INDIRECT_DATA]; } SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; typedef struct { SCSI_PASS_THROUGH_DIRECT spt; ULONG Filler; UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; typedef struct { UCHAR NumberOfLogicalUnits; UCHAR InitiatorBusId; ULONG InquiryDataOffset; } SCSI_BUS_DATA, *PSCSI_BUS_DATA; typedef struct { UCHAR NumberOfBusses; SCSI_BUS_DATA BusData[1]; } SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; typedef struct { UCHAR PathId; UCHAR TargetId; UCHAR Lun; BOOLEAN DeviceClaimed; ULONG InquiryDataLength; ULONG NextInquiryDataOffset; UCHAR InquiryData[1]; } SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; typedef struct { ULONG Length; UCHAR PortNumber; UCHAR PathId; UCHAR TargetId; UCHAR Lun; } SCSI_ADDRESS, *PSCSI_ADDRESS; /* * method codes */ #define METHOD_BUFFERED 0 #define METHOD_IN_DIRECT 1 #define METHOD_OUT_DIRECT 2 #define METHOD_NEITHER 3 /* * file access values */ #define FILE_ANY_ACCESS 0 #ifndef FILE_READ_ACCESS #define FILE_READ_ACCESS 0x0001 #endif #ifndef FILE_WRITE_ACCESS #define FILE_WRITE_ACCESS 0x0002 #endif #define IOCTL_SCSI_BASE 0x00000004 /* * constants for DataIn member of SCSI_PASS_THROUGH* structures */ #define SCSI_IOCTL_DATA_OUT 0 #define SCSI_IOCTL_DATA_IN 1 #define SCSI_IOCTL_DATA_UNSPECIFIED 2 /* * Standard IOCTL define */ #ifndef CTL_CODE #define CTL_CODE(DevType, Function, Method, Access) \ (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #endif #define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, \ METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, \ METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, \ METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, \ METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, \ METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, \ METHOD_BUFFERED, FILE_ANY_ACCESS) #endif ddpt-0.94/include/sg_cmds.h0000644000175000017500000000151710756351213014617 0ustar douggdougg#ifndef SG_CMDS_H #define SG_CMDS_H /******************************************************************** * This header did contain wrapper declarations for many SCSI commands * up until sg3_utils version 1.22 . In that version, the command * wrappers were broken into two groups, the 'basic' ones found in the * "sg_cmds_basic.h" header and the 'extra' ones found in the * "sg_cmds_extra.h" header. This header now simply includes those two * headers. * In sg3_utils version 1.26 the sg_cmds_mmc.h header was added and * contains some MMC specific commands. * The corresponding function definitions are found in the sg_cmds_basic.c, * sg_cmds_extra.c and sg_cmds_mmc.c files. ********************************************************************/ #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" #include "sg_cmds_mmc.h" #endif ddpt-0.94/include/sg_io_linux.h0000644000175000017500000001432112207377272015522 0ustar douggdougg#ifndef SG_IO_LINUX_H #define SG_IO_LINUX_H /* * Copyright (c) 2004-2012 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ /* * Version 1.03 [20120914] */ /* * This header file contains linux specific information related to the SCSI * command pass through in the SCSI generic (sg) driver and the linux * block layer. */ #include "sg_lib.h" #include "sg_linux_inc.h" #ifdef __cplusplus extern "C" { #endif /* The following are 'host_status' codes */ #ifndef DID_OK #define DID_OK 0x00 #endif #ifndef DID_NO_CONNECT #define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */ #define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */ #define DID_TIME_OUT 0x03 /* Timed out for some other reason */ #define DID_BAD_TARGET 0x04 /* Bad target (id?) */ #define DID_ABORT 0x05 /* Told to abort for some other reason */ #define DID_PARITY 0x06 /* Parity error (on SCSI bus) */ #define DID_ERROR 0x07 /* Internal error */ #define DID_RESET 0x08 /* Reset by somebody */ #define DID_BAD_INTR 0x09 /* Received an unexpected interrupt */ #define DID_PASSTHROUGH 0x0a /* Force command past mid-level */ #define DID_SOFT_ERROR 0x0b /* The low-level driver wants a retry */ #endif #ifndef DID_IMM_RETRY #define DID_IMM_RETRY 0x0c /* Retry without decrementing retry count */ #endif #ifndef DID_REQUEUE #define DID_REQUEUE 0x0d /* Requeue command (no immediate retry) also * without decrementing the retry count */ #endif #ifndef DID_TRANSPORT_DISRUPTED #define DID_TRANSPORT_DISRUPTED 0xe #endif #ifndef DID_TRANSPORT_FAILFAST #define DID_TRANSPORT_FAILFAST 0xf #endif #ifndef DID_TARGET_FAILURE #define DID_TARGET_FAILURE 0x10 #endif #ifndef DID_NEXUS_FAILURE #define DID_NEXUS_FAILURE 0x11 #endif /* These defines are to isolate applications from kernel define changes */ #define SG_LIB_DID_OK DID_OK #define SG_LIB_DID_NO_CONNECT DID_NO_CONNECT #define SG_LIB_DID_BUS_BUSY DID_BUS_BUSY #define SG_LIB_DID_TIME_OUT DID_TIME_OUT #define SG_LIB_DID_BAD_TARGET DID_BAD_TARGET #define SG_LIB_DID_ABORT DID_ABORT #define SG_LIB_DID_PARITY DID_PARITY #define SG_LIB_DID_ERROR DID_ERROR #define SG_LIB_DID_RESET DID_RESET #define SG_LIB_DID_BAD_INTR DID_BAD_INTR #define SG_LIB_DID_PASSTHROUGH DID_PASSTHROUGH #define SG_LIB_DID_SOFT_ERROR DID_SOFT_ERROR #define SG_LIB_DID_IMM_RETRY DID_IMM_RETRY #define SG_LIB_DID_REQUEUE DID_REQUEUE #define SG_LIB_TRANSPORT_DISRUPTED DID_TRANSPORT_DISRUPTED #define SG_LIB_DID_TRANSPORT_FAILFAST DID_TRANSPORT_FAILFAST #define SG_LIB_DID_TARGET_FAILURE DID_TARGET_FAILURE #define SG_LIB_DID_NEXUS_FAILURE DID_NEXUS_FAILURE /* The following are 'driver_status' codes */ #ifndef DRIVER_OK #define DRIVER_OK 0x00 #endif #ifndef DRIVER_BUSY #define DRIVER_BUSY 0x01 #define DRIVER_SOFT 0x02 #define DRIVER_MEDIA 0x03 #define DRIVER_ERROR 0x04 #define DRIVER_INVALID 0x05 #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 #define DRIVER_SENSE 0x08 /* Sense_buffer has been set */ /* Following "suggests" are "or-ed" with one of previous 8 entries */ #define SUGGEST_RETRY 0x10 #define SUGGEST_ABORT 0x20 #define SUGGEST_REMAP 0x30 #define SUGGEST_DIE 0x40 #define SUGGEST_SENSE 0x80 #define SUGGEST_IS_OK 0xff #endif #ifndef DRIVER_MASK #define DRIVER_MASK 0x0f #endif #ifndef SUGGEST_MASK #define SUGGEST_MASK 0xf0 #endif /* These defines are to isolate applications from kernel define changes */ #define SG_LIB_DRIVER_OK DRIVER_OK #define SG_LIB_DRIVER_BUSY DRIVER_BUSY #define SG_LIB_DRIVER_SOFT DRIVER_SOFT #define SG_LIB_DRIVER_MEDIA DRIVER_MEDIA #define SG_LIB_DRIVER_ERROR DRIVER_ERROR #define SG_LIB_DRIVER_INVALID DRIVER_INVALID #define SG_LIB_DRIVER_TIMEOUT DRIVER_TIMEOUT #define SG_LIB_DRIVER_HARD DRIVER_HARD #define SG_LIB_DRIVER_SENSE DRIVER_SENSE #define SG_LIB_SUGGEST_RETRY SUGGEST_RETRY #define SG_LIB_SUGGEST_ABORT SUGGEST_ABORT #define SG_LIB_SUGGEST_REMAP SUGGEST_REMAP #define SG_LIB_SUGGEST_DIE SUGGEST_DIE #define SG_LIB_SUGGEST_SENSE SUGGEST_SENSE #define SG_LIB_SUGGEST_IS_OK SUGGEST_IS_OK #define SG_LIB_DRIVER_MASK DRIVER_MASK #define SG_LIB_SUGGEST_MASK SUGGEST_MASK void sg_print_masked_status(int masked_status); void sg_print_host_status(int host_status); void sg_print_driver_status(int driver_status); /* sg_chk_n_print() returns 1 quietly if there are no errors/warnings else it prints errors/warnings (prefixed by 'leadin') to 'sg_warnings_fd' and returns 0. raw_sinfo indicates whether the raw sense buffer (in ASCII hex) should be printed. */ int sg_chk_n_print(const char * leadin, int masked_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len, int raw_sinfo); /* The following function declaration is for the sg version 3 driver. */ struct sg_io_hdr; /* sg_chk_n_print3() returns 1 quietly if there are no errors/warnings; else it prints errors/warnings (prefixed by 'leadin') to 'sg_warnings_fd' and returns 0. */ int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp, int raw_sinfo); /* Calls sg_scsi_normalize_sense() after obtaining the sense buffer and its length from the struct sg_io_hdr pointer. If these cannot be obtained, 0 is returned. */ int sg_normalize_sense(const struct sg_io_hdr * hp, struct sg_scsi_sense_hdr * sshp); int sg_err_category(int masked_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len); int sg_err_category_new(int scsi_status, int host_status, int driver_status, const unsigned char * sense_buffer, int sb_len); /* The following function declaration is for the sg version 3 driver. */ int sg_err_category3(struct sg_io_hdr * hp); /* Note about SCSI status codes found in older versions of Linux. Linux has traditionally used a 1 bit right shifted and masked version of SCSI standard status codes. Now CHECK_CONDITION and friends (in ) are deprecated. */ #ifdef __cplusplus } #endif #endif ddpt-0.94/include/sg_cmds_extra.h0000644000175000017500000004106612270322342016017 0ustar douggdougg#ifndef SG_CMDS_EXTRA_H #define SG_CMDS_EXTRA_H /* * Copyright (c) 2004-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. */ #ifdef __cplusplus extern "C" { #endif /* Note: all functions that have an 'int timeout_secs' argument will use * that value if it is > 0. Otherwise they will set an internal default * which is currently 60 seconds. This timeout is typically applied in the * SCSI stack above the initiator. If it goes off then the SCSI command is * aborted and there can be other unwelcome side effects. Note that some * commands (e.g. FORMAT UNIT and the Third Party copy commands) can take * a lot longer than the default timeout. */ /* Invokes a ATA PASS-THROUGH (12 or 16) SCSI command (SAT). If cdb_len is * 12 then a ATA PASS-THROUGH (12) command is called. If cdb_len is 16 then * a ATA PASS-THROUGH (16) command is called. If cdb_len is any other value * -1 is returned. After copying from cdbp to an internal buffer, the first * byte (i.e. offset 0) is set to 0xa1 if cdb_len is 12; or is set to 0x85 * if cdb_len is 16. The last byte (offset 11 or offset 15) is set to 0x0 in * the internal buffer. For data in or out transfers set dinp or doutp, and * dlen to the number of bytes to transfer. If dlen is zero then no data * transfer is assumed. If sense buffer obtained then it is written to * sensep, else sensep[0] is set to 0x0. If ATA return descriptor is obtained * then written to ata_return_dp, else ata_return_dp[0] is set to 0x0. Either * sensep or ata_return_dp (or both) may be NULL pointers. Returns SCSI * status value (>= 0) or -1 if other error. Users are expected to check the * sense buffer themselves. If available the data in resid is written to * residp. Note in SAT-2 and later, fixed format sense data may be placed in * *sensep in which case sensep[0]==0x70 . */ int sg_ll_ata_pt(int sg_fd, const unsigned char * cdbp, int cdb_len, int timeout_secs, void * dinp, void * doutp, int dlen, unsigned char * sensep, int max_sense_len, unsigned char * ata_return_dp, int max_ata_return_len, int * residp, int verbose); /* Invokes a FORMAT UNIT (SBC-3) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Format unit not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_format_unit(int sg_fd, int fmtpinfo, int longlist, int fmtdata, int cmplist, int dlist_format, int timeout_secs, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI GET LBA STATUS command (SBC). Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> GET LBA STATUS not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp, int alloc_len, int noisy, int verbose); /* Invokes a SCSI PERSISTENT RESERVE IN command (SPC). Returns 0 * when successful, SG_LIB_CAT_INVALID_OP if command not supported, * SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI PERSISTENT RESERVE OUT command (SPC). Returns 0 * when successful, SG_LIB_CAT_INVALID_OP if command not supported, * SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ int sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, int rq_scope, unsigned int rq_type, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI READ BLOCK LIMITS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> READ BLOCK LIMITS not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ int sg_ll_read_block_limits(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI READ BUFFER command (SPC). Return of 0 -> * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI READ DEFECT DATA (10) command (SBC). Return of 0 -> * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist, int dl_format, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI READ LONG (10) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> READ LONG(10) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned int lba, void * resp, int xfer_len, int * offsetp, int noisy, int verbose); /* Invokes a SCSI READ LONG (16) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> READ LONG(16) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_long16(int sg_fd, int pblock, int correct, uint64_t llba, void * resp, int xfer_len, int * offsetp, int noisy, int verbose); /* Invokes a SCSI READ MEDIA SERIAL NUMBER command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Read media serial number not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI REASSIGN BLOCKS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ int sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI RECEIVE DIAGNOSTIC RESULTS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Receive diagnostic results not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI REPORT IDENTIFYING INFORMATION command. This command was * called REPORT DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report identifying information not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_report_id_info(int sg_fd, int itype, void * resp, int max_resp_len, int noisy, int verbose); /* Invokes a SCSI REPORT TARGET PORT GROUPS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Target Port Groups not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose); int sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len, int extended, int noisy, int verbose); /* Invokes a SCSI SET TARGET PORT GROUPS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Target Port Groups not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_set_tgt_prt_grp(int sg_fd, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI REPORT REFERRALS command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Report Referrals not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI SEND DIAGNOSTIC command. Foreground, extended self tests can * take a long time, if so set long_duration flag in which case the timout * is set to 7200 seconds; if the value of long_duration is > 7200 then that * value is taken as the timeout value in seconds. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Send diagnostic not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit, int devofl_bit, int unitofl_bit, int long_duration, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI SET IDENTIFYING INFORMATION command. This command was * called SET DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Set identifying information not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_set_id_info(int sg_fd, int itype, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI UNMAP (SBC-3) command. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> command not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ int sg_ll_unmap(int sg_fd, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI UNMAP (SBC-3) command. Version 2 adds anchor field * (sbc3r22). Otherwise same as sg_ll_unmap() . */ int sg_ll_unmap_v2(int sg_fd, int anchor, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose); /* Invokes a SCSI VERIFY (10) command (SBC and MMC). * Note that 'veri_len' is in blocks while 'data_out_len' is in bytes. * Returns of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Verify(10) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_MEDIUM_HARD -> medium or hardware error, no valid info, * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> as previous, with valid info, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_MISCOMPARE, -1 -> other failure */ int sg_ll_verify10(int sg_fd, int vrprotect, int dpo, int bytechk, unsigned int lba, int veri_len, void * data_out, int data_out_len, unsigned int * infop, int noisy, int verbose); /* Invokes a SCSI VERIFY (16) command (SBC). * Note that 'veri_len' is in blocks while 'data_out_len' is in bytes. * Returns of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Verify(16) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_MEDIUM_HARD -> medium or hardware error, no valid info, * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> as previous, with valid info, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_MISCOMPARE, -1 -> other failure */ int sg_ll_verify16(int sg_fd, int vrprotect, int dpo, int bytechk, uint64_t llba, int veri_len, int group_num, void * data_out, int data_out_len, uint64_t * infop, int noisy, int verbose); /* Invokes a SCSI WRITE BUFFER command (SPC). Return of 0 -> * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset, void * paramp, int param_len, int noisy, int verbose); /* Need a sg_ll_write_buffer_v2() function because SPC-4 rev32 has added * a "mode specific" field. Wait for next rev change of this library */ /* Invokes a SCSI WRITE LONG (10) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> WRITE LONG(10) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_write_long10(int sg_fd, int cor_dis, int wr_uncor, int pblock, unsigned int lba, void * data_out, int xfer_len, int * offsetp, int noisy, int verbose); /* Invokes a SCSI WRITE LONG (16) command (SBC). Note that 'xfer_len' * is in bytes. Returns 0 -> success, * SG_LIB_CAT_INVALID_OP -> WRITE LONG(16) not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_write_long16(int sg_fd, int cor_dis, int wr_uncor, int pblock, uint64_t llba, void * data_out, int xfer_len, int * offsetp, int noisy, int verbose); /* Invokes a SPC-3 SCSI RECEIVE COPY RESULTS command. In SPC-4 this function * supports all service action variants of the THIRD-PARTY COPY IN opcode. * SG_LIB_CAT_INVALID_OP -> Receive copy results not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp, int mx_resp_len, int noisy, int verbose); /* Invokes a SCSI EXTENDED COPY(LID1) command. For EXTENDED COPY(LID4) * including POPULATE TOKEN and WRITE USING TOKEN use * sg_ll_3party_copy_out(). Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> Extended copy not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_extended_copy(int sg_fd, void * paramp, int param_len, int noisy, int verbose); /* Handles various service actions associated with opcode 0x83 which is * called THIRD PARTY COPY OUT. These include the EXTENDED COPY(LID4), * POPULATE TOKEN and WRITE USING TOKEN commands. Return of 0 -> success, * SG_LIB_CAT_INVALID_OP -> opcode 0x83 not supported, * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, * -1 -> other failure */ int sg_ll_3party_copy_out(int sg_fd, int sa, unsigned int list_id, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose); #ifdef __cplusplus } #endif #endif ddpt-0.94/README.win320000644000175000017500000000771111527261361013230 0ustar douggdouggThis port supports Windows NT, 2000, 2003++, XP, Vista and Windows 7 (i.e. not 95, 98, ME or earlier). It uses the Microsoft SCSI Pass Through "Direct" (SPTD). The source can be built in a cygwin environment and can run in a cygwin bash shell. It can also run in a DOS shell if the cygwin1.dll is put in an appropriate place. Alternatively the source can be built with the MinGW compiler using its MSYS shell. This removes the dependency on the cygwin1.dll file. The ddpt executable built by the MinGW compiler can also be run in a DOS (also known as the "Command prompt") shell. In Windows 7 ddpt typically needs to be run with administrator permissions. The device naming schemes attempt to follow what DOS does, with a few short cuts. If volume "D:" is an ATAPI DVD drive then the actual file opened is "\\.\D:". All device nodes of interest to ddpt have a leading "\\.\" so if the user doesn't supply it, ddpt will. Thus 'ddpt if=d: bs=512 count=8' should work. Note that volume names map to Windows partitions so there can be multiple volume names per disk. SCSI devices (or those that use a SCSI command set) can also be accessed via their "class" driver. These have names like "PhysicalDrive", "CDROM" and "TAPE" where is a number starting at 0. Since "PhysicalDrive" is tedious to type, a shortened form of "PD" is accepted. Finally there is a lower level "SCSI:" interface that addresses a SCSI adapter. The device needs further sub-addressing in the form of a bus number (also called a PathId), a target identifier and a lun (logical unit number). ddpt uses this notation: "SCSI:,,". The trailing "," may be omitted in which case a lun of 0 is assumed. Once a device has been "claimed" by an upper level "class" driver the OS will not allow it to be accessed via the "SCSI:" interface. Hence this is only needed for special devices (e.g. with processor or SES peripheral device type) that are not claimed by the class drivers. The Windows version of ddpt supports a '--wscan' (or '-w') option. It shows the mapping between a class driver device name (e.g. PD1) and its associated volume name(s). Here are some examples: $ ddpt -w PD0 [C] FUJITSU MHY2160BH 0000 PD1 [DF] WD 2500BEV External 1.05 WD-WXE90 CDROM0 [E] MATSHITA DVD/CDRW UJDA775 CB03 Now request bus types as well. $ ddpt -ww PD0 [C] FUJITSU MHY2160BH 0000 PD1 [DF] WD 2500BEV External 1.05 WD-WXE90 CDROM0 [E] MATSHITA DVD/CDRW UJDA775 CB03 Now request a SCSI adapter scan as well. $ ddpt -www PD0 [C] FUJITSU MHY2160BH 0000 PD1 [DF] WD 2500BEV External 1.05 WD-WXE90 CDROM0 [E] MATSHITA DVD/CDRW UJDA775 CB03 SCSI0:0,0,0 claimed=1 pdt=0h FUJITSU MHY2160BH 0000 SCSI1:0,0,0 claimed=1 pdt=5h MATSHITA DVD/CDRW UJDA775 CB03 And finally here is a more interesting example showing disks with no Windows (2000) volumes, a tape drive and a weird unclaimed SCSI pseudo device with BCC (Bridge Controller Commands) peripheral device type. $ ddpt -www PD0 [C] ST380011A 8.01 PD1 SEAGATE ST373455SS 2189 PD2 ATA ST3160812AS D PD3 SEAGATE ST336754SS 0003 CDROM0 [F] HL-DT-ST DVDRAM GSA-4163B A103 TAPE0 SONY SDT-7000 0192 SCSI0:0,0,0 claimed=1 pdt=0h dubious ST380011 A 8.01 SCSI1:0,0,0 claimed=1 pdt=5h HL-DT-ST DVDRAM GSA-4163B A103 SCSI2:0,6,0 claimed=1 pdt=1h SONY SDT-7000 0192 SCSI5:0,17,0 claimed=1 pdt=0h SEAGATE ST373455SS 2189 SCSI5:0,19,0 claimed=1 pdt=0h ATA ST3160812AS D SCSI5:0,21,0 claimed=1 pdt=0h SEAGATE ST336754SS 0003 SCSI5:0,112,0 claimed=0 pdt=10h LSI PSEUDO DEVICE 2.34 Douglas Gilbert 17th February 2011 ddpt-0.94/README.solaris0000644000175000017500000000412611361107544013735 0ustar douggdouggIn Solaris, SCSI device names below the '/dev' directory have a form like: c5t4d3s2 where the number following "c" is the controller (HBA) number, the number following "t" is the target number (from the SCSI parallel interface days) and the number following "d" is the LUN. Following the "s" is the slice number which is related to a partition and by convention "s2" is the whole disk. OpenSolaris also has a c5t4d3p2 form where the number following the "p" is the partition number apart from "p0" which is the whole disk. So a whole disk may be referred to as either: - c5t4d3 - c5t4d3s2 - c5t4d3p0 And these device names are duplicated in the /dev/dsk and /dev/rdsk directories. The former is the block device name and the latter is for "raw" (or char device) access. For performance and flexibility it is better for ddpt to use the raw device names (e.g. /dev/rdsk/c5t4d3p0). A safe way to check things is: ddpt if=/dev/rdsk/c5t4d3p0 bs=512 count=0 verbose=4 If it did read anything (it won't due to the "count=0") the normal Unix read() call would be used. To do the same thing at the SCSI pass-through level: ddpt if=/dev/rdsk/c5t4d3p0 iflag=pt bs=512 count=0 verbose=4 The latter won't work on the /dev/dsk/c5t4d3p0 variant device name resulting in an inappropriate ioctl for device error. The device names within the /dev directory are typically symbolic links to much longer topological names in the /device directory. In Solaris cd/dvd/bd players seem to be treated as disks and so are found in the /dev/rdsk directory. There is also a sgen (SCSI generic) driver which by default does not attach to any device. See the /kernel/drv/sgen.conf file to control what is attached. Any attached device will have a device name of the form /dev/scsi/c5t4d3 . Listing available SCSI devices in Solaris seems to be a challenge. "Use the 'format' command" advice works but seems a very dangerous way to list devices. [It does prompt again before doing any damage.] 'devfsadm -Cv' cleans out the clutter in the /dev/rdsk directory, only leaving what is "live". The "cfgadm -v" command looks promising. 8th April 2010