diff -Nru ddpt-0.94/aclocal.m4 ddpt-0.95/aclocal.m4 --- ddpt-0.94/aclocal.m4 2013-10-31 15:09:28.000000000 +0000 +++ ddpt-0.95/aclocal.m4 2014-05-17 14:53:08.000000000 +0000 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.13.3 -*- Autoconf -*- +# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. @@ -32,10 +32,10 @@ # 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' +[am__api_version='1.14' 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], [], +m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,7 +51,7 @@ # 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 +[AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) @@ -418,6 +418,12 @@ # 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. +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- @@ -526,7 +532,48 @@ AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl -]) + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi]) 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 @@ -534,7 +581,6 @@ 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. @@ -781,6 +827,70 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) +# 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_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# 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_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. diff -Nru ddpt-0.94/ChangeLog ddpt-0.95/ChangeLog --- ddpt-0.94/ChangeLog 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/ChangeLog 2014-12-27 06:01:02.000000000 +0000 @@ -2,6 +2,21 @@ the rpm spec file: ddpt.spec ; the debian/changelog file; and the configure.ac file (in the AC_INIT item). +Changelog for ddpt-0.95 [20141226] [svn: r307] + - add oflag=verify[,bytchk] to write using the SCSI + WRITE AND VERIFY command + - add job file that holds options; specified either + freestanding on command line or after --job= + - show percent completed + - add DDPT_DEF_BS environment variable + - add iflag=ff to source 0xff bytes + - ddptctl: add --hex and --readonly options + - add atomic flag for WRITE ATOMIC(16) command on OFILE + - add warning when oflag=strunc copy interrupted + - win32: ddpt --wscan fixes + - point svn:externals to rev 620 of sg3_utils + - upgrade automake to version 1.14.1 + 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 diff -Nru ddpt-0.94/compile ddpt-0.95/compile --- ddpt-0.94/compile 1970-01-01 00:00:00.000000000 +0000 +++ ddpt-0.95/compile 2014-05-17 14:53:08.000000000 +0000 @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# 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: diff -Nru ddpt-0.94/configure ddpt-0.95/configure --- ddpt-0.94/configure 2014-01-22 23:06:58.000000000 +0000 +++ ddpt-0.95/configure 2014-09-23 15:41:34.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for ddpt 0.94. +# Generated by GNU Autoconf 2.69 for ddpt 0.95. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='ddpt' PACKAGE_TARNAME='ddpt' -PACKAGE_VERSION='0.94' -PACKAGE_STRING='ddpt 0.94' +PACKAGE_VERSION='0.95' +PACKAGE_STRING='ddpt 0.95' PACKAGE_BUGREPORT='dgilbert@interlog.com' PACKAGE_URL='' @@ -603,6 +603,7 @@ OS_FREEBSD_FALSE OS_FREEBSD_TRUE os_libs +os_cflags os_deps host_os host_vendor @@ -1260,7 +1261,7 @@ # 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. +\`configure' configures ddpt 0.95 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1330,7 +1331,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ddpt 0.94:";; + short | recursive ) echo "Configuration of ddpt 0.95:";; esac cat <<\_ACEOF @@ -1427,7 +1428,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ddpt configure 0.94 +ddpt configure 0.95 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1705,7 +1706,7 @@ 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 +It was created by ddpt $as_me 0.95, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2054,7 +2055,7 @@ -am__api_version='1.13' +am__api_version='1.14' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do @@ -2569,7 +2570,7 @@ # Define the identity of the package. PACKAGE='ddpt' - VERSION='0.94' + VERSION='0.95' cat >>confdefs.h <<_ACEOF @@ -2620,6 +2621,47 @@ +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi { $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; } @@ -3434,6 +3476,65 @@ 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 + +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 whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +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" @@ -4327,6 +4428,8 @@ #define SG_LIB_LINUX 1 _ACEOF + os_cflags='' + os_libs='' ;; *-*-linux*) @@ -4337,6 +4440,8 @@ #define SG_LIB_LINUX 1 _ACEOF + os_cflags='' + os_libs='' ;; *-*-freebsd*|*-*-kfreebsd*-gnu*) @@ -4347,6 +4452,8 @@ #define SG_LIB_FREEBSD 1 _ACEOF + os_cflags='' + os_libs='-lcam' ;; *-*-solaris*) @@ -4357,6 +4464,8 @@ #define SG_LIB_SOLARIS 1 _ACEOF + os_cflags='' + os_libs='' ;; *-*-cygwin*) @@ -4372,6 +4481,8 @@ #define WIN32_SPT_DIRECT 1 _ACEOF + os_cflags='-Wno-char-subscripts' + os_libs='' ;; *-*-mingw*) @@ -4392,6 +4503,8 @@ #define SG_LIB_MINGW 1 _ACEOF + os_cflags='' + os_libs='' ;; *) @@ -4402,6 +4515,8 @@ #define SG_LIB_LINUX 1 _ACEOF + os_cflags='' + os_libs='' ;; esac @@ -5088,7 +5203,7 @@ # 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 +This file was extended by ddpt $as_me 0.95, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5154,7 +5269,7 @@ 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 +ddpt config.status 0.95 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru ddpt-0.94/configure.ac ddpt-0.95/configure.ac --- ddpt-0.94/configure.ac 2014-01-22 23:06:58.000000000 +0000 +++ ddpt-0.95/configure.ac 2014-09-23 15:41:34.000000000 +0000 @@ -1,4 +1,4 @@ -AC_INIT(ddpt, 0.94, dgilbert@interlog.com) +AC_INIT(ddpt, 0.95, dgilbert@interlog.com) AM_INIT_AUTOMAKE AM_MAINTAINER_MODE @@ -40,33 +40,40 @@ *-*-linux-gnu*) AC_SUBST([os_deps], ['sg_pt_linux.o']) AC_DEFINE_UNQUOTED(SG_LIB_LINUX, 1, [ddpt on linux]) + AC_SUBST([os_cflags], ['']) 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_cflags], ['']) 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_cflags], ['']) 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_cflags], ['']) 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_cflags], ['-Wno-char-subscripts']) 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_cflags], ['']) 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_cflags], ['']) AC_SUBST([os_libs], ['']) ;; esac diff -Nru ddpt-0.94/ddpt.spec ddpt-0.95/ddpt.spec --- ddpt-0.94/ddpt.spec 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/ddpt.spec 2014-12-27 06:01:02.000000000 +0000 @@ -1,5 +1,5 @@ %define name ddpt -%define version 0.94 +%define version 0.95 %define release 1 Summary: Copy files (like dd) especially SCSI/storage devices @@ -50,6 +50,9 @@ %{_mandir}/man8/* %changelog +* Fri Dec 26 2014 - dgilbert at interlog dot com +- show percent completed, job file + * ddpt-0.95 * Mon Apr 07 2014 - dgilbert at interlog dot com - add ODX (subset xcopy(LID4)) support * ddpt-0.94 diff -Nru ddpt-0.94/debian/changelog ddpt-0.95/debian/changelog --- ddpt-0.94/debian/changelog 2018-11-09 11:36:13.000000000 +0000 +++ ddpt-0.95/debian/changelog 2018-09-20 13:44:23.000000000 +0000 @@ -1,8 +1,17 @@ -ddpt (0.94-1build1) bionic; urgency=high +ddpt (0.95-1) unstable; urgency=medium - * No change rebuild to pick up -fPIE compiler default + * New upstream version 0.95 + * New debian/.gitognore: Ignore Emacs version-control files. + * New debian/watch: Enable use of uscan to detect and download new + upstream releases. + * In debian/compat: New minimum debhelper version set to 10. + * In debian/control: Least acceptable version of is now 10. + * In debian/control: Standards-Version is now 4.2.1. + * New debian/source/format: As explained by Lintian: Explicitly + selecting a source format by putting the format in + debian/source/format is recommended. - -- Balint Reczey Tue, 03 Apr 2018 12:18:58 +0000 + -- Tomas Fasth Thu, 20 Sep 2018 15:44:23 +0200 ddpt (0.94-1) unstable; urgency=low diff -Nru ddpt-0.94/debian/compat ddpt-0.95/debian/compat --- ddpt-0.94/debian/compat 2018-11-09 11:36:13.000000000 +0000 +++ ddpt-0.95/debian/compat 2018-09-20 13:44:23.000000000 +0000 @@ -1 +1 @@ -8 +10 diff -Nru ddpt-0.94/debian/control ddpt-0.95/debian/control --- ddpt-0.94/debian/control 2018-11-09 11:36:13.000000000 +0000 +++ ddpt-0.95/debian/control 2018-09-20 13:44:23.000000000 +0000 @@ -1,10 +1,9 @@ Source: ddpt Section: admin Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Tomas Fasth -Build-Depends: cdbs (>= 0.4.15), debhelper (>= 8), autotools-dev -Standards-Version: 3.9.5 +Maintainer: Tomas Fasth +Build-Depends: cdbs (>= 0.4.15), debhelper (>= 10), autotools-dev +Standards-Version: 4.2.1 Package: ddpt Architecture: any diff -Nru ddpt-0.94/debian/source/format ddpt-0.95/debian/source/format --- ddpt-0.94/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ ddpt-0.95/debian/source/format 2018-09-20 13:44:23.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru ddpt-0.94/debian/watch ddpt-0.95/debian/watch --- ddpt-0.94/debian/watch 1970-01-01 00:00:00.000000000 +0000 +++ ddpt-0.95/debian/watch 2018-09-20 13:44:23.000000000 +0000 @@ -0,0 +1,5 @@ +# See uscan(1) for format + +# Compulsory line, this is a version 3 file +version=3 +http://sg.danny.cz/sg/p/ddpt-([0-9.]+)\.tgz diff -Nru ddpt-0.94/doc/ddpt.8 ddpt-0.95/doc/ddpt.8 --- ddpt-0.94/doc/ddpt.8 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/doc/ddpt.8 2014-12-27 06:01:02.000000000 +0000 @@ -1,4 +1,4 @@ -.TH DDPT "8" "April 2014" "ddpt\-0.94" DDPT +.TH DDPT "8" "December 2014" "ddpt\-0.95" DDPT .SH NAME ddpt \- copies data between files and storage devices. Support for devices that understand the SCSI command set. @@ -12,8 +12,9 @@ [\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] +[\fIto=TO\fR] [\fIverbose=VERB\fR] [\fI\-\-help\fR] [\fI\-\-job=JF\fR] +[\fI\-\-odx\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-wscan\fR] +[\fI\-\-xcopy\fR] [\fIJF\fR] .PP For comparison here is the synopsis for GNU's dd command: .PP @@ -121,7 +122,8 @@ 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 +below. The default is 512 bytes unless overridden by the DDPT_DEF_BS +environment variable. 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 @@ -368,6 +370,16 @@ \fB\-h\fR, \fB\-\-help\fR reports usage message then exits. .TP +\fB\-\-job\fR=\fIJF\fR +where \fIJF\fR is a file name. That file can contain options listed in +this section. The options within the file are processed in the order +they are found (i.e. parsing left to right, top (of file) to bottom) and +options may override earlier ones or accumulate. For example '\-v' on the +command line followed by a job file containing '\-vv' will result in a +verbosity level of '\-vvv' during the copy phase. Job files can +recurse (i.e. call another or the same job file) up to a depth of 5. Empty +lines and anything from and including a '#' in a job file line is ignored. +.TP \fB\-o\fR, \fB\-\-odx\fR indicates to this utility that one of the four odx variants is requested. See ODX section. @@ -393,6 +405,14 @@ 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. +.TP +\fBJF\fR +a command line element that does not contain a '=' (i.e. a dd style option) +and does not start with '\-' is treated as a job file (i.e. \fIJF\fR). See +the entry on \fI\-\-job=JF\fR above. For sanity \fIJF\fR is checked to make +sure it is "regular" (i.e. not a device file like /dev/sdc) and for non +ASCII characters lest it be a binary file by accident. Failing those checks +may be overridden by 'iflag=force' or 'oflag=force'. .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. @@ -506,12 +526,24 @@ appended to \fIRTF\fR. The default action is to truncate \fIRTF\fR before new ROD Tokens are written to it. .TP +atomic [o] [pt] +this flag changes the pass\-through SCSI WRITE command to the SCSI WRITE +ATOMIC(16) command on \fIOFILE\fR (and the \fIcdbsz=\fR{6|10|12|16|32} +option is ignored for \fIOFILE\fR). If this flag is applied to \fIIFILE\fR +or to a non pass\-through file then it is ignored. +.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 +bytchk [o] [pt] +only active when used together with oflag=verify. Sets the BYTCHK field in +the SCSI WRITE AND VERIFY command. Since that field is two bits wide, this +flag can be specified multiple times (up to three) to place the coresponding +value in the field. T10 only allows BYTCHK=1 or 1 at this time. +.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 @@ -585,6 +617,12 @@ Flushes data associated with the \fIOFILE\fR to storage at the end of the copy. .TP +ff [i] +This replaces \fIIFILE\fR with a source of 0xff bytes. Can only be used +on input and an error is generated if the \fIif=IFILE\fR option is also +given. Zeros can easily be generated by using "if=/dev/zero" or an +equivalent. +.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() @@ -641,9 +679,8 @@ 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. +difference because the copy manager deletes a ROD Token when its inactivity +time-out occurs. .TP nofm [o] [tape] no File Mark (FM) on close when writing to tape. See TAPE section. @@ -733,12 +770,16 @@ 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] +sparse [io] [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. +.br +The sparse flag may be used on input when a file is only being read (e.g. +when \fIof=OFILE\fR is not given or \fIOFILE\fR is /dev/null) to determine +how many blocks are contained in sparse segments of \fIIFILE\fR. .TP ssync [o] [pt] if \fIOFILE\fR is in "pt" mode then the SCSI SYNCHRONIZE CACHE command is @@ -746,8 +787,9 @@ .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. +of the \fIOFILE\fR if required. Sets the sparse flag internally if this +has not been specified on the command line. 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 @@ -780,6 +822,12 @@ unmap [io] [pt] same as the trim flag. .TP +verify [o] [pt] +this causes SCSI WRITE AND VERIFY commands to be sent to \fIOFILE\fR (instead +of SCSI WRITE (or WRITE ATOMIC) commands). Note that the fua flag is ignored +when this flag is given. The BYTCHK field in the SCSI WRITE AND VERIFY +commands is set to zero unless the bytchk flag is also given. +.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 @@ -1084,6 +1132,14 @@ but "count=-1" is a special case and means "all available"; "verbose=-1" is another special case. .SH NOTES +Copying data behind an Operating System's back can cause problems. In the +case of Linux, users should look at this link: +http://linux\-mm.org/Drop_Caches +.br +This command sequence may be useful: +.br + sync; echo 3 > /proc/sys/vm/drop_caches +.PP 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 @@ -1255,6 +1311,12 @@ 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. +.PP +Sometimes the default block size of 512 can be a nuisance. This can be +overridden by the value associated with the DDPT_DEF_BS environment +variable. If the environment variable is not found, the value cannot +be decoded or is zero or less, then the default block size remains +at 512 bytes. .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 @@ -1288,11 +1350,20 @@ requested command has not been executed by the device. Note that unit attention conditions are usually only reported once by a device. .TP +.B 7 +the device reports a "data protect" sense key. This implies some +mechanism has blocked writes (or possibly all access to the media). +.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 10 +the device reports a "copy aborted". This implies another command or +device problem has stopped and copy operation. The EXTENDED COPY family of +commands (including WRITE USING TOKEN) may return this sense key. +.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 @@ -1312,10 +1383,24 @@ 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 24 +the device reports a SCSI status of "reservation conflict". This +means access to the device with the current command has been blocked +because another machine (HBA or SCSI "initiator") holds a reservation on +this device. On modern SCSI systems this is related to the use of +the PERSISTENT RESERVATION family of commands. +.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 40 +the command sent to a device has received an "aborted command" sense +key with an additional sense code of 0x10. This group is related to +problems with protection information (PI or DIF). For example this error +may occur when reading a block on a drive that has never been written (or +is unmapped) if that drive was formatted with type 1, 2 or 3 protection. +.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. @@ -1442,7 +1527,8 @@ 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. +distribution tarball. The ddpt_examples.txt file contains some examples of +using job files. .SH AUTHORS Written by Doug Gilbert .SH "REPORTING BUGS" diff -Nru ddpt-0.94/doc/ddptctl.8 ddpt-0.95/doc/ddptctl.8 --- ddpt-0.94/doc/ddptctl.8 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/doc/ddptctl.8 2014-12-21 03:23:51.000000000 +0000 @@ -1,14 +1,14 @@ -.TH DDPTCTL "8" "April 2014" "ddpt\-0.94" DDPT +.TH DDPTCTL "8" "December 2014" "ddpt\-0.95" 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] +[\fI\-\-oir=OIR\fR] [\fI\-\-poll\fR] [\fI\-\-pt=GL\fR] [\fI\-\-readonly\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 @@ -53,10 +53,9 @@ .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. +Since an ODX copy manager deletes the ROD Token when its inactivity +time-out is reached, this option is typically not needed. It may +be useful for long\-lived ROD Tokens that 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'). @@ -135,6 +134,10 @@ 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\-y\fR, \fB\-\-readonly\fR +open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag). +The default is to open it read\-write. +.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 diff -Nru ddpt-0.94/doc/ddpt_examples.txt ddpt-0.95/doc/ddpt_examples.txt --- ddpt-0.94/doc/ddpt_examples.txt 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/doc/ddpt_examples.txt 2014-12-27 06:01:02.000000000 +0000 @@ -299,4 +299,50 @@ time to transfer data: 0.747828 secs at 717.91 MB/sec -# Douglas Gilbert 20140407 +# Job files are designed to lessen to tedium of repeatedly entering numerous +# command options to ddpt. Instead, some or all options can be placed in a +# job file can then be named on the command line. For example, assume a file +# called "read_1m_zero.jf" contains the following 9 lines: + +# Example job file for ddpt that reads from /dev/zero 1m blocks, each +# of 512 bytes. The count value of "1m" is 1024*1024=1048576 + +if=/dev/zero +bs=512 +count=1m +of=/dev/null +# -vv + +# This can be used like this (and can be executed by a non-root user since +# /dev/zero can be read by all and the copy is relatively harmless): +$ ddpt read_1m_zero.jf +1048576+0 records in +0+0 records out +time to read data: 0.055672 secs at 9643.46 MB/sec + +# It may not be a good idea to put the if= and particularly of= options +# inside a job file as they are most likely to change. Some options are +# allowed to be changed while others are not, typically with a view to +# safety. For example: +$ ddpt read_1m_zero.jf if=/dev/null +Second IFILE argument?? + +# Some other options can be overridden, in which case the last one seen +# is used: +$ ddpt count=1000x1000 read_1m_zero.jf +1048576+0 records in +0+0 records out +time to read data: 0.052276 secs at 10269.93 MB/sec + +$ ddpt read_1m_zero.jf count=1000x1000 +1000000+0 records in +0+0 records out +time to read data: 0.051909 secs at 9863.41 MB/sec + +# A job file can contain comments: anything from a "#" to the end of a +# line is considered a comment. Blanks lines are permitted and ignored. +# Job files can invoke other job files, to a level of 4 deep. Some checks +# are made that a file assumed to contain text and ddpt options is not +# actually binary, but that is error prone. + +# Douglas Gilbert 20141226 diff -Nru ddpt-0.94/doc/Makefile.in ddpt-0.95/doc/Makefile.in --- ddpt-0.94/doc/Makefile.in 2014-02-23 04:13:58.000000000 +0000 +++ ddpt-0.95/doc/Makefile.in 2014-09-23 15:41:34.000000000 +0000 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -224,6 +224,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +os_cflags = @os_cflags@ os_deps = @os_deps@ os_libs = @os_libs@ pdfdir = @pdfdir@ diff -Nru ddpt-0.94/include/Makefile.in ddpt-0.95/include/Makefile.in --- ddpt-0.94/include/Makefile.in 2013-10-31 15:01:34.000000000 +0000 +++ ddpt-0.95/include/Makefile.in 2014-09-02 00:13:42.000000000 +0000 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -271,6 +271,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +os_cflags = @os_cflags@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ diff -Nru ddpt-0.94/include/sg_cmds_basic.h ddpt-0.95/include/sg_cmds_basic.h --- ddpt-0.94/include/sg_cmds_basic.h 2014-02-23 03:59:50.000000000 +0000 +++ ddpt-0.95/include/sg_cmds_basic.h 2014-06-12 13:35:52.000000000 +0000 @@ -168,13 +168,14 @@ struct sg_simple_inquiry_resp { unsigned char peripheral_qualifier; unsigned char peripheral_type; - unsigned char rmb; + unsigned char byte_1; /* was 'rmb' prior to version 1.39 */ + /* now rmb == !!(0x80 & byte_1) */ 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 vendor[9]; /* T10 field is 8 bytes, NUL char appended */ char product[17]; char revision[5]; }; diff -Nru ddpt-0.94/include/sg_lib_data.h ddpt-0.95/include/sg_lib_data.h --- ddpt-0.94/include/sg_lib_data.h 2013-07-02 04:21:40.000000000 +0000 +++ ddpt-0.95/include/sg_lib_data.h 2014-04-26 05:13:33.000000000 +0000 @@ -22,20 +22,21 @@ #endif /* Commands with service actions that change the command name */ +#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_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_READ_BUFFER 0x3c +#define SG_SANITIZE 0x48 #define SG_SERVICE_ACTION_BIDI 0x9d +#define SG_SERVICE_ACTION_IN_12 0xab #define SG_SERVICE_ACTION_IN_16 0x9e +#define SG_SERVICE_ACTION_OUT_12 0xa9 #define SG_SERVICE_ACTION_OUT_16 0x9f -#define SG_READ_BUFFER 0x3c -#define SG_WRITE_BUFFER 0x3b #define SG_VARIABLE_LENGTH_CMD 0x7f +#define SG_WRITE_BUFFER 0x3b @@ -68,6 +69,7 @@ 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_sanitize_sa_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[]; diff -Nru ddpt-0.94/include/sg_lib.h ddpt-0.95/include/sg_lib.h --- ddpt-0.94/include/sg_lib.h 2014-03-22 17:54:40.000000000 +0000 +++ ddpt-0.95/include/sg_lib.h 2014-05-15 15:54:06.000000000 +0000 @@ -225,35 +225,45 @@ 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 +/* Utilities can use these exit 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 +#define SG_LIB_SYNTAX_ERROR 1 /* command line syntax problem */ +#define SG_LIB_FILE_ERROR 15 /* device or other file problem */ /* The sg_err_category_sense() function returns one of the following. - * These may be used as process status values (on exit). Notice that + * These may be used as exit status values (from a process). 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 */ +#define SG_LIB_CAT_NOT_READY 2 /* sense key, unit stopped? */ /* [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 */ +#define SG_LIB_CAT_UNIT_ATTENTION 6 /* sense key, device state changed */ /* [sk,asc,ascq: 0x6,*,*] */ /* was SG_LIB_CAT_MEDIA_CHANGED earlier [sk,asc,ascq: 0x6,0x28,*] */ +#define SG_LIB_CAT_DATA_PROTECT 7 /* sense key, media write protected? */ + /* [sk,asc,ascq: 0x7,*,*] */ #define SG_LIB_CAT_INVALID_OP 9 /* (Illegal request,) Invalid opcode: */ /* [sk,asc,ascq: 0x5,0x20,0x0] */ +#define SG_LIB_CAT_COPY_ABORTED 10 /* sense key, some data transferred */ + /* [sk,asc,ascq: 0xa,*,*] */ #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: 0xb,! 0x10,*] */ +#define SG_LIB_CAT_MISCOMPARE 14 /* sense key, probably verify */ /* [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_RES_CONFLICT SAM_STAT_RESERVATION_CONFLICT + /* 24: this is a SCSI status, not sense. */ + /* It indicates reservation by another */ + /* machine blocks this command */ +#define SG_LIB_CAT_PROTECTION 40 /* subset of aborted command (for PI, DIF) */ + /* [sk,asc,ascq: 0xb,0x10,*] */ #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 */ @@ -271,8 +281,17 @@ #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_PROTECTION_WITH_INFO 41 /* aborted command sense key, */ + /* protection plus 'info' field: */ + /* [sk,asc,ascq: 0xb,0x10,*] */ #define SG_LIB_CAT_TIMEOUT 33 +/* Yield string associated with sense category. Returns 'buff' (or pointer + * to "Bad sense category" if 'buff' is NULL). If sense_cat unknown then + * yield "Sense category: " string. */ +const char * sg_get_category_sense_str(int sense_cat, int buff_len, + char * buff, int verbose); + /* Iterates to next designation descriptor in the device identification * VPD page. The 'initial_desig_desc' should point to start of first diff -Nru ddpt-0.94/include/sg_pt.h ddpt-0.95/include/sg_pt.h --- ddpt-0.94/include/sg_pt.h 2013-08-28 13:44:26.000000000 +0000 +++ ddpt-0.95/include/sg_pt.h 2014-06-04 00:24:20.000000000 +0000 @@ -2,7 +2,7 @@ #define SG_PT_H /* - * Copyright (c) 2005-2011 Douglas Gilbert. + * Copyright (c) 2005-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. diff -Nru ddpt-0.94/include/sg_unaligned.h ddpt-0.95/include/sg_unaligned.h --- ddpt-0.94/include/sg_unaligned.h 1970-01-01 00:00:00.000000000 +0000 +++ ddpt-0.95/include/sg_unaligned.h 2014-09-18 05:20:09.000000000 +0000 @@ -0,0 +1,251 @@ +#ifndef SG_UNALIGNED_H +#define SG_UNALIGNED_H + +/* + * Copyright (c) 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 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Borrowed from the Linux kernel, via mhvtl */ + +/* In the first section below, functions that copy unsigned integers in + * a computer's native format, to and from an unaligned big endian sequence + * of bytes. Big endian byte format "on the wire" is the default used by + * SCSI standards (www.t10.org). */ + +static inline uint16_t __get_unaligned_be16(const uint8_t *p) +{ + return p[0] << 8 | p[1]; +} + +static inline uint32_t __get_unaligned_be32(const uint8_t *p) +{ + return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +} + +static inline uint64_t __get_unaligned_be64(const uint8_t *p) +{ + return (uint64_t)__get_unaligned_be32(p) << 32 | + __get_unaligned_be32(p + 4); +} + +static inline void __put_unaligned_be16(uint16_t val, uint8_t *p) +{ + *p++ = val >> 8; + *p++ = val; +} + +static inline void __put_unaligned_be32(uint32_t val, uint8_t *p) +{ + __put_unaligned_be16(val >> 16, p); + __put_unaligned_be16(val, p + 2); +} + +static inline void __put_unaligned_be64(uint64_t val, uint8_t *p) +{ + __put_unaligned_be32(val >> 32, p); + __put_unaligned_be32(val, p + 4); +} + +static inline uint16_t sg_get_unaligned_be16(const void *p) +{ + return __get_unaligned_be16((const uint8_t *)p); +} + +static inline uint32_t sg_get_unaligned_be24(const uint8_t *p) +{ + return p[0] << 16 | p[1] << 8 | p[2]; +} + +static inline uint32_t sg_get_unaligned_be32(const void *p) +{ + return __get_unaligned_be32((const uint8_t *)p); +} + +static inline uint64_t sg_get_unaligned_be64(const void *p) +{ + return __get_unaligned_be64((const uint8_t *)p); +} + +static inline void sg_put_unaligned_be16(uint16_t val, void *p) +{ + __put_unaligned_be16(val, (uint8_t *)p); +} + +static inline void sg_put_unaligned_be24(uint32_t val, void *p) +{ + ((uint8_t *)p)[0] = (val >> 16) & 0xff; + ((uint8_t *)p)[1] = (val >> 8) & 0xff; + ((uint8_t *)p)[2] = val & 0xff; +} + +static inline void sg_put_unaligned_be32(uint32_t val, void *p) +{ + __put_unaligned_be32(val, (uint8_t *)p); +} + +static inline void sg_put_unaligned_be64(uint64_t val, void *p) +{ + __put_unaligned_be64(val, (uint8_t *)p); +} + +/* Since cdb and parameter blocks are often memset to zero before these + * unaligned function partially fill them, then check for a val of zero + * and ignore if it is with these variants. */ +static inline void sg_nz_put_unaligned_be16(uint16_t val, void *p) +{ + if (val) + __put_unaligned_be16(val, (uint8_t *)p); +} + +static inline void sg_nz_put_unaligned_be24(uint32_t val, void *p) +{ + if (val) { + ((uint8_t *)p)[0] = (val >> 16) & 0xff; + ((uint8_t *)p)[1] = (val >> 8) & 0xff; + ((uint8_t *)p)[2] = val & 0xff; + } +} + +static inline void sg_nz_put_unaligned_be32(uint32_t val, void *p) +{ + if (val) + __put_unaligned_be32(val, (uint8_t *)p); +} + +static inline void sg_nz_put_unaligned_be64(uint64_t val, void *p) +{ + if (val) + __put_unaligned_be64(val, (uint8_t *)p); +} + + +/* Below are the little endian equivalents of the big endian functions + * above. Little endian is used by ATA, networking and PCI. + * This section could take advantage of the + * 'uint32_t htonl(uint32_t hostlong)' [and the complementary ntohl()] + * family of functions but that would introduce a dependency on the + * header. Also they don't address moving to and from + * an unaligned sequence of bytes. The latter would still need to be + * done. + */ + +static inline uint16_t __get_unaligned_le16(const uint8_t *p) +{ + return p[1] << 8 | p[0]; +} + +static inline uint32_t __get_unaligned_le32(const uint8_t *p) +{ + return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; +} + +static inline uint64_t __get_unaligned_le64(const uint8_t *p) +{ + return (uint64_t)__get_unaligned_le32(p + 4) << 32 | + __get_unaligned_le32(p); +} + +static inline void __put_unaligned_le16(uint16_t val, uint8_t *p) +{ + *p++ = val; + *p++ = val >> 8; +} + +static inline void __put_unaligned_le32(uint32_t val, uint8_t *p) +{ + __put_unaligned_le16(val >> 16, p + 2); + __put_unaligned_le16(val, p); +} + +static inline void __put_unaligned_le64(uint64_t val, uint8_t *p) +{ + __put_unaligned_le32(val >> 32, p + 4); + __put_unaligned_le32(val, p); +} + +static inline uint16_t sg_get_unaligned_le16(const void *p) +{ + return __get_unaligned_le16((const uint8_t *)p); +} + +static inline uint32_t sg_get_unaligned_le24(const uint8_t *p) +{ + return p[2] << 16 | p[1] << 8 | p[0]; +} + +static inline uint32_t sg_get_unaligned_le32(const void *p) +{ + return __get_unaligned_le32((const uint8_t *)p); +} + +static inline uint64_t sg_get_unaligned_le64(const void *p) +{ + return __get_unaligned_le64((const uint8_t *)p); +} + +static inline void sg_put_unaligned_le16(uint16_t val, void *p) +{ + __put_unaligned_le16(val, (uint8_t *)p); +} + +static inline void sg_put_unaligned_le24(uint32_t val, void *p) +{ + ((uint8_t *)p)[2] = (val >> 16) & 0xff; + ((uint8_t *)p)[1] = (val >> 8) & 0xff; + ((uint8_t *)p)[0] = val & 0xff; +} + +static inline void sg_put_unaligned_le32(uint32_t val, void *p) +{ + __put_unaligned_le32(val, (uint8_t *)p); +} + +static inline void sg_put_unaligned_le64(uint64_t val, void *p) +{ + __put_unaligned_le64(val, (uint8_t *)p); +} + +/* Since cdb and parameter blocks are often memset to zero before these + * unaligned function partially fill them, then check for a val of zero + * and ignore if it is with these variants. */ +static inline void sg_nz_put_unaligned_le16(uint16_t val, void *p) +{ + if (val) + __put_unaligned_le16(val, (uint8_t *)p); +} + +static inline void sg_nz_put_unaligned_le24(uint32_t val, void *p) +{ + if (val) { + ((uint8_t *)p)[2] = (val >> 16) & 0xff; + ((uint8_t *)p)[1] = (val >> 8) & 0xff; + ((uint8_t *)p)[0] = val & 0xff; + } +} + +static inline void sg_nz_put_unaligned_le32(uint32_t val, void *p) +{ + if (val) + __put_unaligned_le32(val, (uint8_t *)p); +} + +static inline void sg_nz_put_unaligned_le64(uint64_t val, void *p) +{ + if (val) + __put_unaligned_le64(val, (uint8_t *)p); +} + +#ifdef __cplusplus +} +#endif + +#endif /* SG_UNALIGNED_H */ diff -Nru ddpt-0.94/lib/Makefile.am ddpt-0.95/lib/Makefile.am --- ddpt-0.94/lib/Makefile.am 2013-12-20 06:46:44.000000000 +0000 +++ ddpt-0.95/lib/Makefile.am 2014-10-19 00:18:28.000000000 +0000 @@ -40,9 +40,10 @@ ## 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 +# -Wall is no longer all warnings. Add -W (since renamed to -Wextra) for more +AM_CFLAGS = -iquote ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W +# AM_CFLAGS = -iquote ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c11 +# AM_CFLAGS = -iquote ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c++11 lib_LTLIBRARIES = libsgutils2.la diff -Nru ddpt-0.94/lib/Makefile.in ddpt-0.95/lib/Makefile.in --- ddpt-0.94/lib/Makefile.in 2013-12-16 15:36:21.000000000 +0000 +++ ddpt-0.95/lib/Makefile.in 2014-10-19 00:18:28.000000000 +0000 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -316,6 +316,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +os_cflags = @os_cflags@ os_libs = @os_libs@ pdfdir = @pdfdir@ prefix = @prefix@ @@ -337,9 +338,10 @@ # 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 +# -Wall is no longer all warnings. Add -W (since renamed to -Wextra) for more +AM_CFLAGS = -iquote ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W +# AM_CFLAGS = -iquote ../include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W -pedantic -std=c11 +# AM_CFLAGS = -iquote ../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@ @@ -442,14 +444,14 @@ @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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .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) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff -Nru ddpt-0.94/lib/sg_cmds_basic2.c ddpt-0.95/lib/sg_cmds_basic2.c --- ddpt-0.94/lib/sg_cmds_basic2.c 2013-07-30 23:58:53.000000000 +0000 +++ ddpt-0.95/lib/sg_cmds_basic2.c 2014-10-07 04:38:02.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2013 Douglas Gilbert. + * 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. @@ -67,10 +67,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group, unsigned int lba, unsigned int count, int noisy, @@ -120,19 +117,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -143,10 +133,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_readcap_16(int sg_fd, int pmi, uint64_t llba, void * resp, int mx_resp_len, int noisy, int verbose) @@ -197,19 +184,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -220,10 +200,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba, void * resp, int mx_resp_len, int noisy, int verbose) @@ -264,19 +241,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -287,15 +257,12 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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; + int res, ret, k, sense_cat, resid; unsigned char modesCmdBlk[MODE_SENSE6_CMDLEN] = {MODE_SENSE6_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; @@ -328,23 +295,18 @@ 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); + resid = get_scsi_pt_resid(ptvp); + destruct_scsi_pt_obj(ptvp); 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; + ret = sense_cat; break; } } else { @@ -355,21 +317,27 @@ } ret = 0; } - destruct_scsi_pt_obj(ptvp); + + if (resid > 0) { + if (resid > mx_resp_len) { + fprintf(sg_warnings_strm, "mode sense(6): resid (%d) should " + "never exceed requested len=%d\n", resid, mx_resp_len); + return ret ? ret : SG_LIB_CAT_MALFORMED; + } + /* zero unfilled section of response buffer */ + memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); + } 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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; + int res, ret, k, sense_cat, resid; 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]; @@ -403,23 +371,18 @@ 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); + resid = get_scsi_pt_resid(ptvp); + destruct_scsi_pt_obj(ptvp); 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; + ret = sense_cat; break; } } else { @@ -430,15 +393,21 @@ } ret = 0; } - destruct_scsi_pt_obj(ptvp); + + if (resid > 0) { + if (resid > mx_resp_len) { + fprintf(sg_warnings_strm, "mode sense(10): resid (%d) should " + "never exceed requested len=%d\n", resid, mx_resp_len); + return ret ? ret : SG_LIB_CAT_MALFORMED; + } + /* zero unfilled section of response buffer */ + memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); + } 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp, int param_len, int noisy, int verbose) @@ -483,19 +452,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -506,10 +468,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp, int param_len, int noisy, int verbose) @@ -555,19 +514,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -632,10 +584,8 @@ * 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. + * Return of 0 -> overall success, various SG_LIB_CAT_* positive values or + * -1 -> other errors. * 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 @@ -744,16 +694,13 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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; + int res, ret, k, sense_cat, resid; 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]; @@ -790,23 +737,18 @@ 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); + resid = get_scsi_pt_resid(ptvp); + destruct_scsi_pt_obj(ptvp); 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; + ret = sense_cat; break; } } else { @@ -817,15 +759,21 @@ } ret = 0; } - destruct_scsi_pt_obj(ptvp); + + if (resid > 0) { + if (resid > mx_resp_len) { + fprintf(sg_warnings_strm, "log sense: resid (%d) should " + "never exceed requested len=%d\n", resid, mx_resp_len); + return ret ? ret : SG_LIB_CAT_MALFORMED; + } + /* zero unfilled section of response buffer */ + memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); + } 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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, @@ -874,19 +822,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -898,10 +839,7 @@ /* 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 + * various SG_LIB_CAT_* positive values or -1 -> other errors. * 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 @@ -944,19 +882,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -969,10 +900,7 @@ * [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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy, int verbose) { @@ -1011,19 +939,12 @@ ; 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; + ret = sense_cat; break; } } else diff -Nru ddpt-0.94/lib/sg_cmds_basic.c ddpt-0.95/lib/sg_cmds_basic.c --- ddpt-0.94/lib/sg_cmds_basic.c 2014-03-03 21:25:31.000000000 +0000 +++ ddpt-0.95/lib/sg_cmds_basic.c 2014-10-07 04:38:02.000000000 +0000 @@ -27,7 +27,7 @@ #endif -static const char * version_str = "1.66 20140222"; +static const char * version_str = "1.69 20141006"; #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ @@ -46,7 +46,7 @@ #define TUR_CMD 0x0 #define TUR_CMDLEN 6 -#define INQUIRY_RESP_INITIAL_LEN 36 +#define SAFE_STD_INQ_RESP_LEN 36 /* other lengths lock up some devices */ const char * @@ -94,7 +94,11 @@ case SG_LIB_CAT_INVALID_OP: case SG_LIB_CAT_ILLEGAL_REQ: case SG_LIB_CAT_ABORTED_COMMAND: + case SG_LIB_CAT_COPY_ABORTED: + case SG_LIB_CAT_DATA_PROTECT: + case SG_LIB_CAT_PROTECTION: case SG_LIB_CAT_NO_SENSE: + case SG_LIB_CAT_MISCOMPARE: n = 0; break; case SG_LIB_CAT_RECOVERED: @@ -102,6 +106,7 @@ ++check_data_in; /* drop through */ case SG_LIB_CAT_UNIT_ATTENTION: + case SG_LIB_CAT_SENSE: default: n = noisy; break; @@ -126,8 +131,8 @@ * 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 + * "sense" category (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 @@ -138,7 +143,7 @@ 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; + int got, cat, duration, slen, resid, resp_code, sstat; char b[1024]; if (NULL == sg_warnings_strm) @@ -186,9 +191,14 @@ } else return 0; case SCSI_PT_RESULT_STATUS: /* other than GOOD and CHECK CONDITION */ + sstat = get_scsi_pt_status_response(ptvp); + if ((SAM_STAT_RESERVATION_CONFLICT == sstat) && o_sense_cat) { + /* treat this SCSI status as "sense" category */ + *o_sense_cat = SG_LIB_CAT_RES_CONFLICT; + return -2; + } if (verbose || noisy) { - sg_get_scsi_status_str(get_scsi_pt_status_response(ptvp), - sizeof(b), b); + sg_get_scsi_status_str(sstat, sizeof(b), b); fprintf(sg_warnings_strm, "%s: scsi status: %s\n", leadin, b); } return -1; @@ -219,15 +229,13 @@ } } -/* 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 */ +/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when + * successful, various SG_LIB_CAT_* positive values or -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; + int res, ret, k, sense_cat, resid; unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0}; unsigned char sense_b[SENSE_BUFF_LEN]; unsigned char * up; @@ -266,22 +274,18 @@ 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); + resid = get_scsi_pt_resid(ptvp); 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; + ret = sense_cat; break; } } else if (ret < 4) { @@ -292,13 +296,21 @@ } else ret = 0; + if (resid > 0) { + if (resid > mx_resp_len) { + fprintf(sg_warnings_strm, "inquiry: resid (%d) should never " + "exceed requested len=%d\n", resid, mx_resp_len); + return ret ? ret : SG_LIB_CAT_MALFORMED; + } + /* zero unfilled section of response buffer */ + memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); + } 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 */ + * Returns 0 when successful, various SG_LIB_CAT_* positive values or + * -1 -> other errors */ int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data, int noisy, int verbose) @@ -306,7 +318,7 @@ 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]; + unsigned char inq_resp[SAFE_STD_INQ_RESP_LEN]; struct sg_pt_base * ptvp; if (inq_data) { @@ -340,17 +352,12 @@ ; 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; + ret = sense_cat; break; } } else if (ret < 4) { @@ -361,10 +368,10 @@ } else ret = 0; - if (0 == ret) { + if (inq_data && (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->byte_1 = inq_resp[1]; inq_data->version = inq_resp[2]; inq_data->byte_3 = inq_resp[3]; inq_data->byte_5 = inq_resp[5]; @@ -382,9 +389,8 @@ * '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 */ + * Returns 0 when successful, various SG_LIB_CAT_* positive values or + * -1 -> other errors */ int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress, int noisy, int verbose) @@ -424,19 +430,12 @@ *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; + ret = sense_cat; break; } } else @@ -448,9 +447,8 @@ /* 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 */ + * Returns 0 when successful, various SG_LIB_CAT_* positive values or + * -1 -> other errors */ int sg_ll_test_unit_ready(int sg_fd, int pack_id, int noisy, int verbose) { @@ -458,10 +456,8 @@ 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 */ +/* Invokes a SCSI REQUEST SENSE command. Returns 0 when successful, various + * SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len, int noisy, int verbose) @@ -503,18 +499,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -531,10 +521,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_report_luns(int sg_fd, int select_report, void * resp, int mx_resp_len, int noisy, int verbose) @@ -574,18 +561,12 @@ ; 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; + ret = sense_cat; break; } } else diff -Nru ddpt-0.94/lib/sg_cmds_extra.c ddpt-0.95/lib/sg_cmds_extra.c --- ddpt-0.94/lib/sg_cmds_extra.c 2014-01-23 23:25:22.000000000 +0000 +++ ddpt-0.95/lib/sg_cmds_extra.c 2014-09-22 02:43:43.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2013 Douglas Gilbert. + * 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. @@ -91,9 +91,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp, int alloc_len, int noisy, int verbose) @@ -143,19 +141,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -179,9 +170,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len, int extended, int noisy, int verbose) @@ -226,18 +215,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -253,9 +236,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_set_tgt_prt_grp(int sg_fd, void * paramp, int param_len, int noisy, int verbose) @@ -301,18 +282,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -322,9 +297,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg, void * resp, int mx_resp_len, int noisy, @@ -376,18 +349,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -406,10 +373,7 @@ * 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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, @@ -459,19 +423,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -482,10 +439,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp, int mx_resp_len, int noisy, int verbose) @@ -527,19 +481,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -554,11 +501,8 @@ 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 */ +/* Invokes a SCSI READ DEFECT DATA (10) command (SBC). Return of 0 -> success + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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) @@ -601,19 +545,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -629,10 +566,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose) @@ -674,19 +608,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -703,10 +630,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_report_id_info(int sg_fd, int itype, void * resp, int max_resp_len, int noisy, int verbose) @@ -750,19 +674,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -779,10 +696,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_set_id_info(int sg_fd, int itype, void * paramp, int param_len, int noisy, int verbose) @@ -829,19 +743,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -852,10 +759,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_format_unit(int sg_fd, int fmtpinfo, int longlist, int fmtdata, int cmplst, int dlist_format, int timeout_secs, @@ -906,19 +810,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -929,9 +826,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist, void * paramp, int param_len, int noisy, int verbose) @@ -972,19 +867,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -995,9 +883,8 @@ } /* 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 */ + * when successful, various SG_LIB_CAT_* positive values or + * -1 -> other errors */ int sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp, int mx_resp_len, int noisy, int verbose) @@ -1039,18 +926,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -1066,9 +947,8 @@ } /* 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 */ + * when successful, various SG_LIB_CAT_* positive values or + * -1 -> other errors */ int sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, int rq_scope, unsigned int rq_type, void * paramp, @@ -1115,18 +995,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -1156,11 +1030,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned int lba, void * resp, int xfer_len, int * offsetp, int noisy, @@ -1208,12 +1078,6 @@ ; 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; @@ -1239,7 +1103,7 @@ } break; default: - ret = -1; + ret = sense_cat; break; } } else { @@ -1256,11 +1120,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_read_long16(int sg_fd, int pblock, int correct, uint64_t llba, void * resp, int xfer_len, int * offsetp, int noisy, @@ -1313,12 +1173,6 @@ ; 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; @@ -1344,7 +1198,7 @@ } break; default: - ret = -1; + ret = sense_cat; break; } } else { @@ -1361,12 +1215,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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, @@ -1416,12 +1265,6 @@ ; 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; @@ -1447,7 +1290,7 @@ } break; default: - ret = -1; + ret = sense_cat; break; } } else @@ -1459,12 +1302,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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, @@ -1519,12 +1357,6 @@ ; 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; @@ -1550,7 +1382,7 @@ } break; default: - ret = -1; + ret = sense_cat; break; } } else @@ -1563,12 +1395,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_verify10(int sg_fd, int vrprotect, int dpo, int bytchk, unsigned int lba, int veri_len, void * data_out, @@ -1620,14 +1447,6 @@ ; 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; @@ -1648,7 +1467,7 @@ } break; default: - ret = -1; + ret = sense_cat; break; } } else @@ -1661,12 +1480,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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, @@ -1724,14 +1538,6 @@ ; 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; @@ -1752,7 +1558,7 @@ } break; default: - ret = -1; + ret = sense_cat; break; } } else @@ -1923,11 +1729,8 @@ 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 */ +/* Invokes a SCSI READ BUFFER command (SPC). Return of 0 -> success + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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) @@ -1970,19 +1773,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -1997,11 +1793,8 @@ 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 */ +/* Invokes a SCSI WRITE BUFFER command (SPC). Return of 0 -> success + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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) @@ -2050,19 +1843,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -2073,9 +1859,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_unmap(int sg_fd, int group_num, int timeout_secs, void * paramp, int param_len, int noisy, int verbose) @@ -2099,7 +1883,7 @@ if (anchor) uCmdBlk[1] |= 0x1; tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT; - uCmdBlk[7] = group_num & 0x1f; + uCmdBlk[6] = group_num & 0x1f; uCmdBlk[7] = (param_len >> 8) & 0xff; uCmdBlk[8] = param_len & 0xff; if (NULL == sg_warnings_strm) @@ -2130,18 +1914,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -2151,10 +1929,7 @@ } /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_read_block_limits(int sg_fd, void * resp, int mx_resp_len, int noisy, int verbose) @@ -2189,18 +1964,12 @@ ; 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; + ret = sense_cat; break; } } else { @@ -2217,10 +1986,7 @@ /* 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp, int mx_resp_len, int noisy, int verbose) @@ -2271,19 +2037,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -2299,10 +2058,7 @@ * 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ int sg_ll_extended_copy(int sg_fd, void * paramp, int param_len, int noisy, int verbose) @@ -2349,19 +2105,12 @@ ; 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; + ret = sense_cat; break; } } else @@ -2374,10 +2123,7 @@ * 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 */ + * various SG_LIB_CAT_* positive values or -1 -> other errors */ 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, @@ -2454,19 +2200,12 @@ ; 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; + ret = sense_cat; break; } } else diff -Nru ddpt-0.94/lib/sg_lib.c ddpt-0.95/lib/sg_lib.c --- ddpt-0.94/lib/sg_lib.c 2014-04-02 01:00:54.000000000 +0000 +++ ddpt-0.95/lib/sg_lib.c 2014-08-29 20:21:51.000000000 +0000 @@ -46,9 +46,20 @@ #define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d /* corresponding ASC is 0 */ +/* The following two opcodes were renamed to 'Third party copy out/in' in + * spc4r34 */ +#define SG_THIRD_PARTY_COPY_OUT SG_EXTENDED_COPY +#define SG_THIRD_PARTY_COPY_IN SG_RECEIVE_COPY + FILE * sg_warnings_strm = NULL; /* would like to default to stderr */ +#ifdef __GNUC__ +static int my_snprintf(char * cp, int cp_max_len, const char * fmt, ...) + __attribute__ ((format (printf, 3, 4))); +#else +static int my_snprintf(char * cp, int cp_max_len, const char * fmt, ...); +#endif /* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of * functions. Returns number number of chars placed in cp excluding the @@ -129,7 +140,8 @@ void sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff) { - const char * ccp; + const char * ccp = NULL; + int unknown = 0; if ((NULL == buff) || (buff_len < 1)) return; @@ -144,15 +156,20 @@ 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 0x14: ccp = "Intermediate-Condition Met (obsolete)"; 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; + default: + unknown = 1; + break; } - my_snprintf(buff, buff_len, "%s", ccp); + if (unknown) + my_snprintf(buff, buff_len, "Unknown status [0x%x]", scsi_status); + else + my_snprintf(buff, buff_len, "%s", ccp); } void @@ -167,6 +184,8 @@ fprintf(sg_warnings_strm, "%s ", buff); } +/* 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) { @@ -184,6 +203,7 @@ } } +/* Yield string associated with sense_key value. Returns 'buff'. */ char * sg_get_sense_key_str(int sense_key, int buff_len, char * buff) { @@ -198,6 +218,7 @@ return 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) { @@ -247,6 +268,9 @@ return buff; } +/* 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) @@ -273,6 +297,9 @@ return NULL; } +/* 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) @@ -312,6 +339,10 @@ } } +/* 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) @@ -572,8 +603,9 @@ processed = 0; break; } - n += my_snprintf(b + n, blen - n, " Error in %s byte %d", - (descp[4] & 0x40) ? "Command" : "Data", + n += my_snprintf(b + n, blen - n, " Error in %s: byte %d", + (descp[4] & 0x40) ? "Command" : + "Data parameters", (descp[5] << 8) | descp[6]); if (descp[4] & 0x08) { n += my_snprintf(b + n, blen - n, " bit %d\n", @@ -808,8 +840,7 @@ { int n = 0; - if (slen) { ; } /* unused, suppress warning */ - if (blen < 1) + if ((blen < 1) || (slen < 12)) return; if (SPC_SK_RECOVERED_ERROR != (0xf & sp[2])) n += my_snprintf(b + n, blen - n, " >> expected Sense key: " @@ -947,8 +978,9 @@ 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"), + "Error in %s: byte %d", + ((sense_buffer[15] & 0x40) ? "Command" : + "Data parameters"), (sense_buffer[16] << 8) | sense_buffer[17]); if (sense_buffer[15] & 0x08) r += my_snprintf(b + r, blen - r, " bit %d\n", @@ -1113,12 +1145,17 @@ return SG_LIB_CAT_ILLEGAL_REQ; break; case SPC_SK_ABORTED_COMMAND: - return SG_LIB_CAT_ABORTED_COMMAND; + if (0x10 == ssh.asc) + return SG_LIB_CAT_PROTECTION; + else + return SG_LIB_CAT_ABORTED_COMMAND; case SPC_SK_MISCOMPARE: return SG_LIB_CAT_MISCOMPARE; case SPC_SK_DATA_PROTECT: - case SPC_SK_COMPLETED: + return SG_LIB_CAT_DATA_PROTECT; case SPC_SK_COPY_ABORTED: + return SG_LIB_CAT_COPY_ABORTED; + case SPC_SK_COMPLETED: case SPC_SK_VOLUME_OVERFLOW: return SG_LIB_CAT_SENSE; default: @@ -1168,12 +1205,39 @@ sg_get_opcode_sa_name(cmdp[0], service_action, peri_type, buff_len, buff); } +struct op_code2sa_t { + int op_code; + struct sg_lib_value_name_t * arr; + const char * prefix; +}; + +static struct op_code2sa_t op_code2sa_arr[] = { + {SG_VARIABLE_LENGTH_CMD, sg_lib_variable_length_arr, NULL}, + {SG_MAINTENANCE_IN, sg_lib_maint_in_arr, NULL}, + {SG_MAINTENANCE_OUT, sg_lib_maint_out_arr, NULL}, + {SG_SERVICE_ACTION_IN_12, sg_lib_serv_in12_arr, NULL}, + {SG_SERVICE_ACTION_OUT_12, sg_lib_serv_out12_arr, NULL}, + {SG_SERVICE_ACTION_IN_16, sg_lib_serv_in16_arr, NULL}, + {SG_SERVICE_ACTION_OUT_16, sg_lib_serv_out16_arr, NULL}, + {SG_SERVICE_ACTION_BIDI, sg_lib_serv_bidi_arr, NULL}, + {SG_PERSISTENT_RESERVE_IN, sg_lib_pr_in_arr, "Persistent reserve in"}, + {SG_PERSISTENT_RESERVE_OUT, sg_lib_pr_out_arr, "Persistent reserve out"}, + {SG_THIRD_PARTY_COPY_OUT, sg_lib_xcopy_sa_arr, NULL}, + {SG_THIRD_PARTY_COPY_IN, sg_lib_rec_copy_sa_arr, NULL}, + {SG_READ_BUFFER, sg_lib_read_buff_arr, "Read buffer"}, + {SG_WRITE_BUFFER, sg_lib_write_buff_arr, "Write buffer"}, + {SG_SANITIZE, sg_lib_sanitize_sa_arr, "Sanitize"}, + {0xffff, NULL, NULL}, +}; + 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; + const struct op_code2sa_t * osp; + char b[80]; if ((NULL == buff) || (buff_len < 1)) return; @@ -1181,124 +1245,26 @@ 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; + + for (osp = op_code2sa_arr; osp->arr; ++osp) { + if ((int)cmd_byte0 == osp->op_code) { + vnp = get_value_name(osp->arr, service_action, peri_type); + if (vnp) { + if (osp->prefix) + my_snprintf(buff, buff_len, "%s, %s", osp->prefix, + vnp->name); + else + my_snprintf(buff, buff_len, "%s", vnp->name); + } else { + sg_get_opcode_name(cmd_byte0, peri_type, sizeof(b), b); + my_snprintf(buff, buff_len, "%s service action=0x%x", + b, service_action); + } + return; + } } + + sg_get_opcode_name(cmd_byte0, peri_type, buff_len, buff); } void @@ -1379,6 +1345,139 @@ return (k == page_len) ? -1 : -2; } +static const char * bad_sense_cat = "Bad sense category"; + +/* Yield string associated with sense++ category. Returns 'buff' (or pointer + * to "Bad sense category" if 'buff' is NULL). If sense_cat unknown then + * yield "Sense category: " string. */ +const char * +sg_get_category_sense_str(int sense_cat, int buff_len, char * buff, + int verbose) +{ + int n; + + if (NULL == buff) + return bad_sense_cat; + if (buff_len <= 0) + return buff; + switch (sense_cat) { + case SG_LIB_CAT_CLEAN: /* 0 */ + snprintf(buff, buff_len, "No errors"); + break; + case SG_LIB_SYNTAX_ERROR: /* 1 */ + snprintf(buff, buff_len, "Syntax error"); + break; + case SG_LIB_CAT_NOT_READY: /* 2 */ + n = snprintf(buff, buff_len, "Not ready"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key"); + break; + case SG_LIB_CAT_MEDIUM_HARD: /* 3 */ + n = snprintf(buff, buff_len, "Medium or hardware error"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key (plus blank check)"); + break; + case SG_LIB_CAT_ILLEGAL_REQ: /* 5 */ + n = snprintf(buff, buff_len, "Illegal request"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key, apart from Invalid " + "opcode"); + break; + case SG_LIB_CAT_UNIT_ATTENTION: /* 6 */ + n = snprintf(buff, buff_len, "Unit attention"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key"); + break; + case SG_LIB_CAT_DATA_PROTECT: /* 7 */ + n = snprintf(buff, buff_len, "Data protect"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key, write protected " + "media?"); + break; + case SG_LIB_CAT_INVALID_OP: /* 9 */ + n = snprintf(buff, buff_len, "Illegal request, invalid opcode"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key"); + break; + case SG_LIB_CAT_COPY_ABORTED: /* 10 */ + n = snprintf(buff, buff_len, "Copy aborted"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key"); + break; + case SG_LIB_CAT_ABORTED_COMMAND: /* 11 */ + n = snprintf(buff, buff_len, "Aborted command"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key, other than " + "protection related (asc=0x10)"); + break; + case SG_LIB_CAT_MISCOMPARE: /* 14 */ + n = snprintf(buff, buff_len, "Miscompare"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key"); + break; + case SG_LIB_FILE_ERROR: /* 15 */ + snprintf(buff, buff_len, "File error"); + break; + case SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO: /* 17 */ + snprintf(buff, buff_len, "Illegal request with info"); + break; + case SG_LIB_CAT_MEDIUM_HARD_WITH_INFO: /* 18 */ + snprintf(buff, buff_len, "Medium or hardware error with info"); + break; + case SG_LIB_CAT_NO_SENSE: /* 20 */ + n = snprintf(buff, buff_len, "No sense key"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " probably additional sense " + "information"); + break; + case SG_LIB_CAT_RECOVERED: /* 21 */ + n = snprintf(buff, buff_len, "Recovered error"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " sense key"); + break; + case SG_LIB_CAT_RES_CONFLICT: /* 24 */ + n = snprintf(buff, buff_len, "Reservation conflict"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " SCSI status"); + break; + case SG_LIB_CAT_TIMEOUT: /* 33 */ + snprintf(buff, buff_len, "SCSI command timeout"); + break; + case SG_LIB_CAT_PROTECTION: /* 40 */ + n = snprintf(buff, buff_len, "Aborted command, protection"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " information (PI) problem"); + break; + case SG_LIB_CAT_PROTECTION_WITH_INFO: /* 41 */ + n = snprintf(buff, buff_len, "Aborted command with info, protection"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " information (PI) problem"); + break; + case SG_LIB_CAT_MALFORMED: /* 97 */ + n = snprintf(buff, buff_len, "Malformed response"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, " to SCSI command"); + break; + case SG_LIB_CAT_SENSE: /* 98 */ + n = snprintf(buff, buff_len, "Some other sense data problem"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, ", try '-v' option for more " + "information"); + break; + case SG_LIB_CAT_OTHER: /* 99 */ + n = snprintf(buff, buff_len, "Some other error/warning has occurred"); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, ", possible transport of driver " + "issue"); + default: + n = snprintf(buff, buff_len, "Sense category: %d", sense_cat); + if (verbose && (n < (buff_len - 1))) + snprintf(buff + n, buff_len - n, ", try '-v' option for more " + "information"); + break; + } + return buff; +} /* safe_strerror() contributed by Clayton Weaver * Allows for situation in which strerror() is given a wild value (or the @@ -1406,6 +1505,18 @@ return errstr; } +static void +trimTrailingSpaces(char * b) +{ + int k; + + for (k = ((int)strlen(b) - 1); k >= 0; --k) { + if (' ' != b[k]) + break; + } + if ('\0' != b[k + 1]) + b[k + 1] = '\0'; +} /* Note the ASCII-hex output goes to stdout. [Most other output from functions * in this file go to sg_warnings_strm (default stderr).] @@ -1430,7 +1541,12 @@ if (len <= 0) return; blen = (int)sizeof(buff); - formatstr = (0 == no_ascii) ? "%.76s\n" : "%.48s\n"; + if (0 == no_ascii) /* address at left and ASCII at right */ + formatstr = "%.76s\n"; + else if (no_ascii > 0) + formatstr = "%s\n"; /* was: "%.58s\n" */ + else /* negative: no address at left and no ASCII at right */ + formatstr = "%s\n"; /* was: "%.48s\n"; */ memset(buff, ' ', 80); buff[80] = '\0'; if (no_ascii < 0) { @@ -1438,21 +1554,22 @@ 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))) { + trimTrailingSpaces(buff); fprintf(fp, formatstr, buff); bpos = bpstart; memset(buff, ' ', 80); - } + } else + bpos += 3; } if (bpos > bpstart) { buff[bpos + 2] = '\0'; + trimTrailingSpaces(buff); fprintf(fp, "%s\n", buff); } return; @@ -1476,6 +1593,8 @@ buff[cpos++] = c; } if (cpos > (cpstart + 15)) { + if (no_ascii) + trimTrailingSpaces(buff); fprintf(fp, formatstr, buff); bpos = bpstart; cpos = cpstart; @@ -1487,6 +1606,8 @@ } if (cpos > cpstart) { buff[cpos] = '\0'; + if (no_ascii) + trimTrailingSpaces(buff); fprintf(fp, "%s\n", buff); } } @@ -1518,8 +1639,11 @@ char buff[122]; int bpstart, bpos, k, n; - if (len <= 0) + if (len <= 0) { + if (b_len > 0) + b[0] = '\0'; return; + } if (0 != format) { ; /* do nothing different for now */ } @@ -1544,7 +1668,8 @@ (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); + trimTrailingSpaces(buff); + n += my_snprintf(b + n, b_len - n, "%s\n", buff); if (n >= (b_len - 1)) return; bpos = bpstart; @@ -1554,8 +1679,10 @@ } else bpos += 3; } - if (bpos > bpstart) - n += my_snprintf(b + n, b_len - n, "%.*s\n", bpstart + 48, buff); + if (bpos > bpstart) { + trimTrailingSpaces(buff); + n += my_snprintf(b + n, b_len - n, "%s\n", buff); + } return; } diff -Nru ddpt-0.94/lib/sg_lib_data.c ddpt-0.95/lib/sg_lib_data.c --- ddpt-0.94/lib/sg_lib_data.c 2014-04-02 01:00:54.000000000 +0000 +++ ddpt-0.95/lib/sg_lib_data.c 2014-11-11 05:12:22.000000000 +0000 @@ -12,10 +12,12 @@ #ifdef HAVE_CONFIG_H #include "config.h" +#else +#define SG_SCSI_STRINGS 1 #endif -const char * sg_lib_version_str = "1.96 20140401"; /* spc4r36s, sbc4r01 */ +const char * sg_lib_version_str = "2.08 20141110"; /* spc4r37a, sbc4r02 */ #ifdef SG_SCSI_STRINGS struct sg_lib_value_name_t sg_lib_normal_opcodes[] = { @@ -115,7 +117,7 @@ {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"}, + {0x53, 0, "Xdwriteread(10)"}, {0x54, 0, "Send OPC information"}, {0x55, 0, "Mode select(10)"}, {0x56, 0, "Reserve(10)"}, /* obsolete in SPC-4 r11 */ @@ -156,6 +158,7 @@ {0x92, PDT_TAPE, "Locate(16)"}, {0x93, 0, "Write same(16)"}, {0x93, PDT_TAPE, "Erase(16)"}, + {0x9c, 0, "Write atomic(16)"}, {0x9d, 0, "Service action bidirectional"}, /* added spc4r35 */ {0x9e, 0, "Service action in(16)"}, {0x9f, 0, "Service action out(16)"}, @@ -210,7 +213,8 @@ {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_read_buff_arr[] = { /* opcode 0x3c */ +/* Read buffer [0x3c] service actions, need prefix */ +struct sg_lib_value_name_t sg_lib_read_buff_arr[] = { {0x0, 0, "combined header and data [or multiple modes]"}, {0x2, 0, "data"}, {0x3, 0, "descriptor"}, @@ -221,7 +225,8 @@ {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_write_buff_arr[] = { /* opcode 0x3b */ +/* Write buffer [0x3b] service actions, need prefix */ +struct sg_lib_value_name_t sg_lib_write_buff_arr[] = { {0x0, 0, "combined header and data [or multiple modes]"}, {0x2, 0, "data"}, {0x4, 0, "download microcode and activate"}, @@ -230,7 +235,7 @@ {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"}, + "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"}, @@ -239,7 +244,8 @@ {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_maint_in_arr[] = { /* opcode 0xa3 */ +/* Maintenance in [0xa3] service actions */ +struct sg_lib_value_name_t sg_lib_maint_in_arr[] = { {0x5, 0, "Report identifying information"}, /* was "Report device identifier" prior to spc4r07 */ {0xa, 0, "Report target port groups"}, @@ -249,10 +255,12 @@ {0xe, 0, "Report priority"}, {0xf, 0, "Report timestamp"}, {0x10, 0, "Management protocol in"}, + {0x1f, 0, "Maintenance in vendor specific"}, {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_maint_out_arr[] = { /* opcode 0xa4 */ +/* Maintenance out [0xa4] service actions */ +struct sg_lib_value_name_t sg_lib_maint_out_arr[] = { {0x6, 0, "Set identifying information"}, /* was "Set device identifier" prior to spc4r07 */ {0xa, 0, "Set target port groups"}, @@ -261,61 +269,81 @@ {0xe, 0, "Set priority"}, {0xf, 0, "Set timestamp"}, {0x10, 0, "Management protocol out"}, + {0x1f, 0, "Maintenance out vendor specific"}, {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_serv_in12_arr[] = { /* opcode 0xab */ +/* Sanitize [0x48] service actions, need prefix */ +struct sg_lib_value_name_t sg_lib_sanitize_sa_arr[] = { + {0x1, 0, "overwrite"}, + {0x2, 0, "block erase"}, + {0x3, 0, "cryptographic erase"}, + {0x1f, 0, "exit failure mode"}, + {0xffff, 0, NULL}, +}; + +/* Service action in(12) [0xab] service actions */ +struct sg_lib_value_name_t sg_lib_serv_in12_arr[] = { {0x1, 0, "Read media serial number"}, {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_serv_out12_arr[] = { /* opcode 0xa9 */ +/* Service action out(12) [0xa9] service actions */ +struct sg_lib_value_name_t sg_lib_serv_out12_arr[] = { {0xff, 0, "Impossible command name"}, {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = { /* opcode 0x9e */ +/* Service action in(16) [0x9e] service actions */ +struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = { {0x10, 0, "Read capacity(16)"}, {0x11, 0, "Read long(16)"}, {0x12, 0, "Get LBA status"}, {0x13, 0, "Report referrals"}, + {0x14, PDT_ZBC, "Report zones"}, {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_serv_out16_arr[] = { /* opcode 0x9f */ +/* Service action out(16) [0x9f] service actions */ +struct sg_lib_value_name_t sg_lib_serv_out16_arr[] = { {0x11, 0, "Write long(16)"}, + {0x14, PDT_ZBC, "Reset write pointer"}, {0x1f, PDT_ADC, "Notify data transfer device(16)"}, {0xffff, 0, NULL}, }; -struct sg_lib_value_name_t sg_lib_serv_bidi_arr[] = { /* opcode 0x9d */ +/* Service action bidirectional [0x9d] service actions */ +struct sg_lib_value_name_t sg_lib_serv_bidi_arr[] = { {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"}, +/* Persistent reserve in [0x5e] service actions, need prefix */ +struct sg_lib_value_name_t sg_lib_pr_in_arr[] = { + {0x0, 0, "read keys"}, + {0x1, 0, "read reservation"}, + {0x2, 0, "report capabilities"}, + {0x3, 0, "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"}, +/* Persistent reserve out [0x5f] service actions, need prefix */ +struct sg_lib_value_name_t sg_lib_pr_out_arr[] = { + {0x0, 0, "register"}, + {0x1, 0, "reserve"}, + {0x2, 0, "release"}, + {0x3, 0, "clear"}, + {0x4, 0, "preempt"}, + {0x5, 0, "preempt and abort"}, + {0x6, 0, "register and ignore existing key"}, + {0x7, 0, "register and move"}, + {0x8, 0, "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 */ +/* Third party copy in [0x83] service actions + * Opcode 'Receive copy results' 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[] = { {0x0, 0, "Extended copy(LID1)"}, {0x1, 0, "Extended copy(LID4)"}, {0x10, 0, "Populate token"}, @@ -324,9 +352,10 @@ {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 */ +/* Third party copy out [0x84] service actions + * Opcode 'Extended copy' 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[] = { {0x0, 0, "Receive copy status(LID1)"}, {0x1, 0, "Receive copy data(LID1)"}, {0x3, 0, "Receive copy operating parameters"}, @@ -338,6 +367,7 @@ {0xffff, 0, NULL}, }; +/* Variable length cdb [0x7f] service actions (more than 16 bytes long) */ struct sg_lib_value_name_t sg_lib_variable_length_arr[] = { {0x1, 0, "Rebuild(32)"}, {0x2, 0, "Regenerate(32)"}, @@ -350,9 +380,10 @@ {0x9, 0, "Read(32)"}, {0xa, 0, "Verify(32)"}, {0xb, 0, "Write(32)"}, - {0xc, 0, "Write an verify(32)"}, + {0xc, 0, "Write and verify(32)"}, {0xd, 0, "Write same(32)"}, - {0xe, 0, "Orwrite(32)"}, /* added sbc3r25 */ + {0xe, 0, "Orwrite(32)"}, /* added sbc3r25 */ + {0xf, 0, "Atomic write(32)"}, /* added sbc4r02 */ {0x1800, 0, "Receive credential"}, {0x8801, 0, "Format OSD (osd)"}, {0x8802, 0, "Create (osd)"}, @@ -432,6 +463,10 @@ {0xffff, 0, NULL}, }; +struct sg_lib_value_name_t sg_lib_sanitize_sa_arr[] = { /* opcode 0x94 */ + {0xffff, 0, NULL}, +}; + struct sg_lib_value_name_t sg_lib_serv_in12_arr[] = { /* opcode 0xab */ {0xffff, 0, NULL}, }; @@ -476,7 +511,7 @@ /* 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 */ + * The following should match asc-num.txt dated 20140924 */ #ifdef SG_SCSI_STRINGS struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[] = @@ -516,6 +551,7 @@ {0x00,0x1e,"Conflicting SA creation request"}, {0x00,0x1f,"Logical unit transitioning to another power condition"}, {0x00,0x20,"Extended copy information available"}, + {0x00,0x21,"Atomic command aborted due to ACA"}, {0x01,0x00,"No index/sector signal"}, {0x02,0x00,"No seek complete"}, {0x03,0x00,"Peripheral device write fault"}, @@ -540,6 +576,7 @@ {0x04,0x0c,"Logical unit " "not accessible, target port in unavailable state"}, {0x04,0x0d,"Logical unit not ready, structure check required"}, + {0x04,0x0e,"Logical unit not ready, security session in progress"}, {0x04,0x10,"Logical unit not ready, " "auxiliary memory not accessible"}, {0x04,0x11,"Logical unit not ready, " @@ -575,6 +612,7 @@ {0x09,0x02,"Focus servo failure"}, {0x09,0x03,"Spindle servo failure"}, {0x09,0x04,"Head select fault"}, + {0x09,0x05,"Vibration induced tracking error"}, {0x0A,0x00,"Error log overflow"}, {0x0B,0x00,"Warning"}, {0x0B,0x01,"Warning - specified temperature exceeded"}, @@ -602,6 +640,7 @@ {0x0C,0x0D,"Write error - not enough unsolicited data"}, {0x0C,0x0E,"Multiple write errors"}, {0x0C,0x0F,"Defects in error window"}, + {0x0C,0x10,"Incomplete multiple atomic write operations"}, {0x0D,0x00,"Error detected by third party temporary initiator"}, {0x0D,0x01,"Third party device failure"}, {0x0D,0x02,"Copy target device not reachable"}, @@ -707,6 +746,10 @@ {0x21,0x01,"Invalid element address"}, {0x21,0x02,"Invalid address for write"}, {0x21,0x03,"Invalid write crossing layer jump"}, + {0x21,0x04,"Unaligned write command"}, + {0x21,0x05,"Write boundary violation"}, + {0x21,0x06,"Attempt to read invalid data"}, + {0x21,0x07,"Read boundary violation"}, {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"}, @@ -757,6 +800,7 @@ {0x27,0x05,"Permanent write protect"}, {0x27,0x06,"Conditional write protect"}, {0x27,0x07,"Space allocation failed write protect"}, + {0x27,0x08,"Zone is read only"}, {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"}, diff -Nru ddpt-0.94/lib/sg_pt_common.c ddpt-0.95/lib/sg_pt_common.c --- ddpt-0.94/lib/sg_pt_common.c 2013-08-28 13:44:26.000000000 +0000 +++ ddpt-0.95/lib/sg_pt_common.c 2014-06-06 16:55:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Douglas Gilbert. + * Copyright (c) 2009-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. @@ -14,7 +14,7 @@ #endif -static const char * scsi_pt_version_str = "2.10 20130827"; +static const char * scsi_pt_version_str = "2.12 20140606"; const char * scsi_pt_version() diff -Nru ddpt-0.94/lib/sg_pt_linux.c ddpt-0.95/lib/sg_pt_linux.c --- ddpt-0.94/lib/sg_pt_linux.c 2013-10-14 21:10:47.000000000 +0000 +++ ddpt-0.95/lib/sg_pt_linux.c 2014-06-06 16:55:26.000000000 +0000 @@ -5,7 +5,7 @@ * license that can be found in the BSD_LICENSE file. */ -/* sg_pt_linux version 1.20 20131014 */ +/* sg_pt_linux version 1.22 20140606 */ #include @@ -287,15 +287,14 @@ { struct sg_pt_linux_scsi * ptp = &vp->impl; - /* default action of SG (v3) is QUEUE_AT_HEAD */ + /* default action of sg driver [sg v3 interface] 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) { + if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) { /* favour AT_HEAD */ ptp->io_hdr.flags |= SG_FLAG_Q_AT_HEAD; ptp->io_hdr.flags &= ~SG_FLAG_Q_AT_TAIL; + } else 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; } } @@ -754,17 +753,32 @@ #ifndef BSG_FLAG_Q_AT_TAIL #define BSG_FLAG_Q_AT_TAIL 0x10 #endif +#ifndef BSG_FLAG_Q_AT_HEAD +#define BSG_FLAG_Q_AT_HEAD 0x20 +#endif + +/* Need this later if translated to v3 interface */ +#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 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) + /* default action of bsg driver (sg v4) is QUEUE_AT_HEAD */ + /* default action of block layer SG_IO ioctl is QUEUE_AT_TAIL */ + if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) { /* favour AT_HEAD */ + ptp->io_hdr.flags |= BSG_FLAG_Q_AT_HEAD; ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_TAIL; + } else if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags) { + ptp->io_hdr.flags |= BSG_FLAG_Q_AT_TAIL; + ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_HEAD; + } } /* N.B. Returns din_resid and ignores dout_resid */ @@ -931,6 +945,10 @@ v3_hdr.mx_sb_len = (unsigned char)ptp->io_hdr.max_response_len; } v3_hdr.pack_id = (int)ptp->io_hdr.spare_in; + if (BSG_FLAG_Q_AT_HEAD & ptp->io_hdr.flags) + v3_hdr.flags |= SG_FLAG_Q_AT_HEAD; /* favour AT_HEAD */ + else if (BSG_FLAG_Q_AT_TAIL & ptp->io_hdr.flags) + v3_hdr.flags |= SG_FLAG_Q_AT_TAIL; if (NULL == v3_hdr.cmdp) { if (verbose) diff -Nru ddpt-0.94/lib/sg_pt_win32.c ddpt-0.95/lib/sg_pt_win32.c --- ddpt-0.94/lib/sg_pt_win32.c 2013-08-28 13:44:26.000000000 +0000 +++ ddpt-0.95/lib/sg_pt_win32.c 2014-09-02 00:13:42.000000000 +0000 @@ -1,11 +1,11 @@ /* - * Copyright (c) 2006-2012 Douglas Gilbert. + * Copyright (c) 2006-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. */ -/* sg_pt_win32 version 1.14 20121026 */ +/* sg_pt_win32 version 1.15 20140901 */ #include #include @@ -24,9 +24,9 @@ #endif #ifndef O_EXCL -// #define O_EXCL 0x80 // cygwin ?? -// #define O_EXCL 0x80 // Linux -#define O_EXCL 0x400 // mingw +// #define O_EXCL 0x80 // cygwin ?? +// #define O_EXCL 0x80 // Linux +#define O_EXCL 0x400 // mingw #warning "O_EXCL not defined" #endif @@ -64,9 +64,10 @@ int bus; int target; int lun; + int verbose; /* tunnel verbose through to scsi_pt_close_device */ }; -struct sg_pt_handle handle_arr[MAX_OPEN_SIMULT]; +static struct sg_pt_handle handle_arr[MAX_OPEN_SIMULT]; struct sg_pt_win32_scsi { unsigned char * dxferp; @@ -201,6 +202,7 @@ shp->bus = bus; shp->target = target; shp->lun = lun; + shp->verbose = verbose; memset(shp->adapter, 0, sizeof(shp->adapter)); strncpy(shp->adapter, "\\\\.\\", 4); if (got_pd_name) @@ -216,8 +218,8 @@ 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()); + fprintf(sg_warnings_strm, "Windows CreateFile error=%u\n", + (unsigned int)GetLastError()); shp->in_use = 0; return -ENODEV; } @@ -225,7 +227,11 @@ } -/* Returns 0 if successful. If error in Unix returns negated errno. */ +/* Returns 0 if successful. If device_id seems wild returns -ENODEV, + * other errors return 0. If CloseHandle() fails and verbose > 0 then + * outputs warning with value from GetLastError(). The verbose value + * defaults to zero and is potentially set from the most recent call + * to scsi_pt_open_device() or do_scsi_pt(). */ int scsi_pt_close_device(int device_fd) { @@ -237,12 +243,15 @@ if ((index < 0) || (index >= WIN32_FDOFFSET)) return -ENODEV; shp = handle_arr + index; - CloseHandle(shp->fh); + if ((! CloseHandle(shp->fh)) && shp->verbose) + fprintf(sg_warnings_strm, "Windows CloseHandle error=%u\n", + (unsigned int)GetLastError()); shp->bus = 0; shp->target = 0; shp->lun = 0; memset(shp->adapter, 0, sizeof(shp->adapter)); shp->in_use = 0; + shp->verbose = 0; return 0; } @@ -435,7 +444,7 @@ /* 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 +static int do_scsi_pt_direct(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose) { @@ -443,7 +452,7 @@ struct sg_pt_win32_scsi * psp = vp->implp; struct sg_pt_handle * shp; BOOL status; - ULONG returned; + DWORD returned; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; @@ -473,6 +482,7 @@ psp->os_err = ENODEV; return -psp->os_err; } + shp->verbose = verbose; psp->swb_d.spt.Length = sizeof (SCSI_PASS_THROUGH_DIRECT); psp->swb_d.spt.PathId = shp->bus; psp->swb_d.spt.TargetId = shp->target; @@ -486,13 +496,14 @@ (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", + "DataTransferLength=%u\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); + (unsigned int)psp->swb_d.spt.DataTransferLength); + fprintf(stderr, " TimeOutValue=%u SenseInfoOffset=%u\n", + (unsigned int)psp->swb_d.spt.TimeOutValue, + (unsigned int)psp->swb_d.spt.SenseInfoOffset); } psp->swb_d.spt.DataBuffer = psp->dxferp; status = DeviceIoControl(shp->fh, IOCTL_SCSI_PASS_THROUGH_DIRECT, @@ -503,10 +514,13 @@ &returned, NULL); if (! status) { - psp->transport_err = GetLastError(); + unsigned int u; + + u = (unsigned int)GetLastError(); if (verbose) - fprintf(sg_warnings_strm, "Windows DeviceIoControl error=%d\n", - psp->transport_err); + fprintf(sg_warnings_strm, "Windows DeviceIoControl error=%u\n", + u); + psp->transport_err = (int)u; psp->os_err = EIO; return 0; /* let app find transport error */ } @@ -537,7 +551,7 @@ struct sg_pt_win32_scsi * psp = vp->implp; struct sg_pt_handle * shp; BOOL status; - ULONG returned; + DWORD returned; if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; @@ -568,6 +582,7 @@ psp->os_err = ENODEV; return -psp->os_err; } + shp->verbose = verbose; 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; @@ -576,7 +591,7 @@ 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)); + (int)sizeof(psp->swb_i.ucDataBuf)); epsp = (struct sg_pt_win32_scsi *) calloc(sizeof(struct sg_pt_win32_scsi) + extra, 1); if (NULL == epsp) { @@ -605,15 +620,16 @@ (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", + "DataTransferLength=%u\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); + (unsigned int)psp->swb_i.spt.DataTransferLength); + fprintf(stderr, " TimeOutValue=%u DataBufferOffset=%u " + "SenseInfoOffset=%u\n", + (unsigned int)psp->swb_i.spt.TimeOutValue, + (unsigned int)psp->swb_i.spt.DataBufferOffset, + (unsigned int)psp->swb_i.spt.SenseInfoOffset); } if ((psp->dxfer_len > 0) && (SCSI_IOCTL_DATA_OUT == psp->swb_i.spt.DataIn)) @@ -626,10 +642,13 @@ &returned, NULL); if (! status) { - psp->transport_err = GetLastError(); + unsigned int u; + + u = (unsigned int)GetLastError(); if (verbose) - fprintf(sg_warnings_strm, "Windows DeviceIoControl error=%d\n", - psp->transport_err); + fprintf(sg_warnings_strm, "Windows DeviceIoControl error=%u\n", + u); + psp->transport_err = (int)u; psp->os_err = EIO; return 0; /* let app find transport error */ } diff -Nru ddpt-0.94/Makefile.in ddpt-0.95/Makefile.in --- ddpt-0.94/Makefile.in 2013-10-31 15:09:28.000000000 +0000 +++ ddpt-0.95/Makefile.in 2014-09-23 15:41:34.000000000 +0000 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -81,8 +81,8 @@ 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 + $(srcdir)/config.h.in COPYING TODO compile 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) \ @@ -277,6 +277,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +os_cflags = @os_cflags@ os_deps = @os_deps@ os_libs = @os_libs@ pdfdir = @pdfdir@ @@ -334,8 +335,8 @@ $(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 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 @@ -535,10 +536,16 @@ $(am__post_remove_distdir) dist-tarZ: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) @@ -580,9 +587,10 @@ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ diff -Nru ddpt-0.94/missing ddpt-0.95/missing --- ddpt-0.94/missing 2013-10-31 15:09:28.000000000 +0000 +++ ddpt-0.95/missing 2014-05-17 14:53:08.000000000 +0000 @@ -1,7 +1,7 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2012-06-26.16; # UTC +scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. @@ -160,7 +160,7 @@ ;; autom4te*) echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." + echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) diff -Nru ddpt-0.94/README ddpt-0.95/README --- ddpt-0.94/README 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/README 2014-12-27 06:01:02.000000000 +0000 @@ -93,6 +93,13 @@ - '--disable-scsistrings' excludes the asc/ascq and command name strings (defined by SCSI/T10) in an attempt to reduce the size of executables. +At the request of some Linux distributions, this package will attempt to +use the libsgutils library (name varies between distributions) at build time. +If that library is old then the link at the end of build can fail. One way +to sidestep that problem is by using './configure --disable-libsgutils'. +Another way is to remove the "dev" version of the libsgutils library package +(e.g. 'libsgutils2-dev' on a Debian based distribution). + License ------- This utility is covered by a FreeBSD license also known as the BSD 3-clause @@ -132,4 +139,4 @@ Douglas Gilbert -7th April 2014 +26th December 2014 diff -Nru ddpt-0.94/src/ddpt.c ddpt-0.95/src/ddpt.c --- ddpt-0.94/src/ddpt.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt.c 2014-12-27 06:01:02.000000000 +0000 @@ -68,7 +68,7 @@ #endif -static const char * ddpt_version_str = "0.94 20140407 [svn: r277]"; +static const char * ddpt_version_str = "0.95 20141226 [svn: r307]"; #ifdef SG_LIB_LINUX #include @@ -190,8 +190,8 @@ rt = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); if (rt) - pr2serr("open_if: posix_fadvise(SEQUENTIAL), err=%d\n", - rt); + pr2serr("%s: posix_fadvise(SEQUENTIAL), err=%d\n", + __func__, rt); } #endif } @@ -349,8 +349,11 @@ { int res; struct stat st; + int in_blk_sz, in_type; +#ifndef SG_LIB_WIN32 int64_t num_blks, t; - int in_blk_sz, blk_sz, in_type; + int blk_sz; +#endif const char * ifn = op->idip->fn; *in_num_blksp = -1; @@ -400,6 +403,7 @@ } } } +#ifndef SG_LIB_WIN32 if ((FT_BLOCK & in_type) && (0 == op->iflagp->force) && (0 == get_blkdev_capacity(op, DDPT_ARG_IN, &num_blks, &blk_sz))) { @@ -412,6 +416,7 @@ return -1; } } +#endif } else if ((op->dd_count > 0) && (0 == op->oflagp->resume)) return 0; else if (FT_BLOCK & in_type) { @@ -453,8 +458,11 @@ { int res; struct stat st; + int out_blk_sz, out_type; +#ifndef SG_LIB_WIN32 int64_t num_blks, t; - int out_blk_sz, blk_sz, out_type; + int blk_sz; +#endif const char * ofn = op->odip->fn; *out_num_blksp = -1; @@ -504,6 +512,7 @@ } } } +#ifndef SG_LIB_WIN32 if ((FT_BLOCK & out_type) && (0 == op->oflagp->force) && (0 == get_blkdev_capacity(op, DDPT_ARG_OUT, &num_blks, &blk_sz))) { @@ -516,6 +525,7 @@ return -1; } } +#endif } else if ((op->dd_count > 0) && (0 == op->oflagp->resume)) return 0; if (FT_BLOCK & out_type) { @@ -776,6 +786,9 @@ int numbytes = csp->icbpt * op->ibs_pi; int ibs = op->ibs_pi; + if (op->verbose > 4) + pr2serr("%s: offset=0x%" PRIx64 ", numbytes=%d\n", __func__, offset, + numbytes); in_type = op->idip->d_type; #ifdef SG_LIB_WIN32 if (FT_BLOCK & in_type) { @@ -966,8 +979,8 @@ if (offset != csp->if_filepos) { if (op->verbose > 2) - pr2serr("fifo: _not_ moving IFILE filepos to %" PRId64 "\n", - (int64_t)offset); + pr2serr("%s: _not_ moving IFILE filepos to %" PRId64 "\n", + __func__, (int64_t)offset); csp->if_filepos = offset; } @@ -978,10 +991,10 @@ err = errno; if (op->verbose > 2) - pr2serr("read(fifo): requested bytes=%d, res=%d\n", - numbytes, res); + pr2serr("%s: requested bytes=%d, res=%d\n", __func__, numbytes, + res); if (res < 0) { - pr2serr("read(fifo), skip=%" PRId64 " : %s\n", op->skip, + pr2serr("%s: skip=%" PRId64 " : %s\n", __func__, op->skip, safe_strerror(err)); return SG_LIB_CAT_OTHER; } else if (0 == res) { @@ -1169,15 +1182,15 @@ 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); + pr2serr("%s: padding probable final write at seek=%" PRId64 + "\n", __func__, 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", + pr2serr("%s: failed,%s seek=%" PRId64 "\n", __func__, ((-2 == res) ? " try reducing bpt," : ""), aseek); return res; } else @@ -1453,7 +1466,7 @@ static void cp_sparse_cleanup(struct opts_t * op, struct cp_state_t * csp) { - int64_t offset = op->seek * op->obs; + int64_t offset = (op->seek * op->obs) + csp->partial_write_bytes; struct stat a_st; if (offset > csp->of_filepos) { @@ -1464,18 +1477,18 @@ return; } if (fstat(op->odip->fd, &a_st) < 0) { - pr2serr("cp_sparse_cleanup: fstat: %s\n", safe_strerror(errno)); + pr2serr("%s: fstat: %s\n", __func__, safe_strerror(errno)); return; } if (offset == a_st.st_size) { if (op->verbose > 1) - pr2serr("cp_sparse_cleanup: OFILE already correct length\n"); + pr2serr("%s: OFILE already correct length\n", __func__); return; } if (offset < a_st.st_size) { if (op->verbose > 1) - pr2serr("cp_sparse_cleanup: OFILE longer than required, do " - "nothing\n"); + pr2serr("%s: OFILE longer than required, do nothing\n", + __func__); return; } if (op->oflagp->strunc) { @@ -1498,7 +1511,8 @@ else --op->out_sparse; } - } + } else if (op->verbose > 1) + pr2serr("%s: bypass as output_offset <= output_filepos\n", __func__); } /* Main copy loop's finer grain comparison and possible write (to OFILE) @@ -1743,6 +1757,7 @@ int ibpt, obpt, res, n, sparse_skip, sparing_skip, continual_read; int ret = 0; int first_time = 1; + int first_time_ff = 1; int id_type = op->idip->d_type; int od_type = op->odip->d_type; struct cp_state_t cp_st; @@ -1807,6 +1822,12 @@ ret = SG_LIB_CAT_OTHER; break; #endif + } else if (FT_ALL_FF & id_type) { + if (first_time_ff) { + first_time_ff = 0; + memset(wPos, 0xff, op->ibs * ibpt); + } + op->in_full += csp->icbpt; } else { if ((ret = cp_read_block_reg(op, csp, wPos))) break; @@ -2021,6 +2042,9 @@ return -fd; } idip->fd = fd; + } else if (op->iflagp->ff) { + idip->d_type = FT_ALL_FF; + idip->fd = 9999; /* unlikely file descriptor */ } else { pr2serr("'if=IFILE' option must be given. For stdin as input use " "'if=-'\n"); @@ -2169,7 +2193,7 @@ /* 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: + * Possibilities depend on oflag arguments: * 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. @@ -2363,8 +2387,8 @@ 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))); + op->wrkPos = (unsigned char *)(((uintptr_t)op->wrkBuff + psz - 1) & + (~((uintptr_t)psz - 1))); if (op->oflagp->sparing) { op->wrkBuff2 = (unsigned char*)calloc(len + psz, 1); if (0 == op->wrkBuff2) { @@ -2372,7 +2396,8 @@ return SG_LIB_CAT_OTHER; } op->wrkPos2 = (unsigned char *) - (((unsigned long)op->wrkBuff2 + psz - 1) & (~(psz - 1))); + (((uintptr_t)op->wrkBuff2 + psz - 1) & + (~((uintptr_t)psz - 1))); } #endif /* HAVE_POSIX_MEMALIGN */ } else { @@ -2479,14 +2504,15 @@ { int ret = 0; int started_copy = 0; + int jf_depth = 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); + state_init(op, &iflag, &oflag, &ids, &ods, &o2ds); + ret = cl_process(op, argc, argv, ddpt_version_str, jf_depth); if (op->do_help > 0) { ddpt_usage(op->do_help); return 0; @@ -2543,10 +2569,11 @@ if ((ret = wrk_buffers_init(op))) goto cleanup; - if (ops.verbose) + if (op->verbose) details_pre_copy_print(op); op->read1_or_transfer = !! (FT_DEV_NULL & op->odip->d_type); + op->dd_count_start = op->dd_count; 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"); @@ -2596,9 +2623,13 @@ 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"); + else { + if (op->verbose < 2) + pr2serr("Early termination: some error occurred; try again " + "with '-vv'\n"); + else + pr2serr("Early termination: some error occurred\n"); + } } return (ret >= 0) ? ret : SG_LIB_CAT_OTHER; } diff -Nru ddpt-0.94/src/ddpt_cl.c ddpt-0.95/src/ddpt_cl.c --- ddpt-0.94/src/ddpt_cl.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt_cl.c 2014-12-27 06:01:02.000000000 +0000 @@ -28,7 +28,7 @@ */ /* - * This file contains command line helper functions for ddpt. + * This file contains command line (hence '_cl') helper functions for ddpt. */ /* Was needed for posix_fadvise() */ @@ -103,6 +103,7 @@ #else " [--help] [--odx] [--verbose] [--version] [--xcopy]\n" #endif + " [JF]\n" " where the main options are:\n" " bpt input Blocks Per Transfer (BPT) (def: 128 when " "IBS is 512)\n" @@ -113,8 +114,6 @@ 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" @@ -130,8 +129,6 @@ 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; " @@ -142,6 +139,7 @@ "etc\n" " -1->quiet (stderr->/dev/null)\n" " --help print out this usage message then exit\n" + " --job=JF JF is job file containing options\n" " --odx do ODX copy rather than normal rw copy\n" " --verbose equivalent to verbose=1\n" " --version print version information then exit\n" @@ -149,6 +147,9 @@ " --wscan windows scan for device names and volumes\n" #endif " --xcopy do xcopy(LID1) rather than normal rw copy\n" + " JF job file: a file containing options; can not " + "start\n" + " with '-' or contain '='. Parsed when seen\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 " @@ -164,6 +165,8 @@ " coe_limit limit consecutive 'bad' blocks on reads to CL " "times\n" " when coe=1 (default: 0 which is no limit)\n" + " conv conversions, comma separated list of CONVS " + "(see '-hhh')\n" " delay wait MS milliseconds between each copy segment " "(def: 0)\n" " wait W_MS milliseconds prior to each write " @@ -188,6 +191,8 @@ " prio xcopy: set priority field to PRIO (def: 1)\n" " protect set rdprotect and/or wrprotect fields on " "pt commands\n" + " retries retry pass-through errors RETR times " + "(def: 0)\n" " rtf ROD Token filename (odx)\n" " rtype ROD type (odx), can be pit-any, pit-def, " "pit-pers,\n" @@ -198,6 +203,7 @@ pr2serr("FLAGS: (arguments to oflag= and oflag=; may be comma " "separated)\n" " append (o) append (part of) IFILE to end of OFILE\n" + " atomic (o,pt) use WRITE ATOMIC(16) on 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" @@ -210,6 +216,7 @@ " 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" + " ff (i) input will be all 0xff bytes\n" " flock use advisory exclusive lock [flock()] on " "IFILE/OFILE\n" " force override inconsistent information that would " @@ -283,6 +290,8 @@ "for coe\n" " trunc same as oflag=trunc\n\n" "ENVIRONMENT VARIABLES:\n" + " DDPT_DEF_BS its value replaces the default block size of " + "512 bytes\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) " @@ -291,6 +300,26 @@ " XCOPY_TO_SRC send XCOPY command to IFILE (source)\n"); } +/* Crude attempt to carve a command line into an argv array of pointers + * to arguments/options and returns argc. No more than max_args elements + * placed in argv. Modifies given cmd_line! Everything after the first + * found '#' is ignored. Uses strtok to carve up cmd_line. */ +static int +argcargv(char * cmd_line, char ** argv, int max_args) +{ + int argc = 0; + char * p2; + + if ((p2 = strchr(cmd_line, '#'))) + *p2 = '\0'; /* bad luck if in quotes */ + p2 = strtok(cmd_line, " "); + while (p2 && (argc < max_args)) { + argv[argc++] = p2; + p2 = strtok(0, " "); + } + return argc; +} + /* Returns the number of times 'ch' is found in string 's' given the * string's length. */ static int @@ -448,8 +477,12 @@ *np++ = '\0'; if (0 == strcmp(cp, "append")) ++fp->append; + else if (0 == strcmp(cp, "atomic")) + ++fp->atomic; else if (0 == strcmp(cp, "block")) ++fp->block; + else if (0 == strcmp(cp, "bytchk")) + ++fp->bytchk; else if (0 == strcmp(cp, "cat")) ++fp->cat; else if (0 == strcmp(cp, "coe")) @@ -466,6 +499,8 @@ ++fp->excl; else if (0 == strcmp(cp, "fdatasync")) ++fp->fdatasync; + else if (0 == strcmp(cp, "ff")) + ++fp->ff; else if (0 == strcmp(cp, "flock")) ++fp->flock; else if (0 == strcmp(cp, "force")) @@ -525,6 +560,8 @@ ++fp->wsame16; } else if (0 == strcmp(cp, "trunc")) ++fp->trunc; + else if (0 == strcmp(cp, "verify")) + ++fp->verify; else if (0 == strcmp(cp, "xcopy")) ++fp->xcopy; else { @@ -562,25 +599,40 @@ static int cl_sanity_defaults(struct opts_t * op) { + int def_bs = DEF_BLOCK_SIZE; const char * cp; char * csp; char * cdp; char b[80]; + struct flags_t * ifp = op->iflagp; + struct flags_t * ofp = op->oflagp; + + cp = getenv(DDPT_DEF_BS); + if (cp) { + if (op->verbose) + pr2serr(" %s=%s environment variable detected, modifying block " + "size default\n", DDPT_DEF_BS, cp); + if ((1 == sscanf(cp, "%d", &def_bs)) && (def_bs > 0)) + ; + else + def_bs = DEF_BLOCK_SIZE; + } else + def_bs = DEF_BLOCK_SIZE; if ((0 == op->ibs) && (0 == op->obs)) { - op->ibs = DEF_BLOCK_SIZE; - op->obs = DEF_BLOCK_SIZE; + op->ibs = def_bs; + op->obs = def_bs; if (op->idip->fn[0]) pr2serr("Assume block size of %d bytes for both input and " - "output\n", DEF_BLOCK_SIZE); + "output\n", def_bs); } else if (0 == op->obs) { - op->obs = DEF_BLOCK_SIZE; - if ((op->ibs != DEF_BLOCK_SIZE) && op->odip->fn[0]) + op->obs = def_bs; + if ((op->ibs != def_bs) && 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) + op->ibs = def_bs; + if (op->obs != def_bs) pr2serr("Neither ibs nor bs given so set ibs=%d (default " "block size)\n", op->ibs); } @@ -602,7 +654,7 @@ pr2serr("neither skip nor seek can be negative\n"); return SG_LIB_SYNTAX_ERROR; } - if ((op->oflagp->append > 0) && (op->seek > 0)) { + if ((ofp->append > 0) && (op->seek > 0)) { pr2serr("Can't use both append and seek switches\n"); return SG_LIB_SYNTAX_ERROR; } @@ -610,40 +662,40 @@ pr2serr("internal BPT value 0, cannot continue\n"); return SG_LIB_SYNTAX_ERROR; } - if (op->iflagp->append) + if (ifp->append) pr2serr("append flag ignored on input\n"); - if (op->iflagp->ignoreew) + if (ifp->ignoreew) pr2serr("ignoreew flag ignored on input\n"); - if (op->iflagp->nofm) + if (ifp->nofm) pr2serr("nofm flag ignored on input\n"); - if (op->iflagp->prealloc) + if (ifp->prealloc) pr2serr("pre-alloc flag ignored on input\n"); - if (op->iflagp->sparing) + if (ifp->sparing) pr2serr("sparing flag ignored on input\n"); - if (op->iflagp->ssync) + if (ifp->ssync) pr2serr("ssync flag ignored on input\n"); - if (op->oflagp->trunc) { - if (op->oflagp->resume) { - op->oflagp->trunc = 0; + if (ofp->trunc) { + if (ofp->resume) { + ofp->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; + } else if (ofp->append) { + ofp->trunc = 0; pr2serr("trunc ignored due to append flag\n"); - } else if (op->oflagp->sparing) { + } else if (ofp->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 (ifp->self || ofp->self) { + if (! ofp->self) + ++ofp->self; + if (ifp->wsame16 || ofp->wsame16) { + if (! ofp->wsame16) + ++ofp->wsame16; + if (! ofp->nowrite) + ++ofp->nowrite; } if ('\0' == op->odip->fn[0]) strcpy(op->odip->fn, op->idip->fn); @@ -665,39 +717,39 @@ 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 (ofp->wsame16) + ofp->sparse += 2; + if (ofp->strunc && (0 == ofp->sparse)) + ++ofp->sparse; - if (op->iflagp->xcopy || op->oflagp->xcopy) + if (ifp->xcopy || ofp->xcopy) ++op->has_xcopy; if (op->has_xcopy) { - if ((!! op->iflagp->xcopy) == (!! op->oflagp->xcopy)) { + if ((!! ifp->xcopy) == (!! ofp->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; + if (! ifp->xcopy) + ifp->xcopy = 1; + ofp->xcopy = 0; #else - op->iflagp->xcopy = 0; - if (! op->oflagp->xcopy) - op->oflagp->xcopy = 1; + ifp->xcopy = 0; + if (! ofp->xcopy) + ofp->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; + if (! ifp->xcopy) + ifp->xcopy = 1; + ofp->xcopy = 0; } else { - op->iflagp->xcopy = 0; - if (! op->oflagp->xcopy) - op->oflagp->xcopy = 1; + ifp->xcopy = 0; + if (! ofp->xcopy) + ofp->xcopy = 1; } if (op->verbose > 1) pr2serr("%s dictates which device to send xcopy " @@ -709,30 +761,30 @@ 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; + (ifp->xcopy ? "src" : "dst"), + (ifp->xcopy ? "if" : "of"), + (ifp->xcopy ? op->idip->fn : op->odip->fn)); + } + op->xc_dc = (ifp->dc || ofp->dc); + op->xc_cat = (ifp->cat || ofp->cat); + if (ifp->xcopy) { + if (! ifp->pt) { + ifp->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 (! ofp->pt) { + ofp->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] || + if (ifp->odx || ofp->odx || op->rtf[0] || op->rod_type_given) op->has_odx = op->has_odx ? op->has_odx : 1; if (op->has_odx) { @@ -783,43 +835,139 @@ } if (op->verbose) { /* report flags used but not supported */ #ifndef SG_LIB_LINUX - if (op->iflagp->flock || op->oflagp->flock) + if (ifp->flock || ofp->flock) pr2serr("warning: 'flock' flag not supported on this " "platform\n"); #endif #ifndef HAVE_POSIX_FADVISE - if (op->iflagp->nocache || op->oflagp->nocache) + if (ifp->nocache || ofp->nocache) pr2serr("warning: 'nocache' flag not supported on this " "platform\n"); #endif #if O_SYNC == 0 - if (op->iflagp->sync || op->oflagp->sync) + if (ifp->sync || ofp->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) + if (ifp->direct || ofp->direct) pr2serr("warning: 'direct' flag (O_DIRECT) not supported " "on this platform\n"); #endif } + if (ofp->atomic) + ofp->cdbsz = 16; /* only WRITE ATOMIC(16) supported for now */ + if (ofp->ff) { + pr2serr("oflag=ff disallowed, can only be used for input\n"); + return SG_LIB_SYNTAX_ERROR; + } return 0; } +static int +jf_process(struct opts_t * op, const char * jf_name, const char * version_str, + int jf_depth) +{ + FILE * fp; + char b[4096]; + char bb[256]; + int k, len, off, rlen, argc, first_real; + int ret = 0; + char * cp; + char * argv[DDPT_MAX_JF_ARGS_PER_LINE]; + + ++jf_depth; + if (jf_depth > DDPT_MAX_JF_DEPTH) { + pr2serr("error parsing job_file: %s, depth=%d too great\n", jf_name, + jf_depth); + return SG_LIB_FILE_ERROR; + } + if (op->verbose) + pr2serr("parsing job_file: %s, depth=%d\n", jf_name, jf_depth); + + if (NULL == (fp = fopen(jf_name, "r"))) { + pr2serr("open of job_file: %s (depth=%d) failed: %s\n", jf_name, + jf_depth, strerror(errno)); + return SG_LIB_FILE_ERROR; + } + rlen = sizeof(b); + for (off = 0, k = 0, first_real = 1; + (rlen > 0) && ((cp = fgets(b + off, rlen, fp)) && + (k < DDPT_MAX_JF_LINES)); + rlen -= len, off += len, ++k) { + len = strlen(b + off); + if (0 == len) + continue; + if (first_real) { + first_real = 0; + if ((0 == op->iflagp->force) && (0 == op->oflagp->force)) { + /* in absence of iflag=force or oflag-force, check if job + * file seems to be binary */ + if ((b[0] > 0x7e) || ((len > 1) && (b[1] > 0x7e)) || + ((len > 2) && (b[2] > 0x7e)) || + ((len > 3) && (b[3] > 0x7e))) { + pr2serr("job_file: %s might be binary so exit; use\n" + "iflag=force or oflag=force prior to job " + "file to override\n", jf_name); + return SG_LIB_FILE_ERROR; + } + } + } + if ('\n' == b[off + len - 1]) { + b[off + len - 1] = '\0'; + --len; + if (0 == len) + continue; + else if ('\r' == b[off + len - 1]) { + b[off + len - 1] = '\0'; + --len; + if (0 == len) + continue; + } + } + snprintf(bb, sizeof(bb), "%s (depth=%d) line %d", jf_name, jf_depth, + k + 1); + argv[0] = bb; + argc = argcargv(b + off, argv + 1, DDPT_MAX_JF_ARGS_PER_LINE - 1); + ++argc; + ret = cl_process(op, argc, argv, version_str, jf_depth); + if (ret) { + pr2serr("failed parsing job file %s (depth=%d) at line %d\n", + jf_name, jf_depth, k + 1); + break; + } + } + if (rlen < 1) { + pr2serr("job file %s (depth=%d) too large\n", jf_name, jf_depth); + ret = SG_LIB_FILE_ERROR; + } else if (ferror(fp)) { + pr2serr("job file %s (depth=%d) read error\n", jf_name, jf_depth); + ret = SG_LIB_FILE_ERROR; + } else if (k >= DDPT_MAX_JF_LINES) { + pr2serr("job file %s (depth=%d) more than %d lines\n", jf_name, + jf_depth, DDPT_MAX_JF_LINES); + ret = SG_LIB_FILE_ERROR; + } + fclose(fp); + return ret; +} + /* 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) + const char * version_str, int jf_depth) { char str[STR_SZ]; char * key; char * buf; char * cp; - int k, n, keylen, res; + int k, n, keylen, res, orig_strlen; int64_t i64; + struct flags_t * ifp = op->iflagp; + struct flags_t * ofp = op->oflagp; for (k = 1; k < argc; ++k) { if (argv[k]) { @@ -827,11 +975,14 @@ str[STR_SZ - 1] = '\0'; } else continue; + orig_strlen = strlen(str); // replace '=' with null and set buf pointer to following char - for (key = str, buf = key; *buf && *buf != '=';) + for (key = str, buf = key; *buf && ('=' != *buf); ) ++buf; if (*buf) *buf++ = '\0'; + // If ('\0' == *buf) then there is no '=' in the option/argument + // or '=' is the trailing character. keylen = (int)strlen(key); // check for option names, in alphabetical order if (0 == strcmp(key, "bpt")) { @@ -875,12 +1026,12 @@ } 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; + ifp->cdbsz = sg_get_num(buf); + ofp->cdbsz = ifp->cdbsz; op->cdbsz_given = 1; } else if (0 == strcmp(key, "coe")) { - op->iflagp->coe = sg_get_num(buf); - op->oflagp->coe = op->iflagp->coe; + ifp->coe = sg_get_num(buf); + ofp->coe = ifp->coe; } else if (0 == strcmp(key, "coe_limit")) { op->coe_limit = sg_get_num(buf); if (-1 == op->coe_limit) { @@ -888,7 +1039,7 @@ return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "conv")) { - if (conv_process(buf, op->iflagp, op->oflagp)) { + if (conv_process(buf, ifp, ofp)) { pr2serr("bad argument to 'conv='\n"); return SG_LIB_SYNTAX_ERROR; } @@ -954,10 +1105,13 @@ if ('\0' != op->idip->fn[0]) { pr2serr("Second IFILE argument??\n"); return SG_LIB_SYNTAX_ERROR; + } else if (0 == strlen(buf)) { + pr2serr("expected if=IFILE but no 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)) { + if (flags_process(buf, ifp)) { pr2serr("bad argument to 'iflag='\n"); return SG_LIB_SYNTAX_ERROR; } @@ -1003,6 +1157,9 @@ if ('\0' != op->odip->fn[0]) { pr2serr("Second OFILE argument??\n"); return SG_LIB_SYNTAX_ERROR; + } else if (0 == strlen(buf)) { + pr2serr("expected of=OFILE but no OFILE argument\n"); + return SG_LIB_SYNTAX_ERROR; } strncpy(op->odip->fn, buf, INOUTF_SZ - 1); ++op->outf_given; @@ -1013,7 +1170,7 @@ } else strncpy(op->o2dip->fn, buf, INOUTF_SZ - 1); } else if (0 == strcmp(key, "oflag")) { - if (flags_process(buf, op->oflagp)) { + if (flags_process(buf, ofp)) { pr2serr("bad argument to 'oflag='\n"); return SG_LIB_SYNTAX_ERROR; } @@ -1047,9 +1204,9 @@ 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) { + ifp->retries = sg_get_num(buf); + ofp->retries = ifp->retries; + if (-1 == ifp->retries) { pr2serr("bad argument to 'retries='\n"); return SG_LIB_SYNTAX_ERROR; } @@ -1129,7 +1286,16 @@ /* look for long options that start with '--' */ else if (0 == strncmp(key, "--help", 6)) ++op->do_help; - else if (0 == strncmp(key, "--odx", 5)) + else if (0 == strncmp(key, "--job", 5)) { + if (strlen(buf) > 0) { + res = jf_process(op, buf, version_str, jf_depth); + if (res) + return res; + } else { + pr2serr("'job=' expects a file name\n"); + return SG_LIB_SYNTAX_ERROR; + } + } else if (0 == strncmp(key, "--odx", 5)) ++op->has_odx; else if (0 == strncmp(key, "--verb", 6)) ++op->verbose; @@ -1174,9 +1340,14 @@ if (0 == op->do_help) return -1; } + } else if (('\0' == *buf) && (orig_strlen == (int)strlen(str))) { + res = jf_process(op, str, version_str, jf_depth); + if (res) + return res; } else { pr2serr("Unrecognized option '%s'\n", key); - pr2serr("For more information use '--help'\n"); + if (0 == jf_depth) + pr2serr("For more information use '--help'\n"); return SG_LIB_SYNTAX_ERROR; } } diff -Nru ddpt-0.94/src/ddpt_com.c ddpt-0.95/src/ddpt_com.c --- ddpt-0.94/src/ddpt_com.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt_com.c 2014-12-27 06:01:02.000000000 +0000 @@ -221,8 +221,22 @@ 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 ((op->dd_count > 0) && (! op->reading_fifo)) { + pr2serr(" remaining block count=%" PRId64, op->dd_count); + if ((who < 2) && (op->in_full <= op->dd_count_start) && + (op->dd_count_start >= 4196)) { + /* with ints will overflow around 8 TB for bs=1 */ + int num = (int)((op->in_full * 100) / 4196); + int den = (int)(op->dd_count_start / 4196); /* will be >= 1 */ + int percent; + + percent = num / den; + if ((100 == percent) && (op->in_full < op->dd_count_start)) + --percent; /* don't want rounding to 100 % */ + pr2serr(" %d%% completed\n", percent); + } else + pr2serr("\n"); + } if (who < 2) pr2serr("%s%" PRId64 "+%d records in\n", str, op->in_full, op->in_partial); @@ -303,12 +317,12 @@ return; } while ((cp = fgets(b, sizeof(b), fp))) { - if ((1 == sscanf(b, "%s", a)) && + if ((1 == sscanf(b, "%126s", a)) && (0 == memcmp(a, "Character", 9))) break; } while (cp && (cp = fgets(b, sizeof(b), fp))) { - if (2 == sscanf(b, "%d %s", &n, a)) { + if (2 == sscanf(b, "%d %126s", &n, a)) { if (0 == strcmp("bsg", a)) { bsg_major = n; break; @@ -1194,10 +1208,20 @@ /* 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)) + && (0 == op->oflagp->prealloc)) { + if (op->oflagp->strunc) { + int64_t osize = (op->seek * op->obs); + + pr2serr(">> Did not perform: " + "'truncate --size=%" PRId64 " %s'\n", + osize, op->odip->fn); + pr2serr(">> User should check and perform by hand if " + "necessary\n"); + } pr2serr("To resume, invoke with same arguments plus " "oflag=resume\n"); - ; // >>>>>>>>>>>>> cleanup (); + } + // Could more cleanup or suggestions be made here? } else { pr2serr("Progress report:\n"); print_stats(" ", op, 0); @@ -1361,7 +1385,7 @@ case 3: /* NAA: Locally assigned */ case 5: /* NAA: IEEE Registered */ if (8 != i_len) { - print_p(" << unexpected NAA 5 identifier length: " + print_p(" << unexpected NAA 3 or 5 identifier length: " "0x%x>>\n", i_len); dStrHexp((const char *)ip, i_len, -1); break; @@ -1605,13 +1629,13 @@ case SG_LIB_CAT_UNIT_ATTENTION: /* 6 */ print_p("%sunit attention\n", b); break; - case DDPT_CAT_SK_DATA_PROTECT: /* 7 */ + case SG_LIB_CAT_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 */ + case SG_LIB_CAT_COPY_ABORTED: /* 10 */ print_p("%scopy aborted\n", b); break; case SG_LIB_CAT_ABORTED_COMMAND: /* 11 */ @@ -1629,11 +1653,11 @@ 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); + case SG_LIB_CAT_RES_CONFLICT: /* 24 */ + print_p("%sSCSI status: reservation conflict\n", b); break; case SG_LIB_CAT_TIMEOUT: /* 33 */ - print_p("%sSCSI status: reservation conflict\n", b); + print_p("%sSCSI command timeout\n", b); break; case SG_LIB_CAT_PROTECTION: /* 40 */ print_p("%sprotection error\n", b); @@ -1756,7 +1780,7 @@ pr2serr("'--lba' cannot be read from stdin\n"); return 1; } else { /* list of numbers (default decimal) on command line */ - k = strspn(inp, "0123456789aAbBcCdDeEfFhHxXbBdDiIkKmMgGtTpP, "); + k = strspn(inp, "0123456789aAbBcCdDeEfFhHxXiIkKmMgGtTpP, "); if (in_len != k) { pr2serr("cl_to_sgl: error at pos %d\n", k + 1); return 1; diff -Nru ddpt-0.94/src/ddptctl.c ddpt-0.95/src/ddptctl.c --- ddpt-0.94/src/ddptctl.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddptctl.c 2014-12-27 06:01:02.000000000 +0000 @@ -65,7 +65,7 @@ #include "ddpt.h" -const char * ddptctl_version_str = "0.94 20140407 [svn: r277]"; +const char * ddptctl_version_str = "0.95 20141226 [svn: r307]"; #ifdef SG_LIB_LINUX #include @@ -110,8 +110,9 @@ #include "sg_cmds_basic.h" -#define DEF_3PC_OUT_TIMEOUT (10 * 60) /* is 10 minutes enough? */ +#define DEF_3PC_OUT_TIMEOUT (10 * 60) /* 10 minutes not enough, use IMMED */ #define DEF_3PC_IN_TIMEOUT 60 /* these should be fast */ +#define MAX_NUM_MAN_TOKS 32 #define DEF_ROD_TOK_FILE "ddptctl_rod_tok.bin" @@ -124,12 +125,14 @@ {"block", no_argument, 0, 'b'}, {"del_tkn", no_argument, 0, 'D'}, {"help", no_argument, 0, 'h'}, + {"hex", 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'}, + {"readonly", no_argument, 0, 'y'}, {"receive", no_argument, 0, 'R'}, {"rtf", required_argument, 0, 'r'}, {"rtype", required_argument, 0, 't'}, @@ -148,13 +151,14 @@ { 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" + "[--hex]\n" + " [-immed] [--info] [--list_id=LID] [--oir=OIR] " + "[--poll]\n" + " [--pt=GL] [--readonly] [--receive] [--rtf=RTF] " + "[rtype=RTYPE]\n" + " [--size] [--timeout=ITO[,CMD]] [--verbose] " + "[--version]\n" + " [--wut=SL] [DEVICE]\n" " where:\n" " --abort|-A call COPY OPERATION ABORT command\n" " --all_toks|-a call REPORT ALL ROD TOKENS command\n" @@ -162,6 +166,7 @@ "SCSI commands)\n" " --del_tkn|-D set DEL_TKN bit in WUT command\n" " --help|-h print out usage message\n" + " --hex|-H print response in ASCII hexadecimal\n" " --immed|-I set IMMED bit in PT or WUT, exit " "prior to\n" " data transfer completion (then use " @@ -178,6 +183,8 @@ " --pt=GL|-P GL call PT with gather list GL. GL's " "format is\n" " LBA1,NUM1[,LBA2,NUM2...]\n" + " --readonly|-y open DEVICE read-only (def: " + "read-write)\n" " --receive|-R call RRTI once\n" " --rtf=RTF|-r RTF ROD Token file for analysis (--info); " "output by\n" @@ -206,20 +213,147 @@ ); } +/* If len==96 then assume it is a management ROD Token. Returns 0 if okay. */ static int -odx_rt_info(const struct opts_t * op) +odx_print_rod_tok(const struct opts_t * op, unsigned char * rth, int len) { - int res, fd, err, m, prot_en, p_type, lbppbe, vendor, desig_type; - int all_0, all_1, k, num, bp_chunk; + int vendor, all_0, all_1, m, prot_en, p_type, desig_type, lbppbe; 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; + char b[128]; unsigned char uc; + + 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) + return SG_LIB_CAT_OTHER; + } + 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 CSCD (0xe4) got " + "0x%x\n", rth[16]); + if (! vendor) + return SG_LIB_CAT_OTHER; + } + 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, rth[23], 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: + if (len <= 96) + return 0; + 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, rth[131], 0, + op->verbose); + } else + printf(" Target device descriptor: unexpected designator " + "type [0x%x]\n", desig_type); + } + return 0; +} + +static int +odx_rt_info(const struct opts_t * op) +{ + int res, fd, err, k, m, bp_chunk, num; + int got_rtf_len = 0; + int a_err = 0; + uint64_t bc; unsigned char rth[520]; - char b[128]; struct stat st; if ('\0' == op->rtf[0]) { @@ -276,127 +410,10 @@ 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]); + res = odx_print_rod_tok(op, rth, 512); + if (res && (0 == a_err)) + a_err = res; -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) @@ -419,12 +436,15 @@ op->verbose, op->verbose); } + static int -report_all_toks(struct opts_t * op, struct dev_info_t * dip) +report_all_toks(struct opts_t * op, struct dev_info_t * dip, int do_hex) { - int res, fd; - unsigned int len; - unsigned char rsp[2048]; + int res, fd, k; + int a_err = 0; + unsigned int len, num_mtoks; + unsigned char rsp[8 + (MAX_NUM_MAN_TOKS * 96)]; + unsigned char * ucp; fd = dip->fd; res = pt_3party_copy_in(fd, SA_ALL_ROD_TOKS, op->list_id, @@ -434,17 +454,47 @@ 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); + if (len <= 8) { + printf("No management ROD Tokens reported\n"); + if ((len < 8) && op->verbose) + pr2serr(" somewhat strange available_data=%u\n", len - 4); + return 0; + } + num_mtoks = (len - 8) / 96; + if ((0 != ((len - 8) % 96)) && op->verbose) + pr2serr(" available_data=%u implies non-integral number of " + "management tokens\n", len - 4); + if (num_mtoks > MAX_NUM_MAN_TOKS) { + pr2serr(" %u management ROD Tokens available, can only display " + "first %d\n", num_mtoks, MAX_NUM_MAN_TOKS); + num_mtoks = MAX_NUM_MAN_TOKS; + } + if (do_hex) { + if (do_hex > 1) { + dStrHex((const char *)rsp, ((len < 8) ? len : 8), 1); + for (k = 0, ucp = rsp + 8; k < (int)num_mtoks; ++k, ucp += 96) { + printf("\n"); + dStrHex((const char *)ucp, 96, 1); + } + } else { + if (len > sizeof(rsp)) + len = sizeof(rsp); + dStrHex((const char *)rsp, len , 1); + } + return 0; + } + printf("Number of managed ROD Token headers returned: %u\n", + (len - 8) / 96); + if (num_mtoks < ((len - 8) / 96)) + printf(" Number displayed: %u\n", num_mtoks); + for (k = 0, ucp = rsp + 8; k < (int)num_mtoks; ++k, ucp += 96) { + printf("\n ROD Token header %d\n", k + 1); + + res = odx_print_rod_tok(op, ucp, 96); + if (res && (0 == a_err)) + a_err = res; } - // Hmmm, not supported on HP 3 PAR (and not required for ODX) - return 0; + return a_err; } static int @@ -541,6 +591,7 @@ int req_abort = 0; int req_all_toks = 0; int do_block = 0; + int do_hex = 0; int do_info = 0; int do_poll = 0; int req_pt = 0; @@ -568,8 +619,8 @@ while (1) { int option_index = 0; - c = getopt_long(argc, argv, "AaBDhiIl:O:pP:r:Rst:T:vVw:", long_options, - &option_index); + c = getopt_long(argc, argv, "AaBDhHiIl:O:pP:r:Rst:T:vVw:y", + long_options, &option_index); if (c == -1) break; @@ -590,6 +641,9 @@ case '?': usage(); return 0; + case 'H': + ++do_hex; + break; case 'i': ++do_info; break; @@ -703,6 +757,9 @@ ++req_wut; sglp = optarg; break; + case 'y': + ++op->o_readonly; + break; default: pr2serr("unrecognised option code 0x%x ??\n", c); usage(); @@ -839,7 +896,7 @@ if (ret) goto clean_up; } else if (req_all_toks) { - ret = report_all_toks(op, op->idip); + ret = report_all_toks(op, op->idip, do_hex); if (ret) goto clean_up; } else if (do_poll) { @@ -986,7 +1043,7 @@ printf("unable to print capacity information about device\n"); } } else - printf("Has something been forgotten\n"); + printf("Expecting to see an option; try again with '-h'\n"); clean_up: if ((req_pt || req_wut) && op->iflagp->immed && (0 == ret)) diff -Nru ddpt-0.94/src/ddpt.h ddpt-0.95/src/ddpt.h --- ddpt-0.94/src/ddpt.h 2014-04-02 05:11:51.000000000 +0000 +++ ddpt-0.95/src/ddpt.h 2014-10-26 12:54:52.000000000 +0000 @@ -84,6 +84,9 @@ #define MAX_XC_BPT_POW2 32768 /* BPT maximum that is power of 2 */ #define DEF_SCSI_CDBSZ 10 #define MAX_SCSI_CDBSZ 32 +#define DDPT_MAX_JF_DEPTH 4 +#define DDPT_MAX_JF_LINES 1000 +#define DDPT_MAX_JF_ARGS_PER_LINE 16 #define VPD_DEVICE_ID 0x83 #define VPD_3PARTY_COPY 0x8f @@ -119,6 +122,7 @@ #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 */ +#define FT_ALL_FF 512 /* iflag=ff so input will be 0xff bytes */ /* ODX type requested */ #define ODX_REQ_NONE 0 /* some other type of copy */ @@ -167,7 +171,6 @@ #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 @@ -178,13 +181,12 @@ #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 */ +#define DDPT_DEF_BS "DDPT_DEF_BS" /* default default block size: 512 bytes */ /* ODX: length field inside ROD Token constant, implies 512 byte ROD Token */ #define ODX_ROD_TOK_LEN_FLD 504 /* 0x1f8 */ @@ -232,7 +234,9 @@ * General or for disk unless otherwise marked. */ struct flags_t { int append; + int atomic; int block; /* only for pt, non blocking default */ + int bytchk; /* set field in WRITE AND VERIFY */ int cat; /* xcopy(lid1) related */ int cdbsz; int coe; @@ -243,6 +247,7 @@ int errblk; int excl; int fdatasync; + int ff; /* iflag=ff makes input all 0xff bytes */ int flock; int force; int fsync; @@ -271,6 +276,7 @@ int strunc; int sync; int trunc; + int verify; /* oflag with pt, turns WRITE into WRITE AND VERIFY */ int wsame16; int xcopy; /* xcopy(LID1) */ }; @@ -354,8 +360,10 @@ 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; + /* after copy/read starts, decrements to 0 */ + int64_t dd_count_start; /* dd_count prior to start of copy/read */ + int64_t in_full; /* full blocks read from IFILE so far */ + int64_t out_full; /* full blocks written to OFILE so far */ int64_t out_sparse; /* used for sparse, sparing + trim */ int64_t lowest_unrecovered; /* on reads */ int64_t highest_unrecovered; /* on reads */ @@ -386,6 +394,7 @@ int reading_fifo; int read1_or_transfer; /* 1 when of=/dev/null or similar */ int ibs_hold; + int o_readonly; unsigned char * wrkBuff; unsigned char * wrkPos; unsigned char * wrkBuff2; @@ -537,7 +546,7 @@ /* defined in ddpt_cl.c */ int cl_process(struct opts_t * op, int argc, char * argv[], - const char * version_str); + const char * version_str, int jf_depth); void ddpt_usage(int help); diff -Nru ddpt-0.94/src/ddpt_pt.c ddpt-0.95/src/ddpt_pt.c --- ddpt-0.94/src/ddpt_pt.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt_pt.c 2014-10-26 12:54:52.000000000 +0000 @@ -74,6 +74,9 @@ #define DDPT_WRITE10_OC 0x2a #define DDPT_WRITE12_OC 0xaa #define DDPT_WRITE16_OC 0x8a +#define DDPT_WRITE_ATOMIC16_OC 0x9c /* sbc4r02 */ +#define DDPT_WRITE_VERIFY10_OC 0x2e +#define DDPT_WRITE_VERIFY16_OC 0x8e #define DDPT_VARIABLE_LEN_OC 0x7f #define DDPT_READ32_SA 0x9 #define DDPT_WRITE32_SA 0xb @@ -89,8 +92,6 @@ #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 @@ -147,18 +148,28 @@ flags |= O_EXCL; if (fp->sync) flags |= O_SYNC; - fl = O_RDWR; + fl = op->o_readonly ? O_RDONLY : 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)); + if (op->o_readonly) { + pr2serr("could not open %s ro as pass-through: %s\n", fn, + safe_strerror(-fd)); return -1; + } else { + fl = O_RDONLY; + if (op->verbose) + pr2serr("could not open %s read-write so try read-only\n", + fn); + if ((fd = scsi_pt_open_flags(fn, (fl | flags), op->verbose)) + < 0) { + pr2serr("could not open %s [rw or ro] as pass-through: %s\n", + fn, safe_strerror(-fd)); + return -1; + } } } if (sg_simple_inquiry(fd, &sir, 0, verb)) { @@ -310,33 +321,64 @@ 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; + int opcode_sa, options_byte, rw_sa; + int * opc_arr; - memset(cdbp, 0, cdb_sz); - options_byte = 0; if (cdb_sz < 6) { pr2serr("cdb_sz too small\n"); return 1; } + memset(cdbp, 0, cdb_sz); + opcode_sa = 0; + options_byte = 0; + opc_arr = NULL; + + if (write_true) { + if (fp->atomic) { + if (16 == cdb_sz) + opcode_sa = DDPT_WRITE_ATOMIC16_OC; + else { + pr2serr("atomic flag only for WRITE_ATOMIC(16)\n"); + return 1; + } + } else if (fp->verify) { + if (10 == cdb_sz) + opcode_sa = DDPT_WRITE_VERIFY10_OC; + else if (16 == cdb_sz) + opcode_sa = DDPT_WRITE_VERIFY16_OC; + else { + pr2serr("verify flag for WRITE AND VERIFY (10 or 16) only\n"); + return 1; + } + } else + opc_arr = wr_opcode; + } else { /* a READ */ + opc_arr = rd_opcode; + if (fp->rarc) + options_byte |= 0x4; + } + if (cdb_sz > 6) { if (fp->dpo) options_byte |= 0x10; - if (fp->fua) - options_byte |= 0x8; - if (fp->fua_nv) - options_byte |= 0x2; + if (fp->verify && write_true) { + if (fp->bytchk) + options_byte |= ((fp->bytchk & 0x3) << 1); + } else { + 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 */ + if (0 == opcode_sa) + opcode_sa = opc_arr[0]; + cdbp[0] = (unsigned char)opcode_sa; cdbp[1] = (unsigned char)((start_block >> 16) & 0x1f); cdbp[2] = (unsigned char)((start_block >> 8) & 0xff); cdbp[3] = (unsigned char)(start_block & 0xff); @@ -357,9 +399,9 @@ } break; case 10: - sz_ind = 1; - cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] : - rd_opcode[sz_ind]); + if (0 == opcode_sa) + opcode_sa = opc_arr[1]; + cdbp[0] = (unsigned char)opcode_sa; cdbp[1] = (unsigned char)options_byte; cdbp[2] = (unsigned char)((start_block >> 24) & 0xff); cdbp[3] = (unsigned char)((start_block >> 16) & 0xff); @@ -374,9 +416,9 @@ } break; case 12: - sz_ind = 2; - cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] : - rd_opcode[sz_ind]); + if (0 == opcode_sa) + opcode_sa = opc_arr[2]; + cdbp[0] = (unsigned char)opcode_sa; cdbp[1] = (unsigned char)options_byte; cdbp[2] = (unsigned char)((start_block >> 24) & 0xff); cdbp[3] = (unsigned char)((start_block >> 16) & 0xff); @@ -388,9 +430,9 @@ 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]); + if (0 == opcode_sa) + opcode_sa = opc_arr[3]; + cdbp[0] = (unsigned char)opcode_sa; cdbp[1] = (unsigned char)options_byte; cdbp[2] = (unsigned char)((start_block >> 56) & 0xff); cdbp[3] = (unsigned char)((start_block >> 48) & 0xff); @@ -406,10 +448,11 @@ cdbp[13] = (unsigned char)(blocks & 0xff); break; case 32: - sz_ind = 4; + if (0 == opcode_sa) + opcode_sa = opc_arr[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]; + rw_sa = opcode_sa; cdbp[8] = (unsigned char)((rw_sa >> 8) & 0xff); cdbp[9] = (unsigned char)(rw_sa & 0xff); cdbp[10] = (unsigned char)options_byte; @@ -436,10 +479,9 @@ /* 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, + * plus various other SG_LIB_CAT_* positive values, * -2 -> ENOMEM * -1 other errors */ static int @@ -497,21 +539,19 @@ switch (sense_cat) { case SG_LIB_CAT_NOT_READY: case SG_LIB_CAT_INVALID_OP: + case SG_LIB_CAT_RES_CONFLICT: + case SG_LIB_CAT_DATA_PROTECT: + case SG_LIB_CAT_ABORTED_COMMAND: ++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; - } + case SG_LIB_CAT_PROTECTION: + /* no retry, might have INFO field */ + ++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; break; case SG_LIB_CAT_RECOVERED: ++op->recovered_errs; @@ -594,17 +634,20 @@ int retries_tmp; int ret = 0; int may_coe = 0; + const char * iop; if (in0_out1) { from_block = op->seek; bs = op->obs_pi; pi_len = op->obs_pi - op->obs; fp = op->oflagp; + iop = "ofile"; } else { from_block = op->skip; bs = op->ibs_pi; pi_len = op->ibs_pi - op->ibs; fp = op->iflagp; + iop = "ifile"; } retries_tmp = fp->retries; for (xferred = 0, blks = blocks, lba = from_block, bp = buff; @@ -623,21 +666,25 @@ case -2: /* ENOMEM */ return res; case SG_LIB_CAT_NOT_READY: - pr2serr("Device (r) not ready\n"); + pr2serr("%s: Device not ready [%s]\n", __func__, iop); return res; case SG_LIB_CAT_ABORTED_COMMAND: if (--op->max_aborted > 0) - pr2serr("Aborted command, continuing (r)\n"); + pr2serr("%s: Aborted command, continuing [%s]\n", __func__, + iop); else { - pr2serr("Aborted command, too many (r)\n"); + pr2serr("%s: Aborted command, too many [%s]\n", __func__, + iop); return res; } break; case SG_LIB_CAT_UNIT_ATTENTION: if (--op->max_uas > 0) - pr2serr("Unit attention, continuing (r)\n"); + pr2serr("%s: Unit attention, continuing [%s]\n", __func__, + iop); else { - pr2serr("Unit attention, too many (r)\n"); + pr2serr("%s: Unit attention, too many [%s]\n", __func__, + iop); return res; } break; @@ -670,6 +717,9 @@ if (0 == retries_tmp) errblk_put_range(lba, blks, op); /* fall through */ + case SG_LIB_CAT_RES_CONFLICT: + case SG_LIB_CAT_DATA_PROTECT: + case SG_LIB_CAT_PROTECTION: default: if (retries_tmp > 0) { pr2serr(">>> retrying pt read: starting lba=%" PRId64 " [0x%" @@ -721,16 +771,18 @@ ret = res; goto err_out; case -2: - pr2serr("ENOMEM again, unexpected (r)\n"); + pr2serr("%s: ENOMEM again, unexpected [%s]\n", __func__, iop); return -1; case SG_LIB_CAT_NOT_READY: - pr2serr("device (r) not ready\n"); + pr2serr("%s: device not ready [%s]\n", __func__, iop); return res; case SG_LIB_CAT_UNIT_ATTENTION: - pr2serr("Unit attention, unexpected (r)\n"); + pr2serr("%s: Unit attention, unexpected [%s]\n", __func__, + iop); return res; case SG_LIB_CAT_ABORTED_COMMAND: - pr2serr("Aborted command, unexpected (r)\n"); + pr2serr("%s: Aborted command, unexpected [%s]\n", __func__, + iop); return res; case SG_LIB_CAT_MEDIUM_HARD_WITH_INFO: case SG_LIB_CAT_MEDIUM_HARD: @@ -742,8 +794,8 @@ goto err_out; case SG_LIB_SYNTAX_ERROR: default: - pr2serr(">> unexpected result=%d from pt_low_read() 2\n", - res); + pr2serr(">> unexpected result=%d from pt_low_read() 2 [%s]\n", + res, iop); ret = res; goto err_out; } @@ -816,7 +868,7 @@ 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; + const char * desc; if (pt_build_scsi_cdb(wrCmd, fp->cdbsz, blocks, to_block, 1, fp, op->wrprotect)) { @@ -824,8 +876,14 @@ to_block, blocks); return SG_LIB_SYNTAX_ERROR; } + if (DDPT_WRITE_ATOMIC16_OC == wrCmd[0]) + desc = "WRITE ATOMIC(16)"; + else if (0xe == (0xf & wrCmd[0])) + desc = "WRITE AND VERIFY"; + else + desc = "WRITE"; if (op->verbose > 2) { - pr2serr(" WRITE cdb: "); + pr2serr(" %s cdb: ", desc); for (k = 0; k < fp->cdbsz; ++k) pr2serr("%02x ", wrCmd[k]); pr2serr("\n"); @@ -839,13 +897,16 @@ 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); +#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, 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, + ret = sg_cmds_process_resp(ptvp, desc, res, bs * blocks, sense_b, 0 /* noisy */, vt, &sense_cat); if (-1 == ret) ; @@ -865,19 +926,15 @@ 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: + case SG_LIB_CAT_RES_CONFLICT: + case SG_LIB_CAT_DATA_PROTECT: + case SG_LIB_CAT_PROTECTION: ++op->wr_unrecovered_errs; break; case SG_LIB_CAT_MEDIUM_HARD: @@ -892,7 +949,6 @@ } } else ret = 0; - return ret; } @@ -1008,13 +1064,6 @@ ; 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; @@ -1033,7 +1082,7 @@ ret = sense_cat; break; default: - ret = -1; + ret = sense_cat; break; } } else @@ -1069,12 +1118,6 @@ 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) && @@ -1110,23 +1153,12 @@ } 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; + ret = sense_cat; break; } } else @@ -1232,7 +1264,7 @@ 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; + ret = SG_LIB_CAT_RES_CONFLICT; else ret = pt_tpc_process_res(ret, sense_cat, sense_b, get_scsi_pt_sense_len(ptvp)); @@ -1292,7 +1324,7 @@ 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; + ret = SG_LIB_CAT_RES_CONFLICT; else ret = pt_tpc_process_res(ret, sense_cat, sense_b, get_scsi_pt_sense_len(ptvp)); diff -Nru ddpt-0.94/src/ddpt_win32.c ddpt-0.95/src/ddpt_win32.c --- ddpt-0.94/src/ddpt_win32.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt_win32.c 2014-05-30 04:22:41.000000000 +0000 @@ -107,7 +107,7 @@ * 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 +static const char * win32_errmsg(int errnum, char * b, int blen) { LPTSTR err_txt = 0; @@ -115,15 +115,16 @@ int len = 0; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, + FORMAT_MESSAGE_FROM_SYSTEM, NULL, errn, 0, (LPTSTR)&err_txt, 0, - NULL) == 0) - return -1; - else { + NULL) == 0) { + snprintf(b, blen, "FormatMessage(errnum=%d) failed", errnum); + return b; + } else { len = strlen(err_txt); if (len) { if ('\n' == err_txt[len - 1]) { @@ -145,7 +146,9 @@ } if (err_txt) LocalFree(err_txt); - return len; + len = strlen(b); + snprintf(b + len, blen - len, " [%d]", errnum); + return b; } /* Return 1 for filenames starting with '\', or of the form ':' @@ -350,7 +353,9 @@ DISK_GEOMETRY g; DWORD count, share_mode, err; char b[80]; + int blen; + blen = sizeof(b); if (verbose) pr2serr("CreateFile(%s , in)\n", op->idip->fn); share_mode = (O_EXCL & flags) ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); @@ -363,22 +368,14 @@ 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); + pr2serr("CreateFile(in) failed, %s\n", win32_errmsg(err, b, blen)); 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); + pr2serr("DeviceIoControl(in, geometry) failed, %s\n", + win32_errmsg(err, b, blen)); return 1; } if ((int)g.BytesPerSector != op->ibs) { @@ -396,7 +393,9 @@ DISK_GEOMETRY g; DWORD count, share_mode, err; char b[80]; + int blen; + blen = sizeof(b); if (verbose) pr2serr("CreateFile(%s , out)\n", op->odip->fn); share_mode = (O_EXCL & flags) ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); @@ -409,16 +408,14 @@ 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); + pr2serr("CreateFile(out) failed, %s\n", win32_errmsg(err, b, blen)); 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()); + err = GetLastError(); + pr2serr("DeviceIoControl(out, geometry) failed, %s\n", + win32_errmsg(err, b, blen)); return 1; } if ((int)g.BytesPerSector != op->obs) { @@ -441,7 +438,10 @@ DWORD lo_ret; HANDLE fh; const char * cp; + char b[80]; + int blen; + blen = sizeof(b); fh = (DDPT_ARG_IN == which_arg) ? op->idip->fh : op->odip->fh; cp = (DDPT_ARG_IN == which_arg) ? "in" : "out"; if (verbose > 2) @@ -450,8 +450,8 @@ 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); + pr2serr("SetFilePointer failed to set pos=[0x%" PRIx64 "], %s\n", + pos, win32_errmsg(err, b, blen)); return 1; } return 0; @@ -465,18 +465,15 @@ DWORD num = num_bytes; DWORD howMany, err; char b[80]; + int blen; + blen = sizeof(b); 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 (verbose) + pr2serr("ReadFile failed, %s\n", win32_errmsg(err, b, blen)); if (23 == err) return -SG_LIB_CAT_MEDIUM_HARD; else @@ -493,18 +490,16 @@ DWORD num = num_bytes; DWORD howMany, err; char b[80]; + int blen; + blen = sizeof(b); 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 (verbose) + pr2serr("ReadFile(from_of) failed, %s\n", + win32_errmsg(err, b, blen)); if (23 == err) return -SG_LIB_CAT_MEDIUM_HARD; else @@ -521,18 +516,15 @@ DWORD num = num_bytes; DWORD howMany, err; char b[80]; + int blen; + blen = sizeof(b); 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 (verbose) + pr2serr("WriteFile failed, %s\n", win32_errmsg(err, b, blen)); if (23 == err) return -SG_LIB_CAT_MEDIUM_HARD; else @@ -552,22 +544,27 @@ DISK_GEOMETRY g; GET_LENGTH_INFORMATION gli; ULARGE_INTEGER total_bytes; - DWORD count; + DWORD count, err; HANDLE fh; const char * fname; int64_t byte_len, blks; int fname_len; char dirName[64]; + char b[80]; + int blen; + blen = sizeof(b); 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()); + if (op->verbose) { + err = GetLastError(); + pr2serr("DeviceIoControl(blkdev, geometry) failed, %s\n", + win32_errmsg(err, b, blen)); + } *num_sect = 0; *sect_sz = 0; return -1; @@ -580,9 +577,11 @@ 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()); + } else if (op->verbose > 2) { + err = GetLastError(); + pr2serr("DeviceIoControl(blkdev, length_info) failed, %s\n", + win32_errmsg(err, b, blen)); + } /* Assume if device name finishes in digit then its physical */ fname_len = (int)strlen(fname); @@ -606,9 +605,12 @@ 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()); + } else { + if (op->verbose > 1) { + err = GetLastError(); + pr2serr("GetDiskFreeSpaceEx(%s) failed, %s\n", dirName, + win32_errmsg(err, b, blen)); + } *num_sect = 0; return -1; } diff -Nru ddpt-0.94/src/ddpt_wscan.c ddpt-0.95/src/ddpt_wscan.c --- ddpt-0.94/src/ddpt_wscan.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt_wscan.c 2014-08-29 21:53:07.000000000 +0000 @@ -45,7 +45,12 @@ #include "sg_lib.h" -#ifndef _WIN32_WINNT +#ifdef _WIN32_WINNT + #if _WIN32_WINNT < 0x0602 + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0602 + #endif +#else #define _WIN32_WINNT 0x0602 /* claim its W8 */ #endif @@ -165,7 +170,7 @@ union STORAGE_DEVICE_UID_DATA { STORAGE_DEVICE_UNIQUE_IDENTIFIER desc; - char raw[512]; + char raw[1060]; }; struct storage_elem { @@ -275,20 +280,21 @@ if (verbose > 2) { err = GetLastError(); pr2serr(" IOCTL_STORAGE_QUERY_PROPERTY(Devprop) failed, " - "Error=%ld %s\n", err, get_err_str(err, sizeof(b), b)); + "Error=%u %s\n", (unsigned int)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); + pr2serr(" IOCTL_STORAGE_QUERY_PROPERTY(DevProp) num_out=%u\n", + (unsigned int)num_out); return 0; } static int query_dev_uid(HANDLE hdevice, - union STORAGE_DEVICE_UID_DATA * data) + union STORAGE_DEVICE_UID_DATA * data) { DWORD num_out, err; char b[256]; @@ -296,22 +302,42 @@ PropertyStandardQuery, {0} }; memset(data, 0, sizeof(*data)); + num_out = 0; + query.QueryType = PropertyExistsQuery; + if (! DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(query), NULL, 0, &num_out, NULL)) { + if (verbose > 2) { + err = GetLastError(); + fprintf(stderr, " IOCTL_STORAGE_QUERY_PROPERTY(DevUid(exists)) " + "failed, Error=%u %s\n", (unsigned int)err, + get_err_str(err, sizeof(b), b)); + } + if (verbose > 3) + fprintf(stderr, " num_out=%u\n", (unsigned int)num_out); + /* interpret any error to mean this property doesn't exist */ + return 0; + } + + query.QueryType = PropertyStandardQuery; 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)); + fprintf(stderr, " IOCTL_STORAGE_QUERY_PROPERTY(DevUid) failed, " + "Error=%u %s\n", (unsigned int)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); + fprintf(stderr, " IOCTL_STORAGE_QUERY_PROPERTY(DevUid) num_out=%u\n", + (unsigned int)num_out); return 0; } +/* Updates storage_arr based on sep. Returns 1 if update occurred, 0 if + * no update occured. */ static int check_devices(const struct storage_elem * sep) { @@ -321,7 +347,18 @@ 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 (sep->qp_uid_valid && sarr->qp_uid_valid) { + if (0 == memcmp(&sep->qp_uid, &sarr->qp_uid, + sizeof(sep->qp_uid))) { + 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; + } + } else 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) { @@ -333,7 +370,6 @@ return 1; } } - // should do uid check here (probably before descriptor compare) } return 0; } @@ -349,7 +385,7 @@ BYTE bus; BOOL success; char adapter_name[64]; - char inqDataBuff[2048]; + char inqDataBuff[8192]; PSCSI_ADAPTER_BUS_INFO ai; char b[256]; @@ -362,7 +398,7 @@ hole_count = 0; success = DeviceIoControl(fh, IOCTL_SCSI_GET_INQUIRY_DATA, NULL, 0, inqDataBuff, - sizeof(inqDataBuff), &dummy, FALSE); + sizeof(inqDataBuff), &dummy, NULL); if (success) { PSCSI_BUS_DATA pbd; PSCSI_INQUIRY_DATA pid; @@ -395,17 +431,19 @@ } } else { err = GetLastError(); - pr2serr("%s: IOCTL_SCSI_GET_INQUIRY_DATA failed err=%lu\n" - "\t%s", adapter_name, err, + pr2serr("%s: IOCTL_SCSI_GET_INQUIRY_DATA failed err=%u\n" + "\t%s", adapter_name, (unsigned int)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)); - } + err = GetLastError(); + if (ERROR_SHARING_VIOLATION == err) + fprintf(stderr, "%s: in use by other process (sharing " + "violation [34])\n", adapter_name); + else if (verbose > 3) + pr2serr("%s: CreateFile failed err=%u\n\t%s", adapter_name, + (unsigned int)err, get_err_str(err, sizeof(b), b)); if (++hole_count >= MAX_HOLE_COUNT) break; } @@ -483,11 +521,13 @@ 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)); - } + err = GetLastError(); + if (ERROR_SHARING_VIOLATION == err) + fprintf(stderr, "%s: in use by other process (sharing " + "violation [34])\n", adapter_name); + else if (verbose > 3) + pr2serr("%s: CreateFile failed err=%u\n\t%s", adapter_name, + (unsigned int)err, get_err_str(err, sizeof(b), b)); if (++hole_count >= MAX_HOLE_COUNT) break; } @@ -529,11 +569,13 @@ 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)); - } + err = GetLastError(); + if (ERROR_SHARING_VIOLATION == err) + fprintf(stderr, "%s: in use by other process (sharing " + "violation [34])\n", adapter_name); + else if (verbose > 3) + pr2serr("%s: CreateFile failed err=%u\n\t%s", adapter_name, + (unsigned int)err, get_err_str(err, sizeof(b), b)); if (++hole_count >= MAX_HOLE_COUNT) break; } @@ -575,11 +617,13 @@ 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)); - } + err = GetLastError(); + if (ERROR_SHARING_VIOLATION == err) + fprintf(stderr, "%s: in use by other process (sharing " + "violation [34])\n", adapter_name); + else if (verbose > 3) + pr2serr("%s: CreateFile failed err=%u\n\t%s", adapter_name, + (unsigned int)err, get_err_str(err, sizeof(b), b)); if (++hole_count >= MAX_HOLE_COUNT) break; } @@ -643,9 +687,13 @@ printf("%s", sp->qp_descriptor.raw + j); printf("\n"); if (verbose > 2) - dStrHex(sp->qp_descriptor.raw, 144, 0); + dStrHexErr(sp->qp_descriptor.raw, 144, 0); } else printf("\n"); + if ((verbose > 3) && sp->qp_uid_valid) { + printf(" UID valid, in hex:\n"); + dStrHexErr(sp->qp_uid.raw, sizeof(sp->qp_uid.raw), 1); + } } } diff -Nru ddpt-0.94/src/ddpt_xcopy.c ddpt-0.95/src/ddpt_xcopy.c --- ddpt-0.94/src/ddpt_xcopy.c 2014-04-07 04:40:58.000000000 +0000 +++ ddpt-0.95/src/ddpt_xcopy.c 2014-09-22 02:48:00.000000000 +0000 @@ -63,6 +63,7 @@ #include "sg_lib.h" #include "sg_cmds_basic.h" +#include "sg_unaligned.h" #define DEF_3PC_OUT_TIMEOUT (10 * 60) /* is 10 minutes enough? */ @@ -305,8 +306,8 @@ len = ((rcBuff[0] << 24) | (rcBuff[1] << 16) | (rcBuff[2] << 8) | rcBuff[3]) + 4; if (len > rcBuffLen) { - pr2serr(" < %d too long for internal buffer, output " + "truncated\n", len, rcBuffLen); } if (op->verbose > 2) { pr2serr("\nOutput %s response in hex:\n", rec_copy_op_params_str); @@ -961,104 +962,148 @@ /* 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) +decode_rod_descriptor(const unsigned char * buff, int len, int to_stderr) { const unsigned char * ucp = buff; - int k, bump, j; - uint64_t ull; + int k, bump; + int (*print_p)(const char *, ...); + print_p = to_stderr ? pr2serr : printf; for (k = 0; k < len; k += bump, ucp += bump) { - bump = (ucp[2] << 8) + ucp[3]; + bump = sg_get_unaligned_be16(ucp + 2) + 4; 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); + print_p(" Optimal block ROD length granularity: %d\n", + sg_get_unaligned_be16(ucp + 6)); + print_p(" Maximum Bytes in block ROD: %" PRIu64 "\n", + sg_get_unaligned_be64(ucp + 8)); + print_p(" Optimal Bytes in block ROD transfer: %" PRIu64 "\n", + sg_get_unaligned_be64(ucp + 16)); + print_p(" Optimal Bytes to token per segment: %" PRIu64 "\n", + sg_get_unaligned_be64(ucp + 24)); + print_p(" Optimal Bytes from token per segment:" + " %" PRIu64 "\n", sg_get_unaligned_be64(ucp + 32)); 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); + print_p(" Maximum Bytes in stream ROD: %" PRIu64 "\n", + sg_get_unaligned_be64(ucp + 8)); + print_p(" Optimal Bytes in stream ROD transfer:" + " %" PRIu64 "\n", sg_get_unaligned_be64(ucp + 16)); 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); + print_p(" Maximum Bytes in processor ROD: %" PRIu64 "\n", + sg_get_unaligned_be64(ucp + 8)); + print_p(" Optimal Bytes in processor ROD transfer:" + " %" PRIu64 "\n", sg_get_unaligned_be64(ucp + 16)); break; default: - pr2serr(" Unhandled descriptor (format %d, device type " - "%d)\n", ucp[0] >> 5, ucp[0] & 0x1F); + print_p(" Unhandled descriptor (format %d, device type %d)\n", + ucp[0] >> 5, ucp[0] & 0x1F); break; } } } +struct tpc_desc_type { + unsigned char code; + const char * name; +}; + +static struct tpc_desc_type tpc_desc_arr[] = { + {0x0, "block -> stream"}, + {0x1, "stream -> block"}, + {0x2, "block -> block"}, + {0x3, "stream -> stream"}, + {0x4, "inline -> stream"}, + {0x5, "embedded -> stream"}, + {0x6, "stream -> discard"}, + {0x7, "verify CSCD"}, + {0x8, "block -> stream"}, + {0x9, "stream -> block"}, + {0xa, "block -> block"}, + {0xb, "block -> stream & application_client"}, + {0xc, "stream -> block & application_client"}, + {0xd, "block -> block & application_client"}, + {0xe, "stream -> stream&application_client"}, + {0xf, "stream -> discard&application_client"}, + {0x10, "filemark -> tape"}, + {0x11, "space -> tape"}, + {0x12, "locate -> tape"}, + {0x13, "tape -> tape"}, + {0x14, "register persistent reservation key"}, + {0x15, "third party persistent reservation source I_T nexus"}, + {0x16, "block -> block"}, + {0xbe, "ROD <- block range(n)"}, + {0xbf, "ROD <- block range(1)"}, + {0xe0, "CSCD: FC N_Port_Name"}, + {0xe1, "CSCD: FC N_Port_ID"}, + {0xe2, "CSCD: FC N_Port_ID with N_Port_Name, checking"}, + {0xe3, "CSCD: Parallel interface: I_T"}, + {0xe4, "CSCD: Identification Descriptor"}, + {0xe5, "CSCD: IPv4"}, + {0xe6, "CSCD: Alias"}, + {0xe7, "CSCD: RDMA"}, + {0xe8, "CSCD: IEEE 1394 EUI-64"}, + {0xe9, "CSCD: SAS SSP"}, + {0xea, "CSCD: IPv6"}, + {0xeb, "CSCD: IP copy service"}, + {0xfe, "CSCD: ROD"}, + {0xff, "CSCD: extension"}, + {0x0, NULL}, +}; + +static const char * +get_tpc_desc_name(unsigned char code) +{ + const struct tpc_desc_type * dtp; + + for (dtp = tpc_desc_arr; dtp->name; ++dtp) { + if (code == dtp->code) + return dtp->name; + } + return ""; +} + +struct tpc_rod_type { + uint32_t type; + const char * name; +}; + +static struct tpc_rod_type tpc_rod_arr[] = { + {0x0, "copy manager internal"}, + {0x10000, "access upon reference"}, + {0x800000, "point in time copy - default"}, + {0x800001, "point in time copy - change vulnerable"}, + {0x800002, "point in time copy - persistent"}, + {0x80ffff, "point in time copy - any"}, + {0xffff0001, "block device zero"}, + {0x0, NULL}, +}; + +static const char * +get_tpc_rod_name(uint32_t rod_type) +{ + const struct tpc_rod_type * rtp; + + for (rtp = tpc_rod_arr; rtp->name; ++rtp) { + if (rod_type == rtp->type) + return rtp->name; + } + return ""; +} + /* 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; + int k, j, m, bump, desc_type, desc_len, sa_len; unsigned int u; const unsigned char * ucp; + const char * cp; uint64_t ull; char b[80]; int (*print_p)(const char *, ...); @@ -1071,8 +1116,8 @@ 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]; + desc_type = sg_get_unaligned_be16(ucp); + desc_len = sg_get_unaligned_be16(ucp + 2); if (verbose) print_p("Descriptor type=%d, len=%d\n", desc_type, desc_len); bump = 4 + desc_len; @@ -1087,26 +1132,14 @@ 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]; + sg_get_unaligned_be16(ucp + 10)); + u = sg_get_unaligned_be32(ucp + 12); print_p(" Maximum Inactivity Timeout: %u seconds\n", u); - u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) | - ucp[19]; + u = sg_get_unaligned_be32(ucp + 16); 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]; - } + ull = sg_get_unaligned_be64(ucp + 20); 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]; - } + ull = sg_get_unaligned_be64(ucp + 28); print_p(" Optimal Transfer Count: %" PRIu64 "\n", ull); break; case 0x0001: /* Mandatory (SPC-4) */ @@ -1114,96 +1147,94 @@ 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], + for (m = 0; m < sa_len; ++m) { + sg_get_opcode_sa_name(ucp[5 + j], ucp[7 + j + m], 0, sizeof(b), b); - print_p(" %s\n", b); + print_p(" %s\n", b); } - j += sa_len; + j += sa_len + 2; } break; case 0x0004: print_p(" Parameter Data:\n"); print_p(" Maximum CSCD Descriptor Count: %d\n", - (ucp[8] << 8) + ucp[9]); + sg_get_unaligned_be16(ucp + 8));; 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]; + sg_get_unaligned_be16(ucp + 10)); + u = sg_get_unaligned_be32(ucp + 12); print_p(" Maximum Descriptor List Length: %u\n", u); - u = (ucp[16] << 24) | (ucp[17] << 16) | (ucp[18] << 8) | - ucp[19]; + u = sg_get_unaligned_be32(ucp + 16); 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]); + cp = get_tpc_desc_name(ucp[5 + j]); + if (strlen(cp) > 0) + printf(" %s [0x%x]\n", cp, ucp[5 + j]); + else + printf(" 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]; + u = sg_get_unaligned_be16(ucp + 6 + 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]; + u = sg_get_unaligned_be32(ucp + 16); print_p(" Minimum Token Lifetime: %u seconds\n", u); - u = (ucp[20] << 24) | (ucp[21] << 16) | (ucp[22] << 8) | - ucp[23]; + u = sg_get_unaligned_be32(ucp + 20); print_p(" Maximum Token Lifetime: %u seconds\n", u); - u = (ucp[24] << 24) | (ucp[25] << 16) | (ucp[26] << 8) | - ucp[27]; + u = sg_get_unaligned_be32(ucp + 24); print_p(" Maximum Token inactivity timeout: %d\n", u); - decode_rod_descriptor(&ucp[48], (ucp[46] << 8) + ucp[47]); + decode_rod_descriptor(ucp + 48, + sg_get_unaligned_be16(ucp + 46), to_stderr); 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); + for (j = 0; j < sg_get_unaligned_be16(ucp + 6); j+= 64) { + u = sg_get_unaligned_be32(ucp + 8 + j); + cp = get_tpc_rod_name(u); + if (strlen(cp) > 0) + printf(" ROD Type: %s [0x%x]\n", cp, u); + else + printf(" ROD Type: 0x%x\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"); + ucp[8 + j + 4] & 0x01 ? "yes" : "no"); print_p(" Preference: %d\n", - (ucp[8 + j + 6] << 8) + ucp[8 + j + 7]); + sg_get_unaligned_be16(ucp + 8 + j + 6)); } break; case 0x8001: /* Mandatory (SPC-4) */ print_p(" General Copy Operations:\n"); - u = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | - ucp[7]; + u = sg_get_unaligned_be32(ucp + 4); print_p(" Total Concurrent Copies: %u\n", u); - u = (ucp[8] << 24) | (ucp[9] << 16) | (ucp[10] << 8) | - ucp[11]; + u = sg_get_unaligned_be32(ucp + 8); print_p(" Maximum Identified Concurrent Copies: %u\n", u); - u = (ucp[12] << 24) | (ucp[13] << 16) | (ucp[14] << 8) | - ucp[15]; + u = sg_get_unaligned_be32(ucp + 12); print_p(" Maximum Segment Length: %u\n", u); - ull = (1 << ucp[16]); + ull = (1 << ucp[16]); /* field is power of 2 */ 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]; + u = sg_get_unaligned_be32(ucp + 4); 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]; + u = sg_get_unaligned_be32(ucp + 4); print_p(" Held Data Limit: %u\n", u); ull = (1 << ucp[8]); print_p(" Held Data Granularity: %" PRIu64 "\n", ull); @@ -2059,6 +2090,7 @@ } out_blk_off = 0; op->dd_count = out_num_blks; + op->dd_count_start = op->dd_count; /* Build fixed format ROD Token Block Zero; specified by SBC-3 */ memset(local_rod_token, 0, sizeof(local_rod_token)); @@ -2148,6 +2180,7 @@ in_blk_off = 0; op->dd_count = in_num_blks; + op->dd_count_start = op->dd_count; if (op->verbose > 1) pr2serr("%s: about to read %" PRIi64 " blocks\n", __func__, in_num_blks); @@ -2230,6 +2263,7 @@ out_blk_off = 0; op->dd_count = out_num_blks; + op->dd_count_start = op->dd_count; if (op->verbose > 1) pr2serr("%s: about to write %" PRIi64 " blocks (seen from output)\n", __func__, out_num_blks); @@ -2477,6 +2511,7 @@ in_blk_off = 0; out_blk_off = 0; op->dd_count = in_num_blks; + op->dd_count_start = op->dd_count; if (op->verbose > 1) pr2serr("%s: about to copy %" PRIi64 " blocks (seen from input)\n", __func__, in_num_blks); diff -Nru ddpt-0.94/src/Makefile.am ddpt-0.95/src/Makefile.am --- ddpt-0.94/src/Makefile.am 2014-03-03 22:28:27.000000000 +0000 +++ ddpt-0.95/src/Makefile.am 2014-09-23 15:41:34.000000000 +0000 @@ -1,7 +1,7 @@ bin_PROGRAMS = ddpt ddptctl # for C++/clang testing -## CC = g++ +## CC = gcc ## CC = g++ ## CC = clang ## CC = clang++ @@ -9,9 +9,9 @@ # 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 +AM_CFLAGS = -iquote $(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W @os_cflags@ +## AM_CFLAGS = -iquote $(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W @os_cflags@ -pedantic -std=c11 +## AM_CFLAGS = -iquote $(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W @os_cflags@ -pedantic -std=c++11 diff -Nru ddpt-0.94/src/Makefile.in ddpt-0.95/src/Makefile.in --- ddpt-0.94/src/Makefile.in 2014-03-03 22:28:27.000000000 +0000 +++ ddpt-0.95/src/Makefile.in 2014-09-23 15:41:34.000000000 +0000 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -284,6 +284,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +os_cflags = @os_cflags@ os_deps = @os_deps@ os_libs = @os_libs@ pdfdir = @pdfdir@ @@ -305,7 +306,7 @@ # 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 = -iquote $(top_srcdir)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -W @os_cflags@ 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 \ @@ -462,14 +463,14 @@ @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 $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .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) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(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