aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COVERAGE4
-rw-r--r--ChangeLog3
-rw-r--r--README13
-rw-r--r--aclocal.m410
-rwxr-xr-xconfig.guess192
-rwxr-xr-xconfig.sub30
-rwxr-xr-xconfigure25
-rw-r--r--debian/changelog2
-rw-r--r--doc/Makefile.am6
-rw-r--r--doc/Makefile.in8
-rw-r--r--doc/sg_timestamp.8121
-rw-r--r--lib/sg_cmds_basic.c11
-rw-r--r--lib/sg_cmds_basic2.c42
-rw-r--r--lib/sg_cmds_extra.c188
-rw-r--r--lib/sg_cmds_mmc.c30
-rw-r--r--lib/sg_lib.c58
-rwxr-xr-xltmain.sh4
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.in28
-rw-r--r--src/sg_inq.c152
-rw-r--r--src/sg_timestamp.c407
22 files changed, 907 insertions, 436 deletions
diff --git a/COVERAGE b/COVERAGE
index 4cdf6f3c..3b38b75f 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -66,6 +66,7 @@ REPORT REFERRALS sg_referrals, ++
REPORT SUPPORTED OPERATION CODES sg_opcodes
REPORT SUPPORTED TASK MANAGEMENT FUNCTIONS sg_opcodes
REPORT TARGET PORT GROUPS sg_rtpg, sg_stpg ++
+REPORT TIMESTAMP sg_timestamp
REPORT ZONES sg_rep_zones
REQUEST SENSE sg_requests, ++
RESET WRITE POINTER sg_reset_wp
@@ -73,6 +74,7 @@ SANITIZE sg_sanitize
SEND DIAGNOSTIC sg_senddiag, sg_ses, sg_ses_microcode ++
SET IDENTIFYING INFORMATION sg_ident, ++ (3)
SET TARGET PORT GROUPS sg_stpg, ++
+SET TIMESTAMP sg_timestamp
START STOP sg_start, ++
SYNCHRONIZE CACHE(10) sg_sync, sg_dd, sgm_dd, sgp_dd, ++
SYNCHRONIZE CACHE(16) sg_sync++
@@ -129,4 +131,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-7th January 2015
+1st December 2015
diff --git a/ChangeLog b/ChangeLog
index bfa6057d..22ebcfdf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,8 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.42 [20151127] [svn: r649]
+Changelog for sg3_utils-1.42 [20151201] [svn: r650]
+ - sg_timestamp: new, to report or set timestamp
- sg_stpg: fix truncation of target port field
- sg_inq: cope with unicode strings, udev fixes
- update version descriptor list to 20151101
diff --git a/README b/README
index 8695d06f..424113b7 100644
--- a/README
+++ b/README
@@ -237,9 +237,10 @@ subdirectory of the sg3_utils package:
sg_reassign, sg_referrals, sg_request, sg_reset, sg_rmsn, sg_rtpg,
sg_safte, sg_sanitize, sg_sat_identify, sg_sat_phy_event,
sg_sat_read_gplog, sg_sat_set_features, sg_scan, sg_senddiag, sg_ses,
- sg_ses_microcode, sg_start, sg_stpg, sg_sync, sg_test_rwbuff, sg_turs,
- sg_unmap, sg_verify, sg_vpd, sg_write_buffer, sg_write_long,
- sg_write_same, sg_write_verify sg_wr_mode, sg_xcopy, sg_zone
+ sg_ses_microcode, sg_start, sg_stpg, sg_sync, sg_test_rwbuff,
+ sg_timestamp, sg_turs, sg_unmap, sg_verify, sg_vpd, sg_write_buffer,
+ sg_write_long, sg_write_same, sg_write_verify sg_wr_mode, sg_xcopy,
+ sg_zone
Each of the above utilities depends on header files found in the 'include'
subdirectory and library code found in the 'lib' subdirectory. Associated
@@ -387,8 +388,8 @@ The more recent utilities that use "getopt_long" only are:
sg_referrals, sg_requests, sg_rmsn, sg_rtpg, sg_safte, sg_sanitize,
sg_sat_identify, sg_sat_phy_event, sg_sat_read_gplog, sg_sat_set_features,
sg_scan(w), sg_ses, sg_ses_microcode, sg_stpg, sg_sync, sg_test_rwbuf,
- sg_unmap, sg_verify, sg_vpd, sg_write_buffer, sg_write_long,
- sg_write_same, sg_write_verify, sg_wr_mode, sg_zone
+ sg_timestamp, sg_unmap, sg_verify, sg_vpd, sg_write_buffer,
+ sg_write_long, sg_write_same, sg_write_verify, sg_wr_mode, sg_zone
Dangerous code
@@ -412,4 +413,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-27th November 2015
+1st December 2015
diff --git a/aclocal.m4 b/aclocal.m4
index d6091821..63d68788 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -8705,9 +8705,10 @@ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
-[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
-# Expand $ac_aux_dir to an absolute path.
-am_aux_dir=`cd "$ac_aux_dir" && pwd`
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
@@ -9174,8 +9175,7 @@ to "yes", and re-run configure.
END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
-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
diff --git a/config.guess b/config.guess
index 1f5c50c0..b79252d6 100755
--- a/config.guess
+++ b/config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2014-03-23'
+timestamp='2013-06-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -149,7 +149,7 @@ Linux|GNU|GNU/*)
LIBC=gnu
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
;;
esac
@@ -826,7 +826,7 @@ EOF
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
- *:MSYS*:*)
+ i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
@@ -969,10 +969,10 @@ EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
- openrisc*:Linux:*:*)
- echo or1k-unknown-linux-${LIBC}
+ or1k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
- or32:Linux:*:* | or1k*:Linux:*:*)
+ or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
@@ -1260,26 +1260,16 @@ EOF
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
- if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
fi
- elif test "$UNAME_PROCESSOR" = i386 ; then
- # Avoid executing cc on OS X 10.9, as it ships with a stub
- # that puts up a graphical alert prompting to install
- # developer tools. Any system running Mac OS X 10.7 or
- # later (Darwin 11 and later) is required to have a 64-bit
- # processor. This is not true of the ARM version of Darwin
- # that Apple uses in portable devices.
- UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
@@ -1371,6 +1361,154 @@ EOF
exit ;;
esac
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
cat >&2 <<EOF
$0: unable to guess system type
diff --git a/config.sub b/config.sub
index bba4efb8..9633db70 100755
--- a/config.sub
+++ b/config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2014-09-11'
+timestamp='2013-08-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -68,7 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -265,7 +265,6 @@ case $basic_machine in
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
- | k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
@@ -283,10 +282,8 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
@@ -298,11 +295,11 @@ case $basic_machine in
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | open8 | or1k | or1knd | or32 \
+ | open8 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
- | riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
@@ -327,7 +324,7 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -384,7 +381,6 @@ case $basic_machine in
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
- | k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
@@ -404,10 +400,8 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
@@ -419,7 +413,6 @@ case $basic_machine in
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
- | or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
@@ -829,10 +822,6 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -1378,14 +1367,14 @@ case $os in
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1603,6 +1592,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
diff --git a/configure b/configure
index b9cca779..2a0269da 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sg3_utils 1.41.
+# Generated by GNU Autoconf 2.69 for sg3_utils 1.42.
#
# Report bugs to <dgilbert@interlog.com>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sg3_utils'
PACKAGE_TARNAME='sg3_utils'
-PACKAGE_VERSION='1.41'
-PACKAGE_STRING='sg3_utils 1.41'
+PACKAGE_VERSION='1.42'
+PACKAGE_STRING='sg3_utils 1.42'
PACKAGE_BUGREPORT='dgilbert@interlog.com'
PACKAGE_URL=''
@@ -1331,7 +1331,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sg3_utils 1.41 to adapt to many kinds of systems.
+\`configure' configures sg3_utils 1.42 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1401,7 +1401,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sg3_utils 1.41:";;
+ short | recursive ) echo "Configuration of sg3_utils 1.42:";;
esac
cat <<\_ACEOF
@@ -1513,7 +1513,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sg3_utils configure 1.41
+sg3_utils configure 1.42
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1791,7 +1791,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sg3_utils $as_me 1.41, which was
+It was created by sg3_utils $as_me 1.42, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2341,8 +2341,8 @@ test "$program_suffix" != NONE &&
ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
-# Expand $ac_aux_dir to an absolute path.
-am_aux_dir=`cd "$ac_aux_dir" && pwd`
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
@@ -2655,7 +2655,7 @@ fi
# Define the identity of the package.
PACKAGE='sg3_utils'
- VERSION='1.41'
+ VERSION='1.42'
cat >>confdefs.h <<_ACEOF
@@ -2748,7 +2748,6 @@ END
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; }
# Check whether --enable-maintainer-mode was given.
@@ -12340,7 +12339,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sg3_utils $as_me 1.41, which was
+This file was extended by sg3_utils $as_me 1.42, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12406,7 +12405,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sg3_utils config.status 1.41
+sg3_utils config.status 1.42
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/debian/changelog b/debian/changelog
index 06c1a8f7..36539ae5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.42-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Fri, 27 Nov 2015 17:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Tue, 01 Dec 2015 14:00:00 -0500
sg3-utils (1.41-0.1) unstable; urgency=low
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 730dfa8c..43852c4f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -10,9 +10,9 @@ man_MANS = \
sg_rtpg.8 sg_safte.8 sg_sanitize.8 sg_sat_identify.8 \
sg_sat_phy_event.8 sg_sat_read_gplog.8 sg_sat_set_features.8 \
sg_senddiag.8 sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 \
- sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 sg_wr_mode.8 \
- sg_write_buffer.8 sg_write_long.8 sg_write_same.8 sg_write_verify.8 \
- sg_zone.8
+ sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
+ sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 sg_write_same.8 \
+ sg_write_verify.8 sg_zone.8
CLEANFILES =
if OS_LINUX
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 95261c62..4e981418 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -278,10 +278,10 @@ man_MANS = scsi_mandat.8 scsi_readcap.8 scsi_ready.8 scsi_satl.8 \
sg_rmsn.8 sg_rtpg.8 sg_safte.8 sg_sanitize.8 sg_sat_identify.8 \
sg_sat_phy_event.8 sg_sat_read_gplog.8 sg_sat_set_features.8 \
sg_senddiag.8 sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 \
- sg_sync.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
- sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 sg_write_same.8 \
- sg_write_verify.8 sg_zone.8 $(am__append_1) $(am__append_3) \
- $(am__append_5)
+ sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 \
+ sg_vpd.8 sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 \
+ sg_write_same.8 sg_write_verify.8 sg_zone.8 $(am__append_1) \
+ $(am__append_3) $(am__append_5)
CLEANFILES = $(am__append_2) $(am__append_4) $(am__append_6)
all: all-am
diff --git a/doc/sg_timestamp.8 b/doc/sg_timestamp.8
new file mode 100644
index 00000000..f8dd19dc
--- /dev/null
+++ b/doc/sg_timestamp.8
@@ -0,0 +1,121 @@
+.TH SG_TIMESTAMP "8" "November 2015" "sg3_utils\-1.42" SG3_UTILS
+.SH NAME
+sg_timestamp \- report or set timestamp on SCSI device
+.SH SYNOPSIS
+.B sg_timestamp
+[\fI\-\-help\fR] [\fI\-\-milliseconds=MS\fR] [\fI\-\-origin\fR]
+[\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-seconds=SEC\fR] [\fI\-\-srep\fR]
+[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+Sends a SCSI REPORT TIMESTAMP or SET TIMESTAMP command to the \fIDEVICE\fR.
+These commands are found in the SPC\-5 draft standard revision
+7 (spc5r07.pdf).
+.PP
+If either the \fI\-\-milliseconds=MS\fR or \fI\-\-seconds=SEC\fR option is
+given (and both can't be given) then the SET TIMESTAMP command is sent;
+otherwise the REPORT TIMESTAMP command is sent.
+.PP
+The timestamp is sent and received from the \fIDEVICE\fR as the number of
+milliseconds since the epoch of 1970-01-01 00:00:00 UTC and is held in a 48
+bit unsigned integer. That same epoch is used by Unix machines, but they
+usually hold the number of seconds since that epoch. The Unix date command
+and especally its "+%s" format is useful in converting to and from
+timestamps and more humanly readable forms. See the EXAMPLES section below.
+.SH OPTIONS
+Arguments to long options are mandatory for short options as well.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+output the usage message then exit.
+.TP
+\fB\-m\fR, \fB\-\-milliseconds\fR=\fIMS\fR
+where \fIMS\fR is the number of milliseconds since 1970-01-01 00:00:00 UTC
+to set in the \fIDEVICE\fR with the SCSI SET TIMESTAMP command.
+.TP
+\fB\-o\fR, \fB\-\-origin\fR
+the REPORT TIMESTAMP returned parameter data contains a "timestamp origin"
+field. When this option is given, that field is decoded and printed out
+before the timestamp value is output. The default action (i.e. when the
+option is not given) is not to print out this decoded field.
+.TP
+\fB\-r\fR, \fB\-\-raw\fR
+output the SCSI REPORT TIMESTAMP response (i.e. the data-out buffer) in
+binary (to stdout). Note that the \fI\-\-origin\fR and \fI\-\-srep\fR
+options are ignored when this option is given. Also all error and
+verbose messages are output to stderr.
+.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only. The default action is to open the
+\fIDEVICE\fR read\-write.
+.TP
+\fB\-s\fR, \fB\-\-seconds\fR=\fISEC\fR
+where \fISEC\fR is the number of seconds since 1970-01-01 00:00:00 UTC
+to set in the \fIDEVICE\fR with the SCSI SET TIMESTAMP command. \fISEC\fR
+is multiplied by 1000 before being used in the SET TIMESTAMP command.
+.TP
+\fB\-S\fR, \fB\-\-srep\fR
+report the number of seconds since 1970-01-01 00:00:00 UTC. This is done
+by dividing by 1000 the value returned by the SCSI REPORT TIMESTAMP command.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+increase the level of verbosity, (i.e. debug output).
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+print the version string and then exit.
+.SH EXIT STATUS
+The exit status of sg_timestamp is 0 when it is successful. Otherwise see
+the sg3_utils(8) man page.
+.SH NOTES
+The TCMOS and the SCSIP bits in the Control extension mode page (see sdparm)
+modify the actions of the timestamp held by a \fIDEVICE\fR.
+.PP
+Currently only the "Utilization usage rate based on date and time" parameters
+within the Utilization log page (sbc4r09.pdf) use timestamps. See the sg_logs
+utility. Vendor specific commands and pages may also be using timestamps.
+.SH EXAMPLES
+On Unix machines (e.g. Linux, FreeBSD and Solaris) the date command is useful
+when working with timestamps.
+.PP
+To fetch the timestamp from a \fIDEVICE\fR and display it in a humanly
+readable form the following could be used:
+.PP
+ # sg_timestamp -S /dev/sdb
+.br
+1448993950
+.br
+ # date --date="@1448993950"
+.br
+Tue Dec 1 13:19:10 EST 2015
+.br
+ # date -R --date="@1448993950"
+.br
+Tue, 01 Dec 2015 13:19:10 -0500
+.PP
+The latter two date commands show different forms of the same date (i.e.
+1448993950 seconds since 1970-01-01 00:00:00 UTC).
+.PP
+To set the timestamp on the \fIDEVICE\fR to now (approximately) the
+following could be used:
+.PP
+ # date +%s
+.br
+1448993955
+.br
+ # sg_timestamp --seconds=1448993955 /dev/sdb
+.PP
+Those two command lines could be combined into one by using backquotes:
+.PP
+ # sg_timestamp --seconds=`date +%s` /dev/sdb
+.PP
+.SH AUTHORS
+Written by Douglas Gilbert.
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2015 Douglas Gilbert
+.br
+This software is distributed under a FreeBSD license. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.B sdparm(sdparm), sg_logs(sg3_utils)
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 89fe3ffc..0ede2d84 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -22,6 +22,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
#include "sg_pt.h"
+#include "sg_unaligned.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -33,7 +34,7 @@
#endif
-static const char * version_str = "1.70 20150511";
+static const char * version_str = "1.71 20151130";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -289,8 +290,7 @@ sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp,
inqCmdBlk[1] |= 1;
inqCmdBlk[2] = (unsigned char)pg_op;
/* 16 bit allocation length (was 8) is a recent SPC-3 addition */
- inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- inqCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, inqCmdBlk + 3);
if (verbose) {
pr2ws(" inquiry cdb: ");
for (k = 0; k < INQUIRY_CMDLEN; ++k)
@@ -565,10 +565,7 @@ sg_ll_report_luns(int sg_fd, int select_report, void * resp, int mx_resp_len,
struct sg_pt_base * ptvp;
rlCmdBlk[2] = select_report & 0xff;
- rlCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
- rlCmdBlk[7] = (mx_resp_len >> 16) & 0xff;
- rlCmdBlk[8] = (mx_resp_len >> 8) & 0xff;
- rlCmdBlk[9] = mx_resp_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rlCmdBlk + 6);
if (verbose) {
pr2ws(" report luns cdb: ");
for (k = 0; k < REPORT_LUNS_CMDLEN; ++k)
diff --git a/lib/sg_cmds_basic2.c b/lib/sg_cmds_basic2.c
index c576a36a..578b70ca 100644
--- a/lib/sg_cmds_basic2.c
+++ b/lib/sg_cmds_basic2.c
@@ -105,17 +105,13 @@ sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group,
scCmdBlk[1] |= 4;
if (immed)
scCmdBlk[1] |= 2;
- scCmdBlk[2] = (lba >> 24) & 0xff;
- scCmdBlk[3] = (lba >> 16) & 0xff;
- scCmdBlk[4] = (lba >> 8) & 0xff;
- scCmdBlk[5] = lba & 0xff;
+ sg_put_unaligned_be32((int32_t)lba, scCmdBlk + 2);
scCmdBlk[6] = group & 0x1f;
if (count > 0xffff) {
pr2ws("count too big\n");
return -1;
}
- scCmdBlk[7] = (count >> 8) & 0xff;
- scCmdBlk[8] = count & 0xff;
+ sg_put_unaligned_be16((int16_t)count, scCmdBlk + 7);
if (verbose) {
pr2ws(" synchronize cache(10) cdb: ");
@@ -167,20 +163,10 @@ sg_ll_readcap_16(int sg_fd, int pmi, uint64_t llba, void * resp,
if (pmi) { /* lbs only valid when pmi set */
rcCmdBlk[14] |= 1;
- rcCmdBlk[2] = (llba >> 56) & 0xff;
- rcCmdBlk[3] = (llba >> 48) & 0xff;
- rcCmdBlk[4] = (llba >> 40) & 0xff;
- rcCmdBlk[5] = (llba >> 32) & 0xff;
- rcCmdBlk[6] = (llba >> 24) & 0xff;
- rcCmdBlk[7] = (llba >> 16) & 0xff;
- rcCmdBlk[8] = (llba >> 8) & 0xff;
- rcCmdBlk[9] = llba & 0xff;
+ sg_put_unaligned_be64(llba, rcCmdBlk + 2);
}
/* Allocation length, no guidance in SBC-2 rev 15b */
- rcCmdBlk[10] = (mx_resp_len >> 24) & 0xff;
- rcCmdBlk[11] = (mx_resp_len >> 16) & 0xff;
- rcCmdBlk[12] = (mx_resp_len >> 8) & 0xff;
- rcCmdBlk[13] = mx_resp_len & 0xff;
+ sg_put_unaligned_be32((int32_t)mx_resp_len, rcCmdBlk + 10);
if (verbose) {
pr2ws(" read capacity (16) cdb: ");
for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k)
@@ -231,10 +217,7 @@ sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba, void * resp,
if (pmi) { /* lbs only valid when pmi set */
rcCmdBlk[8] |= 1;
- rcCmdBlk[2] = (lba >> 24) & 0xff;
- rcCmdBlk[3] = (lba >> 16) & 0xff;
- rcCmdBlk[4] = (lba >> 8) & 0xff;
- rcCmdBlk[5] = lba & 0xff;
+ sg_put_unaligned_be32((int32_t)lba, rcCmdBlk + 2);
}
if (verbose) {
pr2ws(" read capacity (10) cdb: ");
@@ -360,8 +343,7 @@ sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code,
modesCmdBlk[1] = (unsigned char)((dbd ? 0x8 : 0) | (llbaa ? 0x10 : 0));
modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
modesCmdBlk[3] = (unsigned char)(sub_pg_code & 0xff);
- modesCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- modesCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((int16_t)mx_resp_len, modesCmdBlk + 7);
if (mx_resp_len > 0xffff) {
pr2ws("mx_resp_len too big\n");
return -1;
@@ -490,8 +472,7 @@ sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp, int param_len,
struct sg_pt_base * ptvp;
modesCmdBlk[1] = (unsigned char)(((pf << 4) & 0x10) | (sp & 0x1));
- modesCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff);
- modesCmdBlk[8] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be16((int16_t)param_len, modesCmdBlk + 7);
if (param_len > 0xffff) {
pr2ws("mode select (10): param_len too big\n");
return -1;
@@ -717,10 +698,8 @@ sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code,
logsCmdBlk[1] = (unsigned char)((ppc ? 2 : 0) | (sp ? 1 : 0));
logsCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
logsCmdBlk[3] = (unsigned char)(subpg_code & 0xff);
- logsCmdBlk[5] = (unsigned char)((paramp >> 8) & 0xff);
- logsCmdBlk[6] = (unsigned char)(paramp & 0xff);
- logsCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- logsCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((int16_t)paramp, logsCmdBlk + 5);
+ sg_put_unaligned_be16((int16_t)mx_resp_len, logsCmdBlk + 7);
if (verbose) {
pr2ws(" log sense cdb: ");
for (k = 0; k < LOG_SENSE_CMDLEN; ++k)
@@ -794,8 +773,7 @@ sg_ll_log_select(int sg_fd, int pcr, int sp, int pc, int pg_code,
logsCmdBlk[1] = (unsigned char)((pcr ? 2 : 0) | (sp ? 1 : 0));
logsCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
logsCmdBlk[3] = (unsigned char)(subpg_code & 0xff);
- logsCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff);
- logsCmdBlk[8] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be16((int16_t)param_len, logsCmdBlk + 7);
if (verbose) {
pr2ws(" log select cdb: ");
for (k = 0; k < LOG_SELECT_CMDLEN; ++k)
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index 606ae1b6..e20bfa4a 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -18,6 +18,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
#include "sg_pt.h"
+#include "sg_unaligned.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -126,18 +127,8 @@ sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
getLbaStatCmd[0] = SERVICE_ACTION_IN_16_CMD;
getLbaStatCmd[1] = GET_LBA_STATUS_SA;
- getLbaStatCmd[2] = (start_llba >> 56) & 0xff;
- getLbaStatCmd[3] = (start_llba >> 48) & 0xff;
- getLbaStatCmd[4] = (start_llba >> 40) & 0xff;
- getLbaStatCmd[5] = (start_llba >> 32) & 0xff;
- getLbaStatCmd[6] = (start_llba >> 24) & 0xff;
- getLbaStatCmd[7] = (start_llba >> 16) & 0xff;
- getLbaStatCmd[8] = (start_llba >> 8) & 0xff;
- getLbaStatCmd[9] = start_llba & 0xff;
- getLbaStatCmd[10] = (alloc_len >> 24) & 0xff;
- getLbaStatCmd[11] = (alloc_len >> 16) & 0xff;
- getLbaStatCmd[12] = (alloc_len >> 8) & 0xff;
- getLbaStatCmd[13] = alloc_len & 0xff;
+ sg_put_unaligned_be64(start_llba, getLbaStatCmd + 2);
+ sg_put_unaligned_be32((uint32_t)alloc_len, getLbaStatCmd + 2);
if (verbose) {
pr2ws(" Get LBA status cmd: ");
for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k)
@@ -204,10 +195,7 @@ sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len,
if (extended) {
rtpgCmdBlk[1] |= 0x20;
}
- rtpgCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
- rtpgCmdBlk[7] = (mx_resp_len >> 16) & 0xff;
- rtpgCmdBlk[8] = (mx_resp_len >> 8) & 0xff;
- rtpgCmdBlk[9] = mx_resp_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rtpgCmdBlk + 6);
if (verbose) {
pr2ws(" report target port groups cdb: ");
for (k = 0; k < MAINTENANCE_IN_CMDLEN; ++k)
@@ -264,10 +252,7 @@ sg_ll_set_tgt_prt_grp(int sg_fd, void * paramp, int param_len, int noisy,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- stpgCmdBlk[6] = (param_len >> 24) & 0xff;
- stpgCmdBlk[7] = (param_len >> 16) & 0xff;
- stpgCmdBlk[8] = (param_len >> 8) & 0xff;
- stpgCmdBlk[9] = param_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)param_len, stpgCmdBlk + 6);
if (verbose) {
pr2ws(" set target port groups cdb: ");
for (k = 0; k < MAINTENANCE_OUT_CMDLEN; ++k)
@@ -322,18 +307,8 @@ sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- repRefCmdBlk[2] = (start_llba >> 56) & 0xff;
- repRefCmdBlk[3] = (start_llba >> 48) & 0xff;
- repRefCmdBlk[4] = (start_llba >> 40) & 0xff;
- repRefCmdBlk[5] = (start_llba >> 32) & 0xff;
- repRefCmdBlk[6] = (start_llba >> 24) & 0xff;
- repRefCmdBlk[7] = (start_llba >> 16) & 0xff;
- repRefCmdBlk[8] = (start_llba >> 8) & 0xff;
- repRefCmdBlk[9] = start_llba & 0xff;
- repRefCmdBlk[10] = (mx_resp_len >> 24) & 0xff;
- repRefCmdBlk[11] = (mx_resp_len >> 16) & 0xff;
- repRefCmdBlk[12] = (mx_resp_len >> 8) & 0xff;
- repRefCmdBlk[13] = mx_resp_len & 0xff;
+ sg_put_unaligned_be64(start_llba, repRefCmdBlk + 2);
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, repRefCmdBlk + 10);
repRefCmdBlk[14] = one_seg & 0x1;
if (verbose) {
pr2ws(" report referrals cdb: ");
@@ -396,8 +371,7 @@ sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit, int devofl_bit,
senddiagCmdBlk[1] = (unsigned char)((sf_code << 5) | (pf_bit << 4) |
(sf_bit << 2) | (devofl_bit << 1) | unitofl_bit);
- senddiagCmdBlk[3] = (unsigned char)((param_len >> 8) & 0xff);
- senddiagCmdBlk[4] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)param_len, senddiagCmdBlk + 3);
if (verbose) {
pr2ws(" Send diagnostic cmd: ");
@@ -458,8 +432,7 @@ sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp,
rcvdiagCmdBlk[1] = (unsigned char)(pcv ? 0x1 : 0);
rcvdiagCmdBlk[2] = (unsigned char)(pg_code);
- rcvdiagCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- rcvdiagCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, rcvdiagCmdBlk + 3);
if (verbose) {
pr2ws(" Receive diagnostic results cmd: ");
@@ -518,8 +491,7 @@ sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist, int dl_format,
rdefCmdBlk[2] = (unsigned char)(((req_plist << 4) & 0x10) |
((req_glist << 3) & 0x8) | (dl_format & 0x7));
- rdefCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- rdefCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, rdefCmdBlk + 7);
if (mx_resp_len > 0xffff) {
pr2ws("mx_resp_len too big\n");
return -1;
@@ -579,10 +551,7 @@ sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- rmsnCmdBlk[6] = (mx_resp_len >> 24) & 0xff;
- rmsnCmdBlk[7] = (mx_resp_len >> 16) & 0xff;
- rmsnCmdBlk[8] = (mx_resp_len >> 8) & 0xff;
- rmsnCmdBlk[9] = mx_resp_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rmsnCmdBlk + 6);
if (verbose) {
pr2ws(" read media serial number cdb: ");
for (k = 0; k < SERVICE_ACTION_IN_12_CMDLEN; ++k)
@@ -640,10 +609,7 @@ sg_ll_report_id_info(int sg_fd, int itype, void * resp, int max_resp_len,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- riiCmdBlk[6] = (max_resp_len >> 24) & 0xff;
- riiCmdBlk[7] = (max_resp_len >> 16) & 0xff;
- riiCmdBlk[8] = (max_resp_len >> 8) & 0xff;
- riiCmdBlk[9] = max_resp_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)max_resp_len, riiCmdBlk + 6);
riiCmdBlk[10] |= (itype << 1) & 0xfe;
if (verbose) {
@@ -703,10 +669,7 @@ sg_ll_set_id_info(int sg_fd, int itype, void * paramp, int param_len,
unsigned char sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
- siiCmdBlk[6] = (param_len >> 24) & 0xff;
- siiCmdBlk[7] = (param_len >> 16) & 0xff;
- siiCmdBlk[8] = (param_len >> 8) & 0xff;
- siiCmdBlk[9] = param_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)param_len, siiCmdBlk + 6);
siiCmdBlk[10] |= (itype << 1) & 0xfe;
if (verbose) {
pr2ws(" Set identifying information cdb: ");
@@ -884,8 +847,7 @@ sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp,
if (rq_servact > 0)
prinCmdBlk[1] = (unsigned char)(rq_servact & 0x1f);
- prinCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- prinCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, prinCmdBlk + 7);
if (verbose) {
pr2ws(" Persistent Reservation In cmd: ");
@@ -947,8 +909,7 @@ sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, int rq_scope,
if (rq_servact > 0)
proutCmdBlk[1] = (unsigned char)(rq_servact & 0x1f);
proutCmdBlk[2] = (((rq_scope & 0xf) << 4) | (rq_type & 0xf));
- proutCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff);
- proutCmdBlk[8] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)param_len, proutCmdBlk + 7);
if (verbose) {
pr2ws(" Persistent Reservation Out cmd: ");
@@ -1029,12 +990,8 @@ sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned int lba,
if (correct)
readLongCmdBlk[1] |= 0x2;
- readLongCmdBlk[2] = (lba >> 24) & 0xff;
- readLongCmdBlk[3] = (lba >> 16) & 0xff;
- readLongCmdBlk[4] = (lba >> 8) & 0xff;
- readLongCmdBlk[5] = lba & 0xff;
- readLongCmdBlk[7] = (xfer_len >> 8) & 0xff;
- readLongCmdBlk[8] = xfer_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)lba, readLongCmdBlk + 2);
+ sg_put_unaligned_be16((uint16_t)xfer_len, readLongCmdBlk + 7);
if (verbose) {
pr2ws(" Read Long (10) cmd: ");
for (k = 0; k < READ_LONG10_CMDLEN; ++k)
@@ -1118,16 +1075,8 @@ sg_ll_read_long16(int sg_fd, int pblock, int correct, uint64_t llba,
if (correct)
readLongCmdBlk[14] |= 0x1;
- readLongCmdBlk[2] = (llba >> 56) & 0xff;
- readLongCmdBlk[3] = (llba >> 48) & 0xff;
- readLongCmdBlk[4] = (llba >> 40) & 0xff;
- readLongCmdBlk[5] = (llba >> 32) & 0xff;
- readLongCmdBlk[6] = (llba >> 24) & 0xff;
- readLongCmdBlk[7] = (llba >> 16) & 0xff;
- readLongCmdBlk[8] = (llba >> 8) & 0xff;
- readLongCmdBlk[9] = llba & 0xff;
- readLongCmdBlk[12] = (xfer_len >> 8) & 0xff;
- readLongCmdBlk[13] = xfer_len & 0xff;
+ sg_put_unaligned_be64(llba, readLongCmdBlk + 2);
+ sg_put_unaligned_be16((uint16_t)xfer_len, readLongCmdBlk + 12);
if (verbose) {
pr2ws(" Read Long (16) cmd: ");
for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k)
@@ -1212,12 +1161,8 @@ sg_ll_write_long10(int sg_fd, int cor_dis, int wr_uncor, int pblock,
if (pblock)
writeLongCmdBlk[1] |= 0x20;
- writeLongCmdBlk[2] = (lba >> 24) & 0xff;
- writeLongCmdBlk[3] = (lba >> 16) & 0xff;
- writeLongCmdBlk[4] = (lba >> 8) & 0xff;
- writeLongCmdBlk[5] = lba & 0xff;
- writeLongCmdBlk[7] = (xfer_len >> 8) & 0xff;
- writeLongCmdBlk[8] = xfer_len & 0xff;
+ sg_put_unaligned_be32((uint32_t)lba, writeLongCmdBlk + 2);
+ sg_put_unaligned_be16((uint16_t)xfer_len, writeLongCmdBlk + 7);
if (verbose) {
pr2ws(" Write Long (10) cmd: ");
for (k = 0; k < (int)sizeof(writeLongCmdBlk); ++k)
@@ -1298,16 +1243,8 @@ sg_ll_write_long16(int sg_fd, int cor_dis, int wr_uncor, int pblock,
if (pblock)
writeLongCmdBlk[1] |= 0x20;
- writeLongCmdBlk[2] = (llba >> 56) & 0xff;
- writeLongCmdBlk[3] = (llba >> 48) & 0xff;
- writeLongCmdBlk[4] = (llba >> 40) & 0xff;
- writeLongCmdBlk[5] = (llba >> 32) & 0xff;
- writeLongCmdBlk[6] = (llba >> 24) & 0xff;
- writeLongCmdBlk[7] = (llba >> 16) & 0xff;
- writeLongCmdBlk[8] = (llba >> 8) & 0xff;
- writeLongCmdBlk[9] = llba & 0xff;
- writeLongCmdBlk[12] = (xfer_len >> 8) & 0xff;
- writeLongCmdBlk[13] = xfer_len & 0xff;
+ sg_put_unaligned_be64(llba, writeLongCmdBlk + 2);
+ sg_put_unaligned_be16((uint16_t)xfer_len, writeLongCmdBlk + 12);
if (verbose) {
pr2ws(" Write Long (16) cmd: ");
for (k = 0; k < SERVICE_ACTION_OUT_16_CMDLEN; ++k)
@@ -1384,12 +1321,8 @@ sg_ll_verify10(int sg_fd, int vrprotect, int dpo, int bytchk,
/* N.B. BYTCHK field expanded to 2 bits sbc3r34 */
vCmdBlk[1] = ((vrprotect & 0x7) << 5) | ((dpo & 0x1) << 4) |
((bytchk & 0x3) << 1) ;
- vCmdBlk[2] = (unsigned char)((lba >> 24) & 0xff);
- vCmdBlk[3] = (unsigned char)((lba >> 16) & 0xff);
- vCmdBlk[4] = (unsigned char)((lba >> 8) & 0xff);
- vCmdBlk[5] = (unsigned char)(lba & 0xff);
- vCmdBlk[7] = (unsigned char)((veri_len >> 8) & 0xff);
- vCmdBlk[8] = (unsigned char)(veri_len & 0xff);
+ sg_put_unaligned_be32((uint32_t)lba, vCmdBlk + 2);
+ sg_put_unaligned_be16((uint16_t)veri_len, vCmdBlk + 7);
if (verbose > 1) {
pr2ws(" Verify(10) cdb: ");
for (k = 0; k < VERIFY10_CMDLEN; ++k)
@@ -1466,18 +1399,8 @@ sg_ll_verify16(int sg_fd, int vrprotect, int dpo, int bytchk, uint64_t llba,
/* N.B. BYTCHK field expanded to 2 bits sbc3r34 */
vCmdBlk[1] = ((vrprotect & 0x7) << 5) | ((dpo & 0x1) << 4) |
((bytchk & 0x3) << 1) ;
- vCmdBlk[2] = (llba >> 56) & 0xff;
- vCmdBlk[3] = (llba >> 48) & 0xff;
- vCmdBlk[4] = (llba >> 40) & 0xff;
- vCmdBlk[5] = (llba >> 32) & 0xff;
- vCmdBlk[6] = (llba >> 24) & 0xff;
- vCmdBlk[7] = (llba >> 16) & 0xff;
- vCmdBlk[8] = (llba >> 8) & 0xff;
- vCmdBlk[9] = llba & 0xff;
- vCmdBlk[10] = (veri_len >> 24) & 0xff;
- vCmdBlk[11] = (veri_len >> 16) & 0xff;
- vCmdBlk[12] = (veri_len >> 8) & 0xff;
- vCmdBlk[13] = veri_len & 0xff;
+ sg_put_unaligned_be64(llba, vCmdBlk + 2);
+ sg_put_unaligned_be32((uint32_t)veri_len, vCmdBlk + 10);
vCmdBlk[14] = group_num & 0x1f;
if (verbose > 1) {
pr2ws(" Verify(16) cdb: ");
@@ -1708,12 +1631,8 @@ sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
rbufCmdBlk[1] = (unsigned char)(mode & 0x1f);
rbufCmdBlk[2] = (unsigned char)(buffer_id & 0xff);
- rbufCmdBlk[3] = (unsigned char)((buffer_offset >> 16) & 0xff);
- rbufCmdBlk[4] = (unsigned char)((buffer_offset >> 8) & 0xff);
- rbufCmdBlk[5] = (unsigned char)(buffer_offset & 0xff);
- rbufCmdBlk[6] = (unsigned char)((mx_resp_len >> 16) & 0xff);
- rbufCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- rbufCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be24((uint32_t)buffer_offset, rbufCmdBlk + 3);
+ sg_put_unaligned_be24((uint32_t)mx_resp_len, rbufCmdBlk + 6);
if (verbose) {
pr2ws(" read buffer cdb: ");
for (k = 0; k < READ_BUFFER_CMDLEN; ++k)
@@ -1770,12 +1689,8 @@ sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
wbufCmdBlk[1] = (unsigned char)(mode & 0x1f);
wbufCmdBlk[2] = (unsigned char)(buffer_id & 0xff);
- wbufCmdBlk[3] = (unsigned char)((buffer_offset >> 16) & 0xff);
- wbufCmdBlk[4] = (unsigned char)((buffer_offset >> 8) & 0xff);
- wbufCmdBlk[5] = (unsigned char)(buffer_offset & 0xff);
- wbufCmdBlk[6] = (unsigned char)((param_len >> 16) & 0xff);
- wbufCmdBlk[7] = (unsigned char)((param_len >> 8) & 0xff);
- wbufCmdBlk[8] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be24((uint32_t)buffer_offset, wbufCmdBlk + 3);
+ sg_put_unaligned_be24((uint32_t)param_len, wbufCmdBlk + 6);
if (verbose) {
pr2ws(" Write buffer cmd: ");
for (k = 0; k < WRITE_BUFFER_CMDLEN; ++k)
@@ -1845,8 +1760,7 @@ sg_ll_unmap_v2(int sg_fd, int anchor, int group_num, int timeout_secs,
uCmdBlk[1] |= 0x1;
tmout = (timeout_secs > 0) ? timeout_secs : DEF_PT_TIMEOUT;
uCmdBlk[6] = group_num & 0x1f;
- uCmdBlk[7] = (param_len >> 8) & 0xff;
- uCmdBlk[8] = param_len & 0xff;
+ sg_put_unaligned_be16((uint16_t)param_len, uCmdBlk + 7);
if (verbose) {
pr2ws(" unmap cdb: ");
for (k = 0; k < UNMAP_CMDLEN; ++k)
@@ -1959,16 +1873,9 @@ sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, void * resp,
rcvcopyresCmdBlk[1] = (unsigned char)(sa & 0x1f);
if (sa <= 4) /* LID1 variants */
rcvcopyresCmdBlk[2] = (unsigned char)(list_id);
- else if ((sa >= 5) && (sa <= 7)) { /* LID4 variants */
- rcvcopyresCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff);
- rcvcopyresCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff);
- rcvcopyresCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff);
- rcvcopyresCmdBlk[5] = (unsigned char)(list_id & 0xff);
- }
- rcvcopyresCmdBlk[10] = (unsigned char)((mx_resp_len >> 24) & 0xff);
- rcvcopyresCmdBlk[11] = (unsigned char)((mx_resp_len >> 16) & 0xff);
- rcvcopyresCmdBlk[12] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- rcvcopyresCmdBlk[13] = (unsigned char)(mx_resp_len & 0xff);
+ else if ((sa >= 5) && (sa <= 7)) /* LID4 variants */
+ sg_put_unaligned_be32((uint32_t)list_id, rcvcopyresCmdBlk + 2);
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rcvcopyresCmdBlk + 10);
if (verbose) {
pr2ws(" %s cmd: ", b);
@@ -2026,10 +1933,7 @@ sg_ll_extended_copy(int sg_fd, void * paramp, int param_len, int noisy,
const char * opcode_name = "Extended copy (LID1)";
xcopyCmdBlk[1] = (unsigned char)(EXTENDED_COPY_LID1_SA & 0x1f);
- xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff);
- xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff);
- xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff);
- xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be32((uint32_t)param_len, xcopyCmdBlk + 10);
if (verbose) {
pr2ws(" %s cmd: ", opcode_name);
@@ -2094,28 +1998,16 @@ sg_ll_3party_copy_out(int sg_fd, int sa, unsigned int list_id, int group_num,
switch (sa) {
case 0x0: /* XCOPY(LID1) */
case 0x1: /* XCOPY(LID4) */
- xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff);
- xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff);
- xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff);
- xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be32((uint32_t)param_len, xcopyCmdBlk + 10);
break;
case 0x10: /* POPULATE TOKEN (SBC-3) */
case 0x11: /* WRITE USING TOKEN (SBC-3) */
- xcopyCmdBlk[6] = (unsigned char)((list_id >> 24) & 0xff);
- xcopyCmdBlk[7] = (unsigned char)((list_id >> 16) & 0xff);
- xcopyCmdBlk[8] = (unsigned char)((list_id >> 8) & 0xff);
- xcopyCmdBlk[9] = (unsigned char)(list_id & 0xff);
- xcopyCmdBlk[10] = (unsigned char)((param_len >> 24) & 0xff);
- xcopyCmdBlk[11] = (unsigned char)((param_len >> 16) & 0xff);
- xcopyCmdBlk[12] = (unsigned char)((param_len >> 8) & 0xff);
- xcopyCmdBlk[13] = (unsigned char)(param_len & 0xff);
+ sg_put_unaligned_be32((uint32_t)list_id, xcopyCmdBlk + 6);
+ sg_put_unaligned_be32((uint32_t)param_len, xcopyCmdBlk + 10);
xcopyCmdBlk[14] = (unsigned char)(group_num & 0x1f);
break;
case 0x1c: /* COPY OPERATION ABORT */
- xcopyCmdBlk[2] = (unsigned char)((list_id >> 24) & 0xff);
- xcopyCmdBlk[3] = (unsigned char)((list_id >> 16) & 0xff);
- xcopyCmdBlk[4] = (unsigned char)((list_id >> 8) & 0xff);
- xcopyCmdBlk[5] = (unsigned char)(list_id & 0xff);
+ sg_put_unaligned_be32((uint32_t)list_id, xcopyCmdBlk + 2);
break;
default:
pr2ws("sg_ll_3party_copy_out: unknown service action 0x%x\n", sa);
diff --git a/lib/sg_cmds_mmc.c b/lib/sg_cmds_mmc.c
index b9cb2083..8bb85691 100644
--- a/lib/sg_cmds_mmc.c
+++ b/lib/sg_cmds_mmc.c
@@ -17,6 +17,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_mmc.h"
#include "sg_pt.h"
+#include "sg_unaligned.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -72,10 +73,8 @@ sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed,
struct sg_pt_base * ptvp;
scsCmdBlk[1] |= (rot_control & 0x3);
- scsCmdBlk[2] = (drv_read_speed >> 8) & 0xff;
- scsCmdBlk[3] = drv_read_speed & 0xff;
- scsCmdBlk[4] = (drv_write_speed >> 8) & 0xff;
- scsCmdBlk[5] = drv_write_speed & 0xff;
+ sg_put_unaligned_be16((uint16_t)drv_read_speed, scsCmdBlk + 2);
+ sg_put_unaligned_be16((uint16_t)drv_write_speed, scsCmdBlk + 4);
if (verbose) {
pr2ws(" set cd speed cdb: ");
@@ -142,14 +141,12 @@ sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
pr2ws("Bad starting field number: 0x%x\n", starting);
return -1;
}
- gcCmdBlk[2] = (unsigned char)((starting >> 8) & 0xff);
- gcCmdBlk[3] = (unsigned char)(starting & 0xff);
+ sg_put_unaligned_be16((uint16_t)starting, gcCmdBlk + 2);
if ((mx_resp_len < 0) || (mx_resp_len > 0xffff)) {
pr2ws("Bad mx_resp_len: 0x%x\n", starting);
return -1;
}
- gcCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- gcCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, gcCmdBlk + 7);
if (verbose) {
pr2ws(" Get Configuration cdb: ");
@@ -193,8 +190,7 @@ sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
int len;
ucp = (unsigned char *)resp;
- len = (ucp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8) + ucp[3] +
- 4;
+ len = sg_get_unaligned_be32(ucp + 0);
if (len < 0)
len = 0;
len = (ret < len) ? ret : len;
@@ -228,16 +224,12 @@ sg_ll_get_performance(int sg_fd, int data_type, unsigned int starting_lba,
return -1;
}
gpCmdBlk[1] = (data_type & 0x1f);
- gpCmdBlk[2] = (unsigned char)((starting_lba >> 24) & 0xff);
- gpCmdBlk[3] = (unsigned char)((starting_lba >> 16) & 0xff);
- gpCmdBlk[4] = (unsigned char)((starting_lba >> 8) & 0xff);
- gpCmdBlk[3] = (unsigned char)(starting_lba & 0xff);
+ sg_put_unaligned_be32((uint32_t)starting_lba, gpCmdBlk + 2);
if ((max_num_desc < 0) || (max_num_desc > 0xffff)) {
pr2ws("Bad max_num_desc: 0x%x\n", max_num_desc);
return -1;
}
- gpCmdBlk[8] = (unsigned char)((max_num_desc >> 8) & 0xff);
- gpCmdBlk[9] = (unsigned char)(max_num_desc & 0xff);
+ sg_put_unaligned_be16((uint16_t)max_num_desc, gpCmdBlk + 8);
if ((ttype < 0) || (ttype > 0xff)) {
pr2ws("Bad type: 0x%x\n", ttype);
return -1;
@@ -286,8 +278,7 @@ sg_ll_get_performance(int sg_fd, int data_type, unsigned int starting_lba,
int len;
ucp = (unsigned char *)resp;
- len = (ucp[0] << 24) + (ucp[1] << 16) + (ucp[2] << 8) + ucp[3] +
- 4;
+ len = sg_get_unaligned_be32(ucp + 0);
if (len < 0)
len = 0;
len = (ret < len) ? ret : len;
@@ -317,8 +308,7 @@ sg_ll_set_streaming(int sg_fd, int type, void * paramp, int param_len,
struct sg_pt_base * ptvp;
ssCmdBlk[8] = type;
- ssCmdBlk[9] = (param_len >> 8) & 0xff;
- ssCmdBlk[10] = param_len & 0xff;
+ sg_put_unaligned_be16((uint16_t)param_len, ssCmdBlk + 9);
if (verbose) {
pr2ws(" set streaming cdb: ");
for (k = 0; k < SET_STREAMING_CMDLEN; ++k)
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index f9c53b8f..38d918e4 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -37,6 +37,7 @@
#include "sg_lib.h"
#include "sg_lib_data.h"
+#include "sg_unaligned.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -316,7 +317,6 @@ int
sg_get_sense_info_fld(const unsigned char * sensep, int sb_len,
uint64_t * info_outp)
{
- int j;
const unsigned char * ucp;
uint64_t ull;
@@ -328,19 +328,13 @@ sg_get_sense_info_fld(const unsigned char * sensep, int sb_len,
case 0x70:
case 0x71:
if (info_outp)
- *info_outp = ((unsigned int)sensep[3] << 24) + (sensep[4] << 16) +
- (sensep[5] << 8) + sensep[6];
+ *info_outp = sg_get_unaligned_be32(sensep + 3);
return (sensep[0] & 0x80) ? 1 : 0;
case 0x72:
case 0x73:
ucp = sg_scsi_sense_desc_find(sensep, sb_len, 0 /* info desc */);
if (ucp && (0xa == ucp[1])) {
- ull = 0;
- for (j = 0; j < 8; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= ucp[4 + j];
- }
+ ull = sg_get_unaligned_be64(ucp + 4);
if (info_outp)
*info_outp = ull;
return !!(ucp[2] & 0x80); /* since spc3r23 should be set */
@@ -422,7 +416,7 @@ sg_get_sense_progress_fld(const unsigned char * sensep, int sb_len,
return 0;
if (sensep[15] & 0x80) { /* SKSV bit set */
if (progress_outp)
- *progress_outp = (sensep[16] << 8) + sensep[17];
+ *progress_outp = sg_get_unaligned_be16(sensep + 16);
return 1;
} else
return 0;
@@ -434,12 +428,12 @@ sg_get_sense_progress_fld(const unsigned char * sensep, int sb_len,
if (sk_pr && ((ucp = sg_scsi_sense_desc_find(sensep, sb_len, 2))) &&
(0x6 == ucp[1]) && (0x80 & ucp[4])) {
if (progress_outp)
- *progress_outp = (ucp[5] << 8) + ucp[6];
+ *progress_outp = sg_get_unaligned_be16(ucp + 5);
return 1;
} else if (((ucp = sg_scsi_sense_desc_find(sensep, sb_len, 0xa))) &&
((0x6 == ucp[1]))) {
if (progress_outp)
- *progress_outp = (ucp[6] << 8) + ucp[7];
+ *progress_outp = sg_get_unaligned_be16(ucp + 6);
return 1;
} else
return 0;
@@ -527,27 +521,17 @@ uds_referral_descriptor_str(char * b, int blen, const unsigned char * dp,
"stop\n");
return n;
}
- ull = 0;
- for (j = 0; j < 8; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= dp[4 + j];
- }
+ ull = sg_get_unaligned_be64(dp + 4);
n += my_snprintf(b + n, blen - n, " first uds LBA: 0x%" PRIx64
"\n", ull);
- ull = 0;
- for (j = 0; j < 8; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= dp[12 + j];
- }
+ ull = sg_get_unaligned_be64(dp + 12);
n += my_snprintf(b + n, blen - n, " last uds LBA: 0x%" PRIx64
"\n", ull);
for (j = 0; j < tpgd; ++j) {
tp = dp + 20 + (j * 4);
decode_tpgs_state(tp[0] & 0xf, c, sizeof(c));
n += my_snprintf(b + n, blen - n, " tpg: %d state: %s\n",
- (tp[2] << 8) + tp[3], c);
+ sg_get_unaligned_be16(tp + 2), c);
}
}
return n;
@@ -626,7 +610,7 @@ sg_get_sense_descriptors_str(const unsigned char * sense_buffer, int sb_len,
n += my_snprintf(b + n, blen - n, " Error in %s: byte %d",
(descp[4] & 0x40) ? "Command" :
"Data parameters",
- (descp[5] << 8) | descp[6]);
+ sg_get_unaligned_be16(descp + 5));
if (descp[4] & 0x08) {
n += my_snprintf(b + n, blen - n, " bit %d\n",
descp[4] & 0x07);
@@ -653,7 +637,7 @@ sg_get_sense_descriptors_str(const unsigned char * sense_buffer, int sb_len,
processed = 0;
break;
}
- progress = (descp[5] << 8) + descp[6];
+ progress = sg_get_unaligned_be16(descp + 5);
pr = (progress * 100) / 65536;
rem = ((progress * 100) % 65536) / 656;
n += my_snprintf(b + n, blen - n, "%d.%02d%%\n", pr, rem);
@@ -669,7 +653,7 @@ sg_get_sense_descriptors_str(const unsigned char * sense_buffer, int sb_len,
"byte %d",
(descp[4] & 0x20) ? "segment descriptor" :
"parameter list",
- (descp[5] << 8) | descp[6]);
+ sg_get_unaligned_be16(descp + 5));
if (descp[4] & 0x08)
n += my_snprintf(b + n, blen - n, " bit %d\n",
descp[4] & 0x07);
@@ -776,7 +760,7 @@ sg_get_sense_descriptors_str(const unsigned char * sense_buffer, int sb_len,
processed = 0;
break;
}
- progress = (descp[6] << 8) + descp[7];
+ progress = sg_get_unaligned_be16(descp + 6);
pr = (progress * 100) / 65536;
rem = ((progress * 100) % 65536) / 656;
n += my_snprintf(b + n, blen - n, " %d.02%d%%", pr, rem);
@@ -966,9 +950,7 @@ sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
r = 0;
valid = sense_buffer[0] & 0x80;
if (len > 6) {
- info = (unsigned int)((sense_buffer[3] << 24) |
- (sense_buffer[4] << 16) | (sense_buffer[5] << 8) |
- sense_buffer[6]);
+ info = sg_get_unaligned_be32(sense_buffer + 3);
if (valid)
r += my_snprintf(b + r, blen - r, " Info fld=0x%x [%u] ",
info, info);
@@ -1001,7 +983,7 @@ sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
"Error in %s: byte %d",
((sense_buffer[15] & 0x40) ? "Command" :
"Data parameters"),
- (sense_buffer[16] << 8) | sense_buffer[17]);
+ sg_get_unaligned_be16(sense_buffer + 16));
if (sense_buffer[15] & 0x08)
r += my_snprintf(b + r, blen - r, " bit %d\n",
sense_buffer[15] & 0x07);
@@ -1010,7 +992,7 @@ sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
break;
case SPC_SK_NO_SENSE:
case SPC_SK_NOT_READY:
- progress = (sense_buffer[16] << 8) + sense_buffer[17];
+ progress = sg_get_unaligned_be16(sense_buffer + 16);
pr = (progress * 100) / 65536;
rem = ((progress * 100) % 65536) / 656;
r += my_snprintf(b + r, blen - r, " Progress "
@@ -1029,8 +1011,7 @@ sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
"%s, byte %d",
((sense_buffer[15] & 0x20) ?
"segment descriptor" : "parameter list"),
- ((sense_buffer[16] << 8) +
- sense_buffer[17]));
+ sg_get_unaligned_be16(sense_buffer + 16));
if (sense_buffer[15] & 0x08)
r += my_snprintf(b + r, blen - r, " bit %d\n",
sense_buffer[15] & 0x07);
@@ -1069,8 +1050,7 @@ sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
(sense_buffer[0] & 0xf));
if (sense_buffer[0] & 0x80)
r += my_snprintf(b + r, blen - r, " lba=0x%x\n",
- ((sense_buffer[1] & 0x1f) << 16) +
- (sense_buffer[2] << 8) + sense_buffer[3]);
+ sg_get_unaligned_be24(sense_buffer + 1) & 0x1fffff);
n += my_snprintf(buff + n, buff_len - n, "%s\n", b);
len = sb_len;
if (len > 32)
@@ -1219,7 +1199,7 @@ sg_get_command_name(const unsigned char * cmdp, int peri_type, int buff_len,
return;
}
service_action = (SG_VARIABLE_LENGTH_CMD == cmdp[0]) ?
- ((cmdp[8] << 8) | cmdp[9]) : (cmdp[1] & 0x1f);
+ sg_get_unaligned_be16(cmdp + 8) : (cmdp[1] & 0x1f);
sg_get_opcode_sa_name(cmdp[0], service_action, peri_type, buff_len, buff);
}
diff --git a/ltmain.sh b/ltmain.sh
index bffda541..a356acaf 100755
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -70,7 +70,7 @@
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.7ubuntu1
# automake: $automake_version
# autoconf: $autoconf_version
#
@@ -80,7 +80,7 @@
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.2 Debian-2.4.2-1.11"
+VERSION="2.4.2 Debian-2.4.2-1.7ubuntu1"
TIMESTAMP=""
package_revision=1.3337
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 93385919..8d8ed0b4 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Fri Nov 27 2015 - dgilbert at interlog dot com
+* Tue Dec 01 2015 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.42
diff --git a/src/Makefile.am b/src/Makefile.am
index 46a3391f..2a34c71d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,8 +7,9 @@ bin_PROGRAMS = \
sg_rep_zones sg_requests sg_reset_wp sg_rmsn sg_rtpg sg_safte \
sg_sanitize sg_sat_identify sg_sat_phy_event sg_sat_read_gplog \
sg_sat_set_features sg_senddiag sg_ses sg_ses_microcode sg_start \
- sg_stpg sg_sync sg_turs sg_unmap sg_verify sg_vpd sg_wr_mode \
- sg_write_buffer sg_write_long sg_write_same sg_write_verify sg_zone
+ sg_stpg sg_sync sg_timestamp sg_turs sg_unmap sg_verify sg_vpd \
+ sg_wr_mode sg_write_buffer sg_write_long sg_write_same \
+ sg_write_verify sg_zone
sg_scan_SOURCES =
@@ -149,6 +150,8 @@ sg_sync_LDADD = ../lib/libsgutils2.la @os_libs@
sg_test_rwbuf_LDADD = ../lib/libsgutils2.la @os_libs@
+sg_timestamp_LDADD = ../lib/libsgutils2.la @os_libs@
+
sg_turs_LDADD = ../lib/libsgutils2.la @os_libs@
sg_unmap_LDADD = ../lib/libsgutils2.la @os_libs@
diff --git a/src/Makefile.in b/src/Makefile.in
index 753830f6..fa19e93a 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -93,11 +93,12 @@ bin_PROGRAMS = sg_compare_and_write$(EXEEXT) sg_decode_sense$(EXEEXT) \
sg_sat_read_gplog$(EXEEXT) sg_sat_set_features$(EXEEXT) \
sg_senddiag$(EXEEXT) sg_ses$(EXEEXT) sg_ses_microcode$(EXEEXT) \
sg_start$(EXEEXT) sg_stpg$(EXEEXT) sg_sync$(EXEEXT) \
- sg_turs$(EXEEXT) sg_unmap$(EXEEXT) sg_verify$(EXEEXT) \
- sg_vpd$(EXEEXT) sg_wr_mode$(EXEEXT) sg_write_buffer$(EXEEXT) \
- sg_write_long$(EXEEXT) sg_write_same$(EXEEXT) \
- sg_write_verify$(EXEEXT) sg_zone$(EXEEXT) $(am__EXEEXT_1) \
- $(am__EXEEXT_2) $(am__EXEEXT_3)
+ sg_timestamp$(EXEEXT) sg_turs$(EXEEXT) sg_unmap$(EXEEXT) \
+ sg_verify$(EXEEXT) sg_vpd$(EXEEXT) sg_wr_mode$(EXEEXT) \
+ sg_write_buffer$(EXEEXT) sg_write_long$(EXEEXT) \
+ sg_write_same$(EXEEXT) sg_write_verify$(EXEEXT) \
+ sg_zone$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \
+ $(am__EXEEXT_3)
@OS_LINUX_TRUE@am__append_1 = \
@OS_LINUX_TRUE@ sg_copy_results sg_dd sg_emc_trespass sg_map sg_map26 sg_rbuf \
@OS_LINUX_TRUE@ sg_read sg_reset sg_scan sg_test_rwbuf sg_xcopy sginfo sgm_dd sgp_dd
@@ -282,6 +283,9 @@ sg_sync_DEPENDENCIES = ../lib/libsgutils2.la
sg_test_rwbuf_SOURCES = sg_test_rwbuf.c
sg_test_rwbuf_OBJECTS = sg_test_rwbuf.$(OBJEXT)
sg_test_rwbuf_DEPENDENCIES = ../lib/libsgutils2.la
+sg_timestamp_SOURCES = sg_timestamp.c
+sg_timestamp_OBJECTS = sg_timestamp.$(OBJEXT)
+sg_timestamp_DEPENDENCIES = ../lib/libsgutils2.la
sg_turs_SOURCES = sg_turs.c
sg_turs_OBJECTS = sg_turs.$(OBJEXT)
sg_turs_DEPENDENCIES = ../lib/libsgutils2.la
@@ -370,8 +374,8 @@ SOURCES = sg_compare_and_write.c sg_copy_results.c sg_dd.c \
sg_sat_identify.c sg_sat_phy_event.c sg_sat_read_gplog.c \
sg_sat_set_features.c $(sg_scan_SOURCES) sg_senddiag.c \
sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c sg_sync.c \
- sg_test_rwbuf.c sg_turs.c sg_unmap.c sg_verify.c \
- $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
+ sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
+ sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
sg_write_long.c sg_write_same.c sg_write_verify.c sg_xcopy.c \
sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
DIST_SOURCES = sg_compare_and_write.c sg_copy_results.c sg_dd.c \
@@ -386,8 +390,8 @@ DIST_SOURCES = sg_compare_and_write.c sg_copy_results.c sg_dd.c \
sg_sat_identify.c sg_sat_phy_event.c sg_sat_read_gplog.c \
sg_sat_set_features.c $(am__sg_scan_SOURCES_DIST) \
sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c \
- sg_sync.c sg_test_rwbuf.c sg_turs.c sg_unmap.c sg_verify.c \
- $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
+ sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
+ sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
sg_write_long.c sg_write_same.c sg_write_verify.c sg_xcopy.c \
sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
am__can_run_installinfo = \
@@ -597,6 +601,7 @@ sg_start_LDADD = ../lib/libsgutils2.la @os_libs@
sg_stpg_LDADD = ../lib/libsgutils2.la @os_libs@
sg_sync_LDADD = ../lib/libsgutils2.la @os_libs@
sg_test_rwbuf_LDADD = ../lib/libsgutils2.la @os_libs@
+sg_timestamp_LDADD = ../lib/libsgutils2.la @os_libs@
sg_turs_LDADD = ../lib/libsgutils2.la @os_libs@
sg_unmap_LDADD = ../lib/libsgutils2.la @os_libs@
sg_verify_LDADD = ../lib/libsgutils2.la @os_libs@
@@ -885,6 +890,10 @@ sg_test_rwbuf$(EXEEXT): $(sg_test_rwbuf_OBJECTS) $(sg_test_rwbuf_DEPENDENCIES) $
@rm -f sg_test_rwbuf$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_test_rwbuf_OBJECTS) $(sg_test_rwbuf_LDADD) $(LIBS)
+sg_timestamp$(EXEEXT): $(sg_timestamp_OBJECTS) $(sg_timestamp_DEPENDENCIES) $(EXTRA_sg_timestamp_DEPENDENCIES)
+ @rm -f sg_timestamp$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sg_timestamp_OBJECTS) $(sg_timestamp_LDADD) $(LIBS)
+
sg_turs$(EXEEXT): $(sg_turs_OBJECTS) $(sg_turs_DEPENDENCIES) $(EXTRA_sg_turs_DEPENDENCIES)
@rm -f sg_turs$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_turs_OBJECTS) $(sg_turs_LDADD) $(LIBS)
@@ -997,6 +1006,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_stpg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_sync.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_test_rwbuf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_timestamp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_turs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_unmap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_verify.Po@am__quote@
diff --git a/src/sg_inq.c b/src/sg_inq.c
index d8335108..0a4c5ad0 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -40,8 +40,9 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
#include "sg_pt.h"
+#include "sg_unaligned.h"
-static const char * version_str = "1.50 20151119"; /* SPC-5 rev 06 */
+static const char * version_str = "1.51 20151201"; /* SPC-5 rev 06 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -945,8 +946,7 @@ pt_inquiry(int sg_fd, int evpd, int pg_op, void * resp, int mx_resp_len,
inqCmdBlk[1] |= 1;
inqCmdBlk[2] = (unsigned char)pg_op;
/* 16 bit allocation length (was 8) is a recent SPC-3 addition */
- inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- inqCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, inqCmdBlk + 3);
if (verbose) {
pr2serr(" inquiry cdb: ");
for (k = 0; k < INQUIRY_CMDLEN; ++k)
@@ -1346,7 +1346,7 @@ decode_net_man_vpd(unsigned char * buff, int len, int do_hex)
printf(" %s, Service type: %s\n",
assoc_arr[(ucp[0] >> 5) & 0x3],
network_service_type_arr[ucp[0] & 0x1f]);
- na_len = (ucp[2] << 8) + ucp[3];
+ na_len = sg_get_unaligned_be16(ucp + 2);
bump = 4 + na_len;
if ((k + bump) > len) {
pr2serr("Management network addresses VPD page, short "
@@ -1427,9 +1427,9 @@ decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex)
len -= 4;
ucp = buff + 4;
for (k = 0; k < len; k += bump, ucp += bump) {
- rel_port = (ucp[2] << 8) + ucp[3];
+ rel_port = sg_get_unaligned_be16(ucp + 2);
printf("Relative port=%d\n", rel_port);
- ip_tid_len = (ucp[6] << 8) + ucp[7];
+ ip_tid_len = sg_get_unaligned_be16(ucp + 6);
bump = 8 + ip_tid_len;
if ((k + bump) > len) {
pr2serr("SCSI Ports VPD page, short descriptor "
@@ -1444,7 +1444,7 @@ decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex)
} else
decode_transport_id(" ", ucp + 8, ip_tid_len);
}
- tpd_len = (ucp[bump + 2] << 8) + ucp[bump + 3];
+ tpd_len = sg_get_unaligned_be16(ucp + bump + 2);
if ((k + bump + tpd_len + 4) > len) {
pr2serr("SCSI Ports VPD page, short descriptor(tgt) "
"length=%d, left=%d\n", bump, (len - k));
@@ -1597,12 +1597,7 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
ci_off = 0;
if (16 == i_len) {
ci_off = 8;
- id_ext = 0;
- for (m = 0; m < 8; ++m) {
- if (m > 0)
- id_ext <<= 8;
- id_ext |= ip[m];
- }
+ id_ext = sg_get_unaligned_be64(ip);
printf(" Identifier extension: 0x%" PRIx64 "\n", id_ext);
} else if ((8 != i_len) && (12 != i_len)) {
pr2serr(" << can only decode 8, 12 and 16 "
@@ -1610,20 +1605,13 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
dStrHexErr((const char *)ip, i_len, -1);
break;
}
- c_id = ((ip[ci_off] << 16) | (ip[ci_off + 1] << 8) |
- ip[ci_off + 2]);
+ c_id = sg_get_unaligned_be24(ip + ci_off);
printf(" IEEE Company_id: 0x%x\n", c_id);
- vsei = 0;
- for (m = 0; m < 5; ++m) {
- if (m > 0)
- vsei <<= 8;
- vsei |= ip[ci_off + 3 + m];
- }
+ vsei = sg_get_unaligned_be48(ip + ci_off + 3);
printf(" Vendor Specific Extension Identifier: 0x%" PRIx64
"\n", vsei);
if (12 == i_len) {
- d_id = ((ip[8] << 24) | (ip[9] << 16) | (ip[10] << 8) |
- ip[11]);
+ d_id = sg_get_unaligned_be32(ip + 8);
printf(" Directory ID: 0x%x\n", d_id);
}
printf(" [0x");
@@ -1648,8 +1636,8 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
break;
}
d_id = (((ip[0] & 0xf) << 8) | ip[1]);
- c_id = ((ip[2] << 16) | (ip[3] << 8) | ip[4]);
- vsi = ((ip[5] << 16) | (ip[6] << 8) | ip[7]);
+ c_id = sg_get_unaligned_be24(ip + 2);
+ vsi = sg_get_unaligned_be24(ip + 5);
printf(" NAA 2, vendor specific identifier A: 0x%x\n",
d_id);
printf(" IEEE Company_id: 0x%x\n", c_id);
@@ -1711,12 +1699,7 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
printf(" NAA 6, IEEE Company_id: 0x%x\n", c_id);
printf(" Vendor Specific Identifier: 0x%" PRIx64 "\n",
vsei);
- vsei = 0;
- for (m = 0; m < 8; ++m) {
- if (m > 0)
- vsei <<= 8;
- vsei |= ip[8 + m];
- }
+ vsei = sg_get_unaligned_be64(ip + 8);
printf(" Vendor Specific Identifier Extension: "
"0x%" PRIx64 "\n", vsei);
printf(" [0x");
@@ -1738,7 +1721,7 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
dStrHexErr((const char *)ip, i_len, -1);
break;
}
- d_id = ((ip[2] << 8) | ip[3]);
+ d_id = sg_get_unaligned_be16(ip + 2);
printf(" Relative target port: 0x%x\n", d_id);
break;
case 5: /* (primary) Target port group */
@@ -1748,7 +1731,7 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
dStrHexErr((const char *)ip, i_len, -1);
break;
}
- d_id = ((ip[2] << 8) | ip[3]);
+ d_id = sg_get_unaligned_be16(ip + 2);
printf(" Target port group: 0x%x\n", d_id);
break;
case 6: /* Logical unit group */
@@ -1758,7 +1741,7 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
dStrHexErr((const char *)ip, i_len, -1);
break;
}
- d_id = ((ip[2] << 8) | ip[3]);
+ d_id = sg_get_unaligned_be16(ip + 2);
printf(" Logical unit group: 0x%x\n", d_id);
break;
case 7: /* MD5 logical unit identifier */
@@ -2017,7 +2000,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
}
break;
}
- d_id = ((ip[2] << 8) | ip[3]);
+ d_id = sg_get_unaligned_be16(ip + 2);
printf("SCSI_IDENT_%s_RELATIVE=%d\n", assoc_str, d_id);
break;
case 5: /* (primary) Target port group */
@@ -2029,7 +2012,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
}
break;
}
- d_id = ((ip[2] << 8) | ip[3]);
+ d_id = sg_get_unaligned_be16(ip + 2);
printf("SCSI_IDENT_%s_TARGET_PORT_GROUP=0x%x\n", assoc_str, d_id);
break;
case 6: /* Logical unit group */
@@ -2041,7 +2024,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
}
break;
}
- d_id = ((ip[2] << 8) | ip[3]);
+ d_id = sg_get_unaligned_be16(ip + 2);
printf("SCSI_IDENT_%s_LOGICAL_UNIT_GROUP=0x%x\n", assoc_str, d_id);
break;
case 7: /* MD5 logical unit identifier */
@@ -2103,7 +2086,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
break;
}
printf("SCSI_IDENT_%s_SOP_ROUTING_ID=0x%x\n", assoc_str,
- ((ip[0] << 8) | ip[1]));
+ sg_get_unaligned_be16(ip + 0));
} else {
pr2serr(" << Protocol specific port identifier "
"protocol_id=0x%x>>\n", p_id);
@@ -2127,7 +2110,7 @@ export_dev_ids(unsigned char * buff, int len, int verbose)
static void
decode_transport_id(const char * leadin, unsigned char * ucp, int len)
{
- int format_code, proto_id, num, j, k;
+ int format_code, proto_id, num, k;
uint64_t ull;
int bump;
@@ -2150,12 +2133,12 @@ decode_transport_id(const char * leadin, unsigned char * ucp, int len)
break;
case TPROTO_SPI:
printf("%s Parallel SCSI initiator SCSI address: 0x%x\n",
- leadin, ((ucp[2] << 8) | ucp[3]));
+ leadin, sg_get_unaligned_be16(ucp + 2));
if (0 != format_code)
printf("%s [Unexpected format code: %d]\n", leadin,
format_code);
printf("%s relative port number (of corresponding target): "
- "0x%x\n", leadin, ((ucp[6] << 8) | ucp[7]));
+ "0x%x\n", leadin, sg_get_unaligned_be16(ucp + 6));
bump = 24;
break;
case TPROTO_SSA: /* SSA */
@@ -2182,7 +2165,7 @@ decode_transport_id(const char * leadin, unsigned char * ucp, int len)
break;
case TPROTO_ISCSI:
printf("%s iSCSI ", leadin);
- num = ((ucp[2] << 8) | ucp[3]);
+ num = sg_get_unaligned_be16(ucp + 2);
if (0 == format_code)
printf("name: %.*s\n", num, &ucp[4]);
else if (1 == format_code)
@@ -2194,12 +2177,7 @@ decode_transport_id(const char * leadin, unsigned char * ucp, int len)
bump = (((num + 4) < 24) ? 24 : num + 4);
break;
case TPROTO_SAS:
- ull = 0;
- for (j = 0; j < 8; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= ucp[4 + j];
- }
+ ull = sg_get_unaligned_be64(ucp + 4);
printf("%s SAS address: 0x%" PRIx64 "\n", leadin, ull);
if (0 != format_code)
printf("%s [Unexpected format code: %d]\n", leadin,
@@ -2226,7 +2204,7 @@ decode_transport_id(const char * leadin, unsigned char * ucp, int len)
break;
case TPROTO_SOP:
printf("%s SOP ", leadin);
- num = ((ucp[2] << 8) | ucp[3]);
+ num = sg_get_unaligned_be16(ucp + 2);
if (0 == format_code)
printf("Routing ID: 0x%x\n", num);
else {
@@ -2278,7 +2256,7 @@ decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
!!(buff[8] & 0x1));
printf(" Multi I_T nexus microcode download=%d\n", buff[9] & 0xf);
printf(" Extended self-test completion minutes=%d\n",
- (buff[10] << 8) + buff[11]); /* spc4r27 */
+ sg_get_unaligned_be16(buff + 10)); /* spc4r27 */
printf(" POA_SUP=%d HRA_SUP=%d VSA_SUP=%d\n", /* spc4r32 */
!!(buff[12] & 0x80), !!(buff[12] & 0x40), !!(buff[12] & 0x20));
printf(" Maximum supported sense data length=%d\n",
@@ -2297,8 +2275,8 @@ decode_softw_inf_id(unsigned char * buff, int len, int do_hex)
buff += 4;
for ( ; len > 5; len -= 6, buff += 6)
printf(" IEEE Company_id: 0x%06x, vendor specific extension "
- "id: 0x%06x\n", (buff[0] << 16) | (buff[1] << 8) | buff[2],
- (buff[3] << 16) | (buff[4] << 8) | buff[5]);
+ "id: 0x%06x\n", sg_get_unaligned_be24(buff + 0),
+ sg_get_unaligned_be24(buff + 3));
}
/* VPD_ATA_INFO */
@@ -2376,17 +2354,17 @@ decode_power_condition(unsigned char * buff, int len, int do_hex)
!!(buff[4] & 0x2), !!(buff[4] & 0x1),
!!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
printf(" Stopped condition recovery time (ms) %d\n",
- (buff[6] << 8) + buff[7]);
+ sg_get_unaligned_be16(buff + 6));
printf(" Standby_z condition recovery time (ms) %d\n",
- (buff[8] << 8) + buff[9]);
+ sg_get_unaligned_be16(buff + 8));
printf(" Standby_y condition recovery time (ms) %d\n",
- (buff[10] << 8) + buff[11]);
+ sg_get_unaligned_be16(buff + 10));
printf(" Idle_a condition recovery time (ms) %d\n",
- (buff[12] << 8) + buff[13]);
+ sg_get_unaligned_be16(buff + 12));
printf(" Idle_b condition recovery time (ms) %d\n",
- (buff[14] << 8) + buff[15]);
+ sg_get_unaligned_be16(buff + 14));
printf(" Idle_c condition recovery time (ms) %d\n",
- (buff[16] << 8) + buff[17]);
+ sg_get_unaligned_be16(buff + 16));
}
/* VPD_BLOCK_LIMITS sbc */
@@ -2395,9 +2373,8 @@ decode_power_condition(unsigned char * buff, int len, int do_hex)
static void
decode_b0_vpd(unsigned char * buff, int len, int do_hex)
{
- int pdt, m;
+ int pdt;
unsigned int u;
- uint64_t mwsl;
if (do_hex) {
dStrHex((const char *)buff, len, (1 == do_hex) ? 0 : -1);
@@ -2412,56 +2389,40 @@ decode_b0_vpd(unsigned char * buff, int len, int do_hex)
}
printf(" Maximum compare and write length: %u blocks\n",
buff[5]);
- u = (buff[6] << 8) | buff[7];
+ u = sg_get_unaligned_be16(buff + 6);
printf(" Optimal transfer length granularity: %u blocks\n", u);
- u = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) |
- buff[11];
+ u = sg_get_unaligned_be32(buff + 8);
printf(" Maximum transfer length: %u blocks\n", u);
- u = (buff[12] << 24) | (buff[13] << 16) | (buff[14] << 8) |
- buff[15];
+ u = sg_get_unaligned_be32(buff + 12);
printf(" Optimal transfer length: %u blocks\n", u);
if (len > 19) { /* added in sbc3r09 */
- u = (buff[16] << 24) | (buff[17] << 16) | (buff[18] << 8) |
- buff[19];
+ u = sg_get_unaligned_be32(buff + 16);
printf(" Maximum prefetch transfer length: %u blocks\n", u);
}
if (len > 27) { /* added in sbc3r18 */
- u = ((unsigned int)buff[20] << 24) | (buff[21] << 16) |
- (buff[22] << 8) | buff[23];
+ u = sg_get_unaligned_be32(buff + 20);
printf(" Maximum unmap LBA count: %u\n", u);
- u = ((unsigned int)buff[24] << 24) | (buff[25] << 16) |
- (buff[26] << 8) | buff[27];
+ u = sg_get_unaligned_be32(buff + 24);
printf(" Maximum unmap block descriptor count: %u\n", u);
}
if (len > 35) { /* added in sbc3r19 */
- u = ((unsigned int)buff[28] << 24) | (buff[29] << 16) |
- (buff[30] << 8) | buff[31];
+ u = sg_get_unaligned_be32(buff + 28);
printf(" Optimal unmap granularity: %u\n", u);
printf(" Unmap granularity alignment valid: %u\n",
!!(buff[32] & 0x80));
- u = ((unsigned int)(buff[32] & 0x7f) << 24) |
- (buff[33] << 16) | (buff[34] << 8) | buff[35];
+ u = 0x7fffffff & sg_get_unaligned_be32(buff + 32);
printf(" Unmap granularity alignment: %u\n", u);
}
if (len > 43) { /* added in sbc3r26 */
- mwsl = 0;
- for (m = 0; m < 8; ++m) {
- if (m > 0)
- mwsl <<= 8;
- mwsl |= buff[36 + m];
- }
printf(" Maximum write same length: 0x%" PRIx64 " blocks\n",
- mwsl);
+ sg_get_unaligned_be64(buff + 36));
}
if (len > 44) { /* added in sbc4r02 */
- u = ((unsigned int)buff[44] << 24) | (buff[45] << 16) |
- (buff[46] << 8) | buff[47];
+ u = sg_get_unaligned_be32(buff + 44);
printf(" Maximum atomic transfer length: %u\n", u);
- u = ((unsigned int)buff[48] << 24) | (buff[49] << 16) |
- (buff[50] << 8) | buff[51];
+ u = sg_get_unaligned_be32(buff + 48);
printf(" Atomic alignment: %u\n", u);
- u = ((unsigned int)buff[52] << 24) | (buff[53] << 16) |
- (buff[54] << 8) | buff[55];
+ u = sg_get_unaligned_be32(buff + 52);
printf(" Atomic transfer length granularity: %u\n", u);
}
break;
@@ -2496,7 +2457,7 @@ decode_b1_vpd(unsigned char * buff, int len, int do_hex)
"short=%d\n", len);
return;
}
- u = (buff[4] << 8) | buff[5];
+ u = sg_get_unaligned_be16(buff + 4);
if (0 == u)
printf(" Medium rotation rate is not reported\n");
else if (1 == u)
@@ -2566,9 +2527,8 @@ decode_b3_vpd(unsigned char * buff, int len, int do_hex)
pr2serr("Referrals VPD page length too short=%d\n", len);
return;
}
- s = (buff[8] << 24) | (buff[9] << 16) | (buff[10] << 8) | buff[11];
- m = (buff[12] << 24) | (buff[13] << 16) | (buff[14] << 8) |
- buff[15];
+ s = sg_get_unaligned_be32(buff + 8);
+ m = sg_get_unaligned_be32(buff + 12);
if (0 == s)
printf(" Single user data segment\n");
else if (0 == m)
@@ -3077,7 +3037,7 @@ std_inq_response(const struct opts_t * op, int act_len)
if (op->do_descriptors) {
for (j = 0, k = 58; ((j < 8) && ((k + 1) < act_len));
k +=2, ++j)
- vdesc_arr[j] = ((rp[k] << 8) + rp[k + 1]);
+ vdesc_arr[j] = sg_get_unaligned_be16(rp + k);
}
if ((op->do_vendor > 1) && (act_len > 96)) {
memcpy(xtra_buff, &rp[96], act_len - 96);
@@ -3125,7 +3085,7 @@ vpd_fetch_page_from_dev(int sg_fd, unsigned char * rp, int page,
int res, resid, rlen, len, n;
if (sg_fd < 0) {
- len = ((rp[2] << 8) + rp[3]) + 4;
+ len = sg_get_unaligned_be16(rp + 2) + 4;
if (vb && (len > mxlen))
pr2serr("warning: VPD page's length (%d) > bytes in --inhex=FN "
"file (%d)\n", len , mxlen);
@@ -3161,7 +3121,7 @@ vpd_fetch_page_from_dev(int sg_fd, unsigned char * rp, int page,
if (mxlen < 0)
len = rp[3] + 4;
else
- len = ((rp[2] << 8) + rp[3]) + 4;
+ len = sg_get_unaligned_be16(rp + 2) + 4;
if (len <= rlen) {
if (rlenp)
*rlenp = len;
@@ -3436,7 +3396,7 @@ vpd_mainly_hex(int sg_fd, const struct opts_t * op, int inhex_len)
if ((! op->do_raw) && (op->do_hex < 2))
printf("VPD INQUIRY, page code=0x%.2x:\n", op->page_num);
if (sg_fd < 0) {
- len = ((rp[2] << 8) + rp[3]) + 4;
+ len = sg_get_unaligned_be16(rp + 2) + 4;
if (op->do_verbose && (len > inhex_len))
pr2serr("warning: VPD page's length (%d) > bytes in --inhex=FN "
"file (%d)\n", len , inhex_len);
diff --git a/src/sg_timestamp.c b/src/sg_timestamp.c
new file mode 100644
index 00000000..7a0d6d95
--- /dev/null
+++ b/src/sg_timestamp.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2015 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 <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "sg_lib.h"
+#include "sg_lib_data.h"
+#include "sg_pt.h"
+#include "sg_cmds_basic.h"
+#include "sg_unaligned.h"
+
+/* A utility program originally written for the Linux OS SCSI subsystem.
+ *
+ *
+ * This program issues a SCSI REPORT TIMESTAMP and SET TIMESTAMP commands
+ * to the given SCSI device. Based on spc5r07.pdf .
+ */
+
+static const char * version_str = "1.00 20151201";
+
+#define REP_TIMESTAMP_CMDLEN 12
+#define SET_TIMESTAMP_CMDLEN 12
+#define REP_TIMESTAMP_SA 0xf
+#define SET_TIMESTAMP_SA 0xf
+
+#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
+#define DEF_PT_TIMEOUT 60 /* 60 seconds */
+
+uint8_t d_buff[256];
+
+/* example Report timestamp parameter data */
+/* uint8_t test[12] = {0, 0xa, 2, 0, 0x1, 0x51, 0x5b, 0xe2, 0xc1, 0x30,
+ * 0, 0}; */
+
+
+static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"milliseconds", required_argument, 0, 'm'},
+ {"origin", no_argument, 0, 'o'},
+ {"raw", no_argument, 0, 'r'},
+ {"readonly", no_argument, 0, 'R'},
+ {"seconds", required_argument, 0, 's'},
+ {"srep", no_argument, 0, 'S'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+/* Indexed by 'timestamp origin' field value */
+static const char * ts_origin_arr[] = {
+ "initialized to zero at power on or by hard reset",
+ "reserved [0x1]",
+ "initialized by SET TIMESTAMP command",
+ "initialized by other method",
+ "reserved [0x4]",
+ "reserved [0x5]",
+ "reserved [0x6]",
+ "reserved [0x7]",
+};
+
+
+#ifdef __GNUC__
+static int pr2serr(const char * fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+#else
+static int pr2serr(const char * fmt, ...);
+#endif
+
+
+static int
+pr2serr(const char * fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return n;
+}
+
+static void
+usage()
+{
+ pr2serr("Usage: "
+ "sg_timestamp [--help] [--milliseconds=MS] [--origin] [--raw]\n"
+ " [--readonly] [--seconds=SEC] [--srep] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n");
+ pr2serr(" where:\n"
+ " --help|-h print out usage message\n"
+ " --milliseconds=MS|-m MS set timestamp to MS "
+ "milliseconds since\n"
+ " 1970-01-01 00:00:00 UTC\n"
+ " --origin|-o show Report timestamp origin "
+ "(def: don't)\n"
+ " --raw|-r output Report timestamp response to "
+ "stdout in\n"
+ " binary\n"
+ " --readonly|-R open DEVICE read only (def: "
+ "read/write)\n"
+ " --seconds=SEC|-s SEC set timestamp to SEC "
+ "seconds since\n"
+ " 1970-01-01 00:00:00 UTC\n"
+ " --srep|-S output Report timestamp in seconds "
+ "(def:\n"
+ " milliseconds)\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string and exit\n\n"
+ "Performs a SCSI REPORT TIMESTAMP or SET TIMESTAMP command. "
+ "The timestamp\nis SET if either the --milliseconds=MS or "
+ "--seconds=SEC option is given,\notherwise the existing "
+ "timestamp is reported. The DEVICE stores the\ntimestamp as "
+ "the number of milliseconds since 1970-01-01 00:00:00 UTC\n"
+ "which also happens to be the time 'epoch' of Unix "
+ "machines. The 'date +%%s'\ncommand in Unix returns the "
+ "number of seconds since the epoch. To\nconvert a reported "
+ "timestamp (in seconds since the epoch) to a more\nreadable "
+ "form use 'date --date='@<secs_since_epoch>' .\n");
+}
+
+/* Invokes a SCSI REPORT TIMESTAMP command. Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors */
+static int
+sg_ll_rep_timestamp(int sg_fd, void * resp, int mx_resp_len, int * residp,
+ int noisy, int verbose)
+{
+ int k, ret, res, sense_cat;
+ unsigned char rtCmdBlk[REP_TIMESTAMP_CMDLEN] =
+ {SG_MAINTENANCE_IN, REP_TIMESTAMP_SA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rtCmdBlk + 6);
+ if (verbose) {
+ pr2serr(" Report timestamp cdb: ");
+ for (k = 0; k < REP_TIMESTAMP_CMDLEN; ++k)
+ pr2serr("%02x ", rtCmdBlk[k]);
+ pr2serr("\n");
+ }
+
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2serr("%s: out of memory\n", __func__);
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, rtCmdBlk, sizeof(rtCmdBlk));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, "report timestamp", res, mx_resp_len,
+ sense_b, noisy, verbose, &sense_cat);
+ if (-1 == ret)
+ ;
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else
+ ret = 0;
+ if (residp)
+ *residp = get_scsi_pt_resid(ptvp);
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
+
+/* Invokes the SET TIMESTAMP command. Return of 0 -> success, various
+ * SG_LIB_CAT_* positive values or -1 -> other errors */
+static int
+sg_ll_set_timestamp(int sg_fd, void * paramp, int param_len, int noisy,
+ int verbose)
+{
+ int k, ret, res, sense_cat;
+ unsigned char stCmdBlk[SET_TIMESTAMP_CMDLEN] =
+ {SG_MAINTENANCE_OUT, SET_TIMESTAMP_SA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ sg_put_unaligned_be32(param_len, stCmdBlk + 6);
+ if (verbose) {
+ pr2serr(" Set timestamp cdb: ");
+ for (k = 0; k < SET_TIMESTAMP_CMDLEN; ++k)
+ pr2serr("%02x ", stCmdBlk[k]);
+ pr2serr("\n");
+ if ((verbose > 1) && paramp && param_len) {
+ pr2serr(" set timestamp parameter list:\n");
+ dStrHexErr((const char *)paramp, param_len, -1);
+ }
+ }
+
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2serr("%s: out of memory\n", __func__);
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, stCmdBlk, sizeof(stCmdBlk));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len);
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, "set timestamp", res, 0, sense_b, noisy,
+ verbose, &sense_cat);
+ if (-1 == ret)
+ ;
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else
+ ret = 0;
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
+static void
+dStrRaw(const char* str, int len)
+{
+ int k;
+
+ for (k = 0 ; k < len; ++k)
+ printf("%c", str[k]);
+}
+
+
+int
+main(int argc, char * argv[])
+{
+ int sg_fd, res, c;
+ int do_origin = 0;
+ int do_set = 0;
+ int do_srep = 0;
+ int do_raw = 0;
+ int readonly = 0;
+ bool secs_given = false;
+ int verbose = 0;
+ uint64_t secs = 0;
+ uint64_t msecs = 0;
+ int64_t ll;
+ const char * device_name = NULL;
+ const char * cmd_name;
+ int ret = 0;
+
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hm:orRs:SvV", long_options,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ case '?':
+ usage();
+ return 0;
+ case 'm':
+ ll = sg_get_llnum(optarg);
+ if (-1 == ll) {
+ pr2serr("bad argument to '--milliseconds=MS'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ msecs = (uint64_t)ll;
+ ++do_set;
+ break;
+ case 'o':
+ ++do_origin;
+ break;
+ case 'r':
+ ++do_raw;
+ break;
+ case 'R':
+ ++readonly;
+ break;
+ case 's':
+ ll = sg_get_llnum(optarg);
+ if (-1 == ll) {
+ pr2serr("bad argument to '--seconds=SEC'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ secs = (uint64_t)ll;
+ ++do_set;
+ secs_given = true;
+ break;
+ case 'S':
+ ++do_srep;
+ break;
+ case 'v':
+ ++verbose;
+ break;
+ case 'V':
+ pr2serr("version: %s\n", version_str);
+ return 0;
+ default:
+ pr2serr("unrecognised option code 0x%x ??\n", c);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (optind < argc) {
+ if (NULL == device_name) {
+ device_name = argv[optind];
+ ++optind;
+ }
+ if (optind < argc) {
+ for (; optind < argc; ++optind)
+ pr2serr("Unexpected extra argument: %s\n", argv[optind]);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+
+ if (do_set > 1) {
+ pr2serr("either --milliseconds=MS or --seconds=SEC may be given, "
+ "not both\n");
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ if (NULL == device_name) {
+ pr2serr("missing device name!\n");
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ sg_fd = sg_cmds_open_device(device_name, readonly, verbose);
+ if (sg_fd < 0) {
+ pr2serr("open error: %s: %s\n", device_name,
+ safe_strerror(-sg_fd));
+ return SG_LIB_FILE_ERROR;
+ }
+
+ memset(d_buff, 0, 12);
+ if (do_set) {
+ cmd_name = "Set timestamp";
+ sg_put_unaligned_be48(secs_given ? secs * 1000 : msecs, d_buff + 4);
+ res = sg_ll_set_timestamp(sg_fd, d_buff, 12, 1, verbose);
+ } else {
+ cmd_name = "Report timestamp";
+ res = sg_ll_rep_timestamp(sg_fd, d_buff, 12, NULL, 1, verbose);
+ if (0 == res) {
+ if (do_raw)
+ dStrRaw((const char *)d_buff, 12);
+ else {
+ int len = sg_get_unaligned_be16(d_buff + 0);
+ if (len < 8)
+ pr2serr("timestamp parameter data length too short, "
+ "expect >= 10, got %d\n", len + 2);
+ else {
+ if (do_origin)
+ printf("Device clock %s\n",
+ ts_origin_arr[0x7 & d_buff[2]]);
+ msecs = sg_get_unaligned_be48(d_buff + 4);
+ printf("%" PRIu64 "\n", do_srep ? (msecs / 1000) : msecs);
+ }
+ }
+ }
+ }
+ ret = res;
+ if (res) {
+ if (SG_LIB_CAT_INVALID_OP == res)
+ pr2serr("%s command not supported\n", cmd_name);
+ else {
+ char b[80];
+
+ sg_get_category_sense_str(res, sizeof(b), b, verbose);
+ pr2serr("%s command: %s\n", cmd_name, b);
+ }
+ }
+
+ res = sg_cmds_close_device(sg_fd);
+ if (res < 0) {
+ pr2serr("close error: %s\n", safe_strerror(-res));
+ if (0 == ret)
+ return SG_LIB_FILE_ERROR;
+ }
+ return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+}