diff -Nru smartmontools-7.1/aclocal.m4 smartmontools-7.3/aclocal.m4 --- smartmontools-7.1/aclocal.m4 2019-12-30 15:00:55.000000000 +0000 +++ smartmontools-7.3/aclocal.m4 2022-02-28 16:34:32.000000000 +0000 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.16.1 -*- Autoconf -*- +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- -# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,13 +14,13 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, -[m4_warning([this file was generated for autoconf 2.69. +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, +[m4_warning([this file was generated for autoconf 2.71. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# Copyright (C) 2002-2018 Free Software Foundation, Inc. +# Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -35,7 +35,7 @@ [am__api_version='1.16' 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.16.1], [], +m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,14 +51,14 @@ # 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.16.1])dnl +[AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Figure out how to run the assembler. -*- Autoconf -*- -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -78,7 +78,7 @@ # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -130,7 +130,7 @@ # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2018 Free Software Foundation, Inc. +# Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -161,7 +161,7 @@ Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -352,7 +352,7 @@ # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -391,7 +391,9 @@ done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments - for automatic dependency tracking. Try re-running configure with the + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi @@ -418,7 +420,7 @@ # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -446,6 +448,10 @@ # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl +m4_ifdef([_$0_ALREADY_INIT], + [m4_fatal([$0 expanded multiple times +]m4_defn([_$0_ALREADY_INIT]))], + [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl @@ -482,7 +488,7 @@ [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( - m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl @@ -534,6 +540,20 @@ [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi +AC_SUBST([CTAGS]) +if test -z "$ETAGS"; then + ETAGS=etags +fi +AC_SUBST([ETAGS]) +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi +AC_SUBST([CSCOPE]) + AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This @@ -615,7 +635,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -636,7 +656,7 @@ fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2018 Free Software Foundation, Inc. +# Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -658,7 +678,7 @@ # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -693,7 +713,7 @@ # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -736,7 +756,7 @@ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2018 Free Software Foundation, Inc. +# Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -757,12 +777,7 @@ [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac + MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then @@ -775,7 +790,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -804,7 +819,7 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -851,7 +866,7 @@ # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -870,7 +885,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -951,7 +966,7 @@ rm -f conftest.file ]) -# Copyright (C) 2009-2018 Free Software Foundation, Inc. +# Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1011,7 +1026,7 @@ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1039,7 +1054,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2018 Free Software Foundation, Inc. +# Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1058,7 +1073,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2018 Free Software Foundation, Inc. +# Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -Nru smartmontools-7.1/atacmds.cpp smartmontools-7.3/atacmds.cpp --- smartmontools-7.1/atacmds.cpp 2019-11-22 20:06:43.000000000 +0000 +++ smartmontools-7.3/atacmds.cpp 2021-06-04 16:39:50.000000000 +0000 @@ -4,7 +4,7 @@ * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-21 Christian Franke * Copyright (C) 1999-2000 Michael Cornwell * Copyright (C) 2000 Andre Hedrick * @@ -26,7 +26,7 @@ #include "utility.h" #include "dev_ata_cmd_set.h" // for parsed_ata_device -const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 4978 2019-11-22 20:06:43Z chrfranke $" +const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 5219 2021-06-04 16:39:50Z chrfranke $" ATACMDS_H_CVSID; // Print ATA debug messages? @@ -563,16 +563,14 @@ ata_cmd_out out; - int64_t start_usec = -1; - if (ata_debugmode) - start_usec = smi()->get_timer_usec(); + auto start_usec = (ata_debugmode ? get_timer_usec() : -1); bool ok = device->ata_pass_through(in, out); if (start_usec >= 0) { - int64_t duration_usec = smi()->get_timer_usec() - start_usec; - if (duration_usec >= 500) - pout(" [Duration: %.3fs]\n", duration_usec / 1000000.0); + auto duration_usec = get_timer_usec() - start_usec; + if (duration_usec > 0) + pout(" [Duration: %.6fs]\n", duration_usec / 1000000.0); } if (ata_debugmode && out.out_regs.is_set()) @@ -819,9 +817,6 @@ int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id, unsigned char * raw_buf /* = 0 */) { - unsigned short *rawshort=(unsigned short *)buf; - unsigned char *rawbyte =(unsigned char *)buf; - // See if device responds either to IDENTIFY DEVICE or IDENTIFY // PACKET DEVICE bool packet = false; @@ -849,6 +844,11 @@ if (raw_buf) memcpy(raw_buf, buf, sizeof(*buf)); + // If there is a checksum there, validate it + unsigned char * rawbyte = (unsigned char *)buf; + if (rawbyte[512-2] == 0xa5 && checksum(rawbyte)) + checksumwarning("Drive Identity Structure"); + // if machine is big-endian, swap byte order as needed if (isbigendian()){ // swap various capability words that are needed @@ -856,15 +856,11 @@ for (i=0; i<33; i++) swap2((char *)(buf->words047_079+i)); for (i=80; i<=87; i++) - swap2((char *)(rawshort+i)); + swap2((char *)(rawbyte+2*i)); for (i=0; i<168; i++) swap2((char *)(buf->words088_255+i)); } - // If there is a checksum there, validate it - if ((rawshort[255] & 0x00ff) == 0x00a5 && checksum(rawbyte)) - checksumwarning("Drive Identity Structure"); - // AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS) // T13/1699-D Revision 6a (Final Draft), September 6, 2008. // Sections 7.16.7 and 7.17.6: @@ -2416,7 +2412,8 @@ // Get/Set SCT Error Recovery Control static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, - bool set, unsigned short & time_limit) + bool set, unsigned short & time_limit, + bool power_on, bool mfg_default) { // Check initial status ata_sct_status_response sts; @@ -2434,7 +2431,17 @@ ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd)); // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK) cmd.action_code = 3; // Error Recovery Control command - cmd.function_code = (set ? 1 : 2); // 1=Set timer, 2=Get timer + + // 1=Set timer, 2=Get timer, 3=Set Power-on timer, 4=Get Power-on timer, 5=Restore mfg default + if (mfg_default) { + cmd.function_code = 5; + } else if (power_on) { + cmd.function_code = (set ? 3 : 4); + } else { + cmd.function_code = (set ? 1 : 2); + } + unsigned short saved_function_code = cmd.function_code; + cmd.selection_code = type; // 1=Read timer, 2=Write timer if (set) cmd.time_limit = time_limit; @@ -2471,7 +2478,7 @@ if (ataReadSCTStatus(device, &sts)) return -1; - if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) { + if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == saved_function_code)) { pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n", sts.ext_status_code, sts.action_code, sts.function_code); return -1; @@ -2500,15 +2507,16 @@ } // Get SCT Error Recovery Control -int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit) +int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit, bool power_on) { - return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit); + return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit, power_on, false); } // Set SCT Error Recovery Control -int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit) +int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit, + bool power_on, bool mfg_default) { - return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit); + return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit, power_on, mfg_default); } @@ -2524,7 +2532,7 @@ public: parsed_ata_device(smart_interface * intf, const char * dev_name); - virtual ~parsed_ata_device() throw(); + virtual ~parsed_ata_device(); virtual bool is_open() const; @@ -2605,7 +2613,7 @@ memset(m_command_table, 0, sizeof(m_command_table)); } -parsed_ata_device::~parsed_ata_device() throw() +parsed_ata_device::~parsed_ata_device() { parsed_ata_device::close(); } diff -Nru smartmontools-7.1/atacmds.h smartmontools-7.3/atacmds.h --- smartmontools-7.1/atacmds.h 2019-07-01 20:54:14.000000000 +0000 +++ smartmontools-7.3/atacmds.h 2021-01-15 18:02:19.000000000 +0000 @@ -13,7 +13,7 @@ #ifndef ATACMDS_H_ #define ATACMDS_H_ -#define ATACMDS_H_CVSID "$Id: atacmds.h 4934 2019-07-01 20:54:14Z chrfranke $" +#define ATACMDS_H_CVSID "$Id: atacmds.h 5166 2021-01-15 18:02:19Z chrfranke $" #include "dev_interface.h" // ata_device #include "static_assert.h" @@ -545,7 +545,7 @@ struct ata_sct_error_recovery_control_command { unsigned short action_code; // 3 = Error Recovery Control - unsigned short function_code; // 1 = Set, 2 = Return + unsigned short function_code; // 1 = Set Current, 2 = Return Current, 3 = Set Power-on, 4 = Return Power-on, 5 = Restore Default unsigned short selection_code; // 1 = Read Timer, 2 = Write Timer unsigned short time_limit; // If set: Recovery time limit in 100ms units unsigned short words004_255[252]; // reserved @@ -792,8 +792,8 @@ int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent); // Get/Set SCT Error Recovery Control -int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit); -int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit); +int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit, bool power_on); +int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default); /* Enable/Disable SMART on device */ diff -Nru smartmontools-7.1/ataidentify.cpp smartmontools-7.3/ataidentify.cpp --- smartmontools-7.1/ataidentify.cpp 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/ataidentify.cpp 2021-06-26 15:20:41.000000000 +0000 @@ -1,9 +1,9 @@ /* * ataidentify.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2012-18 Christian Franke + * Copyright (C) 2012-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -13,7 +13,7 @@ #include "ataidentify.h" -const char * ataidentify_cpp_cvsid = "$Id: ataidentify.cpp 4760 2018-08-19 18:45:53Z chrfranke $" +const char * ataidentify_cpp_cvsid = "$Id: ataidentify.cpp 5227 2021-06-26 15:20:41Z chrfranke $" ATAIDENTIFY_H_CVSID; #include "utility.h" @@ -30,6 +30,7 @@ // Tables 50 and 61 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 // Tables 45 and 50 of T13/2161-D (ACS-3) Revision 5, October 28, 2013 // Table 55 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017 (ATAPI removed) +// Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 const char * const identify_descriptions[] = { " 0 General configuration", @@ -113,7 +114,7 @@ ". 14 OVERWRITE EXT supported", ". 13 CRYPTO SCRAMBLE EXT supported", ". 12 Sanitize Device feature set supported", - ". 11 Cmds during sanitize as specified by this standard", // ACS-3 + ". 11 Cmds during sanitize are as specified by ACS-3", // ACS-3 ". 10 SANITIZE ANTIFREEZE LOCK EXT supported", // ACS-3 ". 9 Reserved", ". 8 Bits 7:0 are valid [OBS-ACS-4]", @@ -157,7 +158,7 @@ ". 4 Device encrypts all user data", ". 3 Extended number of user addressable sectors supported", ". 2 All write cache is non-volatile", // ACS-3 - ". 1:0 Zoned Capabilities", // ACS-4 + ". 1:0 Zoned Capabilities [OBS-ACS-5]", // ACS-4 " 70 Reserved", " 71-74 ATA: Reserved for IDENTIFY PACKET DEVICE", @@ -185,7 +186,8 @@ ". 0 Must be set to 0", " 77 Serial ATA additional capabilities", // ACS-3 - ". 15:9 Reserved for Serial ATA", + ". 15:10 Reserved for Serial ATA", + ". 9 Out Of Band Management supported", // ACS-5 ". 8 Power Disable feature always enabled", // ACS-4 ". 7 DevSleep to ReducedPwrState supported", // ACS-4 ". 6 RECEIVE/SEND FPDMA QUEUED supported", @@ -226,7 +228,8 @@ ". 0 Must be set to 0", " 80 Major version number", - ". 15:12 Reserved", + ". 15:13 Reserved", + ". 12 ACS-5 supported", ". 11 ACS-4 supported", ". 10 ACS-3 supported", ". 9 ACS-2 supported", @@ -390,7 +393,7 @@ ". 4 Device 0 detected the assertion of PDIAG-", ". 3 Device 0 passed diagnostics", ". 2:1 Device 0 detection method: -, Jumper, CSEL, other", - ". 0 Must be set to 1", + ". 0 Must be set to 1 for PATA devices", " 94 AAM level [OBS-ACS-2]", ". 15:8 Recommended AAM level [OBS-ACS-2]", @@ -533,7 +536,9 @@ "222 Transport major version number", ". 15:12 Transport: 0x0 = Parallel, 0x1 = Serial, 0xe = PCIe", // PCIe: ACS-4 - ". 11:9 Reserved | Reserved", + ". 11 Reserved | Reserved", + ". 10 Reserved | SATA 3.5", // ACS-5 + ". 9 Reserved | SATA 3.4", // ACS-5 ". 8 Reserved | SATA 3.3", // ACS-4 ". 7 Reserved | SATA 3.2", // ACS-4 ". 6 Reserved | SATA 3.1", // ACS-3 diff -Nru smartmontools-7.1/ataprint.cpp smartmontools-7.3/ataprint.cpp --- smartmontools-7.1/ataprint.cpp 2019-12-29 13:10:18.000000000 +0000 +++ smartmontools-7.3/ataprint.cpp 2022-02-26 18:30:35.000000000 +0000 @@ -4,7 +4,7 @@ * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-21 Christian Franke * Copyright (C) 1999-2000 Michael Cornwell * * SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +30,7 @@ #include "utility.h" #include "knowndrives.h" -const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 5012 2019-12-29 13:10:18Z chrfranke $" +const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 5336 2022-02-26 18:30:35Z dpgilbert $" ATAPRINT_H_CVSID; @@ -405,8 +405,9 @@ static const char * get_form_factor(unsigned short word168) { // Bits 0:3 are the form factor - // Table A.32 of T13/2161-D (ACS-3) Revision 4p, September 19, 2013 - // Table 236 of T13/BSR INCITS 529 (ACS-4) Revision 04, August 25, 2014 + // Table A.32 of T13/2161-D (ACS-3) Revision 5, October 28, 2013 + // Table 247 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017 + // Table 254 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (word168 & 0xF) { case 0x1: return "5.25 inches"; case 0x2: return "3.5 inches"; @@ -434,8 +435,9 @@ // Table 13 of T13/1153D (ATA/ATAPI-4) revision 18, August 19, 1998 // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 // Table 55 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017 - // Table 55 of T13/BSR INCITS 558 (ACS-5) Revision 1c, June 11, 2019 + // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (find_msb(drive->major_rev_num)) { + case 15: return "ACS >5 (15)"; case 14: return "ACS >5 (14)"; case 13: return "ACS >5 (13)"; case 12: return "ACS-5"; @@ -459,8 +461,10 @@ // Table 10 of X3T13/2008D (ATA-3) Revision 7b, January 27, 1997 // Table 28 of T13/1410D (ATA/ATAPI-6) Revision 3b, February 26, 2002 // Table 31 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 + // Table 52 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 + // Table 47 of T13/2161-D (ACS-3) Revision 5, October 28, 2013 // Table 57 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017 - // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 1c, June 11, 2019 + // Table 59 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (drive->minor_rev_num) { case 0x0001: return "ATA-1 X3T9.2/781D prior to revision 4"; case 0x0002: return "ATA-1 published, ANSI X3.221-1994"; @@ -533,6 +537,8 @@ static const char * get_pata_version(unsigned short word222, char (& buf)[32]) { + // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 + // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (word222 & 0x0fff) { default: snprintf(buf, sizeof(buf), "Unknown (0x%03x)", word222 & 0x0fff); return buf; @@ -544,14 +550,19 @@ static const char * get_sata_version(unsigned short word222) { + // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 + // Table 50 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 + // Table 45 of T13/2161-D (ACS-3) Revision 5, October 28, 2013 + // Table 55 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017 + // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (find_msb(word222 & 0x0fff)) { - case 11: return "SATA >3.3 (11)"; - case 10: return "SATA >3.3 (10)"; - case 9: return "SATA >3.3 (9)"; - case 8: return "SATA 3.3"; - case 7: return "SATA 3.2"; - case 6: return "SATA 3.1"; - case 5: return "SATA 3.0"; + case 11: return "SATA >3.5 (11)"; + case 10: return "SATA 3.5"; // ACS-5 + case 9: return "SATA 3.4"; // ACS-5 + case 8: return "SATA 3.3"; // ACS-4 + case 7: return "SATA 3.2"; // ACS-4 + case 6: return "SATA 3.1"; // ACS-3 + case 5: return "SATA 3.0"; // ACS-2 case 4: return "SATA 2.6"; case 3: return "SATA 2.5"; case 2: return "SATA II Ext"; @@ -565,14 +576,18 @@ { if (speed <= 0) return 0; + // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 + // Table 50 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 + // Table 45 of T13/2161-D (ACS-3) Revision 5, October 28, 2013 + // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (speed) { default: return ">6.0 Gb/s (7)"; case 6: return ">6.0 Gb/s (6)"; case 5: return ">6.0 Gb/s (5)"; case 4: return ">6.0 Gb/s (4)"; - case 3: return "6.0 Gb/s"; + case 3: return "6.0 Gb/s"; // ACS-3 case 2: return "3.0 Gb/s"; - case 1: return "1.5 Gb/s"; + case 1: return "1.5 Gb/s"; // ATA8-ACS } } @@ -620,7 +635,7 @@ static void print_drive_info(const ata_identify_device * drive, const ata_size_info & sizes, int rpm, - const drive_settings * dbentry) + const drive_settings * dbentry, const char * dbversion) { // format drive information (with byte swapping as needed) char model[40+1], serial[20+1], firmware[8+1]; @@ -655,7 +670,7 @@ // (e08130r1, added in ACS-2 Revision 1, December 17, 2008) if (0x2020 <= drive->words088_255[170-88] && drive->words088_255[170-88] <= 0x7e7e) { char add[8+1]; - ata_format_id_string(add, (const unsigned char *)(drive->words088_255+170-88), sizeof(add)-1); + ata_format_id_string(add, (const unsigned char *)(drive->words088_255+(170-88)), sizeof(add)-1); if (add[0]) { jout("Add. Product Id: %s\n", add); jglb["ata_additional_product_id"] = add; @@ -713,10 +728,36 @@ jglb["form_factor"]["name"] = form_factor; } + // Print TRIM support + bool trim_sup = !!(drive->words088_255[169-88] & 0x0001); + unsigned short word069 = drive->words047_079[69-47]; + bool trim_det = !!(word069 & 0x4000), trim_zeroed = !!(word069 & 0x0020); + if (trim_sup || rpm == 1) // HDD: if supported (SMR), SSD: always + jout("TRIM Command: %s%s%s\n", + (!trim_sup ? "Unavailable" : "Available"), + (!(trim_sup && trim_det) ? "" : ", deterministic"), + (!(trim_sup && trim_zeroed) ? "" : ", zeroed") ); + jglb["trim"]["supported"] = trim_sup; + if (trim_sup) { + jglb["trim"]["deterministic"] = trim_det; + jglb["trim"]["zeroed"] = trim_zeroed; + } + + // Print Zoned Device Capabilities if reported + // (added in ACS-4, obsoleted in ACS-5) + unsigned short zoned_caps = word069 & 0x3; + if (zoned_caps) { + jout("Zoned Device: %s\n", + (zoned_caps == 0x1 ? "Host Aware Zones" : + zoned_caps == 0x2 ? "Device managed zones" : "Unknown (0x3)")); + if (zoned_caps < 0x3) + jglb["zoned_device"]["capabilities"] = (zoned_caps == 0x1 ? "host_aware" : "device_managed"); + } + // See if drive is recognized - jout("Device is: %s\n", !dbentry ? - "Not in smartctl database [for details use: -P showall]": - "In smartctl database [for details use: -P show]"); + jout("Device is: %s%s%s\n", + (dbentry ? "In smartctl database" : "Not in smartctl database"), + (*dbversion ? " " : ""), (*dbversion ? dbversion : "")); jglb["in_smartctl_database"] = !!dbentry; // Print ATA version @@ -773,12 +814,7 @@ break; } - // print current time and date and timezone - time_t now = time(0); - char timedatetz[DATEANDEPOCHLEN]; dateandtimezoneepoch(timedatetz, now); - jout("Local Time is: %s\n", timedatetz); - jglb["local_time"]["time_t"] = now; - jglb["local_time"]["asctime"] = timedatetz; + jout_startup_datetime("Local Time is: "); // Print warning message, if there is one if (dbentry && *dbentry->warningmsg) @@ -1384,7 +1420,8 @@ // Table A.2 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 // Table 112 of Serial ATA Revision 3.2, August 7, 2013 // Table A.2 of T13/2161-D (ACS-3) Revision 5, October 28, 2013 - // Table 204 of T13/BSR INCITS 529 (ACS-4) Revision 16, February 21, 2017 + // Table 213 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017 + // Table 213 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021 switch (logaddr) { case 0x00: return "Log Directory"; case 0x01: return "Summary SMART error log"; @@ -1392,8 +1429,8 @@ case 0x03: return "Ext. Comprehensive SMART error log"; case 0x04: return "Device Statistics log"; case 0x05: return "Reserved for CFA"; // ACS-2 - case 0x06: return "SMART self-test log"; - case 0x07: return "Extended self-test log"; + case 0x06: return "SMART self-test log"; // OBS-ACS-5 + case 0x07: return "Extended self-test log"; // OBS-ACS-5 case 0x08: return "Power Conditions log"; // ACS-2 case 0x09: return "Selective self-test log"; case 0x0a: return "Device Statistics Notification"; // ACS-3 @@ -1409,9 +1446,9 @@ case 0x13: return "SATA NCQ Send and Receive log"; // SATA 3.1, ACS-3 case 0x14: return "Hybrid Information log"; // SATA 3.2, ACS-4 case 0x15: return "Rebuild Assist log"; // SATA 3.2, ACS-4 - case 0x16: + case 0x16: return "Out Of Band Management Control log"; // ACS-5 case 0x17: return "Reserved for Serial ATA"; - + case 0x18: return "Command Duration Limits log"; // ACS-5 case 0x19: return "LBA Status log"; // ACS-3 case 0x20: return "Streaming performance log [OBS-8]"; @@ -1421,9 +1458,15 @@ case 0x24: return "Current Device Internal Status Data log"; // ACS-3 case 0x25: return "Saved Device Internal Status Data log"; // ACS-3 - case 0x2f: return "Set Sector Configuration";; // ACS-4 + case 0x2f: return "Set Sector Configuration"; // ACS-4 case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3 + case 0x42: return "Mutate Configurations log"; // ACS-5 + + case 0x47: return "Concurrent Positioning Ranges log"; // ACS-5 + + case 0x53: return "Sense Data log"; // ACS-5 + case 0xe0: return "SCT Command/Status"; case 0xe1: return "SCT Data Transfer"; default: @@ -1444,11 +1487,15 @@ || (0x0f <= logaddr && logaddr <= 0x14) || (0x19 == logaddr) || (0x20 <= logaddr && logaddr <= 0x25) - || (0x30 == logaddr)) + || (0x30 == logaddr) + || (0x42 == logaddr) + || (0x47 == logaddr) + || (0x53 == logaddr)) return "R/O"; - if ( (0x09 <= logaddr && logaddr <= 0x0a) - || (0x15 == logaddr) + if ( ( logaddr <= 0x0a) + || (0x15 <= logaddr && logaddr <= 0x16) + || (0x18 == logaddr) || (0x80 <= logaddr && logaddr <= 0x9f) || (0xe0 <= logaddr && logaddr <= 0xe1)) return "R/W"; @@ -1694,6 +1741,7 @@ devstat_info_0x06, devstat_info_0x07 // TODO: 0x08 Zoned Device Statistics (T13/f16136r7, January 2017) + // TODO: 0x09 Command Duration Limits Statistics (ACS-5 Revision 10, March 2021) }; const int num_devstat_infos = sizeof(devstat_infos)/sizeof(devstat_infos[0]); @@ -3103,25 +3151,28 @@ } // Print SCT Error Recovery Control timers -static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer) +static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default = false) { + const char* power_on_str = (power_on ? "Power-on " : ""); json::ref jref = jglb["ata_sct_erc"]; - jout("SCT Error Recovery Control%s:\n", (set ? " set to" : "")); + jout("SCT Error Recovery Control%s:%s\n", (set ? " set to" : ""), (mfg_default ? " default values." : "")); - jref["read"]["enabled"] = !!read_timer; - if (!read_timer) - jout(" Read: Disabled\n"); - else { - jout(" Read: %6d (%0.1f seconds)\n", read_timer, read_timer/10.0); - jref["read"]["deciseconds"] = read_timer; - } + if (!mfg_default) { + jref["read"]["enabled"] = !!read_timer; + if (!read_timer) + jout(" %sRead: Disabled\n", power_on_str); + else { + jout(" %sRead: %6d (%0.1f seconds)\n", power_on_str, read_timer, read_timer/10.0); + jref["read"]["deciseconds"] = read_timer; + } - jref["write"]["enabled"] = !!write_timer; - if (!write_timer) - jout(" Write: Disabled\n"); - else { - jout(" Write: %6d (%0.1f seconds)\n", write_timer, write_timer/10.0); - jref["write"]["deciseconds"] = write_timer; + jref["write"]["enabled"] = !!write_timer; + if (!write_timer) + jout(" %sWrite: Disabled\n", power_on_str); + else { + jout(" %sWrite: %6d (%0.1f seconds)\n", power_on_str, write_timer, write_timer/10.0); + jref["write"]["deciseconds"] = write_timer; + } } } @@ -3288,7 +3339,11 @@ switch (powermode) { case -1: if (device->is_syscall_unsup()) { - pout("CHECK POWER MODE not implemented, ignoring -n option\n"); break; + if (options.powerexit_unsup >= 0) { + jinf("CHECK POWER MODE not implemented, exit(%d)\n", options.powerexit_unsup); + return options.powerexit_unsup; + } + jinf("CHECK POWER MODE not implemented, ignoring -n option\n"); break; } powername = "SLEEP"; powerlimit = 2; break; @@ -3315,7 +3370,12 @@ powername = "ACTIVE or IDLE"; break; default: - pout("CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode); + if (options.powerexit_unsup >= 0) { + jinf("CHECK POWER MODE returned unknown value 0x%02x, exit(%d)\n", powermode, + options.powerexit_unsup); + return options.powerexit_unsup; + } + jinf("CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode); break; } if (powername) { @@ -3420,6 +3480,8 @@ if (retid < 0) { pout("Read Device Identity failed: %s\n\n", (device->get_errno() ? device->get_errmsg() : "Unknown error")); + pout("If this is a USB connected device, look at the various " + "--device=TYPE variants\n"); failuretest(MANDATORY_CMD, returnval|=FAILID); } else if (!nonempty(&drive, sizeof(drive))) { @@ -3436,10 +3498,14 @@ // Use preset vendor attribute options unless user has requested otherwise. ata_vendor_attr_defs attribute_defs = options.attribute_defs; firmwarebug_defs firmwarebugs = options.firmwarebugs; + std::string dbversion; const drive_settings * dbentry = 0; - if (!options.ignore_presets) + if (!options.ignore_presets) { dbentry = lookup_drive_apply_presets(&drive, attribute_defs, - firmwarebugs); + firmwarebugs, dbversion); + if (!dbversion.empty()) + jglb["smartctl"]["drive_database_version"]["string"] = dbversion; + } // Get capacity, sector sizes and rotation rate ata_size_info sizes; @@ -3456,7 +3522,7 @@ // Print most drive identity information if requested if (options.drive_info) { pout("=== START OF INFORMATION SECTION ===\n"); - print_drive_info(&drive, sizes, rpm, dbentry); + print_drive_info(&drive, sizes, rpm, dbentry, dbversion.c_str()); } // Check and print SMART support and state @@ -3492,10 +3558,10 @@ if (smart_supported < 0) pout("SMART support is: Unknown - Try option -s with argument 'on' to enable it."); else if (!smart_supported) - pout("SMART support is: Unavailable - device lacks SMART capability.\n"); + jout("SMART support is: Unavailable - device lacks SMART capability.\n"); else { if (options.drive_info) - pout("SMART support is: Available - device has SMART capability.\n"); + jout("SMART support is: Available - device has SMART capability.\n"); if (smart_enabled >= 0) { if (device->ata_identify_is_cached()) { if (options.drive_info) @@ -3504,11 +3570,17 @@ smart_enabled = ataDoesSmartWork(device); } if (options.drive_info) - pout("SMART support is: %s\n", + jout("SMART support is: %s\n", (smart_enabled ? "Enabled" : "Disabled")); } } } + + if (options.drive_info || smart_supported <= 0) { + jglb["smart_support"]["available"] = (smart_supported > 0); + if (smart_supported > 0) + jglb["smart_support"]["enabled"] = (smart_enabled > 0); + } } // Print AAM status @@ -3957,7 +4029,9 @@ pout("SMART Status %s: %s\n", (device->is_syscall_unsup() ? "not supported" : "command failed"), device->get_errmsg()); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); + failuretest(OPTIONAL_CMD, returnval | FAILSMART); + if (!(device->is_syscall_unsup() && smart_val_ok && smart_thres_ok)) + returnval |= FAILSMART; // Unknown error or attribute check not possible if (!(smart_val_ok && smart_thres_ok)) { print_on(); @@ -4320,38 +4394,40 @@ failuretest(OPTIONAL_CMD, returnval|=FAILSMART); } else { - bool sct_erc_get = options.sct_erc_get; + int sct_erc_get = options.sct_erc_get; if (options.sct_erc_set) { // Set SCT Error Recovery Control - if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime ) - || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime)) { + bool set_power_on = (options.sct_erc_set == 2), mfg_default = (options.sct_erc_set == 3); + if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime, set_power_on, mfg_default) + || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime, set_power_on, mfg_default)) { pout("SCT (Set) Error Recovery Control command failed\n"); if (!( (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70) || (options.sct_erc_readtime == 0 && options.sct_erc_writetime == 0))) pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - sct_erc_get = false; + sct_erc_get = 0; } else if (!sct_erc_get) ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, - options.sct_erc_writetime); + options.sct_erc_writetime, set_power_on, mfg_default); } if (sct_erc_get) { // Print SCT Error Recovery Control + bool get_power_on = (sct_erc_get == 2); unsigned short read_timer, write_timer; - if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer ) - || ataGetSCTErrorRecoveryControltime(device, 2, write_timer)) { + if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer, get_power_on) + || ataGetSCTErrorRecoveryControltime(device, 2, write_timer, get_power_on)) { pout("SCT (Get) Error Recovery Control command failed\n"); - if (options.sct_erc_set) { + if (options.sct_erc_set == sct_erc_get) { pout("The previous SCT (Set) Error Recovery Control command succeeded\n"); ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, - options.sct_erc_writetime); + options.sct_erc_writetime, get_power_on); } failuretest(OPTIONAL_CMD, returnval|=FAILSMART); } else - ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer); + ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer, get_power_on); } pout("\n"); } diff -Nru smartmontools-7.1/ataprint.h smartmontools-7.3/ataprint.h --- smartmontools-7.1/ataprint.h 2018-11-02 20:09:12.000000000 +0000 +++ smartmontools-7.3/ataprint.h 2021-02-01 17:26:52.000000000 +0000 @@ -1,10 +1,10 @@ /* * ataprint.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-09 Bruce Allen - * Copyright (C) 2008-18 Christian Franke + * Copyright (C) 2008-21 Christian Franke * Copyright (C) 1999-2000 Michael Cornwell * * SPDX-License-Identifier: GPL-2.0-or-later @@ -13,142 +13,95 @@ #ifndef ATAPRINT_H_ #define ATAPRINT_H_ -#define ATAPRINT_H_CVSID "$Id: ataprint.h 4826 2018-11-02 20:09:12Z chrfranke $\n" +#define ATAPRINT_H_CVSID "$Id: ataprint.h 5192 2021-02-01 17:26:52Z chrfranke $\n" #include // Request to dump a GP or SMART log struct ata_log_request { - bool gpl; // false: SMART, true: GP - unsigned char logaddr; // Log address - unsigned page; // First page (sector) - unsigned nsectors; // # Sectors - - ata_log_request() - : gpl(false), logaddr(0), page(0), nsectors(0) - { } + bool gpl = false; // false: SMART, true: GP + unsigned char logaddr = 0; // Log address + unsigned page = 0; // First page (sector) + unsigned nsectors = 0; // # Sectors }; // Options for ataPrintMain struct ata_print_options { - bool drive_info; - int identify_word_level, identify_bit_level; - bool smart_check_status; - bool smart_general_values; - bool smart_vendor_attrib; - bool smart_error_log; - bool smart_selftest_log; - bool smart_selective_selftest_log; - - bool gp_logdir, smart_logdir; - unsigned smart_ext_error_log; - unsigned smart_ext_selftest_log; - bool retry_error_log, retry_selftest_log; + bool drive_info = false; + int identify_word_level = -1, identify_bit_level = -1; + bool smart_check_status = false; + bool smart_general_values = false; + bool smart_vendor_attrib = false; + bool smart_error_log = false; + bool smart_selftest_log = false; + bool smart_selective_selftest_log = false; + + bool gp_logdir = false, smart_logdir = false; + unsigned smart_ext_error_log = 0; + unsigned smart_ext_selftest_log = 0; + bool retry_error_log = false, retry_selftest_log = false; std::vector log_requests; - bool devstat_all_pages, devstat_ssd_page; + bool devstat_all_pages = false, devstat_ssd_page = false; std::vector devstat_pages; - unsigned pending_defects_log; + unsigned pending_defects_log = 0; - bool sct_temp_sts, sct_temp_hist; - bool sct_erc_get; - bool sct_erc_set; - unsigned sct_erc_readtime, sct_erc_writetime; - bool sataphy, sataphy_reset; - - bool smart_disable, smart_enable; - bool smart_auto_offl_disable, smart_auto_offl_enable; - bool smart_auto_save_disable, smart_auto_save_enable; + bool sct_temp_sts = false, sct_temp_hist = false; + int sct_erc_get = 0; // get(1), get_power_on(2) + int sct_erc_set = 0; // set(1), set_power_on(2), mfg_default(3) + unsigned sct_erc_readtime = 0, sct_erc_writetime = 0; + bool sataphy = false, sataphy_reset = false; + + bool smart_disable = false, smart_enable = false; + bool smart_auto_offl_disable = false, smart_auto_offl_enable = false; + bool smart_auto_save_disable = false, smart_auto_save_enable = false; - int smart_selftest_type; // OFFLINE_FULL_SCAN, ..., see atacmds.h. -1 for no test - bool smart_selftest_force; // Ignore already running test + int smart_selftest_type = -1; // OFFLINE_FULL_SCAN, ..., see atacmds.h. -1 for no test + bool smart_selftest_force = false; // Ignore already running test ata_selective_selftest_args smart_selective_args; // Extra args for selective self-test - unsigned sct_temp_int; - bool sct_temp_int_pers; + unsigned sct_temp_int = 0; + bool sct_temp_int_pers = false; enum { FMT_BRIEF = 0x01, FMT_HEX_ID = 0x02, FMT_HEX_VAL = 0x04 }; - unsigned char output_format; // FMT_* flags + unsigned char output_format = 0; // FMT_* flags firmwarebug_defs firmwarebugs; // -F options - bool fix_swapped_id; // Fix swapped ID strings returned by some buggy drivers + bool fix_swapped_id = false; // Fix swapped ID strings returned by some buggy drivers ata_vendor_attr_defs attribute_defs; // -v options - bool ignore_presets; // Ignore presets from drive database - bool show_presets; // Show presets and exit - unsigned char powermode; // Skip check, if disk in idle or standby mode - unsigned char powerexit; // exit() code for low power mode - - bool get_set_used; // true if any get/set command is used - bool get_aam; // print Automatic Acoustic Management status - int set_aam; // disable(-1), enable(1..255->0..254) Automatic Acoustic Management - bool get_apm; // print Advanced Power Management status - int set_apm; // disable(-1), enable(2..255->1..254) Advanced Power Management - bool get_lookahead; // print read look-ahead status - int set_lookahead; // disable(-1), enable(1) read look-ahead - int set_standby; // set(1..255->0..254) standby timer - bool set_standby_now; // set drive to standby - bool get_security; // print ATA security status - bool set_security_freeze; // Freeze ATA security - bool get_wcache; // print write cache status - int set_wcache; // disable(-1), enable(1) write cache - bool sct_wcache_reorder_get; // print write cache reordering status - int sct_wcache_reorder_set; // disable(-1), enable(1) write cache reordering - bool sct_wcache_reorder_set_pers; - bool sct_wcache_sct_get; // print SCT Feature Control of write cache status - int sct_wcache_sct_set; // determined by ata set features command(1), force enable(2), force disable(3) - bool sct_wcache_sct_set_pers; // persistent or volatile - bool get_dsn; // print DSN status - int set_dsn; // disable(02h), enable(01h) DSN - - ata_print_options() - : drive_info(false), - identify_word_level(-1), identify_bit_level(-1), - smart_check_status(false), - smart_general_values(false), - smart_vendor_attrib(false), - smart_error_log(false), - smart_selftest_log(false), - smart_selective_selftest_log(false), - gp_logdir(false), smart_logdir(false), - smart_ext_error_log(0), - smart_ext_selftest_log(0), - retry_error_log(false), retry_selftest_log(false), - devstat_all_pages(false), devstat_ssd_page(false), - pending_defects_log(0), - sct_temp_sts(false), sct_temp_hist(false), - sct_erc_get(false), - sct_erc_set(false), - sct_erc_readtime(0), sct_erc_writetime(0), - sataphy(false), sataphy_reset(false), - smart_disable(false), smart_enable(false), - smart_auto_offl_disable(false), smart_auto_offl_enable(false), - smart_auto_save_disable(false), smart_auto_save_enable(false), - smart_selftest_type(-1), smart_selftest_force(false), - sct_temp_int(0), sct_temp_int_pers(false), - output_format(0), - fix_swapped_id(false), - ignore_presets(false), - show_presets(false), - powermode(0), powerexit(0), - get_set_used(false), - get_aam(false), set_aam(0), - get_apm(false), set_apm(0), - get_lookahead(false), set_lookahead(0), - set_standby(0), set_standby_now(false), - get_security(false), set_security_freeze(false), - get_wcache(false), set_wcache(0), - sct_wcache_reorder_get(false), sct_wcache_reorder_set(0), - sct_wcache_reorder_set_pers(false), - sct_wcache_sct_get(false), sct_wcache_sct_set(0), - sct_wcache_sct_set_pers(false), - get_dsn(false), set_dsn(0) - { } + bool ignore_presets = false; // Ignore presets from drive database + bool show_presets = false; // Show presets and exit + unsigned char powermode = 0; // Skip check, if disk in idle or standby mode + unsigned char powerexit = 0; // exit() code for low power mode + int powerexit_unsup = -1; // exit() code for unsupported power mode or -1 to ignore + + bool get_set_used = false; // true if any get/set command is used + bool get_aam = false; // print Automatic Acoustic Management status + int set_aam = 0; // disable(-1), enable(1..255->0..254) Automatic Acoustic Management + bool get_apm = false; // print Advanced Power Management status + int set_apm = 0; // disable(-1), enable(2..255->1..254) Advanced Power Management + bool get_lookahead = false; // print read look-ahead status + int set_lookahead = 0; // disable(-1), enable(1) read look-ahead + int set_standby = 0; // set(1..255->0..254) standby timer + bool set_standby_now = false; // set drive to standby + bool get_security = false; // print ATA security status + bool set_security_freeze = false; // Freeze ATA security + bool get_wcache = false; // print write cache status + int set_wcache = 0; // disable(-1), enable(1) write cache + bool sct_wcache_reorder_get = false; // print write cache reordering status + int sct_wcache_reorder_set = 0; // disable(-1), enable(1) write cache reordering + bool sct_wcache_reorder_set_pers = false; + bool sct_wcache_sct_get = false; // print SCT Feature Control of write cache status + int sct_wcache_sct_set = 0; // determined by ata set features command(1), force enable(2), force disable(3) + bool sct_wcache_sct_set_pers = false; // persistent or volatile + bool get_dsn = false; // print DSN status + int set_dsn = 0; // disable(02h), enable(01h) DSN }; int ataPrintMain(ata_device * device, const ata_print_options & options); diff -Nru smartmontools-7.1/AUTHORS smartmontools-7.3/AUTHORS --- smartmontools-7.1/AUTHORS 2018-12-02 16:56:12.000000000 +0000 +++ smartmontools-7.3/AUTHORS 2021-01-15 18:02:19.000000000 +0000 @@ -1,9 +1,10 @@ -$Id: AUTHORS 4844 2018-12-02 16:56:12Z chrfranke $ +$Id: AUTHORS 5166 2021-01-15 18:02:19Z chrfranke $ Developers / Maintainers / Contributors: Raghava Aditya <...> Bruce Allen <...> +Jeremy Bauer Casey Biemiller Erik Inge Bolsø <...> Stanislav Brabec @@ -12,6 +13,7 @@ Jonghwan Choi Yuri Dario Casper Dik <...> +Simon Fairweather Christian Franke Guilhem Frézou <...> Thomas Gatterweh diff -Nru smartmontools-7.1/autogen.sh smartmontools-7.3/autogen.sh --- smartmontools-7.1/autogen.sh 2018-11-27 17:27:02.000000000 +0000 +++ smartmontools-7.3/autogen.sh 2022-02-01 18:39:20.000000000 +0000 @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: autogen.sh 4838 2018-11-27 17:27:02Z chrfranke $ +# $Id: autogen.sh 5312 2022-02-01 18:39:20Z chrfranke $ # # Generate ./configure from configure.ac and Makefile.in from Makefile.am. # This also adds files like missing,depcomp,install-sh to the source @@ -60,7 +60,7 @@ # OK ;; - 1.14|1.14.1|1.15|1.15.1|1.16|1.16.1) + 1.14|1.14.1|1.15|1.15.1|1.16|1.16.[1-5]) # TODO: Enable 'subdir-objects' in configure.ac # For now, suppress 'subdir-objects' forward-incompatibility warning test -n "$warnings" || amwarnings="--warnings=no-unsupported" diff -Nru smartmontools-7.1/ChangeLog smartmontools-7.3/ChangeLog --- smartmontools-7.1/ChangeLog 2019-12-30 15:00:49.000000000 +0000 +++ smartmontools-7.3/ChangeLog 2022-02-28 16:34:27.000000000 +0000 @@ -1,4 +1,1178 @@ -$Id: ChangeLog 5022 2019-12-30 15:00:49Z chrfranke $ +$Id: ChangeLog 5338 2022-02-28 16:34:26Z chrfranke $ + +2022-02-28 Christian Franke + + smartmontools 7.3 + +2022-02-27 Douglas Gilbert + + scsicmds.cpp scsiprint.cpp and others: route all SCSI pass + through calls in scsicmds.cpp via the renamed function: + scsi_pass_through_yield_sense() which will absorb up to + three pending Unit Attentions [see ticket 179]. Use + aggregate initialization (e.g. 'uint8_t b[32] = {};') to + bypass the need for many memset() calls. + +2022-02-26 Douglas Gilbert + + ataprint.cpp: add suggestion when 'Read Device Identity + failed: xxx' error generated to look at + --device-type=TYPE variants. May help with USB-C connected + NVMe enclosures (e.g. with M-2 modules inside) + +2022-02-26 Christian Franke + + configure.ac: Print 'deprecated' warning for '--with-signal-func'. + +2022-02-25 Douglas Gilbert + + NEWS: update for changes in previous commit + +2022-02-25 Douglas Gilbert + + smartctl.cpp, scsiprint.cpp: extend --log=defects option so it + works for the SCSI Pending Defects log page (similar to ATA log + page of same name). Add --log=envrep option to output + Environmental Reporting log page (e.g. temperature(s) and + relative humidiy). Add: --log=zdevstat option to output Zone + block device statistics log page. Updated smartctl.8.in for the + above changes. Ran 'spellintian * | grep -v duplica' on source + using Ubuntu 20.04 LTS with Canadian English as the locale. + Fixed reported spelling errors. + +2022-02-23 Christian Franke + + configure.ac, update-smart-drivedb.*: Use RELEASE_7_3_DRIVEDB for + drivedb.h updates. + + Create new branch RELEASE_7_3_DRIVEDB. + +2022-02-22 Christian Franke + + os_win32/update-smart-drivedb.ps1.in: Set console encoding. + Otherwise redirection to gpg occasionally starts with a BOM. + + os_win32/update-smart-drivedb.ps1.in: Unify path syntax. + + do_release: Update code signing key id. + + smartd.cpp: Ensure that '--warn-as-user=restricted' failure is + visible in syslog. + + smartd.cpp: Add '-q *nodev0*' option variants. + These change the exit status to 0 if there are no devices + to monitor. + smartd.8.in: Document new functionality. + +2022-02-20 Douglas Gilbert + + smartctl.cpp, scsiprint.cpp: implement the change to + TapeAlert handling documented in the previous commit. + Add --log=tapealert option to explicitly fetch the + Tape Alert log page. Tweak some tape-specific formatting. + +2022-02-19 Douglas Gilbert + + smartctl.8.in: proposed change to TapeAlert handling. No code + has changed, just the smartctl manpage. Please review. If + rejected just reverse this commit. + +2022-02-19 Christian Franke + + drivedb.h: + - Phison Driven (OEM) SSDs: Remove duplicate options. + - SK hynix SATA SSDs: S31 (#1517), SC210 *3AMNB*, SC300 *32MND*, + SC313 HFS*, SC401, SH920. + - Western Digital Ultrastar DC HC530: WUH721414ALE604 (#1458). + - Western Digital Ultrastar DC HC550: More variants (#1547). + - Western Digital Ultrastar DC HC560 (#1548). + - Western Digital Ultrastar DC HC650 (#1549). + - Western Digital Red Pro: WD102KFBX (#1543). + - Western Digital Gold: WD141KRYZ (#1433, #1470). + +2022-02-18 Christian Franke + + Allow one to specify a separate install location for drivedb.h. + This prevents that update-smart-drivedb overwrites the package + installed file (Debian Bug 976696, Ubuntu Bug 1893202). + + configure.ac, Makefile.am: Add '--with-drivedbinstdir' option. + update-smart-drivedb.in: Add '--install' option. + update-smart-drivedb.8.in: Document new functionality. + smartctl.8.in, smartd.8.in: Adjust path names. + +2022-02-16 Douglas Gilbert + + smartctl.cpp: add new --log=tapedevstat to print out SCSI + Tape (SSC) Device Statistics log page. '-a' does not include + this log page, but '-x' does. May add new --log= option + soon (probably 'tapealert' which must be invoked explicitly); + manpage needs updating + +2022-02-09 Alex Samorukov + + Remove cppcheck 2.7 warning as we are using it now on our CI builds + +2022-02-02 Christian Franke + + update-smart-drivedb.in: Fix regexp quoting. + + os_linux.cpp: Enhance device scan range to '/dev/sdzz'. + smartd.8.in: Update related documentation. + +2022-02-01 Christian Franke + + autogen.sh: automake 1.16.3-5 work. + + os_win32/update-smart-drivedb.nsi: Remove, no longer used. + Makefile.am: Remove related targets. + + os_win32/installer.nsi: Install update-smart-drivedb.ps1. + Delete update-smart-drivedb.exe. Remove outdated delete commands. + + os_win32/update-smart-drivedb.ps1.in: New drivedb.h update script. + It verifies the downloaded drive database with GnuPG (#752). + Makefile.am: Add new file. + +2022-01-29 Douglas Gilbert + + scsiprint.cpp: fix issue with Zoned block device + statistics lpage specific to the WDC DC HC650 + SAS ZBC disk. Visible with smartctl -x + +2022-01-28 Douglas Gilbert + + scsicmds.cpp,scsiprint.cpp: the "Long (extended) + Self-test duration" at the end of smartctl -a output + comes from a 16 bit field holding seconds. If the + value is 0xffff the spec now says to consult the + Extended Inquiry VPD page which has a similar field + but the unit is minutes. Tweak the output if the + duration exceeds 14400 seconds: calculate hours + in brackets [normally minutes]. Reason: my 20 TB + disk reports 38.7 hours to do a long self-test! + +2022-01-16 Douglas Gilbert + + scsiprint.cpp: my tape drive gives a nuisance TapeAlert + warning after each power cycle. With '-xj' output this + leads a JSON array with a lot of 'null' entries. Change + the JSON indexing so it is compact and add a + 'descriptor_idx' attribute if the position is important + to the end user. In the case of TapeAlert the relative + position is the degree of seriousness. Change TapeAlert + 'code' name to 'parameter_code'. + +2022-01-16 Douglas Gilbert + + scsiprint.cpp: small cleanup on (tape) device + statistics lpage (plain and json) + +2022-01-09 Douglas Gilbert + + scsiprint.cpp, add smartctl -x output (plain+json) for + the (tape) device statistics lpage and the Zoned block + device statistics lpage. Listed under -l background + option (may need new option(s)). + +2022-01-14 Alex Samorukov + + drivedb.h: Add xerrorlba flag to the WD Caviar Black (#1558) family + smartd.service: add comment about virtualisation + +2022-01-09 Douglas Gilbert + + scsiprint.cpp, scsicmds.h/.cpp: do some preliminary + work to fetch the Zoned block device characteristics + VPD page if it is present + +2022-01-08 Douglas Gilbert + + scsiprint.cpp: adjust json::str2key() calls as requested + +2022-01-08 Douglas Gilbert + + scsiprint.cpp: add json for the Start stop cycle counter + log page. Rejig some of the other SCSI json. + +2022-01-07 Douglas Gilbert + + scsiprint.cpp: remove jsonify_name() and use + json::str2key() where required. No user space + visible changes. + +2022-01-07 Alex Samorukov + drivedb.h: + - Add L3 EVO SSD (#1354) + - Add INTEL SSDSCKKF512G8 SATA 512GB (#1244) + - Extend regexp for the Sandisk SD9SB8W series (#1112) + +2022-01-06 Christian Franke + + json.cpp, json.h: Allows one to use any string for object keys. + Convert to final key with new public function 'json::str2key()'. + Rename related variables from 'key' to 'keystr'. + +2022-01-06 Alex Samorukov + + drivedb.h: + - SanDisk SSD PLUS 2000GB/UP4504RL (#1503) + - Western Digital PiDrive Foundation Edition (#1007) + - Fixed Supermicro SATA DOM (SuperDOM) entry (#1380) + - Extended regexp to support WDC WD40NDZM-59A8KS1 (#1474) + - Seagate FreePlay HDD (#1405) + +2022-01-05 Douglas Gilbert + + scsiprint.cpp: prefix most SCSI specific JSON + top level names with 'scsi_'. Add SCSI self + test JSON plus a few corrections. + +2022-01-05 Alex Samorukov + + drivedb.h: add Lexar 128GB SSD (#1529) + +2022-01-05 Douglas Gilbert + + scsiprint.cpp: first cut at adding json to the + self-test log page. + scsicmds.h/.cpp: add scsi_get_sense_key_str() + helper to fetch SCSI sense key as a C string + +2022-01-04 Douglas Gilbert + + scsiprint.cpp: printf() spotted in + scsiPrintPendingDefectsLPage() by Yannick Hemery. + Changed to jout(). + +2022-01-03 Douglas Gilbert + + utility.h: overload jsonify_name() to take a C + string or a std::string. Use in scsiprint.cpp + to add more json support. + +2022-01-03 Christian Franke + + json.h: Allows one to use std::string for object keys. + +2022-01-02 Douglas Gilbert + + utility.h: add free functions jsonify_name() and + jsonify_name_s() to lessen the repetition of names + that are very similar. May not save code but reduces + the chance of naming errors. Use jsonify_name() in + scsiprint.cpp as use of concept. + +2022-01-01 Christian Franke + + Happy New Year! Update copyright year in version info. + +2022-01-01 Douglas Gilbert + + scsiprint.cpp: add more json support: SAS transport + settings (partial) and some tape drive. Please review. + +2021-12-29 Douglas Gilbert + + scsiprint.cpp: add more json support: logical_unit_id, + protection_type and lb_provisioning + +2021-12-29 Douglas Gilbert + + scsiprint.cpp: applied patch proposed by Yannick Hemery at: + https://github.com/yhemery/smartmontools/commit/ + cf8462bbf395386c239ea587a26777f2de44f8d6 [note: that url has + been line wrapped]. It is to cope with a Samsung SAS SSD that + considers the "Supported log pages" log page [0x0,0x0] and + the "Supported log pages and subpages" log page [0x0,0xff] + as two sub-inventories that must be merged (i.e. a set + union) rather than [0x0,0xff] being a superset of [0x0,0x0]. + Samsung seems to be alone in that interpretation. + +2021-12-21 Douglas Gilbert + + experimental: add support for printing the SCSI Environmental + Reporting log (sub)page [0xd,0x1] via the -l scttemp option + and select it when '-x' is given. Also generate json output. + Outputs temperature and relative humidity current values and + various min/max values. Manpage has not been updated as this + may not be the best way to hook this in. + +2021-12-21 Douglas Gilbert + + scsiprint.cpp: fix listing of subpages as proposed by Yannick + Hemery in smt's github pull/122 + +2021-12-18 Christian Franke + + smartd.cpp: Windows: Add new option '--warn-as-user=restricted'. + If specified, the warning script is run with a restricted access + token. + + os_win32/popen_win32.cpp, os_win32/popen.h: Add new functions + 'popen_as_restr_user()' and 'popen_as_restr_check()' and a TEST + program. + + smartd.8.in: Document new functionality. + +2021-12-16 Christian Franke + + smartd.cpp: Add new option '--capabilities=mail'. + It initializes the capability bounding set for the exim MTA. + This is based on 'smartmontools-7.2-capnotify.patch' from the + Fedora Package (Red Hat Bugzilla 1954015). + + No longer suppress mail notification if '--capabilities' is used. + Log a related hint instead if the warning script fails. + + smartd.8.in: Document new functionality. + +2021-12-15 Christian Franke + + smartd.cpp: Allow use of '--warn-as-user' with '--capabilities'. + +2021-12-13 Christian Franke + + smartd.cpp: Add ability to run warning script as non-privileged user. + User could be specified with new option '-u, --warn-as-user'. + + popen_as_ugid.cpp, popen_as_ugid.h: New files with popen() wrapper + function. It allows one to change uid/gid and also prevents that + unneeded file descriptors are inherited by the child process. + + configure.ac, Makefile.am: Enable new functionality for all OS with + POSIX API. + + smartd.8.in: Document new functionality. + +2021-12-12 Christian Franke + + update-smart-drivedb.in: Add usage error messages, add '-h' option. + +2021-12-11 Christian Franke + + update-smart-drivedb.in: Allow a directory in the argument of '-t'. + + update-smart-drivedb.in: Add missing long options. + + update-smart-drivedb.in: Allow update from local files or other URLs. + Location could be specified with new options '--file' and '--url' + (#1426). Check VERSION information to prevent downgrades. + Allow override with new option '--force'. + update-smart-drivedb.8.in: Document new functionality. + + update-smart-drivedb.in: Rename some variables. + +2021-11-29 Christian Franke + + smartctl.cpp: Fix possible buffer overflow (#1546). + An overflow of 1-2 bytes occurred only if the '-n' option + was specified with an invalid argument. + +2021-11-28 Christian Franke + + smartd.cpp: Fix write of ATA attributes to state files. + Regression from r5256. + +2021-11-27 Christian Franke + + smartd.cpp: Don't write 'smartd -D' output to syslog on syntax error. + + smartd.cpp: Add ability to specify different check intervals (#336). + The new directive '-c i=N, -c interval=N' overrides the command line + option '-i N, --interval=N' for specific devices. + smartd.8.in, smartd.conf.5.in: Document new directive. + + smartd.cpp: Use some C++11 features. + + smartd.cpp: Add missing 'CloseDevice()' after NVMe error. + +2021-11-24 Alex Samorukov + + megaraid (Linux, FreeBSD): relax RAID matching for the LSI PERC RAID + controller. Reported by alex@alexburke.ca. + drivedb.h: add "PLEXTOR PX-512M8VC +" (GH #108) + +2021-11-23 Alex Samorukov + + drivedb.h: extend Intel regexp to support S4520 (GH #112) + +2021-11-22 Alex Samorukov + + os_freebsd.cpp: initial support of the direct MegaRaid access using + '-d megaraid' option. Code is initially based on Linux version but adopted to + be compatible with FreeBSD IOCTL-s. + +2021-11-13 Christian Franke + + smartctl.8.in, smartd.8.in: Remove EXPERIMENTAL notes for features + added before 7.1. + + smartd.cpp: Allow one to disable preconfigured state/log files with + '-'. The previous method required to specify the '-s' and '-A' options + with empty strings as arguments. This does not work conjunction with + shell variable expansion (GH issues/115). + smartd.8.in: Document new option argument. + +2021-11-08 Yannick Hemery + + scsicmds.cpp: Retry on UNIT ATTENTION when fetching capacity (#1303). + + If a UNIT ATTENTION is raised when READ CAPACITY (16) is called, + smartctl might wrongly assume that the drive only supports READ + CAPACITY (10), and return an invalid drive size / block size as a + result. + +2021-11-06 Christian Franke + + update-smart-drivedb.in: Add '-q' option to suppress info messages. + (GH issues/110). + update-smart-drivedb.8.in: Document new option. + + update-smart-drivedb.in: Stop the gpg-agent started by gpg. + Retry if removal of temp gpg home directory fails. + This prevents dangling agents and temp directories on NFS (#1542). + +2021-11-01 Christian Franke + + os_linux.cpp: Add missing permission bits to mknod() calls. + This fixes access to '-d aacraid' and '-d megaraid' devices from + smartd if '--capabilities' is used (GH issues/113). + Thanks to Michal Hlavinka for finding the root of the problem. + +2021-10-31 Christian Franke + + os_win32.cpp: Decode Windows 10, 11 and Server 2022 21H2 build + numbers. + +2021-10-23 Christian Franke + + Don't pass possible command escapes to the 'mail' command (#1535). + + The 'mail' command from GNU mailutils < 3.13 processes '~! COMMAND' + even if used non-interactively (https://savannah.gnu.org/bugs/?60937). + + smartd.cpp: Sanitize device identify information which is passed to + SMART_DEVICEINFO environment variable and written to syslog. + + smartd_warning.sh.in: Abort script if a message line begins with a + possible command escape. + + Thanks to 0x3l leox14@protonmail.com for reporting this security issue. + +2021-09-14 Christian Franke + + drivedb.h: + - Silicon Motion based SSDs: Mushkin Source-II (#1509). + - Western Digital Ultrastar DC HC550 (#1460). + - Toshiba MG08ACA... Enterprise Capacity HDD: 14TB. + - Toshiba N300/MN NAS HDD: Rename, add HDWG480, + - Seagate BarraCuda 3.5 (SMR): Attribute 9. + - Seagate IronWolf: Attribute 240. + MN series (#1510, #1511). + - USB: LaCie d2 PROFESSIONAL (0x059f:0x10b8) (#1502). + - USB: JMicron JMS576 (0x152d:0x0576) (#1428). + +2021-09-04 Christian Franke + + os_win32.cpp: Disable broken aacraid support until #1515 is fixed. + Print explanatory error message. Add 'force' flag to try anyway. + +2021-08-27 Christian Franke + + os_win32.cpp: aacraid: Fix crash on transfer size > 880 bytes (#1515). + +2021-08-21 Christian Franke + + os_win32.cpp: Decode Windows 10 21H1 build number. + + configure.ac: Add '-Werror=return-type' if supported. + G++ >= 8.0 assumes that control never reaches the end of a + non-void function (GCC Bugzilla 96181). + +2021-06-26 Christian Franke + + ataidentify.cpp, ataprint.cpp: ACS-5 enhancements. + + ataprint.cpp: Don't set bit 2 of exit status if ATA output registers + are missing but attributes are available (#1441, GH issues/98). + +2021-06-06 Christian Franke + + drivedb.h: + - Crucial/Micron Client SSDs: MTFDDAK256TDL-* (#1490). + - Innodisk 1IE3/3IE3/3ME3/3IE4/3ME4 SSDs: Rename, add 1IE3, 3IE4. + - Samsung based SSDs: 870 EVO, 860 QVO (#1457), + 883 DCT 1.92/3.84TB (#1452), CM871 MZ7LF192HCGS (#1475), + PM841 MZMTD128HAFV, PM851 MZNTE512HMJH (GH issues/87). + - SSSTC ER2 GD/CD Series SSDs: *A variant (#1484). + - Xmore Industrial SATA SSDs (based on patch from #1364). + - Toshiba MG09ACA... Enterprise Capacity HDD. + +2021-06-04 Christian Franke + + Rework 'get_timer_usec()', use a C++11 clock if possible. + dev_interface.cpp, dev_interface.h, os_win32.cpp: Move function ... + utility.cpp, utility.h: ... to here. + configure.ac: Remove related checks. + + ataprint.cpp, nvmeprint.cpp: Add JSON values 'smart_support.*' to + keep consistency with scsiprint.cpp. + +2021-05-02 Douglas Gilbert + + scsiprint.cpp: continue JSON work + +2021-04-14 Phillip Schichtel + + os_linux.cpp: Only require '-d cciss,N' if hpsa devices are in + RAID mode. + +2021-04-09 Alex Samorukov + + os_openbsd.cpp: fix SAT autodetection for the sd* devices (#1467) + +2021-03-24 Martin Ziemer + + os_openbsd.cpp: Apply conversion to seconds for timeouts in + scsi_pass_through (#1466). + + os_openbsd.cpp: Use correct devicename for autodetection (#1465). + +2021-03-08 Christian Franke + + drivedb.h: + - Toshiba MG04ACA... Enterprise HDD: Rename, merge entries, + add *NY variant (GH issues/90). + - Toshiba MG05ACA... Enterprise Capacity HDD (#1327). + - Toshiba MG08ACA... Enterprise Capacity HDD. + - Toshiba N300 NAS HDD (#1143, #1236, #1251, #1323). + - Toshiba P300 (CMR): Rename. + - Toshiba P300 (SMR) (#1430). + - Toshiba X300: HDWF180 (#1277), 10-16TB. + +2021-03-02 Christian Franke + + smartd_warning.sh.in: Fix handling of multiple email addresses + in conjunction with plugin scripts (#1454). + Pass modified SMARTD_ADDRESS also to all plugin scripts. + Provide original value as SMARTD_ADDRESS_ORIG. + Exit immediately if a script is missing. + smartd.conf.5.in: Document error handling and SMARTD_ADDRESS_ORIG. + +2021-02-14 Alex Samorukov + + os_darwin.cpp: implement APM set feature, based on hdparm macOS sources + +2021-02-09 Christian Franke + + configure.ac: Include required library functions in check for + '-fstack-protector' (#1439). + + Print drive database version in smartctl and smartd. + knowndrives.cpp, knowndrives.h: Parse VERSION string. + ataprint.cpp: Print version. Remove '-P showall' help string. + smartd.cpp: Print version. + +2021-02-07 Christian Franke + + Makefile.am: 'check' target now also checks the built-in database. + + smartctl.cpp: Fix 'optopt' range check + (cppcheck 2.3: invalidFunctionArg). + + scsiprint.cpp: Silence cppcheck 2.3 'unreadVariable' warning. + + scsiata.cpp: Remove unused function 'has_usbcypress_pass_through()'. + + Improve reproducibility if SOURCE_DATE_EPOCH if set (GH pull/89). + configure.ac: Define SOURCE_DATE_EPOCH in CPPFLAGS. + utility.cpp: Print SOURCE_DATE_EPOCH value if specified. + Don't include configure arguments then. + cppcheck.sh: Silence related 'ConfigurationNotChecked' message. + + Always add timestamp to JSON output (#1436). + Move non-JSON timestamp output to common function. + +2021-02-01 Christian Franke + + Silence more cppcheck 2.3 warnings. + + Add C++11 'override' specifier where applicable (cppcheck: missingOverride). + + os_freebsd.cpp, os_linux.cpp: Replace deprecated bcopy() and bzero() + (cppcheck: bcopyCalled, bzeroCalled). + + cppcheck.sh: Add '-c' option. + Remove suppress: bcopyCalled, bzeroCalled, missingOverride. + Mark cppcheck 1.86, 2.2 and 2.3 as tested. + + json.h: suppress cppcheck: noExplicitConstructor. + + ataprint.cpp, ataprint.h, smartctl.cpp: Optionally exit immediately + if '-n POWERMODE' option is not supported (#1381). + smartctl.8.in: Document new STATUS2 Parameter for '-n POWERMODE'. + +2021-01-27 Christian Franke + + json.cpp, json.h: Add support for nested braced-init-lists. + + json.cpp, json.h: Use some C++11 features. Align output functions. + +2021-01-24 Christian Franke + + ataprint.h, nvmeprint.h, scsiprint.h: Use C++11 in-class member + initializers. + + Drop C++98 restriction, allow C++11. + configure.ac: Enable C++11. Fail if no option found. + Disable C++14 if possible. Warn if no C++14 option found. + + configure.ac: Remove defunct '--with-working-snprintf'. + + scsiprint.cpp: Reduce scope of 'powerlimit' + (cppcheck 1.85: variableScope). + +2021-01-24 Simon Fairweather + + scsiprint.cpp: Move VPD page process to after new powermode processing + added in r5131 to resolve #1413 of Seagate drives spinning up when + -n standby is selected. Simplify code for VPD pages. + +2021-01-23 Christian Franke + + Makefile.am: Enhance config-vc and *clean-vc targets for MSVC15/16. + + os_win32/vc16: Copy from vc15 and change for MSVC16 (VS2019). + + os_win32/vc15: Copy from vc14 and change for MSVC15 (VS2017). + + os_win32/vc14/smart*.vcxproj*: Add missing files. + Suppress warnings for regex/regex.c. + +2021-01-20 Christian Franke + + ataprint.cpp, ataprint.h, smartctl.cpp: Rework sct_erc variables. + Fix handling of '-l scterc*,p' if both get and set are used. + + smartctl.cpp: Change '-l scterc,r' to '-l scterc,reset'. + Make ',p' case sensitive. Simplify parsing of 'scterc...'. + smartctl.8.in: Change documentation accordingly. + +2021-01-17 Christian Franke + + drivedb.h: + - Bump branch VERSION to 7.3. + - USB: Realtek RTL9211 (0x0bda:0x9211, 0x2eb9:0x9211). + - USB: ASMedia ASM2362 (0x174c:0x2362). + + scsinvme.cpp: Add '-d sntasmedia' device type for ASMedia ASM2362 + USB to NVMe bridges (#1221). + dev_interface.cpp: Update help text. + smartctl.8.in, smartd.conf.5.in: Document new option. + + Thanks to Demian from Sabrent. + +2021-01-15 Christian Franke + + smartctl.8.in: Add EXPERIMENTAL note for new '-l scterc' variants. + +2021-01-15 Jeremy Bauer + + Add support for SCT Error Recovery Timer features added in ACS-4 + (#1427). + '-l scterc[,R,W],p' option gets/sets the persistent power-on values. + '-l scterc,r' option restores to the manufacturer's default values. + +2021-01-15 Zhenwei Pi + + nvmeprint.cpp: Add bit 5 of SMART/Health 'Critical Warning' byte + (NVMe 1.4). + +2021-01-10 Christian Franke + + drivedb.h: Add VERSION information to trunk and all branches (#1424). + +2021-01-06 Christian Franke + + drivedb.h: + - Seagate BarraCuda 3.5: Split into ...(CMR) and ...(SMR). + - Seagate Exos 7E8 (#1415). + - Western Digital Blue (SMR): 4TB. + - USB: ADATA HV610 (0x125f:0xa21a) (#1417). + +2021-01-01 Christian Franke + + Happy New Year! Update copyright year in version info. + +2020-12-30 Christian Franke + + smartmontools 7.2 + +2020-12-30 Christian Franke + + configure.ac, update-smart-drivedb.in: Use RELEASE_7_2_DRIVEDB for + drivedb.h updates. + + Create new branch RELEASE_7_2_DRIVEDB. + +2020-12-29 Christian Franke + + drivedb.h: + - Micron 5100 Pro / 52x0 / 5300 SSDs: 5300HC. + - Samsung based SSDs: PM871 MZY* (#1384), 870 QVO (#1388). + - Silicon Motion based SSDs: ADATA IMSS332 (#1399), + ADATA SU650NS38 (#1386), JAJS600M1TB (#1414), NFN025SA31T. + - Silicon Motion based OEM SSDs: Dogfish, + Intenso portable (GH issues/81, GH pull/82), + Intenso Sata III (#1412), KingDian S280 (#1402). + - SK hynix SATA SSDs: SC300 (#1407). + - Hitachi Travelstar 5K500.B: *SA02 (#1408). + - Fix '-v' comments. Remove trailing whitespace. + + scsinvme.cpp: Realtek: Limit NVMe log transfer size to 512 bytes. + +2020-12-21 Christian Franke + + smartctl.8.in: Add EXPERIMENTAL notes for SCSI variants of + '-n POWERMODE' and '-s standby,...'. Fix syntax. + + update-smart-drivedb.in: Add 'Accept-Encoding' HTTP header when + curl is used. This avoids caching problems with svn URL. + + update-smart-drivedb.in: Print output of 'gpg --import' if '-v' is + specified. + + update-smart-drivedb.in: Extend expiration year of current database + signing key from 2020 to 2025 (#1278). + +2020-12-20 Christian Franke + + configure.ac: Use AC_CONFIG_HEADERS instead of obsolete + AC_CONFIG_HEADER. This silences a warning from new autoconf 2.70. + Print 'deprecated' warning for '--with-solaris-sparc-ata'. + + drivedb.h: + - Intel X25-E SSDs: IBM OEM (#1401). + - Seagate BarraCuda 3.5: 12TB + - Seagate Exos X16: 10TB (#1406, GH issues/63), 12TB. + - Seagate Archive HDD: Rename to ...(SMR) (#1392). + - Seagate BarraCuda, Enterprise Capacity, Exos, IronWolf: + Add attributes 18, 200. + - Seagate IronWolf Pro 125 SSDs (#1396). + - Unify indentation. + +2020-12-15 Douglas Gilbert + + smartctl: expand -s option with standby,now and standby,off (or + standby,0) to include SCSI. Modified code from Simon Fairweather + found in github pull #72. As per my 20201205 patch, this + area (i.e. SCSI power conditions including START and STOP) needs + to be revisited; leave that until after the 7.2 release. + +2020-12-14 Alex Samorukov + + drivedb.h: add Sony HD-E1B (#1410) + +2020-12-12 Alex Samorukov + + Add automake 1.16.2 to the list of tested versions + os_freebsd.cpp: number of minor patches from Christian Franke + +2020-12-05 Douglas Gilbert + + smartctl: expand -n option to include SCSI. Code from Simon + Fairweather. Still thinking about how to handle SCSI "stopped" + state which requires the user to send a SCSI command to restart. + +2020-12-04 Christian Franke + + nvmeprint.cpp: Print Log Page Attributes. Print NVMe 1.4 features. + + nvmecmds.cpp, nvmecmds.h, nvmeprint.cpp: Fix check for LPO support. + +2020-12-03 Christian Franke + + nvmeprint.cpp: Print NVMe version. + + nvmecmds.cpp, nvmecmds.h, nvmeprint.cpp: Limit NVMe log transfer size + to one page. This should fix device or kernel crashes on '-l error' + if log has more than 64 entries (#1404, Debian Bug 947803). + + nvmeprint.cpp: Read only requested number of entries from NVMe + Error Information Log. + +2020-11-23 Christian Franke + + smartd.cpp: Allow one to specify a delay limit for staggered + self-tests. + smartd.conf.5.in: Document new functionality. + +2020-11-21 Christian Franke + + smartd.cpp: Add staggered self-tests (#310). + smartd.conf.5.in: Document new functionality. + +2020-11-17 Dmitriy Potapov + + smartd.cpp: Don't write attrlog when device is skipped due to idle or + standby mode, or if attributes were not read for any other reason + (GH pull/75). + +2020-11-09 Christian Franke + + smartd.cpp: Resolve symlinks before device names are checked for + duplicates (#1390). + dev_interface.cpp, dev_interface.h: Add 'get_unique_dev_name()' + and 'is_raid_dev_type()' to support platform specific modifications. + smartd.conf.5.in: Document new functionality. + +2020-11-07 Christian Franke + + json.cpp, json.h: Add YAML support. + smartctl.cpp: Add '--json=y' option. + smartctl.8.in: Document new option. + + smartctl.8.in, smartd.conf.5.in: Remove EXPERIMENTAL notes for + features added before 7.0. + update-smart-drivedb.8.in: Add missing EXPERIMENTAL note. + +2020-11-01 Christian Franke + + drivedb.h: + - Phison Driven SSDs: KINGSTON OM4P0S3* (#1374), OMSP0S3* (#1375). + - InnoDisk iCF 9000 / 1SE2 Cards: Rename entry. Add 1SE2 H (#1351). + - Marvell based SanDisk SSDs: 2TB SDSSDH3 (GH issues/67, GH pull/69), + WD Blue SSD WDS100T2B0A (#1378). + - SanDisk based SSDs: SDSA6GM*. + - Toshiba 2.5" HDD MK..76GSX/GS001A (GH pull/58). + - Toshiba L200 (CMR), Toshiba L200 (SMR) (#1228, patch from #1377). + - Western Digital Blue: Apple OEM (#1385). + - Western Digital Scorpio Blue Serial ATA: 320 GB (patch from #888). + + os_win32.cpp: Decode Windows 10 20H2 and Server 2004, 20H2 + build numbers. + +2020-10-29 Alex Samorukov + + os_freebsd.cpp: skip SCSI subenclosure devices on scan (#1299) + +2020-10-24 Christian Franke + + drivedb.h: + - HGST Travelstar Z5K1000: *B*610 variant. + - Hitachi Travelstar 7K320: HITACHI*SA60 variant (#983). + - Hitachi/HGST Deskstar 5K4000: Rename entry. Add HGST (#1060). + - HGST Deskstar NAS: 8TB. + - Hitachi/HGST Ultrastar 5K3000 (#1055). + - Hitachi Ultrastar 7K3000: Variant without vendor name (#1361). + - Hitachi/HGST Ultrastar 7K4000: Variant without vendor name (#1361). + - HGST Ultrastar HC310/320 (#1157, #1365). + +2020-10-19 Christian Franke + + drivedb.h: + - ATP SATA III aMLC M.2 2242 SSD (based on patch from #1366). + - Silicon Motion based OEM SSDs: TCSUNBOW X3 (#1349), + KingDian S370 (#1350), LDLC (#1353), Lenovo. + - SSSTC ER2 GD/CD Series SSDs (based on patch from #1376). + +2020-10-15 Christian Franke + + drivedb.h: + - Apacer SSDs (based on patch from #1202). + - Crucial/Micron MX500 SSDs (FW <= M3CR032): Remove entry (#1227). + - Crucial/Micron Client SSDs: Rename entry. Fix name of attribute 127. + This prevents false 'Currently unreadable (pending) sectors' warnings + from smartd (#1227, #1294, #1311, #1336). + - Intel 730 and DC S35x0/3610/3700 Series SSDs: *H* variant (#1363). + - Samsung based SSDs: 883 DCT (#1373). + + os_win32.cpp: Fix removal of trailing blanks. + Silence misleading -Wstring-compare warning from g++ 10.2.0 + (GCC Bugzilla 97336). + +2020-10-09 Christian Franke + + scsiprint.cpp: Don't print 'Accumulated power on time' if no + option is specified (GH issues/65, regression from r5075). + Fix setting of 'any_output' (regression from r4188). + + Based on patch from GH pull/66. + +2020-10-06 Christian Franke + + Remove all occurrences of the throw() specifier. + This specifier is deprecated since C++11. + +2020-09-27 Christian Franke + + update-smart-drivedb.in: Add '--branch' option. + Select signing key accordingly. + update-smart-drivedb.8.in: Document new option. + +2020-09-20 Christian Franke + + drivedb.h: + - Crucial/Micron BX/MX1/2/3/500, M5/600, 11/1300 SSDs: BX500 2TB, + 1100 with version suffix (#1178), 1300 without prefix (#1369). + - Micron 5100 Pro / 52x0 / 5300 SSDs: Add attribute 246. + - Phison Driven SSDs: Kingston A400 M.2 (#1362), + Kingston OCP0S3* (#1370), Kingston OM8P0* (#1371). + - Kingston SSDNow UV400/500: UV500 M.2 (#1347). + - SAMSUNG SpinPoint N3U-3 (USB): Rename. + - USB: Samsung S1 Mini (0x04e8:0x2f06) (Debian Bug 964032). + +2020-09-19 Christian Franke + + ataprint.cpp: Report unavailable TRIM command only for SSDs. + +2020-08-23 Christian Franke + + drivedb.h: DEFAULT entry: Limit attribute 231 (Temperature_Celsius) + to HDDs. Various SSDs use this attribute for a different purpose. + + drivedb.h: + - Micron 5100 Pro / 52x0 / 5300 SSDs: Rename, add 5210 (#1356), + 5300 *TDT variant (#1355) + - Phison Driven SSDs: SSD Smartbuy 64GB and other sizes (#1359) + - Indilinx Barefoot_2/Everest/Martini based SSDs: OCZ-OCTANE (#1360) + - Marvell based SanDisk SSDs: Ultra 3D 4TB (#1358) + - Silicon Motion based SSDs: ACPI SED2QII-LP, Transcend 230 + - Western Digital Gold: WD102KRYZ (#1357) + +2020-08-22 Christian Franke + + smartd.service.in: Don't start smartd in virtualized environments + (GH issues/62). + +2020-08-22 Marko Hauptvogel + + smartd.service.in: Remove obsolete 'StandardOutput=syslog'. + +2020-07-11 Christian Franke + + scsiprint.cpp: Add JSON values 'power_on_time.{hours,minutes}' to + 'smartctl -a' output. Add missing pout() -> jout() replacements. + +2020-07-10 Douglas Gilbert + + scsiprint.cpp: Add "Accumulated power on time" entry to + 'smartctl -a' output. Previously this was only output + when the '-x' option was given, together with other + fields in the Background scan results log page. Now + with the '-a' option "Accumulated power on time" is + printed just before the "Manufactured in week ..." line. + +2020-07-06 Douglas Gilbert + + scsiprint.cpp: Attempted fix to tickets 1272, 1331 and 1346 + The difficulty is handling SCSI log _sub_-pages that hold + info about SSDs and newer hard drives, against older + devices (20 year old disks?) that do many and varied + things when asked to list supported sub-pages. Add a + heuristic and change some naming. + +2020-06-24 Alex Samorukov + + os_darwin.cpp: Fix NVMe log support, handle error codes, + remove SMARTReadData call + os_darwin.h: Cleanup, remove all private functions + +2020-06-23 Harry Mallon + + os_darwin.cpp, os_darwin.h: Add support for NVMe logs. + smartctl.8.in: Update related documentation. + +2020-06-20 Christian Franke + + drivedb.h: + - Crucial/Micron BX/MX1/2/3/500, M5/600, 11/1300 SSDs: Rename, + add 1300 + - Plextor M3/M5/M6/M7 Series SSDs: Rename, *M6G variant, *M7CV (#991) + - Silicon Motion based SSDs: ADATA SU650 (#1243), ADATA SU655 + - Seagate IronWolf Pro: 16TB (#1341) + - USB: Toshiba (0x0930:0xa002) + - USB: ADATA HD330 (0x125f:0xa83a) + - USB: AkiTio NT2 (0x2ce5:0x0014) + + os_solaris.cpp: Suggest '-d sat' if '-d ata' is specified. + +2020-06-18 Christian Franke + + scsiprint.cpp: Fix JSON value 'scsi_grown_defect_list'. + + Thanks to Ryan Allgaier for the bug report. + +2020-06-05 Alex Samorukov + + os_netbsd.cpp: fix timeout handling + os_openbsd.cpp (based on Marek Benc GH request): + - Migrate to the new API (#102) + - Fix for the ATA registries on the BE arc (GH PR #56) + - Fix timeout handling (GH PR #56) + +2020-06-01 Christian Franke + + drivedb.h: + - Crucial/Micron MX500 SSDs: Detect firmware <= M3CR032 (#1336) + - Micron 5100 Pro / 5200 / 5300 SSDs: Rename, add 5300 (#1326) + - Phison Driven SSDs: Corsair Force LE200 + - JMicron/Maxiotek based SSDs: Rename, add KingSpec NT + - Plextor M3/M5/M6 Series SSDs: *M6V variant + - Seagate IronWolf: *VN001 variant (GH pull/55) + - WD Blue / Red / Green SSDs: Rename, add WD Red SA500 (#1321) + - Western Digital Blue Mobile: re-add WD10JPZX (removed in r5054) + - USB: OWC Mercury Elite Pro Quad (0x1e91:0xa4a7) (patch from #1337) + + os_win32.cpp: Decode Windows 10 2004 build number. + +2020-05-25 Christian Franke + + ataprint.cpp: Print TRIM Command support info. + Print Zoned Device Capabilities if reported. + May also be useful to detect SMR HDDs (#1313). + +2020-05-24 Christian Franke + + drivedb.h: + - Phison Driven SSDs: GIGABYTE GP-GSTFS31, + KINGSTON DC450R/DC500M/DC500R 7.68TB (#1329), PNY CS900 (#1281) + - Intel 320 Series SSDs: HP OEM (#1332) + - JMicron based SSDs: ADATA SP600NS34 (GH pull/53), + ADATA OEM IM2S3138E* (#1298) + - Plextor M3/M5/M6 Series SSDs: allow extra space (#1293) + - Samsung based SSDs: 860 EVO 4TB, 850/860 PRO 2/4TB (#1316) + - Marvell based SanDisk SSDs: SDSSDA-* + - Silicon Motion based SSDs: Corsair Force LX (#1320) + - WD Blue and Green SSDs: WDBNCE* (#1129) + + drivedb.h: Add separate entries for WDC SMR drives (#1313). + - Western Digital Blue (SMR) + - Western Digital Black (SMR) + - Western Digital Red: Move WD60EFAX to ... + - Western Digital Red (SMR): ... here, add 2TB, 3TB, 4TB + - Western Digital Blue Mobile: Move WD[12]0SPZX to ... + - Western Digital Blue Mobile (SMR): ... here + +2020-04-23 Christian Franke + + drivedb.h: USB: Realtek RTL9210 (0x0bda:0x9210) + + scsinvme.cpp: Add '-d sntrealtek' device type for Realtek RTL9210 + USB to NVMe bridges (#1315). + dev_interface.cpp: Update help text. + smartctl.8.in, smartd.conf.5.in: Document new option. + + Thanks to Plugable Support for providing a NVMe enclosure. + +2020-04-05 Christian Franke + + drivedb.h: + - Crucial/Micron MX500 SSDs: Detect also older firmware (#1311) + - Silicon Motion based SSDs: Add attributes 159 and 231 (#1304) + - Seagate BarraCuda 3.5: Rename, merge entries, + add ST2000DM008 (#1179, #1252, #1286), ST10000DM0004 + - Seagate Exos X14: ST12000NM0538 (#1256) + - Seagate Exos X16 (#1291, #1301) + - Seagate Skyhawk (#1039) + +2020-04-04 Christian Franke + + dev_jmb39x_raid.cpp: Add '-d jms56x,...' device type for protocol + variant used by JMS562 USB to SATA RAID bridges (#1314). + dev_interface.cpp: Parse '-d jms56x*[+TYPE]' option, update help text. + smartctl.8.in, smartd.conf.5.in: Document new option. + +2020-03-29 Christian Franke + + drivedb.h: + - Western Digital Ultrastar He10/12: Rename, add He12 + (#1308, GH issues/51) + - Western Digital Ultrastar DC HC530 (#1257) + - Western Digital Green: WD5000AZRX (#1072) + - Western Digital Red: WD120EMFZ (GH issues/49) + - Western Digital Purple: WD*PURZ, WD80PUZX (#1057) + - Western Digital Gold: WD6003FRYZ + - Western Digital Blue Mobile: Rename, re-add WD10JPVX + (removed in r4991) + - Western Digital Elements / My Passport (USB, AF): + WD10SMZW (#1088), WD50NDZW + +2020-03-28 Christian Franke + + drivedb.h: + - Crucial/Micron BX/MX1/2/3/500, M5/600, 1100 SSDs: CT1000BX500SSD1, + MTFDDAK* (#1276) + - Kingston SSDNow UV400/500: Rename, add UV500 (#1126) + - Silicon Motion based SSDs: KingDian S100/200, Kingdian S280 1TB, + Kingston KC600 (#1304), Transcend MTS420S (#1280), + Transcend 360S (#1282) + - Seagate IronWolf Pro: ST4000NE001 + - Western Digital RE3 Serial ATA: WD*BYS-* variant + - Western Digital Gold: WD4003FRYZ (#1289), WD8004FRYZ (#1287) + - USB: 0x0860:0x0001 (#1295) + - USB: JMicron (0x152d:0x1337) (#1296) + - USB: Corsair SSD & HDD Cloning Kit (0x0984:0x0301) (#1307) + +2020-03-25 Christian Franke + + smartd.cpp: Set 'SMARTD_DEVICETYPE=auto' if DEVICESCAN is used + without '-d TYPE' directive (GH issues/52). + +2020-03-05 Christian Franke + + Silence some cppcheck 1.85 warnings. + nvmeprint.cpp, smartd.cpp: knownConditionTrueFalse. + scsicmds.cpp, scsiprint.cpp: variableScope. + scsicmds.h: Remove unused function supported_vpd_pages::num_pages(). + + cppcheck.sh: Remove no longer used HAVE_*NTDDDISK_H defines. + +2020-03-01 Christian Franke + + dev_intelliprop.cpp, dev_interface.cpp, dev_interface.h: Move option + parsing to get_intelliprop_device(). Move this function to class + smart_interface. + dev_intelliprop.h: Remove file. + Makefile.am, os_win32/vc14/smart*.vcxproj*: Remove old file. + + configure.ac: Fail if '--without-working-snprintf' is specified. + utility.cpp, utility.h: Remove support for pre-C99 snprintf(). + + os_win32.cpp: Remove backward compatibility fixes for include files + of very old versions of Cygwin, MinGW and MSVC. + configure.ac, Makefile.am: Remove check for DDK include files. + +2020-02-25 Christian Franke + + Silence some warnings from g++ 9.2: + atacmds.cpp: -Waddress-of-packed-member. + os_win32.cpp: -Wcast-function-type. + smartd.cpp: -Wformat-truncation. + +2020-02-25 Fabrice Fontaine + + configure.ac: fix stack-protector detection. + Use AC_LINK_IFELSE instead of AC_COMPILE_IFELSE to check for + stack-protector availability as some compilers could missed the + needed library (-lssp or -lssp_nonshared) at linking step. + +2020-01-11 Christian Franke + + dev_jmb39x_raid.cpp: Add '-d jmb39x-q,...' device type for JMB39x + protocol variant used by QNAP-TR004 NAS (#1283). + dev_interface.cpp: Update help text. + smartctl.8.in, smartd.conf.5.in: Document '-q' suffix. + +2020-01-02 Christian Franke + + configure.ac: Use 'uname -n' if 'hostname' is not available + (GH PR 44). Remove check for SVN < 1.7. + +2020-01-01 Christian Franke + + Happy New Year! Update copyright year in version info. 2019-12-30 Christian Franke diff -Nru smartmontools-7.1/ChangeLog-5.0-6.0 smartmontools-7.3/ChangeLog-5.0-6.0 --- smartmontools-7.1/ChangeLog-5.0-6.0 2012-10-10 16:15:26.000000000 +0000 +++ smartmontools-7.3/ChangeLog-5.0-6.0 2022-02-26 00:15:22.000000000 +0000 @@ -1,6 +1,6 @@ CHANGELOG for smartmontools 5.0 to 6.0 -$Id: ChangeLog-5.0-6.0 3645 2012-10-10 16:15:26Z chrfranke $ +$Id: ChangeLog-5.0-6.0 5333 2022-02-26 00:15:22Z dpgilbert $ Maintainers / Developers Key (alphabetic order): [AS] Alex Samorukov @@ -478,7 +478,7 @@ [CF] smartd: Disable auto standby also after start of scheduled self-test. - [CF] smartd: Add smartd.conf DEFAULT directive. Allows to set default + [CF] smartd: Add smartd.conf DEFAULT directive. Allows one to set default settings for multiple devices. [CF] smartd: Re-enable auto standby if smartd.conf is re-read. @@ -1318,7 +1318,7 @@ [CF] Makefile.am: Handle examplescripts in main Makefile. Remove 'examplescripts/Makefile.am'. - [CF] configure.in: New option '--with-exampledir' allows to change + [CF] configure.in: New option '--with-exampledir' allows one to change path of 'DOCDIR/examplescripts' directory. (Debian package uses '/usr/share/doc/smartmontools/examples') @@ -1651,7 +1651,7 @@ - Intel X25-M SSD [CF] Makefile.am: Fix unix2dos and makensis parameters to allow - to build the Windows installer on Linux also. + one to build the Windows installer on Linux also. [CF] Makefile.am: Use a separate build rule for each man page to avoid compatibility problems with BSD make. @@ -1675,7 +1675,7 @@ Patch was provided by Richard Gregory: http://www.csc.liv.ac.uk/~greg/projects/erc/ Modified for new ata_pass_through() interface. - Linux HPT fixes ommitted for now. + Linux HPT fixes omitted for now. [CF] Fix SCT temperature table commands on big endian CPUs. @@ -1815,7 +1815,7 @@ Autoconf 2.5x is still supported. [CF] Move drive database entries from 'knowndrives.cpp' to new file - 'drivedb.h'. This allows to update the drive database from SVN + 'drivedb.h'. This allows one to update the drive database from SVN if installation was configured with '--enable-drivedb'. Remove the Makefile target to create 'drivedb.h'. @@ -1856,7 +1856,7 @@ smartmontools 5.39 2009-12-09 - [CF] do_release: Commit CHANGELOG and NEWS also. Allow to review changes. + [CF] do_release: Commit CHANGELOG and NEWS also. Allows one to review changes. [CF] Linux: Add workaround for Adaptec series 2, 5 and 5Z controllers with firmware >= 17380. Patch was provided by Phil Wilson, see: @@ -1882,7 +1882,7 @@ - WD My Passport hard drive (USB interface) [CF] smartd: Write 'worst' attribute value to '.state' file also. - This allows to use state persistence with 'raw64' attributes. + This allows one to use state persistence with 'raw64' attributes. [CF] Rework ATA SMART attribute check in smartctl and smartd. smartd: Ignore normalized attribute value and threshold @@ -1906,7 +1906,7 @@ [CF] Add '-v ID,raw64[,...]' print format based on a patch provided by Marcin Marszalek. - [CF] Add '-v ID,RAW_FORMAT[,ATTR_NAME]' option. This allows to add new + [CF] Add '-v ID,RAW_FORMAT[,ATTR_NAME]' option. This allows one to add new attributes without the need to enhance the '-v' option. Rework attribute name and raw value formatting. @@ -2013,7 +2013,7 @@ [CF] Add USB IDs of Maxtor Basics Desktop and ISD-300A1. [AS] Use malloc() to ensure that the read buffer lands on a single - page. This avoids some bugs seen on LSI controlers under + page. This avoids some bugs seen on LSI controllers under FreeBSD. [CF] Add missing help text for '-d usb*' options. @@ -2218,7 +2218,7 @@ [CF] Simplify '-v' vendor attribute option parsing. Add '-v 197,increasing' and '-v 198,increasing' options - to specifiy that an uncorrectable count is never reset. + to specify that an uncorrectable count is never reset. This modifies the printed attribute names and smartd's default setting of '-C' and '-U' directives. Both '-v' options can also be preset in the drive database. @@ -2335,7 +2335,7 @@ - Added Hitachi Travelstar E5K160 family - Allow uppercase variants of Hitachi 5K160 drives - [CF] Fix smartctl crash on '-l directory,[gs]'. Allow to override + [CF] Fix smartctl crash on '-l directory,[gs]'. Allows one to override missing GPL feature bit or missing log dir entry with '-T permissive' option. @@ -2422,7 +2422,7 @@ selective self-tests. Useful to perform full tests of large disks not running 24x7. - [CF] Allow to read local drive database entries from optional file + [CF] Allows one to read local drive database entries from optional file '${sysconfdir}/smart_drivedb.h'. Add configure options '--enable-drivedb' and '--with-drivedbdir=DIR'. If specified, drive database is read from '${drivedbdir}/drivedb.h'. @@ -2621,7 +2621,7 @@ [JH] now C++ Support for QNX Target already tested for QNX 6.3.2 on x86 and armle target - [CF] Allow to set BUILD_INFO from make command line. + [CF] Allows one to set BUILD_INFO from make command line. [CF] Windows: Add MSVC8 support, remove MSVC6 project files. @@ -2802,11 +2802,11 @@ NOTE2: NOT TESTED ON LINUX. Do not use this on a production box! I will remove this NOTE2 as soon as some positive test - reports are recieved. + reports are received. NOTE3: NOT TESTED ON FREEBSD. Do not use this on a production box! I will remove this NOTE3 as soon as some positive test - reports are recieved. + reports are received. [CF] Windows installer: Added explorer drive menu, CMD window, UBCD4Win plugin, smartd service update and other minor @@ -2835,7 +2835,7 @@ out. [CF] Windows: Added IOCTL_SCSI_MINIPORT_*SMART* for commands not handled - properly by SMART_IOCTL in disk class driver. This allows to use + properly by SMART_IOCTL in disk class driver. This allows one to use READ_LOG, WRITE_LOG and ABORT_SELFTEST even if the driver does not support ATA_PASS_THROUGH. @@ -3411,7 +3411,7 @@ Windows distribution (dist-win32) and MSVC6 config.h (config-vc6). [EM] Minor change to FreeBSD inclusion of 'twe' include files. Add - code to check if they exising in /usr/include/sys to use those + code to check if they existing in /usr/include/sys to use those in preference to ones added here [EM] Very preliminary support attempt for 3Ware controllers under @@ -3891,7 +3891,7 @@ or mail warning script, and reports any output to SYSLOG. This gives a clearer error message if something is wrong. - [BA] smartd: Solaris init script modified to accomodate grep that + [BA] smartd: Solaris init script modified to accommodate grep that lacks '-q' quiet option. Also check for running process to kill on stop. @@ -4498,7 +4498,7 @@ [EB] Add another Fujitsu disk to knowndrives.c - [GG] match for scsi/ and ide/ in case of devfs to exclude false postives + [GG] match for scsi/ and ide/ in case of devfs to exclude false positives [BA] If SCSI device listed in /etc/smartd.conf fails to open or do SMART stuff correctly, or not enough space @@ -4863,7 +4863,7 @@ Added Italian descriptions to smartmontools.spec file. - Started impementing send-mail-on-error for smartd; not yet enabled. + Started implementing send-mail-on-error for smartd; not yet enabled. Added -P (Permissive) Directive to smartd.conf file to allow SMART monitoring of pre-ATA-3 Rev 4 disks that have SMART but do not have @@ -4924,7 +4924,7 @@ Note: it has now been confirmed that the code modifications between 5.0.23 and 5.0.24 have eliminated the GCC 3.2 problems. Note that - there is a GCC bug howerver, see #8404 at + there is a GCC bug however, see #8404 at http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=query http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8404 @@ -5023,10 +5023,10 @@ library, as it should be. modified length of device name string in smartd internal structure - to accomodate max length device name strings + to accommodate max length device name strings removed un-implemented (-e = Email notification) option from - command line arg list. We'll put it back on when implemeneted. + command line arg list. We'll put it back on when implemented. smartd now logs serious (fatal) conditions in its operation at loglevel LOG_CRIT rather than LOG_INFO before exiting with error. @@ -5071,7 +5071,7 @@ appears incapable of a SMART command that the user has asked for, complain by printing an error message, but go ahead and try anyway. Since unimplemented SMART commands should just return an - error but not cause disk problems, this should't cause any + error but not cause disk problems, this shouldn't cause any difficulty. Added two new flags: q and Q. q is quiet mode - only print: For @@ -5080,7 +5080,7 @@ SMART "disk failing" status or device attributes (pre-failure or usage) which failed either now or in the past; For the -v option device attributes (pre-failure or usage) which failed either now - or in the past. Q is Very Quiet mode: Print no ouput. The only + or in the past. Q is Very Quiet mode: Print no output. The only way to learn about what was found is to use the exit status of smartctl. @@ -5116,7 +5116,7 @@ ID. This is fixed. when starting self-tests in captive mode ioctl returns EIO because - the drive has been busied out. Detect this and don't return an eror + the drive has been busied out. Detect this and don't return an error in this case. Check this this is correct (or how to fix it?) fixed possible error in how to determine ATA standard support @@ -5219,14 +5219,14 @@ added -f and -F options to enable/disable autosave threshold parameters - changed argv parsing to use getops -- elminate buffer overflow + changed argv parsing to use getops -- eliminate buffer overflow vulnerability expanded and corrected documentation fixed problem with smartd. It did not actually call ataSmartEnable()! Since the argument was left out, the test - always suceeded because it evaluated to a pointer to the function. + always succeeded because it evaluated to a pointer to the function. smartd: closed open file descriptors if device does not support smart. Note: this still needs to be fixed for SCSI devices diff -Nru smartmontools-7.1/ChangeLog-6.0-7.0 smartmontools-7.3/ChangeLog-6.0-7.0 --- smartmontools-7.1/ChangeLog-6.0-7.0 2018-12-30 18:44:58.000000000 +0000 +++ smartmontools-7.3/ChangeLog-6.0-7.0 2022-02-26 00:15:22.000000000 +0000 @@ -1,4 +1,4 @@ -$Id: ChangeLog-6.0-7.0 4885 2018-12-30 18:44:58Z chrfranke $ +$Id: ChangeLog-6.0-7.0 5333 2022-02-26 00:15:22Z dpgilbert $ 2018-12-30 Christian Franke @@ -1649,7 +1649,7 @@ nvmeprint.cpp, nvmeprint.h, smartctl.cpp, smartctl.8.in: Add NVMe support for 'smartctl -c'. Print various drive and - namespace capabilites. Remove related info from '-i' output. + namespace capabilities. Remove related info from '-i' output. 2016-04-24 Christian Franke @@ -1980,7 +1980,7 @@ 2016-01-25 Alex Samorukov - os_darwin: add launchctl script for the smartd and remove depricated one. + os_darwin: add launchctl script for the smartd and remove deprecated one. "On current systems there is only one recommend way: launchd" 2016-01-24 Alex Samorukov @@ -2713,7 +2713,7 @@ 2014-10-06 Alex Samorukov - drivedb.h: Exteneded regexp for SanDisk X300s (#463) + drivedb.h: Extended regexp for SanDisk X300s (#463) 2014-09-29 Alex Samorukov @@ -3466,7 +3466,7 @@ scsicmds.h, scsicmds.cpp, scsiprint.h, scsiprint.cpp: - for SCSI disks, in 'smartctl --info' report physical - block size and lowest LBA alignement (if PB size + block size and lowest LBA alignment (if PB size different from LB size); logical block provisioning status (if any); and disk protection (a.k.a. DIF) type @@ -3711,8 +3711,8 @@ 2012-11-22 Alex Samorukov - smartctl: implemeted support for -g/-s rcache and -g/-s wcache for SCSI - devices to control read/write device cache. + smartctl: implemented support for -g/-s rcache and -g/-s wcache for + SCSI devices to control read/write device cache. 2012-11-19 Alex Samorukov diff -Nru smartmontools-7.1/compile smartmontools-7.3/compile --- smartmontools-7.1/compile 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/compile 2022-02-28 16:34:37.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -53,7 +53,7 @@ MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -67,7 +67,7 @@ mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) diff -Nru smartmontools-7.1/config.guess smartmontools-7.3/config.guess --- smartmontools-7.1/config.guess 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/config.guess 2022-02-28 16:34:37.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2019 Free Software Foundation, Inc. +# Copyright 1992-2020 Free Software Foundation, Inc. -timestamp='2019-04-28' +timestamp='2020-04-26' # 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 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2019 Free Software Foundation, Inc. +Copyright 1992-2020 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." @@ -99,6 +99,8 @@ trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || @@ -262,6 +264,9 @@ *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; @@ -271,12 +276,15 @@ *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -918,7 +926,7 @@ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -1325,38 +1333,39 @@ echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build 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 - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc 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 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; @@ -1620,6 +1629,12 @@ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess and https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +EOF + +year=`echo $timestamp | sed 's,-.*,,'` +# shellcheck disable=SC2003 +if test "`expr "\`date +%Y\`" - "$year"`" -lt 3 ; then + cat >&2 < header file. */ #undef HAVE_CAP_NG_H -/* Define to 1 if you have the `clock_gettime' function. */ -#undef HAVE_CLOCK_GETTIME - -/* Define to 1 if you have the header file. */ -#undef HAVE_DDK_NTDDDISK_H - /* Define to 1 if you have the header file. */ #undef HAVE_DEV_ATA_ATAVAR_H /* Define to 1 if you have the header file. */ #undef HAVE_DEV_CISS_CISSIO_H -/* Define to 1 if you have the `ftime' function. */ -#undef HAVE_FTIME - /* Define to 1 if you have the `getopt_long' function. */ #undef HAVE_GETOPT_LONG -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -67,11 +55,8 @@ than `double'. */ #undef HAVE_LONG_DOUBLE_WIDER -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NTDDDISK_H +/* Define to 1 if the OS provides a POSIX API */ +#undef HAVE_POSIX_API /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP @@ -88,6 +73,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H @@ -121,9 +109,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define to 1 if the `snprintf' function is sane. */ -#undef HAVE_WORKING_SNPRINTF - /* Define to 1 if the system has the type `__int128'. */ #undef HAVE___INT128 @@ -172,7 +157,9 @@ /* smartmontools Release Time */ #undef SMARTMONTOOLS_RELEASE_TIME -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Version number of package */ diff -Nru smartmontools-7.1/config.sub smartmontools-7.3/config.sub --- smartmontools-7.1/config.sub 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/config.sub 2022-02-28 16:34:37.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2019 Free Software Foundation, Inc. +# Copyright 1992-2020 Free Software Foundation, Inc. -timestamp='2019-01-05' +timestamp='2020-05-04' # 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 @@ -67,7 +67,7 @@ version="\ GNU config.sub ($timestamp) -Copyright 1992-2019 Free Software Foundation, Inc. +Copyright 1992-2020 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." @@ -337,17 +337,14 @@ basic_machine=m88k-harris os=sysv3 ;; - hp300) + hp300 | hp300hpux) basic_machine=m68k-hp + os=hpux ;; hp300bsd) basic_machine=m68k-hp os=bsd ;; - hp300hpux) - basic_machine=m68k-hp - os=hpux - ;; hppaosf) basic_machine=hppa1.1-hp os=osf @@ -360,10 +357,6 @@ basic_machine=i386-mach os=mach ;; - vsta) - basic_machine=i386-pc - os=vsta - ;; isi68 | isi) basic_machine=m68k-isi os=sysv @@ -612,6 +605,10 @@ basic_machine=vax-dec os=vms ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; vxworks960) basic_machine=i960-wrs os=vxworks @@ -1172,7 +1169,7 @@ | asmjs \ | ba \ | be32 | be64 \ - | bfin | bs2000 \ + | bfin | bpf | bs2000 \ | c[123]* | c30 | [cjt]90 | c4x \ | c8051 | clipper | craynv | csky | cydra \ | d10v | d30v | dlx | dsp16xx \ @@ -1346,11 +1343,11 @@ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ | sym* | kopensolaris* | plan9* \ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ - | aos* | aros* | cloudabi* | sortix* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | knetbsd* | mirbsd* | netbsd* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ @@ -1368,7 +1365,8 @@ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ | skyos* | haiku* | rdos* | toppers* | drops* | es* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ - | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi*) + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode*) # Remember, each alternative MUST END IN *, to match a version number. ;; qnx*) @@ -1452,9 +1450,6 @@ ns2) os=nextstep2 ;; - nsk*) - os=nsk - ;; # Preserve the version number of sinix5. sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` diff -Nru smartmontools-7.1/configure smartmontools-7.3/configure --- smartmontools-7.1/configure 2019-12-30 15:01:08.000000000 +0000 +++ smartmontools-7.3/configure 2022-02-28 16:34:39.000000000 +0000 @@ -1,11 +1,12 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for smartmontools 7.1. +# Generated by GNU Autoconf 2.71 for smartmontools 7.3. # # Report bugs to . # # -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, +# Inc. # # # This configure script is free software; the Free Software Foundation @@ -16,14 +17,16 @@ # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST -else +else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( @@ -33,46 +36,46 @@ fi + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then +if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || @@ -81,13 +84,6 @@ fi -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( @@ -96,8 +92,12 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS @@ -109,30 +109,10 @@ as_myself=$0 fi if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. @@ -154,20 +134,22 @@ exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + as_bourne_compatible="as_nop=: +if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST -else +else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( @@ -187,42 +169,52 @@ as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : +if ( set x; as_fn_ret_success y && test x = \"\$1\" ) +then : -else +else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 +blah=\$(echo \$(echo blah)) +test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + if (eval "$as_required") 2>/dev/null +then : as_have_required=yes -else +else $as_nop as_have_required=no fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null +then : -else +else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base + as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null +then : break 2 fi fi @@ -230,14 +222,21 @@ esac as_found=false done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi +fi - if test "x$CONFIG_SHELL" != x; then : + if test "x$CONFIG_SHELL" != x +then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also @@ -255,18 +254,19 @@ exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." + if test x$as_have_required = xno +then : + printf "%s\n" "$0: This script requires a shell more modern than all" + printf "%s\n" "$0: the shells that I found on your system." + if test ${ZSH_VERSION+y} ; then + printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" + printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else - $as_echo "$0: Please tell bug-autoconf@gnu.org and + printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: smartmontools-support@listi.jpberlin.de about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run @@ -294,6 +294,7 @@ } as_unset=as_fn_unset + # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. @@ -311,6 +312,14 @@ as_fn_set_status $1 exit $1 } # as_fn_exit +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop # as_fn_mkdir_p # ------------- @@ -325,7 +334,7 @@ as_dirs= while :; do case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" @@ -334,7 +343,7 @@ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | +printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -373,12 +382,13 @@ # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : eval 'as_fn_append () { eval $1+=\$2 }' -else +else $as_nop as_fn_append () { eval $1=\$$1\$2 @@ -390,18 +400,27 @@ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : eval 'as_fn_arith () { as_val=$(( $* )) }' -else +else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- @@ -413,9 +432,9 @@ as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $2" >&2 + printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -442,7 +461,7 @@ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | +printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -486,7 +505,7 @@ s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall @@ -500,6 +519,10 @@ exit } + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) @@ -513,6 +536,13 @@ ECHO_N='-n';; esac +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + + rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file @@ -580,48 +610,44 @@ # Identity of this package. PACKAGE_NAME='smartmontools' PACKAGE_TARNAME='smartmontools' -PACKAGE_VERSION='7.1' -PACKAGE_STRING='smartmontools 7.1' +PACKAGE_VERSION='7.3' +PACKAGE_STRING='smartmontools 7.3' PACKAGE_BUGREPORT='smartmontools-support@listi.jpberlin.de' PACKAGE_URL='' ac_unique_file="smartctl.cpp" # Factoring default headers for most tests. ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include +#include +#ifdef HAVE_STDIO_H +# include #endif -#ifdef STDC_HEADERS +#ifdef HAVE_STDLIB_H # include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif #endif #ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif # include #endif -#ifdef HAVE_STRINGS_H -# include -#endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif #ifdef HAVE_UNISTD_H # include #endif" +ac_header_cxx_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS @@ -638,6 +664,8 @@ OS_SOLARIS_TRUE OS_DARWIN_FALSE OS_DARWIN_TRUE +OS_POSIX_FALSE +OS_POSIX_TRUE DRIVEDB_BRANCH os_win32_manifest os_man_filter @@ -681,6 +709,7 @@ ENABLE_DRIVEDB_FALSE ENABLE_DRIVEDB_TRUE drivedbdir +drivedbinstdir exampledir initdfile INSTALL_INITSCRIPT_FALSE @@ -690,9 +719,6 @@ gcc_have_attr_packed NEED_GETOPT_LONG_FALSE NEED_GETOPT_LONG_TRUE -EGREP -GREP -CXXCPP IS_SVN_BUILD_FALSE IS_SVN_BUILD_TRUE svn_deps @@ -745,6 +771,9 @@ AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V +CSCOPE +ETAGS +CTAGS am__untar am__tar AMTAR @@ -816,6 +845,7 @@ enable_dependency_tracking with_initscriptdir with_exampledir +with_drivedbinstdir with_drivedbdir with_update_smart_drivedb with_gnupg @@ -836,7 +866,6 @@ with_nvme_devicescan with_solaris_sparc_ata with_signal_func -with_working_snprintf with_mingw_aslr with_cxx11_option with_cxx11_regex @@ -860,8 +889,7 @@ NM WINDMC WINDRES -MAKENSIS -CXXCPP' +MAKENSIS' # Initialize some variables set by options. @@ -930,8 +958,6 @@ *) ac_optarg=yes ;; esac - # Accept the important Cygnus configure options, so we can diagnose typos. - case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; @@ -972,9 +998,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" @@ -998,9 +1024,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" @@ -1211,9 +1237,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" @@ -1227,9 +1253,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" @@ -1273,9 +1299,9 @@ *) # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; @@ -1291,7 +1317,7 @@ case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1355,7 +1381,7 @@ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | +printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -1412,7 +1438,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 smartmontools 7.1 to adapt to many kinds of systems. +\`configure' configures smartmontools 7.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1483,7 +1509,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of smartmontools 7.1:";; + short | recursive ) echo "Configuration of smartmontools 7.3:";; esac cat <<\_ACEOF @@ -1511,9 +1537,13 @@ --with-initscriptdir=[DIR|no] Location of init scripts [no] --with-exampledir=DIR Location of example scripts [DOCDIR/examplescripts] + --with-drivedbinstdir[=DIR|yes|no] + Optional separate install location of drive database + file [no] (yes=DATADIR/smartmontools) --with-drivedbdir[=DIR|yes|no] Location of drive database file - [DATADIR/smartmontools] + [DATADIR/smartmontools or + LOCALSTATEDIR/lib/smartmontools if separate INSTDIR] --with-update-smart-drivedb[=yes|no|X.Y] Install update-smart-drivedb script (and backport it to branches/RELEASE_X_Y_DRIVEDB) [yes] @@ -1552,15 +1582,11 @@ os_solaris_ata.s from SVN repository) [no] --with-signal-func=[sigaction|sigset|signal] Function to set signal(2) action [sigaction] - --with-working-snprintf[=yes|no] - Function snprintf() handles output truncation as - specified by C99 [yes] --with-mingw-aslr[=auto|yes|low|no] Enable ASLR for MinGW executables [auto] --with-cxx11-option=[OPTION|auto|no] - Compiler option to enable C++11 support for future - versions of smartmontools, 'no' if unsupported - [auto] + Compiler option to enable C++11 support, 'no' to + skip check [auto] --with-cxx11-regex[=yes|no] Use C++11 std::regex instead of POSIX regex(3) [no] @@ -1585,7 +1611,6 @@ WINDMC Windows message compiler command WINDRES Windows resource compiler command MAKENSIS NSIS compiler command - CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1606,9 +1631,9 @@ case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -1636,7 +1661,8 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. + # Check for configure.gnu first; this name is used for a wrapper for + # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive @@ -1644,7 +1670,7 @@ echo && $SHELL "$ac_srcdir/configure" --help=recursive else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done @@ -1653,10 +1679,10 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -smartmontools configure 7.1 -generated by GNU Autoconf 2.69 +smartmontools configure 7.3 +generated by GNU Autoconf 2.71 -Copyright (C) 2012 Free Software Foundation, Inc. +Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1673,14 +1699,14 @@ ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext + rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1688,14 +1714,15 @@ cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err - } && test -s conftest.$ac_objext; then : + } && test -s conftest.$ac_objext +then : ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1711,14 +1738,14 @@ ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext + rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1726,14 +1753,15 @@ cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err - } && test -s conftest.$ac_objext; then : + } && test -s conftest.$ac_objext +then : ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1743,206 +1771,85 @@ } # ac_fn_c_try_compile -# ac_fn_cxx_try_cpp LINENO -# ------------------------ -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_cpp - -# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES # --------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_cxx_check_header_mongrel () +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval \${$3+:} false; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no +if ac_fn_cxx_try_compile "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ------------------------------------------------------ ## -## Report this to smartmontools-support@listi.jpberlin.de ## -## ------------------------------------------------------ ##" - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_cxx_check_header_mongrel +} # ac_fn_cxx_check_header_compile -# ac_fn_cxx_try_run LINENO -# ------------------------ -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_cxx_try_run () +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + } +then : ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_retval=$ac_status + ac_retval=1 fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval -} # ac_fn_cxx_try_run - -# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES -# --------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_cxx_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_cxx_check_header_compile +} # ac_fn_cxx_try_link # ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES # --------------------------------------------- @@ -1951,17 +1858,18 @@ ac_fn_cxx_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main () +main (void) { if (sizeof ($2)) return 0; @@ -1969,12 +1877,13 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main () +main (void) { if (sizeof (($2))) return 0; @@ -1982,79 +1891,35 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : -else +else $as_nop eval "$3=yes" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_type -# ac_fn_cxx_try_link LINENO -# ------------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_link - # ac_fn_cxx_check_func LINENO FUNC VAR # ------------------------------------ # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_cxx_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. @@ -2062,16 +1927,9 @@ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif + which can conflict with char $2 (); below. */ +#include #undef $2 /* Override any GCC internal prototype to avoid an error. @@ -2089,49 +1947,113 @@ #endif int -main () +main (void) { return $2 (); ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : eval "$3=yes" -else +else $as_nop eval "$3=no" fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_func -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by smartmontools $as_me 7.1, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ -_ACEOF -exec 5>>config.log +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that +# executables *can* be run. +ac_fn_cxx_try_run () { -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: program exited with status $ac_status" >&5 + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run +ac_configure_args_raw= +for ac_arg +do + case $ac_arg in + *\'*) + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_configure_args_raw " '$ac_arg'" +done + +case $ac_configure_args_raw in + *$as_nl*) + ac_safe_unquote= ;; + *) + ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. + ac_unsafe_a="$ac_unsafe_z#~" + ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" + ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; +esac + +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 smartmontools $as_me 7.3, which was +generated by GNU Autoconf 2.71. Invocation command line was + + $ $0$ac_configure_args_raw + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` @@ -2150,8 +2072,12 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS @@ -2186,7 +2112,7 @@ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; @@ -2221,11 +2147,13 @@ # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? + # Sanitize IFS. + IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo - $as_echo "## ---------------- ## + printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo @@ -2236,8 +2164,8 @@ case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -2261,7 +2189,7 @@ ) echo - $as_echo "## ----------------- ## + printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo @@ -2269,14 +2197,14 @@ do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - $as_echo "$ac_var='\''$ac_val'\''" + printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo @@ -2284,15 +2212,15 @@ do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - $as_echo "$ac_var='\''$ac_val'\''" + printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then - $as_echo "## ----------- ## + printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo @@ -2300,8 +2228,8 @@ echo fi test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" + printf "%s\n" "$as_me: caught signal $ac_signal" + printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && @@ -2315,63 +2243,48 @@ # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h -$as_echo "/* confdefs.h */" > confdefs.h +printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF +printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF +printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF +printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF +printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF +printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF +printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site + ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site + ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" + +for ac_site_file in $ac_site_files do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} + case $ac_site_file in #( + */*) : + ;; #( + *) : + ac_site_file=./$ac_site_file ;; +esac + if test -f "$ac_site_file" && test -r "$ac_site_file"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi @@ -2381,19 +2294,650 @@ # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi +# Test code for whether the C++ compiler supports C++98 (global declarations) +ac_cxx_conftest_cxx98_globals=' +// Does the compiler advertise C++98 conformance? +#if !defined __cplusplus || __cplusplus < 199711L +# error "Compiler does not advertise C++98 conformance" +#endif + +// These inclusions are to reject old compilers that +// lack the unsuffixed header files. +#include +#include + +// and are *not* freestanding headers in C++98. +extern void assert (int); +namespace std { + extern int strcmp (const char *, const char *); +} + +// Namespaces, exceptions, and templates were all added after "C++ 2.0". +using std::exception; +using std::strcmp; + +namespace { + +void test_exception_syntax() +{ + try { + throw "test"; + } catch (const char *s) { + // Extra parentheses suppress a warning when building autoconf itself, + // due to lint rules shared with more typical C programs. + assert (!(strcmp) (s, "test")); + } +} + +template struct test_template +{ + T const val; + explicit test_template(T t) : val(t) {} + template T add(U u) { return static_cast(u) + val; } +}; + +} // anonymous namespace +' + +# Test code for whether the C++ compiler supports C++98 (body of main) +ac_cxx_conftest_cxx98_main=' + assert (argc); + assert (! argv[0]); +{ + test_exception_syntax (); + test_template tt (2.0); + assert (tt.add (4) == 6.0); + assert (true && !false); +} +' + +# Test code for whether the C++ compiler supports C++11 (global declarations) +ac_cxx_conftest_cxx11_globals=' +// Does the compiler advertise C++ 2011 conformance? +#if !defined __cplusplus || __cplusplus < 201103L +# error "Compiler does not advertise C++11 conformance" +#endif + +namespace cxx11test +{ + constexpr int get_val() { return 20; } + + struct testinit + { + int i; + double d; + }; + + class delegate + { + public: + delegate(int n) : n(n) {} + delegate(): delegate(2354) {} + + virtual int getval() { return this->n; }; + protected: + int n; + }; + + class overridden : public delegate + { + public: + overridden(int n): delegate(n) {} + virtual int getval() override final { return this->n * 2; } + }; + + class nocopy + { + public: + nocopy(int i): i(i) {} + nocopy() = default; + nocopy(const nocopy&) = delete; + nocopy & operator=(const nocopy&) = delete; + private: + int i; + }; + + // for testing lambda expressions + template Ret eval(Fn f, Ret v) + { + return f(v); + } + + // for testing variadic templates and trailing return types + template auto sum(V first) -> V + { + return first; + } + template auto sum(V first, Args... rest) -> V + { + return first + sum(rest...); + } +} +' + +# Test code for whether the C++ compiler supports C++11 (body of main) +ac_cxx_conftest_cxx11_main=' +{ + // Test auto and decltype + auto a1 = 6538; + auto a2 = 48573953.4; + auto a3 = "String literal"; + + int total = 0; + for (auto i = a3; *i; ++i) { total += *i; } + + decltype(a2) a4 = 34895.034; +} +{ + // Test constexpr + short sa[cxx11test::get_val()] = { 0 }; +} +{ + // Test initializer lists + cxx11test::testinit il = { 4323, 435234.23544 }; +} +{ + // Test range-based for + int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, + 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + for (auto &x : array) { x += 23; } +} +{ + // Test lambda expressions + using cxx11test::eval; + assert (eval ([](int x) { return x*2; }, 21) == 42); + double d = 2.0; + assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); + assert (d == 5.0); + assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); + assert (d == 5.0); +} +{ + // Test use of variadic templates + using cxx11test::sum; + auto a = sum(1); + auto b = sum(1, 2); + auto c = sum(1.0, 2.0, 3.0); +} +{ + // Test constructor delegation + cxx11test::delegate d1; + cxx11test::delegate d2(); + cxx11test::delegate d3(45); +} +{ + // Test override and final + cxx11test::overridden o1(55464); +} +{ + // Test nullptr + char *c = nullptr; +} +{ + // Test template brackets + test_template<::test_template> v(test_template(12)); +} +{ + // Unicode literals + char const *utf8 = u8"UTF-8 string \u2500"; + char16_t const *utf16 = u"UTF-8 string \u2500"; + char32_t const *utf32 = U"UTF-32 string \u2500"; +} +' + +# Test code for whether the C compiler supports C++11 (complete). +ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} +${ac_cxx_conftest_cxx11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + ${ac_cxx_conftest_cxx11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C++98 (complete). +ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + return ok; +} +" + +# Test code for whether the C compiler supports C89 (global declarations) +ac_c_conftest_c89_globals=' +/* Does the compiler advertise C89 conformance? + Do not test the value of __STDC__, because some compilers set it to 0 + while being otherwise adequately conformant. */ +#if !defined __STDC__ +# error "Compiler does not advertise C89 conformance" +#endif + +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ +struct buf { int x; }; +struct buf * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not \xHH hex character constants. + These do not provoke an error unfortunately, instead are silently treated + as an "x". The following induces an error, until -std is added to get + proper ANSI mode. Curiously \x00 != x always comes out true, for an + array size at least. It is necessary to write \x00 == 0 to get something + that is true only with -std. */ +int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) '\''x'\'' +int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), + int, int);' + +# Test code for whether the C compiler supports C89 (body of main). +ac_c_conftest_c89_main=' +ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); +' + +# Test code for whether the C compiler supports C99 (global declarations) +ac_c_conftest_c99_globals=' +// Does the compiler advertise C99 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +# error "Compiler does not advertise C99 conformance" +#endif + +#include +extern int puts (const char *); +extern int printf (const char *, ...); +extern int dprintf (int, const char *, ...); +extern void *malloc (size_t); + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +// dprintf is used instead of fprintf to avoid needing to declare +// FILE and stderr. +#define debug(...) dprintf (2, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + #error "your preprocessor is broken" +#endif +#if BIG_OK +#else + #error "your preprocessor is broken" +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static bool +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str = ""; + int number = 0; + float fnumber = 0; + + while (*format) + { + switch (*format++) + { + case '\''s'\'': // string + str = va_arg (args_copy, const char *); + break; + case '\''d'\'': // int + number = va_arg (args_copy, int); + break; + case '\''f'\'': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); + + return *str && number && fnumber; +} +' + +# Test code for whether the C compiler supports C99 (body of main). +ac_c_conftest_c99_main=' + // Check bool. + _Bool success = false; + success |= (argc != 0); + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[0] = argv[0][0]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' + || dynamic_array[ni.number - 1] != 543); +' + +# Test code for whether the C compiler supports C11 (global declarations) +ac_c_conftest_c11_globals=' +// Does the compiler advertise C11 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L +# error "Compiler does not advertise C11 conformance" +#endif + +// Check _Alignas. +char _Alignas (double) aligned_as_double; +char _Alignas (0) no_special_alignment; +extern char aligned_as_int; +char _Alignas (0) _Alignas (int) aligned_as_int; + +// Check _Alignof. +enum +{ + int_alignment = _Alignof (int), + int_array_alignment = _Alignof (int[100]), + char_alignment = _Alignof (char) +}; +_Static_assert (0 < -_Alignof (int), "_Alignof is signed"); + +// Check _Noreturn. +int _Noreturn does_not_return (void) { for (;;) continue; } + +// Check _Static_assert. +struct test_static_assert +{ + int x; + _Static_assert (sizeof (int) <= sizeof (long int), + "_Static_assert does not work in struct"); + long int y; +}; + +// Check UTF-8 literals. +#define u8 syntax error! +char const utf8_literal[] = u8"happens to be ASCII" "another string"; + +// Check duplicate typedefs. +typedef long *long_ptr; +typedef long int *long_ptr; +typedef long_ptr long_ptr; + +// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. +struct anonymous +{ + union { + struct { int i; int j; }; + struct { int k; long int l; } w; + }; + int m; +} v1; +' + +# Test code for whether the C compiler supports C11 (body of main). +ac_c_conftest_c11_main=' + _Static_assert ((offsetof (struct anonymous, i) + == offsetof (struct anonymous, w.k)), + "Anonymous union alignment botch"); + v1.i = 2; + v1.w.k = 5; + ok |= v1.i != 5; +' + +# Test code for whether the C compiler supports C11 (complete). +ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} +${ac_c_conftest_c11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + ${ac_c_conftest_c11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C99 (complete). +ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + return ok; +} +" + +# Test code for whether the C compiler supports C89 (complete). +ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + return ok; +} +" + +as_fn_append ac_header_cxx_list " stdio.h stdio_h HAVE_STDIO_H" +as_fn_append ac_header_cxx_list " stdlib.h stdlib_h HAVE_STDLIB_H" +as_fn_append ac_header_cxx_list " string.h string_h HAVE_STRING_H" +as_fn_append ac_header_cxx_list " inttypes.h inttypes_h HAVE_INTTYPES_H" +as_fn_append ac_header_cxx_list " stdint.h stdint_h HAVE_STDINT_H" +as_fn_append ac_header_cxx_list " strings.h strings_h HAVE_STRINGS_H" +as_fn_append ac_header_cxx_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" +as_fn_append ac_header_cxx_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" +as_fn_append ac_header_cxx_list " unistd.h unistd_h HAVE_UNISTD_H" + +# Auxiliary files required by this configure script. +ac_aux_files="config.guess config.sub compile missing install-sh" + +# Locations in which to look for auxiliary files. +ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." + +# Search for a directory containing all of the required auxiliary files, +# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. +# If we don't find one directory that contains all the files we need, +# we report the set of missing files from the *first* directory in +# $ac_aux_dir_candidates and give up. +ac_missing_aux_files="" +ac_first_candidate=: +printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in $ac_aux_dir_candidates +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + as_found=: + + printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 + ac_aux_dir_found=yes + ac_install_sh= + for ac_aux in $ac_aux_files + do + # As a special case, if "install-sh" is required, that requirement + # can be satisfied by any of "install-sh", "install.sh", or "shtool", + # and $ac_install_sh is set appropriately for whichever one is found. + if test x"$ac_aux" = x"install-sh" + then + if test -f "${as_dir}install-sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 + ac_install_sh="${as_dir}install-sh -c" + elif test -f "${as_dir}install.sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 + ac_install_sh="${as_dir}install.sh -c" + elif test -f "${as_dir}shtool"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 + ac_install_sh="${as_dir}shtool install -c" + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} install-sh" + else + break + fi + fi + else + if test -f "${as_dir}${ac_aux}"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" + else + break + fi + fi + fi + done + if test "$ac_aux_dir_found" = yes; then + ac_aux_dir="$as_dir" + break + fi + ac_first_candidate=false + + as_found=false +done +IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 +fi + + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +if test -f "${ac_aux_dir}config.guess"; then + ac_config_guess="$SHELL ${ac_aux_dir}config.guess" +fi +if test -f "${ac_aux_dir}config.sub"; then + ac_config_sub="$SHELL ${ac_aux_dir}config.sub" +fi +if test -f "$ac_aux_dir/configure"; then + ac_configure="$SHELL ${ac_aux_dir}configure" +fi + # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -2404,12 +2948,12 @@ eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) @@ -2418,24 +2962,24 @@ ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in @@ -2445,11 +2989,12 @@ fi done if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' + and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -2464,36 +3009,9 @@ am__api_version='1.16' -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -# Find a good install program. We prefer a C program (faster), + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install @@ -2507,20 +3025,25 @@ # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else +if test ${ac_cv_path_install+y} +then : + printf %s "(cached) " >&6 +else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + # Account for fact that we put trailing slashes in our PATH walk. +case $as_dir in #(( + ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; @@ -2530,13 +3053,13 @@ # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else @@ -2544,12 +3067,12 @@ echo one > conftest.one echo two > conftest.two mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi @@ -2565,7 +3088,7 @@ rm -rf conftest.one conftest.two conftest.dir fi - if test "${ac_cv_path_install+set}" = set; then + if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a @@ -2575,8 +3098,8 @@ INSTALL=$ac_install_sh fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. @@ -2586,8 +3109,8 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' @@ -2641,8 +3164,8 @@ as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= @@ -2661,26 +3184,23 @@ # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` +program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` + # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac + + if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then @@ -2700,11 +3220,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else @@ -2712,11 +3233,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2727,11 +3252,11 @@ fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +printf "%s\n" "$STRIP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -2740,11 +3265,12 @@ ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else @@ -2752,11 +3278,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2767,11 +3297,11 @@ fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +printf "%s\n" "$ac_ct_STRIP" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then @@ -2779,8 +3309,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP @@ -2792,25 +3322,31 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 +printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else + if test ${ac_cv_path_mkdir+y} +then : + printf %s "(cached) " >&6 +else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ + as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue + case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir ('*'coreutils) '* | \ + 'BusyBox '* | \ 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done @@ -2821,7 +3357,7 @@ fi test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then + if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a @@ -2831,18 +3367,19 @@ MKDIR_P="$ac_install_sh -d" fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AWK+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else @@ -2850,11 +3387,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -2865,24 +3406,25 @@ fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +printf "%s\n" "$AWK" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else +ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval test \${ac_cv_prog_make_${ac_make}_set+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @@ -2898,12 +3440,12 @@ rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } SET_MAKE= else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi @@ -2917,7 +3459,8 @@ rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : +if test ${enable_silent_rules+y} +then : enableval=$enable_silent_rules; fi @@ -2927,12 +3470,13 @@ *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +printf %s "checking whether $am_make supports nested variables... " >&6; } +if test ${am_cv_make_support_nested_variables+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 @@ -2944,8 +3488,8 @@ am_cv_make_support_nested_variables=no fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' @@ -2977,17 +3521,13 @@ # Define the identity of the package. PACKAGE='smartmontools' - VERSION='7.1' + VERSION='7.3' -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF +printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF +printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. @@ -3027,6 +3567,20 @@ +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi + +if test -z "$ETAGS"; then + ETAGS=etags +fi + +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi + + # 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 @@ -3072,36 +3626,26 @@ # Version of drive database branch -smartmontools_drivedb_version=7.0 +smartmontools_drivedb_version=7.3 -smartmontools_cvs_tag=`echo '$Id: configure.ac 5022 2019-12-30 15:00:49Z chrfranke $'` -smartmontools_release_date=2019-12-30 -smartmontools_release_time="15:00:11 UTC" +smartmontools_cvs_tag=`echo '$Id: configure.ac 5338 2022-02-28 16:34:26Z chrfranke $'` +smartmontools_release_date=2022-02-28 +smartmontools_release_time="16:33:40 UTC" -cat >>confdefs.h <<_ACEOF -#define SMARTMONTOOLS_CONFIGURE_ARGS "$ac_configure_args" -_ACEOF +printf "%s\n" "#define SMARTMONTOOLS_CONFIGURE_ARGS \"$ac_configure_args\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define SMARTMONTOOLS_RELEASE_DATE "$smartmontools_release_date" -_ACEOF +printf "%s\n" "#define SMARTMONTOOLS_RELEASE_DATE \"$smartmontools_release_date\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define SMARTMONTOOLS_RELEASE_TIME "$smartmontools_release_time" -_ACEOF +printf "%s\n" "#define SMARTMONTOOLS_RELEASE_TIME \"$smartmontools_release_time\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define CONFIG_H_CVSID "$smartmontools_cvs_tag" -_ACEOF +printf "%s\n" "#define CONFIG_H_CVSID \"$smartmontools_cvs_tag\"" >>confdefs.h -cat >>confdefs.h <<_ACEOF -#define PACKAGE_HOMEPAGE "https://www.smartmontools.org/" -_ACEOF +printf "%s\n" "#define PACKAGE_HOMEPAGE \"https://www.smartmontools.org/\"" >>confdefs.h @@ -3109,17 +3653,18 @@ -{ $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; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +printf %s "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. -if test "${enable_maintainer_mode+set}" = set; then : +if test ${enable_maintainer_mode+y} +then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval -else +else $as_nop USE_MAINTAINER_MODE=no fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 -$as_echo "$USE_MAINTAINER_MODE" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +printf "%s\n" "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' @@ -3138,6 +3683,12 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + + + ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3148,15 +3699,16 @@ CXX=$CCC else if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else @@ -3164,11 +3716,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3179,11 +3735,11 @@ fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +printf "%s\n" "$CXX" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3192,15 +3748,16 @@ fi if test -z "$CXX"; then ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else @@ -3208,11 +3765,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3223,11 +3784,11 @@ fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +printf "%s\n" "$ac_ct_CXX" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3239,8 +3800,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX @@ -3250,7 +3811,7 @@ fi fi # Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do @@ -3260,7 +3821,7 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -3270,7 +3831,7 @@ cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done @@ -3278,7 +3839,7 @@ /* end confdefs.h. */ int -main () +main (void) { ; @@ -3290,9 +3851,9 @@ # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 -$as_echo_n "checking whether the C++ compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +printf %s "checking whether the C++ compiler works... " >&6; } +ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" @@ -3313,11 +3874,12 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, @@ -3334,7 +3896,7 @@ # certainly right. break;; *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi @@ -3350,44 +3912,46 @@ done test "$ac_cv_exeext" = no && ac_cv_exeext= -else +else $as_nop ac_file='' fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 +if test -z "$ac_file" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C++ compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 -$as_echo_n "checking for C++ compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +printf %s "checking for C++ compiler default output file name... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with @@ -3401,15 +3965,15 @@ * ) break;; esac done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext @@ -3418,7 +3982,7 @@ /* end confdefs.h. */ #include int -main () +main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; @@ -3430,8 +3994,8 @@ ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in @@ -3439,10 +4003,10 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in @@ -3450,39 +4014,40 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C++ compiled programs. + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +printf %s "checking for suffix of object files... " >&6; } +if test ${ac_cv_objext+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; @@ -3496,11 +4061,12 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in @@ -3509,31 +4075,32 @@ break;; esac done -else - $as_echo "$as_me: failed program was:" >&5 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 +printf %s "checking whether the compiler supports GNU C++... " >&6; } +if test ${ac_cv_cxx_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { #ifndef __GNUC__ choke me @@ -3543,29 +4110,33 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : ac_compiler_gnu=yes -else +else $as_nop ac_compiler_gnu=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi -ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +printf %s "checking whether $CXX accepts -g... " >&6; } +if test ${ac_cv_prog_cxx_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no @@ -3574,57 +4145,60 @@ /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : ac_cv_prog_cxx_g=yes -else +else $as_nop CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : -else +else $as_nop ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : ac_cv_prog_cxx_g=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } +if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then @@ -3639,6 +4213,100 @@ CXXFLAGS= fi fi +ac_prog_cxx_stdcxx=no +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 +printf %s "checking for $CXX option to enable C++11 features... " >&6; } +if test ${ac_cv_prog_cxx_11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_11=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx11_program +_ACEOF +for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx11" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx11" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 + ac_prog_cxx_stdcxx=cxx11 +fi +fi +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 +printf %s "checking for $CXX option to enable C++98 features... " >&6; } +if test ${ac_cv_prog_cxx_98+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_98=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx98_program +_ACEOF +for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx98=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx98" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx98" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx98" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx98" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 + ac_prog_cxx_stdcxx=cxx98 +fi +fi + ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3648,8 +4316,8 @@ ac_config_commands="$ac_config_commands depfiles" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 -$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out @@ -3685,11 +4353,12 @@ fi done rm -f confinc.* confmf.* -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 -$as_echo "${_am_result}" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : +if test ${enable_dependency_tracking+y} +then : enableval=$enable_dependency_tracking; fi @@ -3710,11 +4379,12 @@ depcc="$CXX" am_compiler_list= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CXX_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For @@ -3821,8 +4491,8 @@ fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if @@ -3836,6 +4506,15 @@ fi + + + + + + + + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3844,11 +4523,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3856,11 +4536,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3871,11 +4555,11 @@ fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3884,11 +4568,12 @@ ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -3896,11 +4581,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3911,11 +4600,11 @@ fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then @@ -3923,8 +4612,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -3937,11 +4626,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3949,11 +4639,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3964,11 +4658,11 @@ fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -3977,11 +4671,12 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3990,15 +4685,19 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4014,18 +4713,18 @@ # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -4036,11 +4735,12 @@ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -4048,11 +4748,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4063,11 +4767,11 @@ fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -4080,11 +4784,12 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -4092,11 +4797,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4107,11 +4816,11 @@ fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -4123,8 +4832,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -4132,25 +4841,129 @@ fi fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "clang", so it can be a program name with args. +set dummy clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +fi + + +test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 -for ac_option in --version -v -V -qversion; do +for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 +printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -4160,20 +4973,21 @@ cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 +printf %s "checking whether the compiler supports GNU C... " >&6; } +if test ${ac_cv_c_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { #ifndef __GNUC__ choke me @@ -4183,29 +4997,33 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_compiler_gnu=yes -else +else $as_nop ac_compiler_gnu=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_c_compiler_gnu + if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi -ac_test_CFLAGS=${CFLAGS+set} +ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +printf %s "checking whether $CC accepts -g... " >&6; } +if test ${ac_cv_prog_cc_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no @@ -4214,57 +5032,60 @@ /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_g=yes -else +else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : -else +else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_g=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +printf "%s\n" "$ac_cv_prog_cc_g" >&6; } +if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then @@ -4279,94 +5100,144 @@ CFLAGS= fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else +ac_prog_cc_stdc=no +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 +printf %s "checking for $CC option to enable C11 features... " >&6; } +if test ${ac_cv_prog_cc_c11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c11=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c11_program +_ACEOF +for ac_arg in '' -std=gnu11 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c11" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 +printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } + CC="$CC $ac_cv_prog_cc_c11" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 + ac_prog_cc_stdc=c11 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 +printf %s "checking for $CC option to enable C99 features... " >&6; } +if test ${ac_cv_prog_cc_c99+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c99_program +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c99" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c99" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } + CC="$CC $ac_cv_prog_cc_c99" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 + ac_prog_cc_stdc=c99 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 +printf %s "checking for $CC option to enable C89 features... " >&6; } +if test ${ac_cv_prog_cc_c89+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} +$ac_c_conftest_c89_program _ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : + if ac_fn_c_try_compile "$LINENO" +then : ac_cv_prog_cc_c89=$ac_arg fi -rm -f core conftest.err conftest.$ac_objext +rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC - fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : +if test "x$ac_cv_prog_cc_c89" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c89" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } + CC="$CC $ac_cv_prog_cc_c89" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 + ac_prog_cc_stdc=c89 +fi fi ac_ext=cpp @@ -4375,21 +5246,23 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -ac_ext=c + + 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 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +printf %s "checking whether $CC understands -c and -o together... " >&6; } +if test ${am_cv_prog_cc_c_o+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; @@ -4417,8 +5290,8 @@ 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; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +printf "%s\n" "$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. @@ -4436,11 +5309,12 @@ depcc="$CC" am_compiler_list= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CC_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For @@ -4547,8 +5421,8 @@ fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if @@ -4571,11 +5445,12 @@ depcc="$CCAS" am_compiler_list= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CCAS_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CCAS_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For @@ -4680,8 +5555,8 @@ fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CCAS_dependencies_compiler_type" >&6; } CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type if @@ -4710,11 +5585,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. @@ -4724,11 +5600,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4740,11 +5620,11 @@ fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +printf "%s\n" "$PKG_CONFIG" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -4753,11 +5633,12 @@ ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. @@ -4767,11 +5648,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4783,11 +5668,11 @@ fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then @@ -4795,8 +5680,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG @@ -4808,14 +5693,14 @@ fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi @@ -4826,26 +5711,29 @@ -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else + + + # Make sure we can run config.sub. +$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +printf %s "checking build system type... " >&6; } +if test ${ac_cv_build+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` + ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 +ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; @@ -4864,21 +5752,22 @@ case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +printf %s "checking host system type... " >&6; } +if test ${ac_cv_host+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 + ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; @@ -4901,11 +5790,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args. set dummy ${ac_tool_prefix}nm; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_NM+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_NM+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$NM"; then ac_cv_prog_NM="$NM" # Let the user override the test. else @@ -4913,11 +5803,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_NM="${ac_tool_prefix}nm" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4928,11 +5822,11 @@ fi NM=$ac_cv_prog_NM if test -n "$NM"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5 -$as_echo "$NM" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NM" >&5 +printf "%s\n" "$NM" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -4941,11 +5835,12 @@ ac_ct_NM=$NM # Extract the first word of "nm", so it can be a program name with args. set dummy nm; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_NM+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_NM+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_NM"; then ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test. else @@ -4953,11 +5848,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NM="nm" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4968,11 +5867,11 @@ fi ac_ct_NM=$ac_cv_prog_ac_ct_NM if test -n "$ac_ct_NM"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NM" >&5 -$as_echo "$ac_ct_NM" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NM" >&5 +printf "%s\n" "$ac_ct_NM" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_NM" = x; then @@ -4980,8 +5879,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NM=$ac_ct_NM @@ -4995,11 +5894,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windmc", so it can be a program name with args. set dummy ${ac_tool_prefix}windmc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_WINDMC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_WINDMC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$WINDMC"; then ac_cv_prog_WINDMC="$WINDMC" # Let the user override the test. else @@ -5007,11 +5907,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_WINDMC="${ac_tool_prefix}windmc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5022,11 +5926,11 @@ fi WINDMC=$ac_cv_prog_WINDMC if test -n "$WINDMC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDMC" >&5 -$as_echo "$WINDMC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WINDMC" >&5 +printf "%s\n" "$WINDMC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -5035,11 +5939,12 @@ ac_ct_WINDMC=$WINDMC # Extract the first word of "windmc", so it can be a program name with args. set dummy windmc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_WINDMC+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_WINDMC+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_WINDMC"; then ac_cv_prog_ac_ct_WINDMC="$ac_ct_WINDMC" # Let the user override the test. else @@ -5047,11 +5952,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_WINDMC="windmc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5062,11 +5971,11 @@ fi ac_ct_WINDMC=$ac_cv_prog_ac_ct_WINDMC if test -n "$ac_ct_WINDMC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDMC" >&5 -$as_echo "$ac_ct_WINDMC" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDMC" >&5 +printf "%s\n" "$ac_ct_WINDMC" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_WINDMC" = x; then @@ -5074,8 +5983,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac WINDMC=$ac_ct_WINDMC @@ -5087,11 +5996,12 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_WINDRES+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_WINDRES+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$WINDRES"; then ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. else @@ -5099,11 +6009,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_WINDRES="${ac_tool_prefix}windres" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5114,11 +6028,11 @@ fi WINDRES=$ac_cv_prog_WINDRES if test -n "$WINDRES"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 -$as_echo "$WINDRES" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 +printf "%s\n" "$WINDRES" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi @@ -5127,11 +6041,12 @@ ac_ct_WINDRES=$WINDRES # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_WINDRES+:} false; then : - $as_echo_n "(cached) " >&6 -else +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_WINDRES+y} +then : + printf %s "(cached) " >&6 +else $as_nop if test -n "$ac_ct_WINDRES"; then ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test. else @@ -5139,11 +6054,15 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_WINDRES="windres" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5154,11 +6073,11 @@ fi ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES if test -n "$ac_ct_WINDRES"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 -$as_echo "$ac_ct_WINDRES" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 +printf "%s\n" "$ac_ct_WINDRES" >&6; } else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi if test "x$ac_ct_WINDRES" = x; then @@ -5166,8 +6085,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac WINDRES=$ac_ct_WINDRES @@ -5177,8 +6096,8 @@ fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for makensis" >&5 -$as_echo_n "checking for makensis... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for makensis" >&5 +printf %s "checking for makensis... " >&6; } if test -z "$MAKENSIS"; then if test -n "$PROGRAMFILES" && "$PROGRAMFILES/NSIS/makensis" -VERSION >/dev/null 2>&1; then MAKENSIS="$PROGRAMFILES/NSIS/makensis" @@ -5186,22 +6105,33 @@ MAKENSIS=makensis fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${MAKENSIS:-no}" >&5 -$as_echo "${MAKENSIS:-no}" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${MAKENSIS:-no}" >&5 +printf "%s\n" "${MAKENSIS:-no}" >&6; } ;; esac +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether reproducible build is selected (SOURCE_DATE_EPOCH)" >&5 +printf %s "checking whether reproducible build is selected (SOURCE_DATE_EPOCH)... " >&6; } +res=no +if test -n "$SOURCE_DATE_EPOCH"; then + res=yes + test -z "`echo "$SOURCE_DATE_EPOCH" | sed 's,[0-9]*,,'`" || res=error +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $res" >&5 +printf "%s\n" "$res" >&6; } +case $res in + error) as_fn_error $? "Malformed SOURCE_DATE_EPOCH" "$LINENO" 5 ;; + yes) CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-DSOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" ;; +esac + # Check for SVN. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether this is a build from SVN" >&5 -$as_echo_n "checking whether this is a build from SVN... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether this is a build from SVN" >&5 +printf %s "checking whether this is a build from SVN... " >&6; } is_svn_build=no svn_deps= if test -f "$srcdir/.svn/wc.db"; then - # SVN 1.7, 1.8 working copy + # SVN >= 1.7 working copy svn_deps='${srcdir}/.svn/wc.db' -elif test -f "${srcdir}/.svn/entries"; then - # SVN <= 1.6 working copy (SVN 1.7 has empty entries file) - svn_deps='${srcdir}/.svn/entries' fi if test -n "$svn_deps"; then is_svn_build=unknown @@ -5218,555 +6148,213 @@ IS_SVN_BUILD_FALSE= fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $is_svn_build" >&5 -$as_echo "$is_svn_build" >&6; } - -# Note: On Linux, clock_gettime() requires -lrt which implies -lpthreads -# Check omitted for now, gettimeofday() provides reasonable precision -# AC_SEARCH_LIBS(clock_gettime, rt) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $is_svn_build" >&5 +printf "%s\n" "$is_svn_build" >&6; } # Checks for header files. -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_GREP" || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_GREP=$GREP -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +ac_header= ac_cache= +for ac_item in $ac_header_cxx_list do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count + if test $ac_cache; then + ac_fn_cxx_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" + if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then + printf "%s\n" "#define $ac_item 1" >> confdefs.h fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + ac_header= ac_cache= + elif test $ac_header; then + ac_cache=$ac_item + else + ac_header=$ac_item fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : +done -else - ac_cv_header_stdc=no -fi -rm -f conftest* -fi -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_cxx_try_run "$LINENO"; then : -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then -$as_echo "#define STDC_HEADERS 1" >>confdefs.h -fi +if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes +then : -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF +printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi - -done - - -for ac_header in locale.h -do : - ac_fn_cxx_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" -if test "x$ac_cv_header_locale_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LOCALE_H 1 -_ACEOF +ac_fn_cxx_check_header_compile "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = xyes +then : + printf "%s\n" "#define HAVE_LOCALE_H 1" >>confdefs.h fi -done - -for ac_header in byteswap.h -do : - ac_fn_cxx_check_header_mongrel "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default" -if test "x$ac_cv_header_byteswap_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_BYTESWAP_H 1 -_ACEOF +ac_fn_cxx_check_header_compile "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default" +if test "x$ac_cv_header_byteswap_h" = xyes +then : + printf "%s\n" "#define HAVE_BYTESWAP_H 1" >>confdefs.h fi -done - case "$host" in *-*-freebsd*|*-*-dragonfly*|*-*-kfreebsd*-gnu*) # Check for FreeBSD twe and twa include files - for ac_header in sys/tweio.h sys/twereg.h sys/tw_osl_ioctl.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF + ac_fn_cxx_check_header_compile "$LINENO" "sys/tweio.h" "ac_cv_header_sys_tweio_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_tweio_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TWEIO_H 1" >>confdefs.h + +fi +ac_fn_cxx_check_header_compile "$LINENO" "sys/twereg.h" "ac_cv_header_sys_twereg_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_twereg_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TWEREG_H 1" >>confdefs.h + +fi +ac_fn_cxx_check_header_compile "$LINENO" "sys/tw_osl_ioctl.h" "ac_cv_header_sys_tw_osl_ioctl_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_tw_osl_ioctl_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TW_OSL_IOCTL_H 1" >>confdefs.h fi -done - # Check for the FreeBSD CCISS system header and use internal one if not found - for ac_header in dev/ciss/cissio.h + for ac_header in dev/ciss/cissio.h do : - ac_fn_cxx_check_header_mongrel "$LINENO" "dev/ciss/cissio.h" "ac_cv_header_dev_ciss_cissio_h" "$ac_includes_default" -if test "x$ac_cv_header_dev_ciss_cissio_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DEV_CISS_CISSIO_H 1 -_ACEOF + ac_fn_cxx_check_header_compile "$LINENO" "dev/ciss/cissio.h" "ac_cv_header_dev_ciss_cissio_h" "$ac_includes_default" +if test "x$ac_cv_header_dev_ciss_cissio_h" = xyes +then : + printf "%s\n" "#define HAVE_DEV_CISS_CISSIO_H 1" >>confdefs.h -$as_echo "#define CISS_LOCATION " >>confdefs.h +printf "%s\n" "#define CISS_LOCATION " >>confdefs.h -else +else $as_nop -$as_echo "#define CISS_LOCATION \"cissio_freebsd.h\"" >>confdefs.h +printf "%s\n" "#define CISS_LOCATION \"cissio_freebsd.h\"" >>confdefs.h fi done - ;; *-*-linux*) # is needed for cciss_ioctl.h at least on SuSE LINUX - for ac_header in sys/sysmacros.h linux/compiler.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF + ac_fn_cxx_check_header_compile "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sysmacros_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SYSMACROS_H 1" >>confdefs.h fi +ac_fn_cxx_check_header_compile "$LINENO" "linux/compiler.h" "ac_cv_header_linux_compiler_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_compiler_h" = xyes +then : + printf "%s\n" "#define HAVE_LINUX_COMPILER_H 1" >>confdefs.h -done +fi # Check for Linux CCISS include file - for ac_header in linux/cciss_ioctl.h -do : - ac_fn_cxx_check_header_compile "$LINENO" "linux/cciss_ioctl.h" "ac_cv_header_linux_cciss_ioctl_h" "$ac_includes_default + ac_fn_cxx_check_header_compile "$LINENO" "linux/cciss_ioctl.h" "ac_cv_header_linux_cciss_ioctl_h" "$ac_includes_default #ifdef HAVE_LINUX_COMPILER_H # include #endif " -if test "x$ac_cv_header_linux_cciss_ioctl_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_CCISS_IOCTL_H 1 -_ACEOF +if test "x$ac_cv_header_linux_cciss_ioctl_h" = xyes +then : + printf "%s\n" "#define HAVE_LINUX_CCISS_IOCTL_H 1" >>confdefs.h fi -done - ;; *-*-netbsd*|*-*-openbsd*) - for ac_header in dev/ata/atavar.h -do : - ac_fn_cxx_check_header_mongrel "$LINENO" "dev/ata/atavar.h" "ac_cv_header_dev_ata_atavar_h" "$ac_includes_default" -if test "x$ac_cv_header_dev_ata_atavar_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DEV_ATA_ATAVAR_H 1 -_ACEOF + ac_fn_cxx_check_header_compile "$LINENO" "dev/ata/atavar.h" "ac_cv_header_dev_ata_atavar_h" "$ac_includes_default" +if test "x$ac_cv_header_dev_ata_atavar_h" = xyes +then : + printf "%s\n" "#define HAVE_DEV_ATA_ATAVAR_H 1" >>confdefs.h fi -done - ;; - *-*-cygwin*|*-*-mingw*) - # Check for Windows DDK header files - for ac_header in ntdddisk.h ddk/ntdddisk.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -#include + *-*-mingw*) + # Older MinGW-w64 (5.0.3) require -lwinpthread + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +printf %s "checking for library containing clock_gettime... " >&6; } +if test ${ac_cv_search_clock_gettime+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +namespace conftest { + extern "C" int clock_gettime (); +} +int +main (void) +{ +return conftest::clock_gettime (); + ; + return 0; +} _ACEOF +for ac_lib in '' winpthread +do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO" +then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext + if test ${ac_cv_search_clock_gettime+y} +then : + break +fi +done +if test ${ac_cv_search_clock_gettime+y} +then : +else $as_nop + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +printf "%s\n" "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no +then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" -done +fi ;; esac # Checks for typedefs, and compiler characteristics. ac_fn_cxx_check_type "$LINENO" "__int128" "ac_cv_type___int128" "$ac_includes_default" -if test "x$ac_cv_type___int128" = xyes; then : +if test "x$ac_cv_type___int128" = xyes +then : -cat >>confdefs.h <<_ACEOF -#define HAVE___INT128 1 -_ACEOF +printf "%s\n" "#define HAVE___INT128 1" >>confdefs.h fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long double with more range or precision than double" >&5 -$as_echo_n "checking for long double with more range or precision than double... " >&6; } -if ${ac_cv_type_long_double_wider+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for long double with more range or precision than double" >&5 +printf %s "checking for long double with more range or precision than double... " >&6; } +if test ${ac_cv_type_long_double_wider+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -5783,7 +6371,7 @@ } int -main () +main (void) { static int test_array [1 - 2 * !((0 < ((DBL_MAX_EXP < LDBL_MAX_EXP) + (DBL_MANT_DIG < LDBL_MANT_DIG) @@ -5798,36 +6386,37 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : ac_cv_type_long_double_wider=yes -else +else $as_nop ac_cv_type_long_double_wider=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_double_wider" >&5 -$as_echo "$ac_cv_type_long_double_wider" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_double_wider" >&5 +printf "%s\n" "$ac_cv_type_long_double_wider" >&6; } if test $ac_cv_type_long_double_wider = yes; then -$as_echo "#define HAVE_LONG_DOUBLE_WIDER 1" >>confdefs.h +printf "%s\n" "#define HAVE_LONG_DOUBLE_WIDER 1" >>confdefs.h fi # Checks for library functions. -for ac_func in getopt_long + + for ac_func in getopt_long do : ac_fn_cxx_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" -if test "x$ac_cv_func_getopt_long" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_GETOPT_LONG 1 -_ACEOF +if test "x$ac_cv_func_getopt_long" = xyes +then : + printf "%s\n" "#define HAVE_GETOPT_LONG 1" >>confdefs.h need_getopt_long=no -else +else $as_nop need_getopt_long=yes fi -done +done if test "$need_getopt_long" = "yes"; then NEED_GETOPT_LONG_TRUE= NEED_GETOPT_LONG_FALSE='#' @@ -5837,25 +6426,13 @@ fi -for ac_func in clock_gettime ftime gettimeofday -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - # Check byte ordering (defines WORDS_BIGENDIAN) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 -$as_echo_n "checking whether byte ordering is bigendian... " >&6; } -if ${ac_cv_c_bigendian+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +printf %s "checking whether byte ordering is bigendian... " >&6; } +if test ${ac_cv_c_bigendian+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5866,7 +6443,8 @@ typedef int dummy; _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. @@ -5890,7 +6468,7 @@ fi done fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -5899,7 +6477,7 @@ #include int -main () +main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ @@ -5911,7 +6489,8 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5919,7 +6498,7 @@ #include int -main () +main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian @@ -5929,14 +6508,15 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : ac_cv_c_bigendian=yes -else +else $as_nop ac_cv_c_bigendian=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). @@ -5945,7 +6525,7 @@ #include int -main () +main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros @@ -5955,14 +6535,15 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main () +main (void) { #ifndef _BIG_ENDIAN not big endian @@ -5972,31 +6553,33 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : ac_cv_c_bigendian=yes -else +else $as_nop ac_cv_c_bigendian=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. - if test "$cross_compiling" = yes; then : + if test "$cross_compiling" = yes +then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -short int ascii_mm[] = +unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; - short int ascii_ii[] = + unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } - short int ebcdic_ii[] = + unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; - short int ebcdic_mm[] = + unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; @@ -6004,14 +6587,15 @@ extern int foo; int -main () +main (void) { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi @@ -6024,13 +6608,13 @@ fi fi fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int -main () +main (void) { /* Are we little or big endian? From Harbison&Steele. */ @@ -6046,9 +6630,10 @@ return 0; } _ACEOF -if ac_fn_cxx_try_run "$LINENO"; then : +if ac_fn_cxx_try_run "$LINENO" +then : ac_cv_c_bigendian=no -else +else $as_nop ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -6057,17 +6642,17 @@ fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 -$as_echo "$ac_cv_c_bigendian" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) - $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h + printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) -$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h +printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) @@ -6079,13 +6664,13 @@ # check for __attribute__((packed)) # (sizeof() check is required to avoid false positives if other # __attribute__((x)) are supported) -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports __attribute__((packed))" >&5 -$as_echo_n "checking whether $CXX supports __attribute__((packed))... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports __attribute__((packed))" >&5 +printf %s "checking whether $CXX supports __attribute__((packed))... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { struct s { char a; short b; } __attribute__((packed)); @@ -6094,20 +6679,21 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : gcc_have_attr_packed=yes -else +else $as_nop gcc_have_attr_packed=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test "$gcc_have_attr_packed" = "yes"; then -$as_echo "#define HAVE_ATTR_PACKED 1" >>confdefs.h +printf "%s\n" "#define HAVE_ATTR_PACKED 1" >>confdefs.h fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_have_attr_packed" >&5 -$as_echo "$gcc_have_attr_packed" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gcc_have_attr_packed" >&5 +printf "%s\n" "$gcc_have_attr_packed" >&6; } @@ -6116,7 +6702,8 @@ initddir= # Check whether --with-initscriptdir was given. -if test "${with_initscriptdir+set}" = set; then : +if test ${with_initscriptdir+y} +then : withval=$with_initscriptdir; case "$withval" in auto|yes) as_fn_error $? "'--with-initscriptdir=$withval' is no longer supported" "$LINENO" 5 ;; no) ;; @@ -6154,21 +6741,39 @@ # Check whether --with-exampledir was given. -if test "${with_exampledir+set}" = set; then : +if test ${with_exampledir+y} +then : withval=$with_exampledir; exampledir="$withval" -else +else $as_nop exampledir='${docdir}/examplescripts' fi drivedbdir='${datadir}/${PACKAGE}' +drivedbinstdir= + +# Check whether --with-drivedbinstdir was given. +if test ${with_drivedbinstdir+y} +then : + withval=$with_drivedbinstdir; case "$withval" in + no) ;; + yes) drivedbinstdir=$drivedbdir; drivedbdir='${localstatedir}/lib/${PACKAGE}' ;; + *) drivedbinstdir=$withval; drivedbdir='${localstatedir}/lib/${PACKAGE}' ;; + esac + +fi + + # Check whether --with-drivedbdir was given. -if test "${with_drivedbdir+set}" = set; then : +if test ${with_drivedbdir+y} +then : withval=$with_drivedbdir; case "$withval" in yes) ;; no) drivedbdir= ;; *) drivedbdir="$withval" ;; esac fi +test -n "$drivedbinstdir" || drivedbinstdir=$drivedbdir + if test -n "$drivedbdir"; then ENABLE_DRIVEDB_TRUE= @@ -6182,14 +6787,15 @@ drivedb_version=$smartmontools_drivedb_version # Check whether --with-update-smart_drivedb was given. -if test "${with_update_smart_drivedb+set}" = set; then : +if test ${with_update_smart_drivedb+y} +then : withval=$with_update_smart_drivedb; case "$withval" in yes|no) ;; - 5.4[0-3]|6.[0-9]) drivedb_version=$withval; with_update_smart_drivedb=yes ;; + 5.4[0-3]|6.[0-6]|7.[023]) drivedb_version=$withval; with_update_smart_drivedb=yes ;; *) as_fn_error $? "Invalid drivedb branch version: $withval" "$LINENO" 5 ;; esac -else +else $as_nop with_update_smart_drivedb=yes fi @@ -6208,7 +6814,8 @@ # Also check for '--with-gnupg[=yes]' because 'yes' is a valid command with infinite output # Check whether --with-gnupg was given. -if test "${with_gnupg+set}" = set; then : +if test ${with_gnupg+y} +then : withval=$with_gnupg; case "$withval" in yes) ;; no) gnupg= ;; *) gnupg="$withval" ;; esac fi @@ -6224,9 +6831,10 @@ # Check whether --with-smartdscriptdir was given. -if test "${with_smartdscriptdir+set}" = set; then : +if test ${with_smartdscriptdir+y} +then : withval=$with_smartdscriptdir; smartdscriptdir="$withval" -else +else $as_nop smartdscriptdir='${sysconfdir}' fi @@ -6234,9 +6842,10 @@ # Check whether --with-smartdplugindir was given. -if test "${with_smartdplugindir+set}" = set; then : +if test ${with_smartdplugindir+y} +then : withval=$with_smartdplugindir; smartdplugindir=; test "$withval" != "no" && smartdplugindir="$withval" -else +else $as_nop smartdplugindir='${smartdscriptdir}/smartd_warning.d' fi @@ -6244,9 +6853,10 @@ # Check whether --with-scriptpath was given. -if test "${with_scriptpath+set}" = set; then : +if test ${with_scriptpath+y} +then : withval=$with_scriptpath; scriptpath=; test "$withval" != "no" && scriptpath="$withval" -else +else $as_nop scriptpath="/usr/local/bin:/usr/bin:/bin" fi @@ -6263,7 +6873,8 @@ savestates= # Check whether --with-savestates was given. -if test "${with_savestates+set}" = set; then : +if test ${with_savestates+y} +then : withval=$with_savestates; case "$withval" in yes) savestates='${localstatedir}/lib/${PACKAGE}/smartd.' ;; no) ;; *) savestates="$withval" ;; esac fi @@ -6283,7 +6894,8 @@ attributelog= # Check whether --with-attributelog was given. -if test "${with_attributelog+set}" = set; then : +if test ${with_attributelog+y} +then : withval=$with_attributelog; case "$withval" in yes) attributelog='${localstatedir}/lib/${PACKAGE}/attrlog.' ;; no) ;; *) attributelog="$withval" ;; esac fi @@ -6301,19 +6913,21 @@ # Check whether --enable-sample was given. -if test "${enable_sample+set}" = set; then : +if test ${enable_sample+y} +then : enableval=$enable_sample; smartd_suffix=; test "$enableval" = "yes" && smartd_suffix=".sample" -else +else $as_nop smartd_suffix=; fi # Check whether --enable-scsi-cdb-check was given. -if test "${enable_scsi_cdb_check+set}" = set; then : +if test ${enable_scsi_cdb_check+y} +then : enableval=$enable_scsi_cdb_check; if test "$enableval" = "yes"; then -$as_echo "#define SCSI_CDB_CHECK 1" >>confdefs.h +printf "%s\n" "#define SCSI_CDB_CHECK 1" >>confdefs.h fi @@ -6321,10 +6935,11 @@ # Check whether --enable-fast-lebe was given. -if test "${enable_fast_lebe+set}" = set; then : +if test ${enable_fast_lebe+y} +then : enableval=$enable_fast_lebe; if test "$enableval" = "no"; then -$as_echo "#define IGNORE_FAST_LEBE 1" >>confdefs.h +printf "%s\n" "#define IGNORE_FAST_LEBE 1" >>confdefs.h fi @@ -6333,7 +6948,8 @@ # Check whether --with-os-deps was given. -if test "${with_os_deps+set}" = set; then : +if test ${with_os_deps+y} +then : withval=$with_os_deps; for x in $with_os_deps; do case $x in *.o) ;; @@ -6346,66 +6962,62 @@ # Check whether --with-selinux was given. -if test "${with_selinux+set}" = set; then : +if test ${with_selinux+y} +then : withval=$with_selinux; if test "$withval" = "yes"; then - for ac_header in selinux/selinux.h + for ac_header in selinux/selinux.h do : - ac_fn_cxx_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default" -if test "x$ac_cv_header_selinux_selinux_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SELINUX_SELINUX_H 1 -_ACEOF + ac_fn_cxx_check_header_compile "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default" +if test "x$ac_cv_header_selinux_selinux_h" = xyes +then : + printf "%s\n" "#define HAVE_SELINUX_SELINUX_H 1" >>confdefs.h -else +else $as_nop as_fn_error $? "Missing SELinux header files" "$LINENO" 5 fi done - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for matchpathcon in -lselinux" >&5 -$as_echo_n "checking for matchpathcon in -lselinux... " >&6; } -if ${ac_cv_lib_selinux_matchpathcon+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for matchpathcon in -lselinux" >&5 +printf %s "checking for matchpathcon in -lselinux... " >&6; } +if test ${ac_cv_lib_selinux_matchpathcon+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lselinux $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char matchpathcon (); +namespace conftest { + extern "C" int matchpathcon (); +} int -main () +main (void) { -return matchpathcon (); +return conftest::matchpathcon (); ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : ac_cv_lib_selinux_matchpathcon=yes -else +else $as_nop ac_cv_lib_selinux_matchpathcon=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_matchpathcon" >&5 -$as_echo "$ac_cv_lib_selinux_matchpathcon" >&6; } -if test "x$ac_cv_lib_selinux_matchpathcon" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBSELINUX 1 -_ACEOF +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_matchpathcon" >&5 +printf "%s\n" "$ac_cv_lib_selinux_matchpathcon" >&6; } +if test "x$ac_cv_lib_selinux_matchpathcon" = xyes +then : + printf "%s\n" "#define HAVE_LIBSELINUX 1" >>confdefs.h LIBS="-lselinux $LIBS" -else +else $as_nop as_fn_error $? "Missing or incorrect SELinux library files" "$LINENO" 5 fi @@ -6416,9 +7028,10 @@ # Check whether --with-libcap-ng was given. -if test "${with_libcap_ng+set}" = set; then : +if test ${with_libcap_ng+y} +then : withval=$with_libcap_ng; -else +else $as_nop with_libcap_ng=auto fi @@ -6426,72 +7039,70 @@ use_libcap_ng=no case "$with_libcap_ng:$host_os" in auto:linux*|yes:*) - for ac_header in cap-ng.h + for ac_header in cap-ng.h do : - ac_fn_cxx_check_header_mongrel "$LINENO" "cap-ng.h" "ac_cv_header_cap_ng_h" "$ac_includes_default" -if test "x$ac_cv_header_cap_ng_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_CAP_NG_H 1 -_ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for capng_clear in -lcap-ng" >&5 -$as_echo_n "checking for capng_clear in -lcap-ng... " >&6; } -if ${ac_cv_lib_cap_ng_capng_clear+:} false; then : - $as_echo_n "(cached) " >&6 -else + ac_fn_cxx_check_header_compile "$LINENO" "cap-ng.h" "ac_cv_header_cap_ng_h" "$ac_includes_default" +if test "x$ac_cv_header_cap_ng_h" = xyes +then : + printf "%s\n" "#define HAVE_CAP_NG_H 1" >>confdefs.h + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for capng_clear in -lcap-ng" >&5 +printf %s "checking for capng_clear in -lcap-ng... " >&6; } +if test ${ac_cv_lib_cap_ng_capng_clear+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lcap-ng $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char capng_clear (); +namespace conftest { + extern "C" int capng_clear (); +} int -main () +main (void) { -return capng_clear (); +return conftest::capng_clear (); ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : ac_cv_lib_cap_ng_capng_clear=yes -else +else $as_nop ac_cv_lib_cap_ng_capng_clear=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_ng_capng_clear" >&5 -$as_echo "$ac_cv_lib_cap_ng_capng_clear" >&6; } -if test "x$ac_cv_lib_cap_ng_capng_clear" = xyes; then : +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_ng_capng_clear" >&5 +printf "%s\n" "$ac_cv_lib_cap_ng_capng_clear" >&6; } +if test "x$ac_cv_lib_cap_ng_capng_clear" = xyes +then : -$as_echo "#define HAVE_LIBCAP_NG 1" >>confdefs.h +printf "%s\n" "#define HAVE_LIBCAP_NG 1" >>confdefs.h CAPNG_LDADD="-lcap-ng"; use_libcap_ng=yes -else +else $as_nop as_fn_error $? "libcap-ng headers found but library is missing" "$LINENO" 5 fi -else +else $as_nop test "$with_libcap_ng" != "yes" || as_fn_error $? "Missing libcap-ng header files" "$LINENO" 5 fi done - ;; esac # Check whether --with-libsystemd was given. -if test "${with_libsystemd+set}" = set; then : +if test ${with_libsystemd+y} +then : withval=$with_libsystemd; -else +else $as_nop with_libsystemd=auto fi @@ -6499,72 +7110,70 @@ use_libsystemd=no case "$with_libsystemd:$host_os" in auto:linux*|yes:*) - for ac_header in systemd/sd-daemon.h + for ac_header in systemd/sd-daemon.h do : - ac_fn_cxx_check_header_mongrel "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default" -if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYSTEMD_SD_DAEMON_H 1 -_ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sd_notify in -lsystemd" >&5 -$as_echo_n "checking for sd_notify in -lsystemd... " >&6; } -if ${ac_cv_lib_systemd_sd_notify+:} false; then : - $as_echo_n "(cached) " >&6 -else + ac_fn_cxx_check_header_compile "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default" +if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes +then : + printf "%s\n" "#define HAVE_SYSTEMD_SD_DAEMON_H 1" >>confdefs.h + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sd_notify in -lsystemd" >&5 +printf %s "checking for sd_notify in -lsystemd... " >&6; } +if test ${ac_cv_lib_systemd_sd_notify+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsystemd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char sd_notify (); +namespace conftest { + extern "C" int sd_notify (); +} int -main () +main (void) { -return sd_notify (); +return conftest::sd_notify (); ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : ac_cv_lib_systemd_sd_notify=yes -else +else $as_nop ac_cv_lib_systemd_sd_notify=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_systemd_sd_notify" >&5 -$as_echo "$ac_cv_lib_systemd_sd_notify" >&6; } -if test "x$ac_cv_lib_systemd_sd_notify" = xyes; then : +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_systemd_sd_notify" >&5 +printf "%s\n" "$ac_cv_lib_systemd_sd_notify" >&6; } +if test "x$ac_cv_lib_systemd_sd_notify" = xyes +then : -$as_echo "#define HAVE_LIBSYSTEMD 1" >>confdefs.h +printf "%s\n" "#define HAVE_LIBSYSTEMD 1" >>confdefs.h SYSTEMD_LDADD="-lsystemd"; use_libsystemd=yes -else +else $as_nop as_fn_error $? "libsystemd headers found but library is missing" "$LINENO" 5 fi -else +else $as_nop test "$with_libsystemd" != "yes" || as_fn_error $? "Missing libsystemd header files" "$LINENO" 5 fi done - ;; esac # Check whether --with-systemdsystemunitdir was given. -if test "${with_systemdsystemunitdir+set}" = set; then : +if test ${with_systemdsystemunitdir+y} +then : withval=$with_systemdsystemunitdir; -else +else $as_nop with_systemdsystemunitdir=auto fi @@ -6573,11 +7182,11 @@ case "$with_systemdsystemunitdir:$use_libsystemd" in auto:yes|yes:yes) if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemdsystemunitdir" >&5 -$as_echo_n "checking for systemdsystemunitdir... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for systemdsystemunitdir" >&5 +printf %s "checking for systemdsystemunitdir... " >&6; } systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd 2>/dev/null` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${systemdsystemunitdir:-no}" >&5 -$as_echo "${systemdsystemunitdir:-no}" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${systemdsystemunitdir:-no}" >&5 +printf "%s\n" "${systemdsystemunitdir:-no}" >&6; } fi case "$with_systemdsystemunitdir:$sysconfdir:$systemdsystemunitdir" in yes:*:) as_fn_error $? "Location of systemd service files not found" "$LINENO" 5 ;; @@ -6600,9 +7209,10 @@ # Check whether --with-systemdenvfile was given. -if test "${with_systemdenvfile+set}" = set; then : +if test ${with_systemdenvfile+y} +then : withval=$with_systemdenvfile; -else +else $as_nop with_systemdenvfile=auto fi @@ -6610,16 +7220,16 @@ systemdenvfile= case "$with_systemdenvfile:$cross_compiling:$systemdsystemunitdir" in auto:no:?*|yes:*:?*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for path of systemd EnvironmentFile" >&5 -$as_echo_n "checking for path of systemd EnvironmentFile... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for path of systemd EnvironmentFile" >&5 +printf %s "checking for path of systemd EnvironmentFile... " >&6; } for dir in sysconfig default; do if test -d /etc/$dir; then systemdenvfile='${sysconfdir}'/$dir/smartmontools break fi done - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${systemdenvfile:-no}" >&5 -$as_echo "${systemdenvfile:-no}" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${systemdenvfile:-no}" >&5 +printf "%s\n" "${systemdenvfile:-no}" >&6; } case "$with_systemdenvfile:$systemdenvfile" in yes:) as_fn_error $? "Path of systemd EnvironmentFile not found" "$LINENO" 5 ;; esac ;; @@ -6632,14 +7242,17 @@ # TODO: Remove when NVMe support is no longer EXPERIMENTAL # Check whether --with-nvme-devicescan was given. -if test "${with_nvme_devicescan+set}" = set; then : +if test ${with_nvme_devicescan+y} +then : withval=$with_nvme_devicescan; fi +# TODO: Remove after smartmontools 7.3 # Check whether --with-solaris-sparc-ata was given. -if test "${with_solaris_sparc_ata+set}" = set; then : +if test ${with_solaris_sparc_ata+y} +then : withval=$with_solaris_sparc_ata; fi @@ -6652,16 +7265,18 @@ available in the SVN repository." "$LINENO" 5 fi -$as_echo "#define WITH_SOLARIS_SPARC_ATA 1" >>confdefs.h +printf "%s\n" "#define WITH_SOLARIS_SPARC_ATA 1" >>confdefs.h ;; esac +# TODO: Remove after smartmontools 7.4 # Check whether --with-signal-func was given. -if test "${with_signal_func+set}" = set; then : +if test ${with_signal_func+y} +then : withval=$with_signal_func; -else +else $as_nop with_signal_func=sigaction fi @@ -6669,63 +7284,48 @@ case "$host:$with_signal_func" in *-*-mingw*:*) ;; *:sigaction) - for ac_func in sigaction + + for ac_func in sigaction do : ac_fn_cxx_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" -if test "x$ac_cv_func_sigaction" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SIGACTION 1 -_ACEOF +if test "x$ac_cv_func_sigaction" = xyes +then : + printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h -else +else $as_nop as_fn_error $? "Missing function 'sigaction()'. Try '--with-signal-func=sigset' or '--with-signal-func=signal'. Please send info about your system to $PACKAGE_BUGREPORT." "$LINENO" 5 fi -done - ;; + +done ;; *:sigset) - for ac_func in sigset + + for ac_func in sigset do : ac_fn_cxx_check_func "$LINENO" "sigset" "ac_cv_func_sigset" -if test "x$ac_cv_func_sigset" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SIGSET 1 -_ACEOF +if test "x$ac_cv_func_sigset" = xyes +then : + printf "%s\n" "#define HAVE_SIGSET 1" >>confdefs.h -else +else $as_nop as_fn_error $? "Missing function 'sigset()'" "$LINENO" 5 fi -done - ;; + +done ;; *:signal) ;; *) as_fn_error $? "Invalid option '--with-signal-func=$with_signal_func'" "$LINENO" 5 ;; esac -# TODO: Remove after smartmontools 6.7 - -# Check whether --with-working-snprintf was given. -if test "${with_working_snprintf+set}" = set; then : - withval=$with_working_snprintf; -else - with_working_snprintf=yes -fi - - -if test "$with_working_snprintf" = "yes"; then - -$as_echo "#define HAVE_WORKING_SNPRINTF 1" >>confdefs.h - fi - -case "$with_working_snprintf:$host_os: $CPPFLAGS $CXXFLAGS" in - yes:mingw*:*\ -[DU]__USE_MINGW_ANSI_STDIO*) +case "$host_os: $CPPFLAGS $CXXFLAGS" in + mingw*:*\ -[DU]__USE_MINGW_ANSI_STDIO*) ;; - yes:mingw*:*) + mingw*:*) # Older MinGW (4.6.3) do not properly define PRI?64 if __USE_MINGW_ANSI_STDIO is set. # Newer MinGW (4.9.1) set __USE_MINGW_ANSI_STDIO in first C++ include which may be too late. # Set __USE_MINGW_ANSI_STDIO always and fail if not fully supported. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports __USE_MINGW_ANSI_STDIO" >&5 -$as_echo_n "checking whether $CXX supports __USE_MINGW_ANSI_STDIO... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports __USE_MINGW_ANSI_STDIO" >&5 +printf %s "checking whether $CXX supports __USE_MINGW_ANSI_STDIO... " >&6; } save_CXXFLAGS=$CXXFLAGS CXXFLAGS="-Wformat -Werror -D__USE_MINGW_ANSI_STDIO" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6739,18 +7339,19 @@ snprintf(buf2, size, "%" PRId64, (int64_t)42); } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : result=yes -else +else $as_nop result=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $result" >&5 -$as_echo "$result" >&6; } +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $result" >&5 +printf "%s\n" "$result" >&6; } if test "$result" != "yes"; then as_fn_error $? " This version of $CXX does not support __USE_MINGW_ANSI_STDIO. -Use option '--without-working-snprintf' to skip this check. +Use option 'CPPFLAGS=-U__USE_MINGW_ANSI_STDIO' to skip this check. Please send info about your system to $PACKAGE_BUGREPORT. " "$LINENO" 5 fi @@ -6760,9 +7361,10 @@ # Check whether --with-mingw-aslr was given. -if test "${with_mingw_aslr+set}" = set; then : +if test ${with_mingw_aslr+y} +then : withval=$with_mingw_aslr; -else +else $as_nop with_mingw_aslr=auto fi @@ -6784,8 +7386,8 @@ case "$host:$with_mingw_aslr" in x86_64-*-mingw*:auto) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports --high-entropy-va" >&5 -$as_echo_n "checking whether $CXX supports --high-entropy-va... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports --high-entropy-va" >&5 +printf %s "checking whether $CXX supports --high-entropy-va... " >&6; } save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,--dynamicbase,-pie,-emainCRTStartup,--high-entropy-va,--image-base,0x140000000" # Link libstdc++ to detect MinGW-w64 problems with high '--image-base' @@ -6795,23 +7397,24 @@ #include std::string s(42, '.'); int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : with_mingw_aslr=yes -else +else $as_nop with_mingw_aslr=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_mingw_aslr" >&5 -$as_echo "$with_mingw_aslr" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_mingw_aslr" >&5 +printf "%s\n" "$with_mingw_aslr" >&6; } test "$with_mingw_aslr" = "yes" || with_mingw_aslr=low ;; esac @@ -6829,21 +7432,22 @@ case "$host" in *-*-mingw*) # Newer MinGW may add a default manifest - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX adds an application manifest" >&5 -$as_echo_n "checking whether $CXX adds an application manifest... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX adds an application manifest" >&5 +printf %s "checking whether $CXX adds an application manifest... " >&6; } cc_adds_manifest=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : if "$WINDRES" -O rc conftest.exe 2>/dev/null | grep '^1.*RT_MANIFEST' >/dev/null 2>&1; then cc_adds_manifest=incomplete @@ -6852,96 +7456,142 @@ cc_adds_manifest=yes fi fi -else +else $as_nop as_fn_error $? "test compile failed" "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cc_adds_manifest" >&5 -$as_echo "$cc_adds_manifest" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cc_adds_manifest" >&5 +printf "%s\n" "$cc_adds_manifest" >&6; } test "$cc_adds_manifest" = "yes" || os_win32_manifest='os_win32/default.manifest' ;; esac # Check whether --with-cxx11-option was given. -if test "${with_cxx11_option+set}" = set; then : +if test ${with_cxx11_option+y} +then : withval=$with_cxx11_option; -else +else $as_nop with_cxx11_option=auto fi -check_cxx11_support() -{ - save_CXXFLAGS=$CXXFLAGS - CXXFLAGS=$1 - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cxx14_option= +case "$with_cxx11_option" in + no) ;; + *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to accept C++14" >&5 +printf %s "checking for $CXX option to accept C++14... " >&6; } + cxx14_option=unknown + save_CXXFLAGS=$CXXFLAGS + for option in "" "-std=gnu++14" "-std=gnu++1y" "-std=c++14" "-std=c++1y"; do + CXXFLAGS="$save_CXXFLAGS $option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #if __cplusplus < 201103L - #error false - #endif - // use some C++11 features (and return v * 42 :-) - auto cxx11(long v) noexcept -> decltype(v) { - typedef decltype(v) t; t r = v; - static const t a[] = { -7, -1, 1, 2, 3 }; - static_assert(sizeof(r) == sizeof(a[0]), "fail"); - auto f = [](t x, t y){ return x * y; }; - for (const auto & e : a) r = f(r, e); - return r; - } + #if __cplusplus < 201402 + #error false + #endif int -main () +main (void) { ; return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - CXXFLAGS=$save_CXXFLAGS; return 0 -else - CXXFLAGS=$save_CXXFLAGS; return 1 +if ac_fn_cxx_try_compile "$LINENO" +then : + cxx14_option=$option fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -} +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + test "$cxx14_option" = "unknown" || break + done + CXXFLAGS=$save_CXXFLAGS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${cxx14_option:-none needed}" >&5 +printf "%s\n" "${cxx14_option:-none needed}" >&6; } + ;; +esac case "$with_cxx11_option" in no) ;; auto) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CXX option to accept C++11" >&5 -$as_echo_n "checking for $CXX option to accept C++11... " >&6; } - with_cxx11_option=unknown + res=; test "$cxx14_option" = "unknown" || res=" but not C++14" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to accept C++11$res" >&5 +printf %s "checking for $CXX option to accept C++11$res... " >&6; } + save_CXXFLAGS=$CXXFLAGS + res=unknown for option in "" "-std=gnu++11" "-std=gnu++0x" "-std=c++11" "-std=c++0x"; do - if check_cxx11_support "$option"; then with_cxx11_option=$option; break; fi + test "$option" != "$cxx14_option" || continue + CXXFLAGS="$save_CXXFLAGS $option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #if __cplusplus < 201103 || 201402 <= __cplusplus + #error false + #endif +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + res=$option +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + test "$res" = "unknown" || break done - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_cxx11_option:-none needed}" >&5 -$as_echo "${with_cxx11_option:-none needed}" >&6; } - test "$with_cxx11_option" != "unknown" || as_fn_error $? " -This version of smartmontools does not use C++11 features, but future -versions possibly will. -This script was unable to determine a compiler option to enable C++11. -Use option '--with-cxx11-option=OPTION' to specify the compiler option -(it will be used in the actual build only if '--with-cxx11-regex' is set). -Use option '--without-cxx11-option' to suppress this error message if the -compiler lacks C++11 support. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${res:-none needed}" >&5 +printf "%s\n" "${res:-none needed}" >&6; } + test "$res" != "unknown" || res=$cxx14_option + test "$res" != "unknown" || as_fn_error $? " +This script was unable to determine a compiler option to accept C++11. +Use option '--with-cxx11-option=OPTION' to specify a compiler option. +Use option '--without-cxx11-option' to try anyway without this check. In both cases, please send info about compiler and platform to $PACKAGE_BUGREPORT - Thanks!" "$LINENO" 5 + CXXFLAGS="$save_CXXFLAGS${res:+ }$res" ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX $with_cxx11_option accepts C++11" >&5 -$as_echo_n "checking whether $CXX $with_cxx11_option accepts C++11... " >&6; } - res=no; check_cxx11_support "$with_cxx11_option" && res=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $res" >&5 -$as_echo "$res" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX $with_cxx11_option accepts C++11" >&5 +printf %s "checking whether $CXX $with_cxx11_option accepts C++11... " >&6; } + CXXFLAGS="$CXXFLAGS${with_cxx11_option:+ }$with_cxx11_option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #if __cplusplus < 201103 + #error false + #endif +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + res=yes +else $as_nop + res=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $res" >&5 +printf "%s\n" "$res" >&6; } test "$res" = "yes" || as_fn_error $? "$CXX $with_cxx11_option does not accept C++11" "$LINENO" 5 ;; esac # Check whether --with-cxx11-regex was given. -if test "${with_cxx11_regex+set}" = set; then : +if test ${with_cxx11_regex+y} +then : withval=$with_cxx11_regex; fi @@ -6949,27 +7599,22 @@ need_regex=no if test "$with_cxx11_regex" = "yes"; then -$as_echo "#define WITH_CXX11_REGEX 1" >>confdefs.h +printf "%s\n" "#define WITH_CXX11_REGEX 1" >>confdefs.h - case "$with_cxx11_option: $CXXFLAGS " in - no:*) as_fn_error $? "'--with-cxx11-regex' requires C++11 support" "$LINENO" 5 ;; - ?*:*\ $with_cxx11_option\ *) ;; - ?*:*) CXXFLAGS="$CXXFLAGS $with_cxx11_option" ;; - esac else + for ac_func in regcomp do : ac_fn_cxx_check_func "$LINENO" "regcomp" "ac_cv_func_regcomp" -if test "x$ac_cv_func_regcomp" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_REGCOMP 1 -_ACEOF +if test "x$ac_cv_func_regcomp" = xyes +then : + printf "%s\n" "#define HAVE_REGCOMP 1" >>confdefs.h -else +else $as_nop need_regex=yes fi -done +done fi if test "$need_regex" = "yes"; then NEED_REGEX_TRUE= @@ -6989,9 +7634,10 @@ os_libs= os_dltools='curl wget lynx svn' os_mailer=mail -os_hostname="'hostname'" +os_hostname="'hostname' 'uname -n'" os_dnsdomainname= os_nisdomainname="'domainname'" +os_posix=yes os_darwin=no os_solaris=no os_win32=no @@ -7011,46 +7657,43 @@ os_deps='os_freebsd.o cciss.o dev_areca.o' os_libs='-lcam -lsbuf' os_dltools='fetch curl wget lynx svn' - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb20_dev_get_device_desc in -lusb" >&5 -$as_echo_n "checking for libusb20_dev_get_device_desc in -lusb... " >&6; } -if ${ac_cv_lib_usb_libusb20_dev_get_device_desc+:} false; then : - $as_echo_n "(cached) " >&6 -else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libusb20_dev_get_device_desc in -lusb" >&5 +printf %s "checking for libusb20_dev_get_device_desc in -lusb... " >&6; } +if test ${ac_cv_lib_usb_libusb20_dev_get_device_desc+y} +then : + printf %s "(cached) " >&6 +else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char libusb20_dev_get_device_desc (); +namespace conftest { + extern "C" int libusb20_dev_get_device_desc (); +} int -main () +main (void) { -return libusb20_dev_get_device_desc (); +return conftest::libusb20_dev_get_device_desc (); ; return 0; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : ac_cv_lib_usb_libusb20_dev_get_device_desc=yes -else +else $as_nop ac_cv_lib_usb_libusb20_dev_get_device_desc=no fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_libusb20_dev_get_device_desc" >&5 -$as_echo "$ac_cv_lib_usb_libusb20_dev_get_device_desc" >&6; } -if test "x$ac_cv_lib_usb_libusb20_dev_get_device_desc" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBUSB 1 -_ACEOF +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_libusb20_dev_get_device_desc" >&5 +printf "%s\n" "$ac_cv_lib_usb_libusb20_dev_get_device_desc" >&6; } +if test "x$ac_cv_lib_usb_libusb20_dev_get_device_desc" = xyes +then : + printf "%s\n" "#define HAVE_LIBUSB 1" >>confdefs.h LIBS="-lusb $LIBS" @@ -7088,7 +7731,7 @@ *-*-cygwin*) os_deps='os_win32.o dev_areca.o' os_mailer='email' - os_hostname="'hostname' 'echo "'"${HOSTNAME?unset}"'"'" + os_hostname="'hostname' 'uname -n' 'echo "'"${HOSTNAME?unset}"'"'" os_dnsdomainname="'dnsdomainname' 'hostname -d' 'echo "'"${USERDNSDOMAIN?unset}"'"'" os_nisdomainname= os_win32=yes @@ -7097,6 +7740,7 @@ ;; x86_64-*-mingw*) os_deps='os_win32.o dev_areca.o' + os_posix=no os_win32=yes os_win32_mingw=yes os_win64=yes @@ -7105,6 +7749,7 @@ ;; *-*-mingw*) os_deps='os_win32.o dev_areca.o' + os_posix=no os_win32=yes os_win32_mingw=yes os_man_filter=Windows @@ -7122,6 +7767,7 @@ ;; *-*-os2-*) os_deps='os_os2.o' + os_posix=no ;; *) os_deps='os_generic.o' @@ -7131,36 +7777,46 @@ # Replace if '--with-os-deps' was specified test -z "$with_os_deps" || os_deps="$with_os_deps" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the OS provides a POSIX API" >&5 +printf %s "checking whether the OS provides a POSIX API... " >&6; } +if test "$os_posix" = "yes"; then + +printf "%s\n" "#define HAVE_POSIX_API 1" >>confdefs.h + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $os_posix" >&5 +printf "%s\n" "$os_posix" >&6; } + # Check if we need adapter to old interface (dev_legacy.cpp) os_src=`echo "${os_deps}"|sed -n 's,^\([^ .]*\)\.o.*$,\1.cpp,p'` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${os_src} uses new interface" >&5 -$as_echo_n "checking whether ${os_src} uses new interface... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${os_src} uses new interface" >&5 +printf %s "checking whether ${os_src} uses new interface... " >&6; } if grep "smart_interface" "${srcdir}/${os_src}" >/dev/null 2>&1; then os_new_interface=yes else os_new_interface=no os_deps="${os_deps} dev_legacy.o" -$as_echo "#define OLD_INTERFACE 1" >>confdefs.h +printf "%s\n" "#define OLD_INTERFACE 1" >>confdefs.h fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $os_new_interface" >&5 -$as_echo "$os_new_interface" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $os_new_interface" >&5 +printf "%s\n" "$os_new_interface" >&6; } # TODO: Remove when NVMe support is no longer EXPERIMENTAL case "$os_nvme_devicescan:${with_nvme_devicescan+set}" in no:|yes:) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NVMe device scanning could be safely enabled" >&5 -$as_echo_n "checking whether NVMe device scanning could be safely enabled... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether NVMe device scanning could be safely enabled" >&5 +printf %s "checking whether NVMe device scanning could be safely enabled... " >&6; } with_nvme_devicescan=$os_nvme_devicescan - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $os_nvme_devicescan" >&5 -$as_echo "$os_nvme_devicescan" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $os_nvme_devicescan" >&5 +printf "%s\n" "$os_nvme_devicescan" >&6; } os_nvme_devicescan=used ;; esac if test "$with_nvme_devicescan" = "yes"; then -$as_echo "#define WITH_NVME_DEVICESCAN 1" >>confdefs.h +printf "%s\n" "#define WITH_NVME_DEVICESCAN 1" >>confdefs.h fi @@ -7183,6 +7839,14 @@ # Enable platform-specific makefile sections + if test "$os_posix" = "yes"; then + OS_POSIX_TRUE= + OS_POSIX_FALSE='#' +else + OS_POSIX_TRUE='#' + OS_POSIX_FALSE= +fi + if test "$os_darwin" = "yes"; then OS_DARWIN_TRUE= OS_DARWIN_FALSE='#' @@ -7243,34 +7907,39 @@ *\ -W\ *|*\ -Wextra\ *) ;; *) CXXFLAGS="$CXXFLAGS -W" ;; esac - # Add -Wformat=2 (GCC 3.0) -fstack-protector[-strong] (GCC 4.1[4.9]) if supported - # and no -W or -f option was set in configure cmdline (TODO: -Wformat-signedness) - for option in "-Wformat=2" "-fstack-protector-strong" "-fstack-protector"; do + # Add -Wformat=2 (GCC 3.0), + # -Werror=return-type (G++ >= 8.0 assumes that control never reaches the end of a non-void function), + # -fstack-protector[-strong] (GCC 4.1[4.9]) + # if supported and no -W or -f option was set in configure cmdline (TODO: -Wformat-signedness) + for option in "-Wformat=2" "-Werror=return-type" "-fstack-protector-strong" "-fstack-protector"; do case " $orig_CXXFLAGS:$option" in *\ -W*:-W*|*\ -f*:-f*) continue ;; esac case " $CXXFLAGS:$option" in *\ -fstack-p*:-fstack-p*) continue ;; esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports $option" >&5 -$as_echo_n "checking whether $CXX supports $option... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports $option" >&5 +printf %s "checking whether $CXX supports $option... " >&6; } save_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS $option" + # For -fstack-protector*, check that '__stack_chk_*()' functions are available. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +int i; int -main () +main (void) { - +volatile char buf[10]; buf[i] = 0; ; return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : res=yes -else +else $as_nop res=no; CXXFLAGS=$save_CXXFLAGS fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $res" >&5 -$as_echo "$res" >&6; } +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $res" >&5 +printf "%s\n" "$res" >&6; } done else # We are NOT using gcc, so enable host-specific compiler flags @@ -7297,8 +7966,8 @@ esac fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether _FORTIFY_SOURCE is predefined" >&5 -$as_echo_n "checking whether _FORTIFY_SOURCE is predefined... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _FORTIFY_SOURCE is predefined" >&5 +printf %s "checking whether _FORTIFY_SOURCE is predefined... " >&6; } # Use COMPILE check to detect compiler presets and C*FLAGS. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -7307,21 +7976,22 @@ #error false #endif _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : +if ac_fn_cxx_try_compile "$LINENO" +then : res=yes -else +else $as_nop res=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $res" >&5 -$as_echo "$res" >&6; } +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $res" >&5 +printf "%s\n" "$res" >&6; } if test "$res" = "no"; then # Heuristic to check for _FORTIFY_SOURCE=2 support. # Done after check for -fstack-protector because this may add an additional lib. # Note: Even if _FORTIFY_SOURCE is present in the include files, it may not be # detected here because it is disabled for C++. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports _FORTIFY_SOURCE=2" >&5 -$as_echo_n "checking whether $CXX supports _FORTIFY_SOURCE=2... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports _FORTIFY_SOURCE=2" >&5 +printf %s "checking whether $CXX supports _FORTIFY_SOURCE=2... " >&6; } save_CPPFLAGS=$CPPFLAGS CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-D_FORTIFY_SOURCE=2" # Use LINK instead of COMPILE to make sure that the required lib is also present @@ -7335,22 +8005,21 @@ if (argc == 2) strcpy(buf, argv[1]); return buf[0]; } _ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : +if ac_fn_cxx_try_link "$LINENO" +then : res=yes; $NM conftest$EXEEXT 2>/dev/null | grep '_strcpy_chk' >/dev/null 2>&1 || res=no -else +else $as_nop res=unknown fi -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext test "$res" = "yes" || CPPFLAGS=$save_CPPFLAGS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $res" >&5 -$as_echo "$res" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $res" >&5 +printf "%s\n" "$res" >&6; } fi -cat >>confdefs.h <<_ACEOF -#define SMARTMONTOOLS_BUILD_HOST "${host}" -_ACEOF +printf "%s\n" "#define SMARTMONTOOLS_BUILD_HOST \"${host}\"" >>confdefs.h @@ -7384,8 +8053,8 @@ case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -7415,15 +8084,15 @@ /^ac_cv_env_/b end t clear :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else @@ -7437,8 +8106,8 @@ fi fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache @@ -7455,7 +8124,7 @@ for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" @@ -7466,14 +8135,14 @@ LTLIBOBJS=$ac_ltlibobjs -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 -$as_echo_n "checking that generated files are newer than configure... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +printf %s "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 -$as_echo "done" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 +printf "%s\n" "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' @@ -7543,6 +8212,10 @@ as_fn_error $? "conditional \"NEED_REGEX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${OS_POSIX_TRUE}" && test -z "${OS_POSIX_FALSE}"; then + as_fn_error $? "conditional \"OS_POSIX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${OS_DARWIN_TRUE}" && test -z "${OS_DARWIN_FALSE}"; then as_fn_error $? "conditional \"OS_DARWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -7572,8 +8245,8 @@ ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL @@ -7596,14 +8269,16 @@ # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST -else +else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( @@ -7613,46 +8288,46 @@ fi + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then +if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || @@ -7661,13 +8336,6 @@ fi -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( @@ -7676,8 +8344,12 @@ for as_dir in $PATH do IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS @@ -7689,30 +8361,10 @@ as_myself=$0 fi if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] @@ -7725,13 +8377,14 @@ as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $2" >&2 + printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error + # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. @@ -7758,18 +8411,20 @@ { eval $1=; unset $1;} } as_unset=as_fn_unset + # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : eval 'as_fn_append () { eval $1+=\$2 }' -else +else $as_nop as_fn_append () { eval $1=\$$1\$2 @@ -7781,12 +8436,13 @@ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : eval 'as_fn_arith () { as_val=$(( $* )) }' -else +else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` @@ -7817,7 +8473,7 @@ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | +printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -7839,6 +8495,10 @@ as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) @@ -7852,6 +8512,12 @@ ECHO_N='-n';; esac +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file @@ -7893,7 +8559,7 @@ as_dirs= while :; do case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" @@ -7902,7 +8568,7 @@ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | +printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -7964,8 +8630,8 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by smartmontools $as_me 7.1, which was -generated by GNU Autoconf 2.69. Invocation command line was +This file was extended by smartmontools $as_me 7.3, which was +generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -8027,14 +8693,16 @@ Report bugs to ." _ACEOF +ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` +ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -smartmontools config.status 7.1 -configured by $0, generated by GNU Autoconf 2.69, +smartmontools config.status 7.3 +configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" -Copyright (C) 2012 Free Software Foundation, Inc. +Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -8074,15 +8742,15 @@ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; + printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; + printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" @@ -8090,7 +8758,7 @@ --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; @@ -8099,7 +8767,7 @@ as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; + printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; @@ -8127,7 +8795,7 @@ if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" @@ -8141,7 +8809,7 @@ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX - $as_echo "$ac_log" + printf "%s\n" "$ac_log" } >&5 _ACEOF @@ -8173,9 +8841,9 @@ # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands + test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files + test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers + test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree @@ -8511,7 +9179,7 @@ esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done @@ -8519,17 +9187,17 @@ # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | + ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac @@ -8546,7 +9214,7 @@ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | +printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -8570,9 +9238,9 @@ case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -8634,8 +9302,8 @@ case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' @@ -8679,9 +9347,9 @@ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" @@ -8697,20 +9365,20 @@ # if test x"$ac_file" != x-; then { - $as_echo "/* $configure_input */" \ + printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -$as_echo "$as_me: $ac_file is unchanged" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else - $as_echo "/* $configure_input */" \ + printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi @@ -8730,7 +9398,7 @@ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$_am_arg" | +printf "%s\n" X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -8750,8 +9418,8 @@ s/.*/./; q'`/stamp-h$_am_stamp_count ;; - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} + :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac @@ -8777,7 +9445,7 @@ for am_mf do # Strip MF so we end up with the name of the file. - am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line @@ -8789,7 +9457,7 @@ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$am_mf" | +printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -8811,7 +9479,7 @@ $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$am_mf" | +printf "%s\n" X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -8836,10 +9504,12 @@ (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments - for automatic dependency tracking. Try re-running configure with the + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } @@ -8885,17 +9555,18 @@ $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else +ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval test \${ac_cv_prog_make_${ac_make}_set+y} +then : + printf %s "(cached) " >&6 +else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @@ -8911,12 +9582,12 @@ rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } SET_MAKE= else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi @@ -8963,6 +9634,9 @@ echo "doc file install path: \`eval eval eval echo $docdir\`" echo "examples install path: \`eval eval eval echo $exampledir\`" if test -n "$drivedbdir"; then + if test "$drivedbinstdir" != "$drivedbdir"; then + echo "installed drivedb file: \`eval eval eval echo $drivedbinstdir\`/drivedb.h" + fi echo "drive database file: \`eval eval eval echo $drivedbdir\`/drivedb.h" if test "$with_update_smart_drivedb" = "yes"; then echo "database update script: \`eval eval eval echo $sbindir\`/update-smart-drivedb" @@ -9031,37 +9705,37 @@ echo "-----------------------------------------------------------------------------" ` -{ $as_echo "$as_me:${as_lineno-$LINENO}: +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: $info " >&5 -$as_echo "$as_me: +printf "%s\n" "$as_me: $info " >&6;} # TODO: Remove when NVMe support is no longer EXPERIMENTAL case "$os_nvme_devicescan:$with_nvme_devicescan" in - used:yes) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + used:yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: The default for the inclusion of NVME devices in smartd.conf 'DEVICESCAN' and 'smartctl --scan' has been changed to 'yes' on this platform. If '--without-nvme-devicescan' is still needed, please inform $PACKAGE_BUGREPORT. Use option '--with-nvme-devicescan' to suppress this warning. " >&5 -$as_echo "$as_me: WARNING: +printf "%s\n" "$as_me: WARNING: The default for the inclusion of NVME devices in smartd.conf 'DEVICESCAN' and 'smartctl --scan' has been changed to 'yes' on this platform. If '--without-nvme-devicescan' is still needed, please inform $PACKAGE_BUGREPORT. Use option '--with-nvme-devicescan' to suppress this warning. " >&2;} ;; - used:no) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + used:no) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: This version of smartmontools provides NVMe support which is still EXPERIMENTAL. NVMe devices are not yet included in smartd.conf 'DEVICESCAN' and 'smartctl --scan' unless '-d nvme' is specified. Use option '--with-nvme-devicescan' to include NVMe devices. Use option '--without-nvme-devicescan' to suppress this warning. " >&5 -$as_echo "$as_me: WARNING: +printf "%s\n" "$as_me: WARNING: This version of smartmontools provides NVMe support which is still EXPERIMENTAL. NVMe devices are not yet included in smartd.conf 'DEVICESCAN' and 'smartctl --scan' unless '-d nvme' is specified. @@ -9070,32 +9744,61 @@ " >&2;} ;; esac -# TODO: Remove after smartmontools 6.7 -if test "$with_working_snprintf" != "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -The option '--without-working-snprintf' is deprecated and will be removed -in a future version of smartmontools. If you still need support for -pre-C99 snprintf(), please inform $PACKAGE_BUGREPORT. +# TODO: Remove after smartmontools 7.3 +if test -n "$with_solaris_sparc_ata"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: +The option '--with-solaris-sparc-ata' is deprecated and will be +removed in a future version of smartmontools. If this option is +still needed, please inform $PACKAGE_BUGREPORT. " >&5 -$as_echo "$as_me: WARNING: -The option '--without-working-snprintf' is deprecated and will be removed -in a future version of smartmontools. If you still need support for -pre-C99 snprintf(), please inform $PACKAGE_BUGREPORT. +printf "%s\n" "$as_me: WARNING: +The option '--with-solaris-sparc-ata' is deprecated and will be +removed in a future version of smartmontools. If this option is +still needed, please inform $PACKAGE_BUGREPORT. " >&2;} fi +# TODO: Remove after smartmontools 7.4 +case "$host:$with_signal_func" in + *-*-mingw*:*|*:sigaction) ;; + *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: +The option '--with-signal-func=$with_signal_func' is deprecated and will be +removed in a future version of smartmontools. If this option is +still needed, please inform $PACKAGE_BUGREPORT. +" >&5 +printf "%s\n" "$as_me: WARNING: +The option '--with-signal-func=$with_signal_func' is deprecated and will be +removed in a future version of smartmontools. If this option is +still needed, please inform $PACKAGE_BUGREPORT. +" >&2;} ;; +esac + case "$host_os:$with_libsystemd:$use_libsystemd:$PKG_CONFIG" in linux*:auto:no:?*) if $PKG_CONFIG systemd >/dev/null 2>&1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: systemd(1) is used on this system but smartd systemd notify support will not be available because libsystemd-dev[el] package is not installed. Use option '--without-libsystemd' to suppress this warning. " >&5 -$as_echo "$as_me: WARNING: +printf "%s\n" "$as_me: WARNING: systemd(1) is used on this system but smartd systemd notify support will not be available because libsystemd-dev[el] package is not installed. Use option '--without-libsystemd' to suppress this warning. " >&2;} fi ;; esac + +test "$cxx14_option" != "unknown" || { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: +This version of smartmontools does not use C++14 enhancements, but +future versions possibly will. +This script was unable to determine a compiler option to enable C++14. +Please send info about compiler and platform to +$PACKAGE_BUGREPORT - Thanks!" >&5 +printf "%s\n" "$as_me: WARNING: +This version of smartmontools does not use C++14 enhancements, but +future versions possibly will. +This script was unable to determine a compiler option to enable C++14. +Please send info about compiler and platform to +$PACKAGE_BUGREPORT - Thanks!" >&2;} + diff -Nru smartmontools-7.1/configure.ac smartmontools-7.3/configure.ac --- smartmontools-7.1/configure.ac 2019-12-30 15:00:49.000000000 +0000 +++ smartmontools-7.3/configure.ac 2022-02-28 16:34:27.000000000 +0000 @@ -1,17 +1,17 @@ # -# $Id: configure.ac 5022 2019-12-30 15:00:49Z chrfranke $ +# $Id: configure.ac 5338 2022-02-28 16:34:26Z chrfranke $ # dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.60]) -AC_INIT([smartmontools], [7.1], [smartmontools-support@listi.jpberlin.de]) +AC_INIT([smartmontools],[7.3],[smartmontools-support@listi.jpberlin.de]) AM_INIT_AUTOMAKE([1.10 foreign]) # Version of drive database branch -smartmontools_drivedb_version=7.0 +smartmontools_drivedb_version=7.3 -smartmontools_cvs_tag=`echo '$Id: configure.ac 5022 2019-12-30 15:00:49Z chrfranke $'` -smartmontools_release_date=2019-12-30 -smartmontools_release_time="15:00:11 UTC" +smartmontools_cvs_tag=`echo '$Id: configure.ac 5338 2022-02-28 16:34:26Z chrfranke $'` +smartmontools_release_date=2022-02-28 +smartmontools_release_time="16:33:40 UTC" AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args", [smartmontools Configure Arguments]) AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_DATE, "$smartmontools_release_date", [smartmontools Release Date]) @@ -20,7 +20,7 @@ AC_DEFINE_UNQUOTED(PACKAGE_HOMEPAGE, "https://www.smartmontools.org/", [smartmontools Home Page]) AC_CONFIG_SRCDIR([smartctl.cpp]) -AC_CONFIG_HEADER([config.h]) +AC_CONFIG_HEADERS([config.h]) AM_MAINTAINER_MODE @@ -61,16 +61,25 @@ ;; esac +AC_MSG_CHECKING([whether reproducible build is selected (SOURCE_DATE_EPOCH)]) +res=no +if test -n "$SOURCE_DATE_EPOCH"; then + res=yes + test -z "`echo "$SOURCE_DATE_EPOCH" | sed 's,[[0-9]]*,,'`" || res=error +fi +AC_MSG_RESULT([$res]) +case $res in + error) AC_MSG_ERROR([Malformed SOURCE_DATE_EPOCH]) ;; + yes) CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-DSOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" ;; +esac + # Check for SVN. AC_MSG_CHECKING([whether this is a build from SVN]) is_svn_build=no svn_deps= if test -f "$srcdir/.svn/wc.db"; then - # SVN 1.7, 1.8 working copy + # SVN >= 1.7 working copy svn_deps='${srcdir}/.svn/wc.db' -elif test -f "${srcdir}/.svn/entries"; then - # SVN <= 1.6 working copy (SVN 1.7 has empty entries file) - svn_deps='${srcdir}/.svn/entries' fi if test -n "$svn_deps"; then is_svn_build=unknown @@ -82,10 +91,6 @@ AM_CONDITIONAL(IS_SVN_BUILD, [test "$is_svn_build" = "yes"]) AC_MSG_RESULT([$is_svn_build]) -# Note: On Linux, clock_gettime() requires -lrt which implies -lpthreads -# Check omitted for now, gettimeofday() provides reasonable precision -# AC_SEARCH_LIBS(clock_gettime, rt) - # Checks for header files. AC_CHECK_HEADERS([locale.h]) AC_CHECK_HEADERS([byteswap.h], [], [], []) @@ -112,11 +117,9 @@ *-*-netbsd*|*-*-openbsd*) AC_CHECK_HEADERS([dev/ata/atavar.h]) ;; - *-*-cygwin*|*-*-mingw*) - # Check for Windows DDK header files - AC_CHECK_HEADERS([ntdddisk.h ddk/ntdddisk.h], [], [], [AC_INCLUDES_DEFAULT -#include -]) + *-*-mingw*) + # Older MinGW-w64 (5.0.3) require -lwinpthread + AC_SEARCH_LIBS([clock_gettime], [winpthread]) ;; esac @@ -128,8 +131,6 @@ AC_CHECK_FUNCS([getopt_long], [need_getopt_long=no], [need_getopt_long=yes]) AM_CONDITIONAL(NEED_GETOPT_LONG, [test "$need_getopt_long" = "yes"]) -AC_CHECK_FUNCS([clock_gettime ftime gettimeofday]) - # Check byte ordering (defines WORDS_BIGENDIAN) AC_C_BIGENDIAN @@ -186,9 +187,23 @@ AC_SUBST(exampledir) drivedbdir='${datadir}/${PACKAGE}' +drivedbinstdir= +AC_ARG_WITH(drivedbinstdir, + [AS_HELP_STRING([--with-drivedbinstdir@<:@=DIR|yes|no@:>@], + [Optional separate install location of drive database file [no] (yes=DATADIR/smartmontools)])], + [ case "$withval" in + no) ;; + yes) drivedbinstdir=$drivedbdir; drivedbdir='${localstatedir}/lib/${PACKAGE}' ;; + *) drivedbinstdir=$withval; drivedbdir='${localstatedir}/lib/${PACKAGE}' ;; + esac + ]) + AC_ARG_WITH(drivedbdir, - [AS_HELP_STRING([--with-drivedbdir@<:@=DIR|yes|no@:>@], [Location of drive database file [DATADIR/smartmontools]])], + [AS_HELP_STRING([--with-drivedbdir@<:@=DIR|yes|no@:>@], + [Location of drive database file [DATADIR/smartmontools or LOCALSTATEDIR/lib/smartmontools if separate INSTDIR]])], [case "$withval" in yes) ;; no) drivedbdir= ;; *) drivedbdir="$withval" ;; esac]) +test -n "$drivedbinstdir" || drivedbinstdir=$drivedbdir +AC_SUBST(drivedbinstdir) AC_SUBST(drivedbdir) AM_CONDITIONAL(ENABLE_DRIVEDB, [test -n "$drivedbdir"]) @@ -198,7 +213,7 @@ [Install update-smart-drivedb script (and backport it to branches/RELEASE_X_Y_DRIVEDB) [yes]])], [ case "$withval" in yes|no) ;; - 5.4[[0-3]]|6.[[0-9]]) drivedb_version=$withval; with_update_smart_drivedb=yes ;; + 5.4[[0-3]]|6.[[0-6]]|7.[[023]]) drivedb_version=$withval; with_update_smart_drivedb=yes ;; *) AC_MSG_ERROR([Invalid drivedb branch version: $withval]) ;; esac ], @@ -390,6 +405,7 @@ [AS_HELP_STRING([--with-nvme-devicescan@<:@=yes|no@:>@], [Include NVMe devices in smartd DEVICESCAN [Linux,Windows:yes;Others:no]])]) +# TODO: Remove after smartmontools 7.3 AC_ARG_WITH(solaris-sparc-ata, [AS_HELP_STRING([--with-solaris-sparc-ata@<:@=yes|no@:>@], [Enable legacy ATA support on Solaris SPARC (requires os_solaris_ata.s from SVN repository) [no]])]) @@ -405,6 +421,7 @@ ;; esac +# TODO: Remove after smartmontools 7.4 AC_ARG_WITH(signal-func, [AS_HELP_STRING([--with-signal-func=@<:@sigaction|sigset|signal@:>@], [Function to set signal(2) action [sigaction]])], @@ -422,20 +439,10 @@ *) AC_MSG_ERROR([Invalid option '--with-signal-func=$with_signal_func']) ;; esac -# TODO: Remove after smartmontools 6.7 -AC_ARG_WITH(working-snprintf, - [AS_HELP_STRING([--with-working-snprintf@<:@=yes|no@:>@], - [Function snprintf() handles output truncation as specified by C99 [yes]])], - [], [with_working_snprintf=yes]) - -if test "$with_working_snprintf" = "yes"; then - AC_DEFINE(HAVE_WORKING_SNPRINTF, 1, [Define to 1 if the `snprintf' function is sane.]) dnl `vim syntax -fi - -case "$with_working_snprintf:$host_os: $CPPFLAGS $CXXFLAGS" in - yes:mingw*:*\ -[[DU]]__USE_MINGW_ANSI_STDIO*) +case "$host_os: $CPPFLAGS $CXXFLAGS" in + mingw*:*\ -[[DU]]__USE_MINGW_ANSI_STDIO*) ;; - yes:mingw*:*) + mingw*:*) # Older MinGW (4.6.3) do not properly define PRI?64 if __USE_MINGW_ANSI_STDIO is set. # Newer MinGW (4.9.1) set __USE_MINGW_ANSI_STDIO in first C++ include which may be too late. # Set __USE_MINGW_ANSI_STDIO always and fail if not fully supported. @@ -455,7 +462,7 @@ if test "$result" != "yes"; then AC_MSG_ERROR([ This version of $CXX does not support __USE_MINGW_ANSI_STDIO. -Use option '--without-working-snprintf' to skip this check. +Use option 'CPPFLAGS=-U__USE_MINGW_ANSI_STDIO' to skip this check. Please send info about your system to $PACKAGE_BUGREPORT. ]) fi @@ -529,52 +536,62 @@ AC_ARG_WITH(cxx11-option, [AS_HELP_STRING([--with-cxx11-option=@<:@OPTION|auto|no@:>@], - [Compiler option to enable C++11 support for future versions of smartmontools, 'no' if unsupported [auto]])], + [Compiler option to enable C++11 support, 'no' to skip check [auto]])], [], [with_cxx11_option=auto]) -check_cxx11_support() -{ - save_CXXFLAGS=$CXXFLAGS - CXXFLAGS=$1 - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #if __cplusplus < 201103L - #error false - #endif - // use some C++11 features (and return v * 42 :-) - auto cxx11(long v) noexcept -> decltype(v) { - typedef decltype(v) t; t r = v; - static const t a[] = { -7, -1, 1, 2, 3 }; - static_assert(sizeof(r) == sizeof(a[0]), "fail"); - auto f = [](t x, t y){ return x * y; }; - for (const auto & e : a) r = f(r, e); - return r; - }]])], - [CXXFLAGS=$save_CXXFLAGS; return 0], [CXXFLAGS=$save_CXXFLAGS; return 1]) -} +cxx14_option= +case "$with_cxx11_option" in + no) ;; + *) + AC_MSG_CHECKING([for $CXX option to accept C++14]) + cxx14_option=unknown + save_CXXFLAGS=$CXXFLAGS + for option in "" "-std=gnu++14" "-std=gnu++1y" "-std=c++14" "-std=c++1y"; do + CXXFLAGS="$save_CXXFLAGS $option" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #if __cplusplus < 201402 + #error false + #endif]])], [cxx14_option=$option]) + test "$cxx14_option" = "unknown" || break + done + CXXFLAGS=$save_CXXFLAGS + AC_MSG_RESULT([${cxx14_option:-none needed}]) + ;; +esac case "$with_cxx11_option" in no) ;; auto) - AC_MSG_CHECKING([for $CXX option to accept C++11]) - with_cxx11_option=unknown + res=; test "$cxx14_option" = "unknown" || res=" but not C++14" + AC_MSG_CHECKING([for $CXX option to accept C++11$res]) + save_CXXFLAGS=$CXXFLAGS + res=unknown for option in "" "-std=gnu++11" "-std=gnu++0x" "-std=c++11" "-std=c++0x"; do - if check_cxx11_support "$option"; then with_cxx11_option=$option; break; fi + test "$option" != "$cxx14_option" || continue + CXXFLAGS="$save_CXXFLAGS $option" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #if __cplusplus < 201103 || 201402 <= __cplusplus + #error false + #endif]])], [res=$option]) + test "$res" = "unknown" || break done - AC_MSG_RESULT([${with_cxx11_option:-none needed}]) - test "$with_cxx11_option" != "unknown" || AC_MSG_ERROR([ -This version of smartmontools does not use C++11 features, but future -versions possibly will. -This script was unable to determine a compiler option to enable C++11. -Use option '--with-cxx11-option=OPTION' to specify the compiler option -(it will be used in the actual build only if '--with-cxx11-regex' is set). -Use option '--without-cxx11-option' to suppress this error message if the -compiler lacks C++11 support. + AC_MSG_RESULT([${res:-none needed}]) + test "$res" != "unknown" || res=$cxx14_option + test "$res" != "unknown" || AC_MSG_ERROR([ +This script was unable to determine a compiler option to accept C++11. +Use option '--with-cxx11-option=OPTION' to specify a compiler option. +Use option '--without-cxx11-option' to try anyway without this check. In both cases, please send info about compiler and platform to $PACKAGE_BUGREPORT - Thanks!]) + CXXFLAGS="$save_CXXFLAGS${res:+ }$res" ;; *) AC_MSG_CHECKING([whether $CXX $with_cxx11_option accepts C++11]) - res=no; check_cxx11_support "$with_cxx11_option" && res=yes + CXXFLAGS="$CXXFLAGS${with_cxx11_option:+ }$with_cxx11_option" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #if __cplusplus < 201103 + #error false + #endif]])], [res=yes], [res=no]) AC_MSG_RESULT([$res]) test "$res" = "yes" || AC_MSG_ERROR([$CXX $with_cxx11_option does not accept C++11]) ;; @@ -587,11 +604,6 @@ need_regex=no if test "$with_cxx11_regex" = "yes"; then AC_DEFINE(WITH_CXX11_REGEX, 1, [Define to 1 to use C++11 std::regex instead of POSIX regex(3)]) - case "$with_cxx11_option: $CXXFLAGS " in - no:*) AC_MSG_ERROR(['--with-cxx11-regex' requires C++11 support]) ;; - ?*:*\ $with_cxx11_option\ *) ;; - ?*:*) CXXFLAGS="$CXXFLAGS $with_cxx11_option" ;; - esac else AC_CHECK_FUNCS([regcomp], [], [need_regex=yes]) fi @@ -605,9 +617,10 @@ os_libs= os_dltools='curl wget lynx svn' os_mailer=mail -os_hostname="'hostname'" +os_hostname="'hostname' 'uname -n'" os_dnsdomainname= os_nisdomainname="'domainname'" +os_posix=yes os_darwin=no os_solaris=no os_win32=no @@ -660,7 +673,7 @@ *-*-cygwin*) os_deps='os_win32.o dev_areca.o' os_mailer='email' - os_hostname="'hostname' 'echo "'"${HOSTNAME?unset}"'"'" + os_hostname="'hostname' 'uname -n' 'echo "'"${HOSTNAME?unset}"'"'" os_dnsdomainname="'dnsdomainname' 'hostname -d' 'echo "'"${USERDNSDOMAIN?unset}"'"'" os_nisdomainname= os_win32=yes @@ -669,6 +682,7 @@ ;; x86_64-*-mingw*) os_deps='os_win32.o dev_areca.o' + os_posix=no os_win32=yes os_win32_mingw=yes os_win64=yes @@ -677,6 +691,7 @@ ;; *-*-mingw*) os_deps='os_win32.o dev_areca.o' + os_posix=no os_win32=yes os_win32_mingw=yes os_man_filter=Windows @@ -694,6 +709,7 @@ ;; *-*-os2-*) os_deps='os_os2.o' + os_posix=no ;; *) os_deps='os_generic.o' @@ -703,6 +719,12 @@ # Replace if '--with-os-deps' was specified test -z "$with_os_deps" || os_deps="$with_os_deps" +AC_MSG_CHECKING([whether the OS provides a POSIX API]) +if test "$os_posix" = "yes"; then + AC_DEFINE(HAVE_POSIX_API, 1, [Define to 1 if the OS provides a POSIX API]) +fi +AC_MSG_RESULT([$os_posix]) + # Check if we need adapter to old interface (dev_legacy.cpp) os_src=`echo "${os_deps}"|sed -n 's,^\([[^ .]]*\)\.o.*$,\1.cpp,p'` AC_MSG_CHECKING([whether ${os_src} uses new interface]) @@ -747,6 +769,7 @@ AC_SUBST([DRIVEDB_BRANCH]) # Enable platform-specific makefile sections +AM_CONDITIONAL(OS_POSIX, [test "$os_posix" = "yes"]) AM_CONDITIONAL(OS_DARWIN, [test "$os_darwin" = "yes"]) AM_CONDITIONAL(OS_SOLARIS, [test "$os_solaris" = "yes"]) AM_CONDITIONAL(OS_WIN32, [test "$os_win32" = "yes"]) @@ -765,15 +788,20 @@ *\ -W\ *|*\ -Wextra\ *) ;; *) CXXFLAGS="$CXXFLAGS -W" ;; esac - # Add -Wformat=2 (GCC 3.0) -fstack-protector[-strong] (GCC 4.1[4.9]) if supported - # and no -W or -f option was set in configure cmdline (TODO: -Wformat-signedness) - for option in "-Wformat=2" "-fstack-protector-strong" "-fstack-protector"; do + # Add -Wformat=2 (GCC 3.0), + # -Werror=return-type (G++ >= 8.0 assumes that control never reaches the end of a non-void function), + # -fstack-protector[-strong] (GCC 4.1[4.9]) + # if supported and no -W or -f option was set in configure cmdline (TODO: -Wformat-signedness) + for option in "-Wformat=2" "-Werror=return-type" "-fstack-protector-strong" "-fstack-protector"; do case " $orig_CXXFLAGS:$option" in *\ -W*:-W*|*\ -f*:-f*) continue ;; esac case " $CXXFLAGS:$option" in *\ -fstack-p*:-fstack-p*) continue ;; esac AC_MSG_CHECKING([whether $CXX supports $option]) save_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS $option" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [res=yes], [res=no; CXXFLAGS=$save_CXXFLAGS]) + # For -fstack-protector*, check that '__stack_chk_*()' functions are available. + AC_LINK_IFELSE([AC_LANG_PROGRAM([[int i;]], + [[volatile char buf[10]; buf[i] = 0;]])], + [res=yes], [res=no; CXXFLAGS=$save_CXXFLAGS]) AC_MSG_RESULT([$res]) done else @@ -880,6 +908,9 @@ echo "doc file install path: \`eval eval eval echo $docdir\`" echo "examples install path: \`eval eval eval echo $exampledir\`" if test -n "$drivedbdir"; then + if test "$drivedbinstdir" != "$drivedbdir"; then + echo "installed drivedb file: \`eval eval eval echo $drivedbinstdir\`/drivedb.h" + fi echo "drive database file: \`eval eval eval echo $drivedbdir\`/drivedb.h" if test "$with_update_smart_drivedb" = "yes"; then echo "database update script: \`eval eval eval echo $sbindir\`/update-smart-drivedb" @@ -970,15 +1001,25 @@ ]) ;; esac -# TODO: Remove after smartmontools 6.7 -if test "$with_working_snprintf" != "yes"; then +# TODO: Remove after smartmontools 7.3 +if test -n "$with_solaris_sparc_ata"; then AC_MSG_WARN([ -The option '--without-working-snprintf' is deprecated and will be removed -in a future version of smartmontools. If you still need support for -pre-C99 snprintf(), please inform $PACKAGE_BUGREPORT. +The option '--with-solaris-sparc-ata' is deprecated and will be +removed in a future version of smartmontools. If this option is +still needed, please inform $PACKAGE_BUGREPORT. ]) fi +# TODO: Remove after smartmontools 7.4 +case "$host:$with_signal_func" in + *-*-mingw*:*|*:sigaction) ;; + *) AC_MSG_WARN([ +The option '--with-signal-func=$with_signal_func' is deprecated and will be +removed in a future version of smartmontools. If this option is +still needed, please inform $PACKAGE_BUGREPORT. +]) ;; +esac + case "$host_os:$with_libsystemd:$use_libsystemd:$PKG_CONFIG" in linux*:auto:no:?*) if $PKG_CONFIG systemd >/dev/null 2>&1; then @@ -989,3 +1030,10 @@ ]) fi ;; esac + +test "$cxx14_option" != "unknown" || AC_MSG_WARN([ +This version of smartmontools does not use C++14 enhancements, but +future versions possibly will. +This script was unable to determine a compiler option to enable C++14. +Please send info about compiler and platform to +$PACKAGE_BUGREPORT - Thanks!]) diff -Nru smartmontools-7.1/cppcheck.sh smartmontools-7.3/cppcheck.sh --- smartmontools-7.1/cppcheck.sh 2019-10-19 15:34:34.000000000 +0000 +++ smartmontools-7.3/cppcheck.sh 2022-02-09 08:02:23.000000000 +0000 @@ -4,11 +4,11 @@ # # Home page of code is: https://www.smartmontools.org # -# Copyright (C) 2019 Christian Franke +# Copyright (C) 2019-21 Christian Franke # # SPDX-License-Identifier: GPL-2.0-or-later # -# $Id: cppcheck.sh 4974 2019-10-19 15:34:34Z chrfranke $ +# $Id: cppcheck.sh 5316 2022-02-09 08:02:23Z samm2 $ # set -e @@ -17,18 +17,20 @@ usage() { - echo "Usage: $myname [-v|-q] [-jJOBS] [--library=CFG] [--platform=TYPE] [FILE ...]" + echo "Usage: $myname [-v|-q] [-c CPPCHECK] [-jJOBS] [--library=CFG] [--platform=TYPE] [FILE ...]" exit 1 } # Parse options jobs= v= +cppcheck="cppcheck" library="--library=posix" platform="--platform=unix64" unused_func=",unusedFunction" while true; do case $1 in + -c) shift; test -n "$1" || usage; cppcheck=$1 ;; -j?*) jobs=$1; unused_func= ;; -q) v="-q" ;; -v) v="-v" ;; @@ -58,10 +60,10 @@ fi # Check cppcheck version -ver=$(cppcheck --version) || exit 1 +ver=$("$cppcheck" --version) || exit 1 ver=${ver##* } case $ver in - 1.85) ;; + 1.8[56]|2.[237]) ;; *) echo "$myname: cppcheck $ver not tested with this script" ;; esac @@ -74,12 +76,9 @@ #style asctime_rCalled:utility.cpp asctime_sCalled:utility.cpp - bzeroCalled - bcopyCalled ftimeCalled readdirCalled strtokCalled - missingOverride unusedStructMember unusedFunction:sg_unaligned.h unmatchedSuppression @@ -105,13 +104,12 @@ -DENOTSUP=1 -DHAVE_ATTR_PACKED -DHAVE_CONFIG_H - -UHAVE_DDK_NTDDDISK_H - -DHAVE_NTDDDISK_H -DSG_IO=1 -DSMARTMONTOOLS_SVN_REV=\"r1\" -DSMARTMONTOOLS_ATTRIBUTELOG=\"/file\" -DSMARTMONTOOLS_SAVESTATES=\"/file\" -DSMARTMONTOOLS_DRIVEDBDIR=\"/dir\" + -DSOURCE_DATE_EPOCH=1665402854 -Umakedev -Ustricmp" @@ -128,7 +126,7 @@ EOF # Run cppcheck with swapped stdout<>stderr -cppcheck \ +"$cppcheck" \ $v \ $jobs \ --enable="$enable" \ diff -Nru smartmontools-7.1/debian/changelog smartmontools-7.3/debian/changelog --- smartmontools-7.1/debian/changelog 2020-07-19 09:34:42.000000000 +0000 +++ smartmontools-7.3/debian/changelog 2023-07-05 09:18:50.000000000 +0000 @@ -1,14 +1,38 @@ -smartmontools (7.1-2~simonarons) focal; urgency=medium +smartmontools (7.3-2~simonarons) focal; urgency=medium - * Updated drive database. + * Backport to focal. - -- Simon Arons Sun, 19 Jul 2020 09:34:42 +0000 + -- Simon Arons Wed, 05 Jul 2023 09:18:50 +0000 -smartmontools (7.1-1build1) focal; urgency=medium +smartmontools (7.3-1) unstable; urgency=medium - * No-change rebuild for libgcc-s1 package name change. + * New upstream release. + * Standards-Version: 4.6.0. + * Updated Homepage URL (Closes: #979547). + Thanks, Paul Wise. + * Removed "default_never-quit.patch" (Closes: #1006630). + Thanks, Christian Franke. + + -- Dmitry Smirnov Wed, 27 Apr 2022 15:39:01 +1000 + +smartmontools (7.2-1) unstable; urgency=medium + + * New upstream release. + + fixed failure with Micron 2200S NVME (Closes: #947803). + + service: removed "StandardOutput=syslog" (Closes: #969048, #968168). + * smartd-runner: replaced "tmpfile" with "mktemp" (Closes: #969667) + Thanks, Bob Proulx. + * rules: don't set INSTALL_PROGRAM and CFLAGS optimisation flags + (Closes: #968526). + Thanks, Simon McVittie. + * Install "drivedb.h" to "/usr/share/smartmontools" and copy it into + "/var/lib/smartmontools/drivedb/" in postinst (Closes: #976696). + Thanks, Paul Wise. + * Removed ancient workaround from postinst. + * Standards-Version: 4.5.0 + * Rules-Requires-Root: no - -- Matthias Klose Sat, 21 Mar 2020 13:29:22 +0100 + -- Dmitry Smirnov Thu, 07 Jan 2021 20:47:11 +1100 smartmontools (7.1-1) unstable; urgency=medium diff -Nru smartmontools-7.1/debian/control smartmontools-7.3/debian/control --- smartmontools-7.1/debian/control 2020-01-04 08:33:20.000000000 +0000 +++ smartmontools-7.3/debian/control 2023-07-05 09:18:39.000000000 +0000 @@ -1,7 +1,7 @@ Source: smartmontools Section: utils Priority: optional -Standards-Version: 4.4.1 +Standards-Version: 4.6.0 Maintainer: Dmitry Smirnov Uploaders: Florian Maier , Jonathan Dowland , @@ -17,7 +17,8 @@ pkg-config, Vcs-Git: https://salsa.debian.org/debian/smartmontools.git Vcs-Browser: https://salsa.debian.org/debian/smartmontools -Homepage: http://smartmontools.sourceforge.net/ +Homepage: https://www.smartmontools.org/ +Rules-Requires-Root: no Package: smartmontools Architecture: any diff -Nru smartmontools-7.1/debian/copyright smartmontools-7.3/debian/copyright --- smartmontools-7.1/debian/copyright 2020-01-04 08:32:52.000000000 +0000 +++ smartmontools-7.3/debian/copyright 2023-07-05 09:18:39.000000000 +0000 @@ -5,7 +5,7 @@ Files: * Copyright: - 2004-2019 Christian Franke + 2004-2022 Christian Franke 2016 Casey Biemiller 2014 Alex Samorukov 2000 Andre Hedrick @@ -13,7 +13,7 @@ 2002-2018 Bruce Allen 2003-2015 Casper Dik 2004-2010 David Snyder - 2003-2018 Douglas Gilbert + 2003-2020 Douglas Gilbert 2003-2010 Eduard Martinescu 2012 Hank Wu 2013 Hannes von Haugwitz @@ -91,7 +91,7 @@ Files: debian/* Copyright: - 2019-2020 Dmitry Smirnov + 2019-2022 Dmitry Smirnov 2003-2009 Guido Guenther 2009-2015 Giuseppe Iuculano 2010 Florian Weimer diff -Nru smartmontools-7.1/debian/patches/52_remove-pragma.diff smartmontools-7.3/debian/patches/52_remove-pragma.diff --- smartmontools-7.1/debian/patches/52_remove-pragma.diff 2020-01-04 08:33:20.000000000 +0000 +++ smartmontools-7.3/debian/patches/52_remove-pragma.diff 2023-07-05 09:18:39.000000000 +0000 @@ -232,7 +232,7 @@ struct ata_sct_error_recovery_control_command { unsigned short action_code; // 3 = Error Recovery Control - unsigned short function_code; // 1 = Set, 2 = Return + unsigned short function_code; // 1 = Set Current, 2 = Return Current, 3 = Set Power-on, 4 = Return Power-on, 5 = Restore Default @@ -554,9 +531,8 @@ STATIC_ASSERT(sizeof(ata_sct_error_recovery_control_command) == 512); diff -Nru smartmontools-7.1/debian/patches/61_cciss-doc.patch smartmontools-7.3/debian/patches/61_cciss-doc.patch --- smartmontools-7.1/debian/patches/61_cciss-doc.patch 2019-10-09 10:15:46.000000000 +0000 +++ smartmontools-7.3/debian/patches/61_cciss-doc.patch 2023-07-05 09:18:39.000000000 +0000 @@ -33,7 +33,7 @@ #/dev/sdd -d hpt,1/1 -a -s L/../../7/01 --- a/smartd.conf.5.in +++ b/smartd.conf.5.in -@@ -150,8 +150,14 @@ +@@ -162,8 +162,14 @@ /dev/tws0 \-d 3ware,1 \-a \-s L/../../7/02 .\" %ENDIF OS FreeBSD .\" %IF OS FreeBSD Linux @@ -48,7 +48,7 @@ # Start short self\-tests daily between 1\-2, 2\-3, and # 3\-4 am. .\" %ENDIF OS FreeBSD Linux -@@ -225,8 +231,12 @@ +@@ -237,8 +243,12 @@ # ################################################ .Ve diff -Nru smartmontools-7.1/debian/patches/63_removable.patch smartmontools-7.3/debian/patches/63_removable.patch --- smartmontools-7.1/debian/patches/63_removable.patch 2019-10-09 10:11:03.000000000 +0000 +++ smartmontools-7.3/debian/patches/63_removable.patch 2023-07-05 09:18:39.000000000 +0000 @@ -9,11 +9,10 @@ smartd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/smartd.conf b/smartd.conf -index 59addd4..4cdede7 100644 --- a/smartd.conf +++ b/smartd.conf -@@ -18,7 +18,7 @@ +@@ -17,9 +17,9 @@ + # ATA and SCSI devices. DEVICESCAN may be followed by any of the # Directives listed below, which will be applied to all devices that # are found. Most users should comment out DEVICESCAN and explicitly # list the devices that they wish to monitor. @@ -22,3 +21,4 @@ # Alternative setting to ignore temperature and power-on hours reports # in syslog. + #DEVICESCAN -I 194 -I 231 -I 9 diff -Nru smartmontools-7.1/debian/patches/default_never-quit.patch smartmontools-7.3/debian/patches/default_never-quit.patch --- smartmontools-7.1/debian/patches/default_never-quit.patch 2019-12-01 08:56:10.000000000 +0000 +++ smartmontools-7.3/debian/patches/default_never-quit.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -Last-Update: 2019-10-18 -Forwarded: not-needed -Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=862908 -Bug-Upstream: https://www.smartmontools.org/ticket/1248 -Author: Dmitry Smirnov -Description: smartd to keep running without disks. - Daemon should behave consistently on all systems. By allowing daemon to - start even on the diskless system one can implement udev handler to HUP - daemon to trigger rescan for new disks. - See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=893665 - ---- a/smartd.8.in -+++ b/smartd.8.in -@@ -349,9 +349,9 @@ - arguments are to this option are: - .Sp - .I nodev - \- Exit if there are no devices to monitor, or if any errors are found --at startup in the configuration file. This is the default. -+at startup in the configuration file. - .Sp - .I errors - \- Exit if there are no devices to monitor, or if any errors are found - in the configuration file /usr/local/etc/smartd.conf at startup or whenever it -@@ -367,8 +367,9 @@ - invalid command line arguments). In this mode, even if there are no - devices to monitor, or if the configuration file - \fB/usr/local/etc/smartd.conf\fP has errors, \fBsmartd\fP will continue to run, - waiting to load a configuration file listing valid devices. -+This is the default. - .Sp - .I onecheck - \- Start \fBsmartd\fP in debug mode, then register devices, then check - device's SMART status once, and then exit with zero exit status if all ---- a/smartd.cpp -+++ b/smartd.cpp -@@ -181,9 +181,9 @@ - enum quit_t { - QUIT_NODEV, QUIT_NODEVSTARTUP, QUIT_NEVER, QUIT_ONECHECK, - QUIT_SHOWTESTS, QUIT_ERRORS - }; --static quit_t quit = QUIT_NODEV; -+static quit_t quit = QUIT_NEVER; - - // command-line; this is the default syslog(3) log facility to use. - static int facility=LOG_DAEMON; - diff -Nru smartmontools-7.1/debian/patches/manpage.diff smartmontools-7.3/debian/patches/manpage.diff --- smartmontools-7.1/debian/patches/manpage.diff 2020-01-04 08:33:20.000000000 +0000 +++ smartmontools-7.3/debian/patches/manpage.diff 2023-07-05 09:18:39.000000000 +0000 @@ -9,7 +9,7 @@ --- a/smartd.conf.5.in +++ b/smartd.conf.5.in -@@ -1651,9 +1651,9 @@ +@@ -1749,9 +1749,9 @@ /sbin/shutdown \-hf now .Ve .Sp diff -Nru smartmontools-7.1/debian/patches/series smartmontools-7.3/debian/patches/series --- smartmontools-7.1/debian/patches/series 2020-07-19 09:30:29.000000000 +0000 +++ smartmontools-7.3/debian/patches/series 2023-07-05 09:18:39.000000000 +0000 @@ -3,7 +3,5 @@ 54_remove-Id-from-smartd.conf.diff 61_cciss-doc.patch 63_removable.patch -default_never-quit.patch manpage.diff service-alias.patch -updated_drive_database.patch diff -Nru smartmontools-7.1/debian/patches/service-alias.patch smartmontools-7.3/debian/patches/service-alias.patch --- smartmontools-7.1/debian/patches/service-alias.patch 2019-10-10 00:21:35.000000000 +0000 +++ smartmontools-7.3/debian/patches/service-alias.patch 2023-07-05 09:18:39.000000000 +0000 @@ -5,8 +5,8 @@ --- a/smartd.service.in +++ b/smartd.service.in -@@ -10,4 +10,5 @@ - StandardOutput=syslog +@@ -13,4 +13,5 @@ + ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target diff -Nru smartmontools-7.1/debian/patches/updated_drive_database.patch smartmontools-7.3/debian/patches/updated_drive_database.patch --- smartmontools-7.1/debian/patches/updated_drive_database.patch 2020-07-19 09:34:06.000000000 +0000 +++ smartmontools-7.3/debian/patches/updated_drive_database.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,737 +0,0 @@ -Last-Update: 2020-07-19 -Author: Simon Arons -Description: Update driver database. - ---- smartmontools-7.1.orig/drivedb.h -+++ smartmontools-7.1/drivedb.h -@@ -4,7 +4,7 @@ - * Home page of code is: https://www.smartmontools.org - * - * Copyright (C) 2003-11 Philip Williams, Bruce Allen -- * Copyright (C) 2008-19 Christian Franke -+ * Copyright (C) 2008-20 Christian Franke - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ -@@ -68,7 +68,7 @@ - /* - const drive_settings builtin_knowndrives[] = { - */ -- { "$Id: drivedb.h 5008 2019-12-28 21:40:37Z chrfranke $", -+ { "$Id$", - "-", "-", - "This is a dummy entry to hold the SVN-Id of drivedb.h", - "" -@@ -353,9 +353,10 @@ const drive_settings builtin_knowndrives - "-v 206,raw48,Write_Error_Rate" - }, - { "Crucial/Micron MX500 SSDs", -- "CT(250|500|1000|2000)MX500SSD[14]", // tested with CT500MX500SSD1/M3CR023, -- // .../M3CR020, .../M3CR022 -- "M3CR02[0-3]", // Firmware with bogus attribute 197 (see ticket #1227) -+ "CT(250|500|1000|2000)MX500SSD[14]", // tested with CT500MX500SSD1/M3CR020, -+ // .../M3CR022, .../M3CR023, CT1000MX500SSD1/M3CR010, .../M3CR032 -+ "M3CR0([012][0-9]|3[0-2])", // Assume FW <= M3CR032 have bogus attribute 197 -+ // (tickets #1227, #1311, #1336) - "This firmware returns bogus raw values in attribute 197", - //"-v 1,raw48,Raw_Read_Error_Rate " - "-v 5,raw48,Reallocate_NAND_Blk_Cnt " -@@ -381,7 +382,7 @@ const drive_settings builtin_knowndrives - "-v 247,raw48,Host_Program_Page_Count " - "-v 248,raw48,FTL_Program_Page_Count" - }, -- { "Crucial/Micron BX/MX1/2/3/500, M5/600, 1100 SSDs", -+ { "Crucial/Micron BX/MX1/2/3/500, M5/600, 11/1300 SSDs", - "Crucial_CT(128|256|512)MX100SSD1|"// Marvell 88SS9189, tested with Crucial_CT256MX100SSD1/MU01 - "Crucial_CT(200|250|256|500|512|1000|1024)MX200SSD[1346]|" // Marvell 88SS9189, tested with - // Crucial_CT500MX200SSD1/MU01, Crucial_CT1024MX200SSD1/MU01, Crucial_CT250MX200SSD3/MU01, -@@ -396,7 +397,8 @@ const drive_settings builtin_knowndrives - // Crucial_CT1024M550SSD1/MU01, Crucial_CT128M550SSD4/MU02 - "CT(120|240|480)BX300SSD1|" // Silicon Motion SM2258, same attributes as Marvell-based Crucial SSDs, - // tested with CT240BX300SSD1/M2CR010 -- "CT(120|240|480|960)BX500SSD1|" // Silicon Motion SM2258XT, tested with CT120BX500SSD1/M6CR013 -+ "CT(120|240|480|960|1000)BX500SSD1|" // Silicon Motion SM2258XT, tested with CT120BX500SSD1/M6CR013, -+ // CT1000BX500SSD1/M6CR030 - "CT(250|500|1000|2000)MX500SSD[14]|" // Silicon Motion SM2258, tested with CT250MX500SSD1/M3CR010 - // CT500MX500SSD1/M3CR010, CT1000MX500SSD1/M3CR010, CT2000MX500SSD1/M3CR010, - // CT250MX500SSD4/M3CR022 (now handled by above entry) -@@ -407,10 +409,13 @@ const drive_settings builtin_knowndrives - "(Micron_)?M510[_-]MTFDDA[KTV](128|256)MAZ|" // tested with M510-MTFDDAK256MAZ/MU01 - "MICRON_M510DC_(EE|MT)FDDAK(120|240|480|800|960)MBP|" // tested with Micron_M510DC_MTFDDAK240MBP/0005 - "(Micron_)?M550[_-]MTFDDA[KTV](064|128|256|512|1T0)MAY|" // tested with M550-MTFDDAK256MAY/MU01 -- "Micron_M600_(EE|MT)FDDA[KTV](128|256|512|1T0)MBF[25Z]?|" // tested with Micron_M600_MTFDDAK1T0MBF/MU01 -+ "(Micron_M600_)?(EE|MT)FDDA[KTV](128|256|512|1T0)MBF[25Z]?(-.*)?|" // tested with Micron_M600_MTFDDAK1T0MBF/MU01, -+ // MTFDDAK256MBF-1AN1ZABHA/M603 - "(Micron_1100_)?MTFDDA[KV](256|512|1T0|2T0)TBN|" // Marvell 88SS1074, tested with - // Micron_1100_MTFDDAK256TBN/M0MU020, MTFDDAK256TBN/M0MA020 (OEM) -- "Micron 1100 SATA (256G|512G|1T|2T)B", // tested with Micron 1100 SATA 256GB/M0DL022 -+ "Micron 1100 SATA (256G|512G|1T|2T)B|" // tested with Micron 1100 SATA 256GB/M0DL022 -+ "Micron_1300_(EE|MT)FDDA[KV](256|512|1T0|2T0)TDL", // tested with Micron_1300_MTFDDAK256TDL/M5MU000, -+ // Micron_1300_MTFDDAK1T0TDL/M5MU000 - "", "", - //"-v 1,raw48,Raw_Read_Error_Rate " - "-v 5,raw48,Reallocate_NAND_Blk_Cnt " -@@ -434,17 +439,25 @@ const drive_settings builtin_knowndrives - "-v 202,raw48,Percent_Lifetime_Remain " - "-v 206,raw48,Write_Error_Rate " - "-v 210,raw48,Success_RAIN_Recov_Cnt " -+ "-v 223,raw48,Unkn_CrucialMicron_Attr " // M6CR030 - "-v 246,raw48,Total_LBAs_Written " - "-v 247,raw48,Host_Program_Page_Count " -- "-v 248,raw48,FTL_Program_Page_Count" -+ "-v 248,raw48,FTL_Program_Page_Count " -+ "-v 249,raw48,Unkn_CrucialMicron_Attr " // M6CR030 -+ //"-v 250,raw48,Read_Error_Retry_Rate " // M6CR030 -+ "-v 251,raw48,Unkn_CrucialMicron_Attr " // M6CR030 -+ "-v 252,raw48,Unkn_CrucialMicron_Attr " // M6CR030 -+ "-v 253,raw48,Unkn_CrucialMicron_Attr " // M6CR030 -+ "-v 254,raw48,Unkn_CrucialMicron_Attr" // M6CR030 - }, - // Reference: https://www.micron.com/resource-details/feec878a-265e-49a7-8086-15137c5f9011 - // TN-FD-34: 5100 SSD SMART Implementation - { -- "Micron 5100 Pro / 5200 SSDs", -+ "Micron 5100 Pro / 5200 / 5300 SSDs", - "(Micron_5100_)?(EE|MT)FDDA[KV](240|480|960|1T9|3T8|7T6)T(BY|CB|CC)|" // Matches both stock and Dell OEM - // tested with Micron_5100_MTFDDAK3T8TCB/D0MU410, MTFDDAK3T8TCB/D0MU410 -- "(Micron_5200_)?MTFDDAK(480|960|1T9|3T8|7T6)TD(C|D|N)", // tested with Micron_5200_MTFDDAK3T8TDD/D1MU505 -+ "(Micron_5200_)?MTFDDAK(480|960|1T9|3T8|7T6)TD(C|D|N)|" // tested with Micron_5200_MTFDDAK3T8TDD/D1MU505 -+ "Micron_5300_MTFDDA[KV](240|480|960|1T9|3T8|7T6)TDS", // tested with Micron_5300_MTFDDAK1T9TDS/D3MU001 - "", "", - //"-v 1,raw48,Raw_Read_Error_Rate " - //"-v 5,raw48,Reallocated_Block_Count " -@@ -472,6 +485,7 @@ const drive_settings builtin_knowndrives - "-v 211,raw48,Integ_Scan_Complete_Cnt " // Number of periodic data integrity scans completed - "-v 212,raw48,Integ_Scan_Folding_Cnt " // Number of blocks reallocated by integrity scans - "-v 213,raw48,Integ_Scan_Progress " // Current is percentage, raw is absolute number of superblocks scanned by the current integrity scan -+ "-v 246,raw48,Unknown_Micron_Attrib " // 5300/D3MU001 - "-v 247,raw48,Host_Program_Page_Count " - "-v 248,raw48,Bckgnd_Program_Page_Cnt" - }, -@@ -670,14 +684,16 @@ const drive_settings builtin_knowndrives - }, - { "Phison Driven SSDs", // see MKP_521_Phison_SMART_attribute.pdf - "BP4 mSATA SSD|" // MyDigital BP4, tested with BP4 mSATA SSD/S8FM06.9 -+ "Corsair Force LE200 SSD|" // tested with Corsair Force LE200 SSD/SBFM10, .../SBFM60.9 -+ "GIGABYTE GP-GSTFS31((120|240|256|480)G|100T)NTD|" // tested with GIGABYTE GP-GSTFS31120GNTD/SBFM61.3 - "GOODRAM IRIDIUM PRO|" // tested with GOODRAM IRIDIUM PRO/SAFM01.5 - "IR-SSDPR-S25A-(120|240|480|960)|" // Goodram IRIDM, tested with IR-SSDPR-S25A-120/SBFM91.3, - // IR-SSDPR-S25A-240/SBFM91.2 - "KINGSTON SEDC400S37(400|480|800|960|1600|1800)G|" // DC400, tested with - // KINGSTON SEDC400S37480G/SAFM02.[GH], KINGSTON SEDC400S37960G/SAFM32.I -- "KINGSTON SEDC(450R|500[MR])(480|960|1920|3840)G|" // DC450R, DC500M/R, tested with -+ "KINGSTON SEDC(450R|500[MR])(480|960|1920|3840|7680)G|" // DC450R, DC500M/R, tested with - // KINGSTON SEDC450R480G/SCEKH3. KINGSTON SEDC500M1920G/SCEKJ2.3, -- // KINGSTON SEDC500R480G/SCEKJ2.3 -+ // KINGSTON SEDC500R480G/SCEKJ2.3, KINGSTON SEDC450R7680G/SCEKH3.4 - "KINGSTON SUV300S37A(120|240|480)G|" // UV300 SSD, tested with KINGSTON SUV300S37A120G/SAFM11.K - "KINGSTON SKC310S3B?7A960G|" // SSDNow KC310, KINGSTON SKC310S37A960G/SAFM00.r - "KINGSTON SKC400S37(128G|256G|512G|1T)|" // SSDNow KC400, KINGSTON SKC400S37128G -@@ -689,8 +705,8 @@ const drive_settings builtin_knowndrives - // KINGSTON SA400S37480G/SBFK10D7 (two spaces) - "Patriot (Flare|Blast|Blaze|Burst)|" // tested with Patriot Flare/SBFM91.2, - // Patriot Blast/SAFM11.3, Patriot Blaze/S9FM02, Patriot Burst/SBFM11.2 -- "PNY CS(13|22)11 (120|240|480|960)GB SSD|" // tested with PNY CS1311 120GB SSD/CS131122, -- // PNY CS2211 240GB SSD/CS221016 -+ "PNY CS(900|1311|2211) (120|240|480|960)GB SSD|" // tested with PNY CS900 120GB SSD/CS900612, -+ // PNY CS900 240GB SSD/CS900613, PNY CS1311 120GB SSD/CS131122, PNY CS2211 240GB SSD/CS221016 - "SSD Smartbuy (60|120|240)GB|" // SSD Smartbuy 240GB/SBFM91.1 - "SSD PHISON 256GB PS3110-S10C|" // tested with SSD PHISON 256GB PS3110-S10C/SAFM12.2 - "SSDPR-CX400-(128|256|512|1024)|" // Goodram CX400, tested with SSDPR-CX400-512/SBFM61.3 -@@ -1184,9 +1200,10 @@ const drive_settings builtin_knowndrives - }, - { "Intel 320 Series SSDs", // tested with INTEL SSDSA2CT040G3/4PC10362, - // INTEL SSDSA2CW160G3/4PC10362, SSDSA2BT040G3/4PC10362, SSDSA2BW120G3A/4PC10362, -- // INTEL SSDSA2BW300G3D/4PC10362, SSDSA2BW160G3L/4PC1LE04, SSDSA1NW160G3/4PC10362 -- "INTEL SSDSA[12][BCN][WT](040|080|120|160|300|600)G3[ADL]?", -- // 2B = 2.5" 7mm, 2C = 2.5" 9.5mm, 1N = 1.8" microSATA -+ // INTEL SSDSA2BW300G3D/4PC10362, SSDSA2BW160G3L/4PC1LE04, SSDSA1NW160G3/4PC10362, -+ // INTEL SSDSA2BW160G3H/4PC10365 -+ "INTEL SSDSA[12][BCN][WT](040|080|120|160|300|600)G3[ADHL]?", -+ // 2B = 2.5" 7mm, 2C = 2.5" 9.5mm, 1N = 1.8" microSATA, *H = HP OEM - "", "", - "-F nologdir " - //"-v 3,raw16(avg16),Spin_Up_Time " -@@ -1617,14 +1634,20 @@ const drive_settings builtin_knowndrives - "-v 227,raw48,Workld_Host_Reads_Perc " - "-v 228,raw48,Workload_Minutes" - }, -- { "Kingston SSDNow UV400", -- "KINGSTON SUV400S37A?(120|240|480|960)G", // KINGSTON SUV400S37120G/0C3J96R9, -- "", -- "", -+ { "Kingston SSDNow UV400/500", -+ "KINGSTON SUV400S37A?(120|240|480|960)G|" // tested with KINGSTON SUV400S37120G/0C3J96R9, -+ // KINGSTON SUV400S37240G/0C3J96R9, KINGSTON SUV400S37240G/0C3K87RA, -+ // KINGSTON SUV400S37120G/0C3K87RA -+ "KINGSTON SUV500(MS)?(120|240|480|960)G", // tested with KINGSTON SUV500120G/003056R6, -+ // KINGSTON SUV500240G/003056R6, KINGSTON SUV500480G/003056RI, -+ // KINGSTON SUV500MS120G/003056RA, KINGSTON SUV500MS120G/003056RI -+ "", "", - // "-v 1,raw48,Raw_Read_Error_Rate " - // "-v 5,raw16(raw16),Reallocated_Sector_Ct " - // "-v 9,raw24(raw8),Power_On_Hours " - // "-v 12,raw48,Power_Cycle_Count " -+ "-v 100,raw48,Unknown_Kingston_Attr " -+ "-v 101,raw48,Unknown_Kingston_Attr " - "-v 170,raw48,Reserved_Block_Count " - "-v 171,raw48,Program_Fail_Count " - "-v 172,raw48,Erase_Fail_Count " -@@ -1644,9 +1667,9 @@ const drive_settings builtin_knowndrives - "-v 201,raw48,Unc_Read_Error_Rate " - // "-v 204,raw48,Soft_ECC_Correction " - "-v 231,raw48,SSD_Life_Left " -- // "-v 241,raw48,Total_LBAs_Written " -- // "-v 242,raw48,Total_LBAs_Read " -- "-v 250,raw48,Read_Retry_Count " -+ "-v 241,raw48,Host_Writes_GiB " -+ "-v 242,raw48,Host_Reads_GiB " -+ "-v 250,raw48,Read_Retry_Count" - }, - { "JMicron based SSDs", // JMicron JMF60x - "Kingston SSDNow V Series [0-9]*GB|" // tested with Kingston SSDNow V Series 64GB/B090522a -@@ -1663,12 +1686,13 @@ const drive_settings builtin_knowndrives - "-v 234,raw24/raw24:w01234,Avg/Max_Erase_Count " - "-v 235,raw24/raw24:w01z23,Good/Sys_Block_Count" - }, -- { "JMicron based SSDs", // JMicron JMF61x, JMF66x, JMF670 -+ { "JMicron/Maxiotek based SSDs", // JMicron JMF61x, JMF66x, JMF670 - "ADATA S596 Turbo|" // tested with ADATA S596 Turbo 256GB SATA SSD (JMicron JMF616) -- "ADATA SP600|" // tested with ADATA SP600/2.4 (JMicron JMF661) - "ADATA SP310|" // Premier Pro SP310 mSATA, JMF667, tested with ADATA SP310/3.04 -+ "ADATA SP600(NS34)?|" // tested with ADATA SP600/2.4 (JMicron JMF661) - "ADATA SX930|" // tested with ADATA SX930/6.8SE - "APPLE SSD TS(064|128|256|512)C|" // Toshiba?, tested with APPLE SSD TS064C/CJAA0201 -+ "IM2S3138E-(128|256)GM-B|" // ADATA OEM, tested with IM2S3138E-128GM-B/DA002 - "KingSpec KDM-SA\\.51-008GMJ|" // tested with KingSpec KDM-SA.51-008GMJ/1.092.37 (JMF605?) - "KINGSTON SNV425S2(64|128)GB|" // SSDNow V Series (2. Generation, JMF618), - // tested with KINGSTON SNV425S264GB/C091126a -@@ -1678,6 +1702,7 @@ const drive_settings builtin_knowndrives - "KINGSTON SVP?100S2B?(64|96|128|256|512)G|" // SSDNow V100/V+100 Series, - // tested with KINGSTON SVP100S296G/CJR10202, KINGSTON SV100S2256G/D110225a - "KINGSTON SV200S3(64|128|256)G|" // SSDNow V200 Series, tested with KINGSTON SV200S3128G/E120506a -+ "NT-(64|128|256|512|[12]T)|" // KingSpec NT, MAS0902A-B2C or CS1802A-B2C, tested with NT-512/T191212 - "TOSHIBA THNS128GG4BBAA|" // Toshiba / Super Talent UltraDrive DX, - // tested with Toshiba 128GB 2.5" SSD (built in MacBooks) - "TOSHIBA THNSNC128GMLJ|" // tested with THNSNC128GMLJ/CJTA0202 (built in Toshiba Protege/Dynabook) -@@ -1714,12 +1739,13 @@ const drive_settings builtin_knowndrives - //"-v 241,raw48,Total_LBAs_Written " // FW SVN423b - //"-v 242,raw48,Total_LBAs_Read " // FW SVN423b - }, -- { "Plextor M3/M5/M6 Series SSDs", // Marvell 88SS9174 (M3, M5S), 88SS9187 (M5P, M5Pro), 88SS9188 (M6M/S), -+ { "Plextor M3/M5/M6/M7 Series SSDs", // Marvell 88SS9174 (M3, M5S), 88SS9187 (M5P, M5Pro), 88SS9188 (M6M/S), - // tested with PLEXTOR PX-128M3/1.01, PX-128M3P/1.04, PX-256M3/1.05, PX-128M5S/1.02, PX-256M5S/1.03, - // PX-128M5M/1.05, PX-128M5S/1.05, PX-128M5Pro/1.05, PX-512M5Pro/1.06, PX-256M5P/1.01, PX-128M6S/1.03 - // (1.04/5 Firmware self-test log lifetime unit is bogus, possibly 1/256 hours) -- // PLEXTOR PX-256M6S+/1.00 -- "PLEXTOR PX-(64|128|256|512|768)M(3P?|5[MPS]|5Pro|6[MS])\\+?", -+ // PLEXTOR PX-256M6S+/1.00, PLEXTOR PX-128M3/1.00, PLEXTOR PX-128M3/1.07, PLEXTOR PX-128M6V/1.04, -+ // PLEXTOR PX-128M6G-2242/1.01, PLEXTOR PX-512M7VC/1.05 -+ "PLEXTOR ?PX-(64|128|256|512|768)M(3P?|5[MPS]|5Pro|6[GMSV]|7VC)(\\+|-.*)?", - "", "", - //"-v 1,raw48,Raw_Read_Error_Rate " - //"-v 5,raw16(raw16),Reallocated_Sector_Ct " -@@ -1768,17 +1794,19 @@ const drive_settings builtin_knowndrives - "MZ7PC(512|256|128|064)HA(GH|FU|DR)-000.*|" // probably PM830, tested with SAMSUNG MZ7PC128HAFU-000L1/CXM04L1Q - "Samsung SSD 840 (PRO )?Series|" // tested with Samsung SSD 840 PRO Series 128GB/DXM04B0Q, - // Samsung SSD 840 Series/DXT06B0Q -- "Samsung SSD 8[456]0 EVO (mSATA |M\\.2 )?((120|250|500|750)G|[12]T)B|" // tested with -+ "Samsung SSD 8[456]0 EVO (mSATA |M\\.2 )?((120|250|500|750)G|[124]T)B|" // tested with - // Samsung SSD 840 EVO (120|250|500|750)GB/EXT0AB0Q, - // Samsung SSD 840 EVO (120|250)GB/EXT0BB6Q, 1TB/EXT0BB0Q, 120GB mSATA/EXT41B6Q, - // Samsung SSD 850 EVO 250GB/EMT01B6Q, Samsung SSD 850 EVO M.2 250GB/EMT21B6Q, - // Samsung SSD 850 EVO mSATA 120GB/EMT41B6Q, Samsung SSD 850 EVO 2TB/EMT02B6Q, - // Samsung SSD 860 EVO 250GB/RVT01B6Q, Samsung SSD 860 EVO mSATA 250GB/RVT41B6Q, - // Samsung SSD 860 EVO 500GB/RVT01B6Q, Samsung SSD 860 EVO mSATA 500GB/RVT41B6Q, -- // Samsung SSD 860 EVO mSATA 1TB/RVT41B6Q, Samsung SSD 860 EVO 2TB/RVT01B6Q -- "Samsung SSD 8[56]0 PRO ((128|256|512)G|1T)B|" // tested with Samsung SSD 850 PRO 128GB/EXM01B6Q, -- // Samsung SSD 850 PRO 1TB/EXM01B6Q, Samsung SSD 860 PRO 256GB/RVM01B6Q, -- // Samsung SSD 860 PRO 512GB/RVM01B6Q, Samsung SSD 860 PRO 1TB/RVM01B6Q -+ // Samsung SSD 860 EVO mSATA 1TB/RVT41B6Q, Samsung SSD 860 EVO 2TB/RVT01B6Q, -+ // Samsung SSD 860 EVO 4TB/RVT04B6Q -+ "Samsung SSD 8[56]0 PRO ((128|256|512)G|[124]T)B|" // tested with Samsung SSD 850 PRO 128GB/EXM01B6Q, -+ // Samsung SSD 850 PRO 1TB/EXM01B6Q, Samsung SSD 850 PRO 2TB/EXM02B6Q, -+ // Samsung SSD 860 PRO 256GB/RVM01B6Q, Samsung SSD 860 PRO 512GB/RVM01B6Q, -+ // Samsung SSD 860 PRO 1TB/RVM01B6Q - "SAMSUNG MZ7PA256HMDR-.*|" // PM810 (470 Series), tested with SAMSUNG MZ7PA256HMDR-010H1/AXM07H1Q - "Samsung SSD 845DC EVO .*|" // Samsung SSD 845DC EVO 960GB/EXT03X3Q - "SAMSUNG MZ[7M]PC(032|064|128|256|512)HBCD-.*|" // PM830, tested with SAMSUNG MZMPC032HBCD-000L1/CXM12L1Q -@@ -1865,6 +1893,7 @@ const drive_settings builtin_knowndrives - // SanDisk SD7SB6S128G1122/X3310000, SanDisk SD7SN6S-512G-1006/X3511006 - "SanDisk SD8S[BN]8U-?((128|256|512)G|1T00)(1122|-1006)|" // X400 (88SS1074), tested with SanDisk SD8SB8U128G1122/X4120000 - "SanDisk SD9S[BN]8W-?((128|256|512)G|[12]T00)1122|" // X600, tested with SanDisk SD9SB8W128G1122/X6107000 -+ "SanDisk SDSSDA-((120|240|480)G|[12]T00)|" // Plus, tested with SanDisk SDSSDA-2T00/411040RL - "SanDisk SDSSDHP[0-9]*G|" // Ultra Plus (88SS9175), tested with SanDisk SDSSDHP128G/X23[01]6RL - "SanDisk (SDSSDHII|Ultra II )[0-9]*GB?|" // Ultra II (88SS9190/88SS9189), tested with - // SanDisk SDSSDHII120G/X31200RL, SanDisk Ultra II 960GB/X41100RL -@@ -1989,8 +2018,10 @@ const drive_settings builtin_knowndrives - "-v 245,raw48,DriveLife_Used% " - }, - { "Silicon Motion based SSDs", -- "ADATA (SP550|SU[89]00)|" // tested with ADATA SP550/O0803B5a, ADATA SU800/Q0913A, ADATA SU800/R0427A, -- // ADATA SU800/R0918B, ADATA SU900/Q0125A, ADATA SU900/Q0710B -+ "ADATA (SP550|SU(65[05]|[89]00))|" // tested with ADATA SP550/O0803B5a, ADATA SU650/S0212B0, -+ // ADATA SU650/V8X01c45, ADATA SU650/V8X21c64, ADATA SU655/V8X01c55, ADATA SU800/Q0913A, -+ // ADATA SU800/R0427A, ADATA SU800/R0918B, ADATA SU900/Q0125A, ADATA SU900/Q0710B -+ "CORSAIR FORCE LX SSD|" // tested with CORSAIR FORCE LX SSD/N0307A - "CHN mSATAM3 (128|256|512)|" // Zheino M3, tested with CHN mSATAM3 128/Q1124A0 - "CIS 2S M305 (16|32|64|128|256)GB|" // Ceroz M305, tested with CIS 2S M305 64GB/P0316B - "CT(120|250|500|1000)BX100SSD1|" // Crucial BX100, tested with CT250BX100SSD1/MU02, -@@ -1999,9 +2030,11 @@ const drive_settings builtin_knowndrives - "DREVO X1 SSD|" // tested with DREVO X1 SSD/Q0111A - "Drevo X1 pro (64|128|256)G|" // tested with Drevo X1 pro 64G/Q0303B - "JAJS500M(120|240|480|960)C-1|" // J&A LEVEN JS500, tested with JAJS500M120C-1/P0614D -- "KingDian S(280|400) (120|240|480)GB|" // SM2256EN, tested with KingDian S280 120GB/Q0526A, -- // KingDian S400 120GB/Q0607A -+ "KingDian S100 (32|64)GB|" // SM2244LT, tested with KingDian S100 32GB/0311A -+ "KingDian S(200|280|400) ((60|120|240|480)GB|1TB)|" // SM2256EN, tested with KingDian S200 60GB/R0724A0 -+ // KingDian S280 120GB/Q0526A, KingDian S280 1TB/S0509A0, KingDian S400 120GB/Q0607A - "KingSpec KSD-[PS]A25\\.[1-9]-(016|032|064|128)(MS|SJ)|" // tested with KingSpec KSD-PA25.6-064MS/20140803 -+ "KINGSTON SKC600(256|512|1024|2048)G|" // SM2259, tested with KINGSTON SKC600256G/S4500105 - "LITEON LMH-(128|256|512)V2M-.*|" // tested with LITEON LMH-256V2M-11 MSATA 256GB/FM8110C - "LITEON LCH-(128|256V|512)2S-.*|" // tested with LITEON LCH-256V2S-HP/2C02 - "MKNSSDRE(1TB|2TB|512GB|500GB|256GB|250GB)|" // tested with MKNSSDRE256GB/N1007C -@@ -2020,13 +2053,14 @@ const drive_settings builtin_knowndrives - // TS256GSSD370/N0815B, TS256GSSD370S/N1114H, TS512GSSD370S/N1114H, TS32GSSD420I/N1114H, - // TS32GSSD420K/P1225CE - "TS(16|32|64|128|512|256)GMTS4[03]0S?|" // TS256GMTS400, TS256GMTS430S/S0423A -- "TS(120|240)GMTS420|" // Transcend MTS420 -+ "TS(120|240)GMTS420S?|" // Transcend MTS420, tested with TS120GMTS420S/R0510A0 - "TS(128G|256G|512G|1T)SSD230S|" // TS128GSSD230S/P1025F8 - "TS(120|240|480|960)GSSD220S|" // TS480GSSD220S/P0520AA - "TS(16G|32G|64G|128G|256G|512G|1T)MTS800S?|" // MTS800, tested with TS1TMTS800/O1225H1 - "TS(16|32|64)GMSA630|" // MSA630 mSATA SSD, tested with TS32GMSA630/N0113E1 - "TS(32|64|128)GPSD330|" // Transcend PSD SSD, tested with TS64GPSD330/20140121 -- "TS(16|32|64|96|128|256)GSSD630|" // Transcend 630, tested with TS16GSSD630/N0113E1 -+ "TS(16|32|64|96|128|256)GSSD(630|360S)|" // Transcend 630/360S, tested with TS16GSSD630/N0113E1, -+ // TS256GSSD360S/R0123A0 - "TS(128G|256G|512G|1T)ESD400K", // Transcend ESD400 Portable, tested with - // TS256GESD400K/R0605AS (0x2174:0x2000) - "", "", -@@ -2038,7 +2072,7 @@ const drive_settings builtin_knowndrives - "-v 149,raw48,Max_SLC_Erase_Ct " - "-v 150,raw48,Min_SLC_Erase_Ct " - "-v 151,raw48,Average_SLC_Erase_Ct " -- "-v 159,raw48,Unkn_SiliconMotion_Attr " // SU800/R0427A, SU900/Q0710B, TS256GMTS430S/S0423A -+ "-v 159,raw48,DRAM_1_Bit_Error_Count " // KINGSTON SKC600256G/S4500105 - "-v 160,raw48,Uncorrectable_Error_Cnt " - "-v 161,raw48,Valid_Spare_Block_Cnt " - "-v 163,raw48,Initial_Bad_Block_Count " -@@ -2063,6 +2097,7 @@ const drive_settings builtin_knowndrives - //"-v 198,raw48,Offline_Uncorrectable " - //"-v 199,raw48,UDMA_CRC_Error_Count " - "-v 225,raw48,Host_Writes_32MiB " // FW 20140402 -+ "-v 231,raw48,SSD_Life_Left " // KINGSTON SKC600256G/S4500105 - //"-v 232,raw48,Available_Reservd_Space " - "-v 241,raw48,Host_Writes_32MiB " - "-v 242,raw48,Host_Reads_32MiB " -@@ -2070,6 +2105,7 @@ const drive_settings builtin_knowndrives - "-v 246,raw48,SLC_Writes_32MiB " - "-v 247,raw48,Raid_Recoverty_Ct " - "-v 248,raw48,Unkn_SiliconMotion_Attr " // ADATA SU900/Q0125A -+ "-v 249,raw48,Unkn_SiliconMotion_Attr " // ADATA SU650/V8X01c45 - //"-v 250,raw48,Read_Error_Retry_Rate " // ADATA SU800/Q0913A - "-v 251,raw48,Unkn_SiliconMotion_Attr" // ADATA SU800/Q0913A - }, -@@ -2629,8 +2665,8 @@ const drive_settings builtin_knowndrives - "ST(1500|2000)LM0(03|04|06|07|10) HN-M[0-9]*RAD", - "", "", "" - }, -- { "Seagate Mobile HDD", // tested with ST2000LM007-1R8174/WDZD1BYX -- // ST1000LM035-1RK172/ACM1 -+ { "Seagate Mobile HDD", // tested with ST1000LM035-1RK172/ACM1, -+ // ST1000LM035-1RK172/ACM2, ST2000LM007-1R8174/SBK2 - "ST(2000LM0(07|09|10)|1000LM03[578])-.*", - "", "", "" - }, -@@ -3378,10 +3414,11 @@ const drive_settings builtin_knowndrives - "", "", - "-v 22,raw48,Helium_Level" - }, -- { "WDC HGST Ultrastar He10", // WD white label, tested with -- // WDC WD80EMAZ-00WJTA0/83.H0A83, WDC WD80EZAZ-11TDBA0/83.H0A83, -- // WDC WD100EMAZ-00WJTA0/83.H0A83, WDC WD100EZAZ-11TDBA0/83.H0A83 -- "WDC WD(80|100)E[MZ]AZ-.*", -+ { "Western Digital Ultrastar He10/12", // WD white label, tested with -+ // WDC WD80EMAZ-00WJTA0/83.H0A83 (Easystore 0x1058:0x25fb), -+ // WDC WD80EZAZ-11TDBA0/83.H0A83, WDC WD100EMAZ-00WJTA0/83.H0A83, -+ // WDC WD100EZAZ-11TDBA0/83.H0A83, WDC WD120EMAZ-11BLFA0/81.00A81 -+ "WDC WD(80|100|120)E[MZ]AZ-.*", - "", "", - "-v 22,raw48,Helium_Level" - }, -@@ -3390,6 +3427,11 @@ const drive_settings builtin_knowndrives - "", "", - "-v 22,raw48,Helium_Level" - }, -+ { "Western Digital Ultrastar DC HC530", // tested with WDC WUH721414ALE6L4/LDGNW07G -+ "WDC ?WUH721414ALE6L4", -+ "", "", -+ "-v 22,raw48,Helium_Level" -+ }, - { "HGST MegaScale 4000", // tested with HGST HMS5C4040ALE640/MPAOA580 - "HGST HMS5C4040[AB]LE64[01]", // B = DC 4000.B - "", "", "" -@@ -3433,7 +3475,7 @@ const drive_settings builtin_knowndrives - "", - "-v 9,minutes" - }, -- { "Toshiba 2.5\" HDD MK..52GSX", -+ { "Toshiba 2.5\" HDD MK..52GSX", // tested with TOSHIBA MK3252GSX/LV010A - "TOSHIBA MK(80|12|16|25|32)52GSX", - "", "", "" - }, -@@ -3901,27 +3943,15 @@ const drive_settings builtin_knowndrives - "", "", - "-v 188,raw16 -v 240,msec24hour32" - }, -- // should be ST4000DM005, ST3000DM008,ST3000DM009,ST2000DM006,ST2000DM007 -- // ST1000DM010, ST500DM009 -- // tested: ST3000DM008-2DM166/CC26 -- { "Seagate Barracuda 3.5", // tested on ST1000DM010-2EP102/Z9ACZM97 -- "ST(4000DM00[45]|3000DM008|3000DM009|2000DM006|2000DM007|1000DM010|500DM009)-.*", -- "", "", -- "-v 188,raw16 -v 240,msec24hour32" -- }, -- // ST8000DM004, ST6000DM003, ST4000DM004, ST3000DM007, ST2000DM005 -- { "Seagate Barracuda Compute", // tested on ST8000DM004-2CX188/0001 -- "ST(8000DM004|6000DM003|4000DM004|3000DM007|2000DM005)-.*", -- "", "", -- "" -- }, -- { "Seagate Barracuda Pro", // tested on ST8000DM004-2CX188/0001 -- "ST(8000DM005|6000DM004|4000DM006|2000DM009)-.*", -+ { "Seagate Barracuda 7200.14 (AF)", // < 1TB, tested with ST250DM000-1BC141 -+ "ST(250|320|500|750)DM00[0-3]-.*", - "", "", - "-v 188,raw16 -v 240,msec24hour32" - }, -- { "Seagate Barracuda 7200.14 (AF)", // < 1TB, tested with ST250DM000-1BC141 -- "ST(250|320|500|750)DM00[0-3]-.*", -+ { "Seagate BarraCuda 3.5", // tested with ST1000DM010-2EP102/Z9ACZM97, -+ // ST2000DM008-2FR102/0001, ST3000DM008-2DM166/CC26, ST4000DM005-2DP166/0001, -+ // ST4000DM006-2G5107/DN02, ST8000DM004-2CX188/0001, ST10000DM0004-1ZC101/DN01 -+ "ST(500DM009|1000DM010|2000DM00[5-9]|3000DM00[789]|4000DM00[456]|6000DM00[34]|8000DM00[45]|10000DM0004)-.*", - "", "", - "-v 188,raw16 -v 240,msec24hour32" - }, -@@ -4049,6 +4079,7 @@ const drive_settings builtin_knowndrives - // ST4000NM0035-1V4107/TNC3 - // ST1000NM0055-1V410C/TN02 - // ST8000NM0055-1RM112/SN04 -+ // ST10000NM0156-2AA111/SS05 - "ST([1234568]|10)000NM0[01][0-68][456]-.*", // *[069]4 = 4Kn - "", "", - "-v 188,raw16 -v 240,msec24hour32" -@@ -4068,9 +4099,18 @@ const drive_settings builtin_knowndrives - "", "", - "-v 240,msec24hour32" - }, -- { "Seagate Exos X14", // ST12000NM0008-2H3101/SN02 -- "ST(14000NM04[24]8|14000NM0(01|25)8|12000NM0(00|24)8|10000NM0(47|56)8)-.*", -+ { "Seagate Exos X14", // tested with ST12000NM0008-2H3101/SN02, -+ // ST12000NM0538-2K2101/CMA2 (OEM?) -+ "ST(14000NM04[24]8|14000NM0(01|25)8|12000NM0(00|24|53)8|10000NM0(47|56)8)-.*", -+ "", "", -+ "-v 18,raw48,Unknown_Seagate_Attrib " -+ "-v 240,msec24hour32" -+ }, -+ { "Seagate Exos X16", // tested with X16 ST14000NM001G-2KJ103/SN02, -+ // ST16000NM001G-2KK103/SN02 -+ "ST1[46]000NM00[13]G-.*", - "", "", -+ "-v 18,raw48,Unknown_Seagate_Attrib " - "-v 240,msec24hour32" - }, - // new models: ST8000VN0002, ST6000VN0021, ST4000VN000 -@@ -4088,15 +4128,18 @@ const drive_settings builtin_knowndrives - "ST(8000NE|[65432]000VN)00[01]1-.*", - "", "", "" - }, -- { "Seagate IronWolf", // tested with ST6000VN0033-2EE110/SC60, -- // ST6000VN0041-2EL11C/SC61, ST12000VN0007-2GS116/SC60, ST12000VN0008-2JH101/SC60 -- "ST(1|2|3|4|6|8|10|12)000VN00(0?[2478]|22|33|41)-.*", -+ { "Seagate IronWolf", // tested with ST3000VN007-2E4166/SC60, ST4000VN008-2DR166/SC60, -+ // ST6000VN0033-2EE110/SC60, ST6000VN0041-2EL11C/SC61, ST8000VN0022-2EL112/SC61, -+ // ST10000VN0004-1ZD101/SC60, ST12000VN0007-2GS116/SC60, ST12000VN0008-2JH101/SC60 -+ "ST(1|2|3|4|6|8|10|12)000VN00(0?[2478]|1|22|33|41)-.*", - "", "", "" - }, - { "Seagate IronWolf Pro", // tested with ST4000NE0025-2EW107/EN02, -- // ST8000NE0004-1ZF11G/EN01, ST8000NE0021-2EN112/EN02 -- "ST([24]000NE0025|6000NE0023|8000NE00(04|08|21)|(10|12|14)000NE000[478])-.*", -- "", "", "" -+ // ST8000NE0004-1ZF11G/EN01, ST8000NE0021-2EN112/EN02, ST16000NE000-2RW103/EN02 -+ "ST([24]000NE0025|4000NE001|6000NE0023|8000NE00(04|08|21)|(10|12|14)000NE000[478]|16000NE000)-.*", -+ "", "", -+ "-v 18,raw48,Unknown_Seagate_Attrib " // ST16000NE000 -+ "-v 240,msec24hour32" - }, - { "Seagate Archive HDD", // tested with ST8000AS0002-1NA17Z/AR13 - "ST[568]000AS00[01][12]-.*", -@@ -4143,9 +4186,15 @@ const drive_settings builtin_knowndrives - // ST3000VX000, ST3000VX004, ST2000VX000, ST2000VX004, ST1000VX000 - { "Seagate Surveillance", // tested with ST1000VX001-1HH162/CV11, ST2000VX000-9YW164/CV12, - // ST4000VX000-1F4168/CV14, ST2000VX003-1HH164/CV12 -- "ST([1-6]000VX00[01234]1?|31000526SV|3500411SV)(-.*)?", -+ "ST([1-5]000VX00[01234]1?|31000526SV|3500411SV)(-.*)?", - "", "", "" - }, -+ { "Seagate Skyhawk", // tested with ST3000VX010-2H916L/CV11, ST6000VX0023-2EF110/SC60 -+ "ST(1000VX005|2000VX008|3000VX0(09|10)|4000VX007|6000VX00(1|23)|8000VX00(4|22))-.*", -+ "", "", -+ "-v 9,msec24hour32 " // CV* Firmware only? -+ "-v 240,msec24hour32" -+ }, - { "Seagate DB35", // tested with ST3250823ACE/3.03, ST3300831SCE/3.03 - "ST3(200826|250823|300831|400832)[AS]CE", - "", "", "" -@@ -4242,13 +4291,17 @@ const drive_settings builtin_knowndrives - "-v 242,raw48,Lifetime_Rds_Frm_Hst_GB " - "-v 243,hex56,Free_Space " - }, -- { "WD Blue and Green SSDs", // tested with WDC WDS250G1B0A-00H9H0/X41000WD, -+ { "WD Blue / Red / Green SSDs", // tested with WDC WDS250G1B0A-00H9H0/X41000WD, - // WDC WDS250G1B0A-00H9H0/X41100WD, WDC WDS100T1B0A-00H9H0, - // WDC WDS120G2G0A-00JH30/UE360000, WDC WDS240G2G0A-00JH30/UF300000, - // WDC WDS500G2B0A-00SM50/X61130WD, WDC WDS200T2B0A-00SM50/X61130WD, - // WDC WDS200T2B0A/X61190WD, WDC WDS120G1G0A-00SS50/Z3311000 -- // WDC WDS500G2B0A-00SM50/401000WD -- "WDC ?WDS((120|240|250|480|500)G|[12]00T)(1B|2B|1G|2G)0[AB](-.*)?", // *B* = Blue, *G* = Green, *2B* = Blue 3D NAND -+ // WDC WDS500G2B0A-00SM50/401000WD, -+ // WDC WDBNCE2500PNC/X61130WD, WDC WDBNCE0010PNC-WRSN/X41110WD, -+ // WDC WDS200T1R0A-68A4W0/411000WR -+ "WDC WDBNCE(250|500|00[124])0PNC(-.*)?|" // Blue 3D -+ "WDC ?WDS((120|240|250|480|500)G|[12]00T)(1B|2B|1G|2G|1R)0[AB](-.*)?", -+ // *B* = Blue, *G* = Green, *2B* = Blue 3D NAND, *1R* = Red SA500 - "", "", - //"-v 5,raw48,Reallocated_Sector_Ct " // Reassigned Block Count - //"-v 9,raw48,Power_On_Hours " -@@ -4379,6 +4432,10 @@ const drive_settings builtin_knowndrives - "WDC WD((25|32|50)00AAKX|5000AZ(LX|RZ)|7500A(AL|ZE)X|10E(AL|ZE)X|[1-6]0EZRZ)-.*", - "", "", "" - }, -+ { "Western Digital Blue (SMR)", // ticket #1313 -+ "WDC WD(20|60)EZAZ-.*", -+ "", "", "" -+ }, - { "Western Digital RE Serial ATA", - "WDC WD(12|16|25|32)00(SD|YD|YS)-.*", - "", "", "" -@@ -4391,8 +4448,9 @@ const drive_settings builtin_knowndrives - "WDC WD(5000AB|7500AY|1000FY)PS-.*", - "", "", "" - }, -- { "Western Digital RE3 Serial ATA", // tested with WDC WD7502ABYS-02A6B0/03.00C06 -- "WDC WD((25|32|50|75)02A|(75|10)02F)BYS-.*", -+ { "Western Digital RE3 Serial ATA", // tested with WDC WD7502ABYS-02A6B0/03.00C06, -+ // WD1002FBYS-12/03.M0300 -+ "(WDC )?WD((25|32|50|75)02A|(75|10)02F)BYS-.*", - "", "", "" - }, - { "Western Digital RE4", // tested with WDC WD2003FYYS-18W0B0/01.01D02, -@@ -4435,8 +4493,8 @@ const drive_settings builtin_knowndrives - { "Western Digital Green", // tested with - // WDC WD10EZRX-00A8LB0/01.01A01, WDC WD20EZRX-00DC0B0/80.00A80, - // WDC WD30EZRX-00MMMB0/80.00A80, WDC WD40EZRX-00SPEB0/80.00A80, -- // WDC WD60EZRX-00MVLB1/80.00A80 -- "WDC WD(7500AA|(10|15|20)EA|(10|20|25|30|40|50|60)EZ)RX-.*", -+ // WDC WD60EZRX-00MVLB1/80.00A80, WDC WD5000AZRX-00A8LB0/01.01A01 -+ "WDC WD(5000AZ|7500AA|(10|15|20)EA|(10|20|25|30|40|50|60)EZ)RX-.*", - "", "", "" - }, - { "Western Digital Caviar Black", // tested with WDC WD7501AAES/06.01D06 -@@ -4457,6 +4515,10 @@ const drive_settings builtin_knowndrives - // old series: WD4001FAEX WD3001FAEX WD2002FAEX WD1002FAEX WD5003AZEX - "", "", "" - }, -+ { "Western Digital Black (SMR)", // ticket #1313 -+ "WDC WD10SPSX-.*", -+ "", "", "" -+ }, - { "Western Digital AV ATA", // tested with WDC WD3200AVJB-63J5A0/01.03E01 - "WDC WD(8|16|25|32|50)00AV[BJ]B-.*", - "", "", "" -@@ -4528,10 +4590,15 @@ const drive_settings builtin_knowndrives - // WDC WD40EFRX-68WT0N0/80.00A80, WDC WD60EFRX-68MYMN1/82.00A82, - // WDC WD80EFAX-68LHPN0/83.H0A83, WDC WD80EFZX-68UW8N0/83.H0A83, - // WDC WD80EZZX-11CSGA0/83.H0A03 (My Book 0x1058:0x25ee), -- // WDC WD60EFAX-68SHWN0/82.00A82, WDC WD100EFAX-68LHPN0/83.H0A83 -- "WDC WD(7500BFC|10JFC|[1-6]0EFR|[68]0E[FZ][AZ]|100EFA)X-.*", -+ // WDC WD100EFAX-68LHPN0/83.H0A83, -+ // WDC WD120EMFZ-11A6JA0/81.00A81 (Easystore 0x1058:0x25fb) -+ "WDC WD(7500BFCX|10JFCX|[1-6]0EFRX|[68]0E[FZ]ZX|(8|10)0EFAX|120EMFZ)-.*", - "", "", -- "-v 22,raw48,Helium_Level" // WD80EFZX, WD100EFAX -+ "-v 22,raw48,Helium_Level" // WD80EFAX, WD80EFZX, WD100EFAX, WD120EMFZ -+ }, -+ { "Western Digital Red (SMR)", // ticket #1313, tested with WDC WD60EFAX-68SHWN0/82.00A82 -+ "WDC WD[2346]0EFAX-.*", -+ "", "", "" - }, - { "Western Digital Red Pro", // tested with WDC WD2001FFSX-68JNUN0/81.00A81, - // WDC WD6002FFWX-68TZ4N0/83.H0A83, WDC WD101KFBX-68R56N0/83.H0A03 -@@ -4539,22 +4606,32 @@ const drive_settings builtin_knowndrives - "", "", - "-v 22,raw48,Helium_Level" // WD101KFBX - }, -- { "Western Digital Purple", // tested with WDC WD40PURX-64GVNY0/80.00A80 -- "WDC WD[123456]0PURX-.*", -+ { "Western Digital Purple", // tested with WDC WD40PURX-64GVNY0/80.00A80, -+ // WDC WD40PURZ-85TTDY0/80.00A80 -+ // WDC WD80PUZX-64NEAY0/80.H0A80 -+ "WDC WD[1234568]0PU[RZ][XZ]-.*", - "", "", "" - }, - { "Western Digital Gold", // tested with WDC WD1005FBYZ-01YCBB2/RR07, - // WDC WD2005FBYZ-01YCBB2/RR07, WDC WD4002FYYZ-01B7CB0/01.01M02, -- // WDC WD8003FRYZ-01JPDB1/01.01H02, WDC WD121KRYZ-01W0RB0/01.01H01 -- "WDC WD([12]005FB|4002FY|6002FR|800[23]FR|1[02]1KR)YZ-.*", -+ // WDC WD4003FRYZ-01F0DB0/01.01H01, WDC WD6003FRYZ-01F0DB0/01.01H01, -+ // WDC WD8003FRYZ-01JPDB1/01.01H02, WDC WD8004FRYZ-01VAEB0/01.01H01, -+ // WDC WD121KRYZ-01W0RB0/01.01H01, -+ "WDC WD([12]005FB|4002FY|4003FR|600[23]FR|800[234]FR|1[02]1KR)YZ-.*", - "", "", - "-v 22,raw48,Helium_Level" // WD121KRYZ - }, -- { "Western Digital Blue", // tested with WDC WD5000LPVX-08V0TT2/03.01A03, -- // WDC WD20NPVZ-00WFZT0/01.01A01 -- // WDC WD10SPZX-22Z10T0/01.01A01 -- "WDC WD(20SPZX|20NPVZ|15NPVZ|10[SJ]PZX|7500BPVX|5000[BL]PVX|5000LPCX|3200LPCX)-.*", -- "", "", "" -+ { "Western Digital Blue Mobile", // tested with WDC WD5000LPVX-08V0TT2/03.01A03, -+ // WDC WD10JPVX-75JC3T0/0301A03, WDC WD10JPVX-22JC3T0/01.01A01, -+ // WDC WD20NPVZ-00WFZT0/01.01A01 -+ "WDC WD(3200LPCX|5000[BL]P[CV]X|7500BPVX|10JP[VZ]X|(15|20)NPVZ)-.*", -+ "", "", "" -+ }, -+ { "Western Digital Blue Mobile (SMR)", // ticket #1313, tested with -+ // WDC WD10SPZX-22Z10T0/01.01A01, WDC WD10SPZX-21Z10T0/02.01A02, -+ // WDC WD20SPZX-22CRAT0/01.01A01, WDC WD20SPZX-22UA7T0/01.01A01 -+ "WDC WD[12]0SPZX-.*", -+ "", "", "" - }, - { "Western Digital Green Mobile", // tested with WDC WD20NPVX-00EA4T0/01.01A01 - "WDC WD(15|20)NPV[TX]-.*", -@@ -4577,6 +4654,7 @@ const drive_settings builtin_knowndrives - // WDC WD10JMVW-11AJGS2/01.01A01 (0x1058:0x10b8), - // WDC WD10JMVW-11AJGS4/01.01A01 (0x1058:0x25a0/25a2), - // WDC WD10JMVW-11S5XS1/01.01A01, -+ // WDC WD10SMZW-11Y0TS0/01.01A01, - // WDC WD10TMVW-11ZSMS5/01.01A01, - // WDC WD20NMVW-11AV3S2/01.01A01 (0x1058:0x0822), - // WDC WD20NMVW-11AV3S3/01.01A01 (0x1058:0x0837), -@@ -4586,7 +4664,8 @@ const drive_settings builtin_knowndrives - // WDC WD20NMVW-59AV3S3/01.01A01 (0x1058:0x107d), - // WDC WD30NMVW-11C3NS4/01.01A01, - // WDC WD40NMZW-11GX6S1/01.01A01 (0x1058:0x2599/25e2/25fa) -- "WDC WD(5000[LK]|7500[BK]|10[JT]|[234]0N)M[VZ][VW]-.*", // *W-* = USB 3.0 -+ // WDC WD50NDZW-11MR8S1/02.01A02 -+ "WDC WD((5000[LK]|7500[BK]|10[JST]|[234]0N)M|50ND)[VZ][VW]-.*", // *W-* = USB 3.0 - "", "", "" - }, - { "Quantum Bigfoot", // tested with TS10.0A/A21.0G00, TS12.7A/A21.0F00 -@@ -5170,6 +5249,13 @@ const drive_settings builtin_knowndrives - "", - "-d sat" - }, -+ // 0x0860 (?) -+ { "USB: ; ", -+ "0x0860:0x0001", -+ "", // 0x0100 -+ "", -+ "-d sat" -+ }, - // Oxford Semiconductor, Ltd - { "USB: ; Oxford", - "0x0928:0x0000", -@@ -5214,6 +5300,12 @@ const drive_settings builtin_knowndrives - "", - "-d sat" - }, -+ { "USB: Toshiba; Sunplus", -+ "0x0930:0xa002", -+ "", // 0x0103 -+ "", -+ "-d usbsunplus" -+ }, - // Lumberg, Inc. - { "USB: Toshiba Stor.E; Sunplus", - "0x0939:0x0b1[56]", -@@ -5229,8 +5321,8 @@ const drive_settings builtin_knowndrives - }, - // Apricorn - { "USB: Apricorn SATA Wire; ", -- "0x0984:0x0040", -- "", -+ "0x0984:0x0(040|301)", // 0x0040: Apricorn SATA Wire -+ "", // 0x0301 (0x0201): Corsair SSD & HDD Cloning Kit - "", - "-d sat" - }, -@@ -5260,6 +5352,13 @@ const drive_settings builtin_knowndrives - "", - "-d sat" - }, -+ // Realtek -+ { "USB: ; Realtek RTL9210", // USB->PCIe (NVMe) -+ "0x0bda:0x9210", -+ "", // 0x2100 -+ "", -+ "-d sntrealtek" -+ }, - // Addonics - { "USB: Addonics HDMU3; ", // (ticket #609) - "0x0bf6:0x1001", -@@ -5386,9 +5485,9 @@ const drive_settings builtin_knowndrives - }, - // ADATA - { "USB: ADATA; ", -- "0x125f:0xa(11|13|15|31|35|37|75)a", // 0xa11a: Classic CH11 1TB, 0xa13a: NH13 1TB, -+ "0x125f:0xa(11|13|15|31|35|37|75|83)a", // 0xa11a: Classic CH11 1TB, 0xa13a: NH13 1TB, - "", // 0xa15a: HD710 1TB, 0xa31a: HV620 2TB (0x0100), 0xa35a: HD650 2TB (0x6503), -- "", // 0xa37a: Silverstone MS10 M.2 (0x3103), 0xa75a: HD710P 4TB -+ "", // 0xa37a: Silverstone MS10 M.2 (0x3103), 0xa75a: HD710P 4TB, 0xa83a: HD330 (0x0100) - "-d sat" - }, - { "USB: ADATA; Cypress", -@@ -5491,6 +5590,12 @@ const drive_settings builtin_knowndrives - "", - "" // unsupported - }, -+ { "USB: ; JMicron", -+ "0x152d:0x1337", -+ "", // 0x0508, Digitus DA-71106 -+ "", -+ "-d sat" -+ }, - { "USB: ; JMicron JMS561", // USB2/3->2xSATA - "0x152d:0x[19]561", // 0x1561(0x0106), Sabrent USB 3.0 Dual Bay SATA Dock - "", // 0x9561(0x0105), Orico 6629US3-C USB 3.0 Dual Bay SATA Dock -@@ -5704,6 +5809,12 @@ const drive_settings builtin_knowndrives - "", - "-d sat" - }, -+ { "USB: OWC Mercury Elite Pro Quad; ", -+ "0x1e91:0xa4a7", -+ "", // 0x0100 -+ "", -+ "-d sat" -+ }, - // Innostor - { "USB: ; Innostor IS611", // USB3->SATA+PATA - "0x1f75:0x0611", // SMART access via PATA does not work -@@ -5755,6 +5866,13 @@ const drive_settings builtin_knowndrives - "", // 0x0100 - "", - "-d sat" -+ }, -+ // AKiTiO (?) -+ { "USB: AkiTio NT2 U3.1C; ", -+ "0x2ce5:0x0014", -+ "", // 0x0100 -+ "", -+ "-d sat" - }, - // Power Quotient International - { "USB: PQI H560; ", diff -Nru smartmontools-7.1/debian/rules smartmontools-7.3/debian/rules --- smartmontools-7.1/debian/rules 2020-01-04 08:33:20.000000000 +0000 +++ smartmontools-7.3/debian/rules 2023-07-05 09:18:39.000000000 +0000 @@ -21,16 +21,6 @@ endif CFLAGS += -fsigned-char -Wall -ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) - CFLAGS += -O0 -else - CFLAGS += -O2 -endif -ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) - INSTALL_PROGRAM = install -s -else - INSTALL_PROGRAM = install -endif %: dh $@ @@ -73,6 +63,8 @@ debian/smartmontools/usr/share/doc/smartmontools/INSTALL \ debian/smartmontools/usr/share/doc/smartmontools/TODO \ ; + ## #976696 + mv -v debian/smartmontools/var/lib/smartmontools/drivedb/* debian/smartmontools/usr/share/smartmontools/ override_dh_fixperms: dh_fixperms diff -Nru smartmontools-7.1/debian/smartd-runner smartmontools-7.3/debian/smartd-runner --- smartmontools-7.1/debian/smartd-runner 2019-10-09 10:11:03.000000000 +0000 +++ smartmontools-7.3/debian/smartd-runner 2023-07-05 09:18:39.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/bash -e -tmp=$(tempfile) +tmp=$(mktemp) cat >$tmp run-parts --report --lsbsysinit --arg=$tmp --arg="$1" \ diff -Nru smartmontools-7.1/debian/smartmontools.dirs smartmontools-7.3/debian/smartmontools.dirs --- smartmontools-7.1/debian/smartmontools.dirs 1970-01-01 00:00:00.000000000 +0000 +++ smartmontools-7.3/debian/smartmontools.dirs 2023-07-05 09:18:39.000000000 +0000 @@ -0,0 +1 @@ +/var/lib/smartmontools/drivedb diff -Nru smartmontools-7.1/debian/smartmontools.lintian-overrides smartmontools-7.3/debian/smartmontools.lintian-overrides --- smartmontools-7.1/debian/smartmontools.lintian-overrides 2019-10-09 10:11:03.000000000 +0000 +++ smartmontools-7.3/debian/smartmontools.lintian-overrides 2023-07-05 09:18:39.000000000 +0000 @@ -1,3 +1,3 @@ # Full stop at end of synopsis is OK - it doesn't end a sentence but is part of # an abbreviation. -smartmontools: description-synopsis-might-not-be-phrased-properly +smartmontools: synopsis-is-a-sentence diff -Nru smartmontools-7.1/debian/smartmontools.postinst smartmontools-7.3/debian/smartmontools.postinst --- smartmontools-7.1/debian/smartmontools.postinst 2019-10-09 12:58:09.000000000 +0000 +++ smartmontools-7.3/debian/smartmontools.postinst 2023-07-05 09:18:39.000000000 +0000 @@ -4,15 +4,12 @@ # Remove shutdown and reboot links; this init script does not need them. case "$1" in configure) - if dpkg --compare-versions "$2" lt "5.38+svn2879-1"; then - if [ -e /etc/rc0.d/K20smartmontools ]; then - rm -f /etc/rc0.d/K20smartmontools - fi - if [ -e /etc/rc6.d/K20smartmontools ]; then - rm -f /etc/rc6.d/K20smartmontools - fi - fi - ;; + ## https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=976696 + ## TODO: As suggested in #976696, it would be better to avoid replacing + ## newer "drivedb.h" unconditionally if user updated it with + ## "update-smart-drivedb". + cp -f /usr/share/smartmontools/drivedb.h /var/lib/smartmontools/drivedb/ + ;; esac #DEBHELPER# diff -Nru smartmontools-7.1/debian/upstream/signing-key.asc smartmontools-7.3/debian/upstream/signing-key.asc --- smartmontools-7.1/debian/upstream/signing-key.asc 2020-01-04 08:33:20.000000000 +0000 +++ smartmontools-7.3/debian/upstream/signing-key.asc 2023-07-05 09:18:39.000000000 +0000 @@ -1,56 +1,29 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -mQENBFhnw5YBCACsoIZ3/63lo1i4k626AnLYh2k2lueijumTuY86F7iwMeud1dLW -Ue2pjWT7bwIB+CnjdOQk4G0UBidBf+NtQQ0w/vafGXe0kTEPtVGT1fTVLjBK9IyL -lyN0A2aJTnj0tFolZXq12DVf5S9AECWibujnnHDMYyUYAcq3pLcG+xSOaWvOCB37 -svLGoxXm89zcl90LfQT8iEVjNJSFP/8G2Soa4+RAONLnN8MDSJ63P0g391o2y8IY -X4RvIb3ZdcLTiiEEkKNINLqXE8xSZckLs1HkpUEenLSON2QR/QnuWjfyGnFjyKsx -zExug3eANm7zeB1DaRW8LXo0r62+ZFVj0e0vABEBAAG0UlNtYXJ0bW9udG9vbHMg -U2lnbmluZyBLZXkgKHRocm91Z2ggMjAxOCkgPHNtYXJ0bW9udG9vbHMtc3VwcG9y -dEBsaXN0aS5qcGJlcmxpbi5kZT6JAUEEEwECACsCGwMFCQPCZwAGCwkIBwMCBhUI -AgkKCwQWAgMBAh4BAheABQJZ7jP9AhkBAAoJEBjs2kbL9rrGUVsIAJLuDQRXvr9c -h2J4Kw0LcGGD4NBbdX5/DNarSh00YK7iVPih0x+V5nbnaeRd1FvzYjWpbcxHOMoA -n2db8c6/I7cSEe0EC8vG+2G4EpjDtKkR8PAdvDkEmATconcGBlBCDu8ApF0JGXmH -2LDubsmK874I3WbewS7IRDUiZvcLLwva+odDuIHdoCaqytvAyH0SmeUMd1CsDYwB -49TyefDurRGqLxdDtfSlfvY1sxZEFIRaz1H2sqvda87hLGeDgIqzpEiPOCkWdfQ0 -h/RnL1BoJxOtCELAA8qmlqItjvW3+BiPqCbokD0jupMYnTX1myNIOUKLJXal0Y10 -k4IgW1uFcg20VlNtYXJ0bW9udG9vbHMgU2lnbmluZyBLZXkgKHRocm91Z2ggMjAx -OCkgPHNtYXJ0bW9udG9vbHMtc3VwcG9ydEBsaXN0cy5zb3VyY2Vmb3JnZS5uZXQ+ -iQE+BBMBAgAoBQJYZ8OWAhsDBQkDwmcABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIX -gAAKCRAY7NpGy/a6xjiRCACsbz5xPUoX1EFVFV3TO4/lrYSOcnR4Wp2VXtM/52a1 -x7yIbE5AKJXRxj+FcC0qOMj9ApLRooMhxjRgBGTXg3djyAXAYlGrjNuwGGz//5ax -QbdbTUi6TldBJCmZDuDBCY1CEOcS1iHuFg76FI0eK7X7mf2z9Qf8t3ClvHQpfCnH -3gWkalsISs9kvoWLo+uqx24DIJEOxeVYw3qmnFRKABXdWGD5fRW17WBsGGV3Db9N -qD7CDcxvBxtGFhD2i5FadaQJkAPJu061JQW15LVLefvXuPkAac9vQLb7wgStwQbg -9oaTg/fj4FqPR92yFg+Sw/f9yeX6zKJNqH24VwLAN+zs -=AGpr ------END PGP PUBLIC KEY BLOCK----- ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFwmhqoBEADbig8V2B28xk78xdn7r6BgJ5xojZXdAOqpELy3ZmCZWc11vN/e -d7x2fuDUBmK6w51KTzJP+9G+tLZqXTnvz0gGwNLvnR+0a+qotba2EScgU/IKSk8v -mllaexV3tEADzkQ5mykiPCqX5WdTU/HJ/O3t1oJhMTaq1WfdLLxTiFZgv5RxPwiC -KbIlllwwNyMMnvma2tujaBUkFt8iogk+or9Ulxn1xGiCJgZua2OJzIxLVTvMXBPm -ZVnaLkSMFSpEmXseXZBqPeoNPFgfv1pCHXPC6HVlQJSO3Tgoj3fCC910IyOqP/9a -pyIq7TpM7BM3dfUZbZzQ56zM5r2yhFnbVpwsaCa81/TDMedkZq2jHjacyiYRm1ou -5FgtjSaxK3EQMHhzHJwj8KL9Dm3rZC8r1qyozJT8DWp7zyGcp6WarBs2db2ZvDDa -/dxNlDkcvuaeYV+OVWgUoXNxoMuIdi0xg0Op3ELywy6R9qM52vQ1RHsLCcRHKzX2 -6a4Dqlzakc2fjXGT+S22vpTiyORzQipZ7VFvntgnJ0nKF+YAQibonzHumQwy4JG3 -LRGKuX2Wq/ZxTP0CkBCjYc6AQLmKLUduy6v+vSSbVFlS67SRE4WVoXFSxf2L1/0+ -UTcCilAeQKkBPtY8oiW7TaUsAL/29i2qxX9Nx1JRpc/744INsFu7S69kxQARAQAB -tFJTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjApIDxzbWFy -dG1vbnRvb2xzLXN1cHBvcnRAbGlzdGkuanBiZXJsaW4uZGU+iQI+BBMBAgAoBQJc -JoaqAhsDBQkDx60ABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRC/CzOcZLyq -iz50D/9gGITv/Je81CkH/lw6dw3DuKN66kuSwEPxA3wIdcYkI8XBXxt4A6xLi860 -T/h477jIIZ+0W9vJfe74qhyx2KrvhwXJW6LhgApk0sED0nkSE+5fEBBa4Y+ryc40 -X3Q2mepsTl857uKGaC4E/iHZdM2UO/FvqvQ9fcSnXZUDzUcyyerdgBL2aktJrYeo -z2Rq7m7Aae1rziV5GS874EmYYhp6VYA4JAhYSpUMps52q8/WahcEbCjJYR7baI73 -C5qZV1DnRjMwH2W85t+5ZpgMo+/PhXTbQ1ZuftpQHxV+Pu0O0Rb5skdFXhfpkn0w -qe5nYROm5Va1QUCjKw4JpVzWQ8QUJ8YKmgu2GBcA9IIcOxDFWhO3VnxwCMll9RZz -mXCTo8HHp6X7Z+iP5oW3mXro2mxyxOVdV9IAtD7Hrpg7lJLBitaz06NomyOVmmpQ -B9EgdC8LIn848jmJ8bzuBbemD/NRhRd6Ytf87js9s/PO2Y4kAvx3bUVlvRT9cjEa -B4RlmXfIwQKw5m/wpHboHHY4d/PrLpG1zqS8NIFSnBk+QNloZA3Ws53uO5qq1r/P -76FFCMxU+WSKdnXRkrJsB8vKE4nE4mGl7H0Sx4O9eUQw69DJq7brV4ep8aWONujp -p2D9JBmehtIKwwaegsyliWOGe82PbQClk1lmlA3aw+poRlWDfQ== -=buaE +mQINBF/gs9YBEADyn0P5OLnlgjujm1VsVyltEqFm3iOtniHoeiUAZYhBdG0b9gQE +G/NFMtyd5h9WY4ZWUu3rlD30cHKK52IHz1zvHFoscz+T32hBAPN6xG+990PCRtZ7 +9qZRt6KlfV/7gCQk31W5BBUOaQaquhP5Ud1m+VFUjShta4r0bXya00PZvfI02Ky2 +l+9mwrD5FsGP3ri7Yf81Lx2xLmiW2BwphDYmqJ0uzGBKeJgi5myUjqTbfWTRAsaX +ji0n570Pd6xtEvCjWdPU7q+/3XmD8rIoizOB0ChGoLLQc5cjNCzAeuiExFd9ule2 +RomO+czylB2rsmxbw2vUlkcZ2LmRBvZskMAZWmc0z9LGnGQA9RZZFyEOTC10cC69 +YMae5JHp+veS/2qw/5UOsR6RfbT+BUPLLJW+/RrUvgfxs36oG/DCxSNqrQpRuvlk +gGsmrl+W8s+pxL8dn5F1W4mkkiR6g5P5xVrYckkQnXblQL8qAVtBLFClvyme9ilf +ZzeGpamk8+m/8P1omlnfJjMTXueWz47+XXFLj37+lnWhRo+B+u7orphTUCYi7zYy +fYYXQcZsT2j+804aKTRyNDksoaAp1fa6oqOvBkkHq/FlkIDsxfCbF++WFgRZZfyK +R8HAdn9MrRkSWjUoJLVd+1EEr3OZYk/lYhOFYfwlGpuY5VPmkRxfS2FSOQARAQAB +tFJTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjUpIDxzbWFy +dG1vbnRvb2xzLXN1cHBvcnRAbGlzdGkuanBiZXJsaW4uZGU+iQI+BBMBAgAoBQJf +4LPWAhsDBQkJdIIABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAKMIEu/zrv +9VjhEADLuXMN7pRyOj9sMcio72fI2rmATxawd3vxWuW6aaGqwJlO78r7yxTI7Myi +EmZ4qCJWvR7/98t/1NXPDB1mMedicVcLl154EyJeeYhWJxtKe95yuib5lSlJmGTu +gue/n1dbIIqPSd4v3s8Y7DUpsjnebnShqXSoSXhq3hGpcL3cYsL1M0+4vEweHEeN +aE2URjb2eaQMYBvI25upH+cQ5YEa3X5XpCv72oAJvgGJFckAKUasuDMAYxWNenJw +quREHffotRtOOycdET2as3dapF8NuZXUJTPJBX76ctAng6UF5B4uqn/e9+j8Ch40 +SJkg/Em0xNmNeu790HPkQxlpoPyRv8HNpaWZb2JLqPhGFVruiIBDKq3jXCWNpjba +g2ZYM+eHXyWg/w5OkDfeEnlBo7d3AhuE5b3k1GQgcyob1yt0QAUiDRUW3AlBSRQo +LJAorU+QEoTQR2uUOWbk51Kecoyd1YEPbcbIpEQASddDxyzgsipFcKRszUDBYSYs +bZIR1mp1QUQ6SX2/Vi7xyBGrCRnv8S7SWLISQp2wgI7qEqRG7S+0NEyDn87ju7q5 +MxAk99iCTBBSWk95q1e9uf5tFJO5deWfwNlWTIGWK9nvJt1VGLGr+oZ4qe2aBC8K +lLWNbng9PX/1L1WIAUvYa4xooXClGC6nthrC381A6d93/mG0uQ== +=D1Nc -----END PGP PUBLIC KEY BLOCK----- diff -Nru smartmontools-7.1/depcomp smartmontools-7.3/depcomp --- smartmontools-7.1/depcomp 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/depcomp 2022-02-28 16:34:38.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Copyright (C) 1999-2021 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff -Nru smartmontools-7.1/dev_areca.cpp smartmontools-7.3/dev_areca.cpp --- smartmontools-7.1/dev_areca.cpp 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/dev_areca.cpp 2022-02-27 07:53:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * dev_areca.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2012 Hank Wu * @@ -13,7 +13,7 @@ #include "dev_interface.h" #include "dev_areca.h" -const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 4760 2018-08-19 18:45:53Z chrfranke $" +const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 5337 2022-02-27 07:53:55Z dpgilbert $" DEV_ARECA_H_CVSID; #include "atacmds.h" @@ -78,7 +78,7 @@ set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum); } -generic_areca_device::~generic_areca_device() throw() +generic_areca_device::~generic_areca_device() { } @@ -120,11 +120,11 @@ int ioctlreturn = 0; sSRB_BUFFER sBuf; - struct scsi_cmnd_io iop; + struct scsi_cmnd_io iop = {}; int dir = DXFER_TO_DEVICE; - uint8_t cdb[10]={0}; - uint8_t sense[32]={0}; + uint8_t cdb[10]={}; + uint8_t sense[32]={}; unsigned char *areca_return_packet; int total = 0; @@ -133,7 +133,6 @@ unsigned char *ptr = &return_buff[0]; memset((unsigned char *)&sBuf, 0, sizeof(sBuf)); - memset(&iop, 0, sizeof(iop)); sBuf.srbioctl.HeaderLength = sizeof(sARCMSR_IO_HDR); memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR)); @@ -653,7 +652,7 @@ set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum); } -areca_ata_device::~areca_ata_device() throw() +areca_ata_device::~areca_ata_device() { } @@ -681,7 +680,7 @@ set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum); } -areca_scsi_device::~areca_scsi_device() throw() +areca_scsi_device::~areca_scsi_device() { } diff -Nru smartmontools-7.1/dev_areca.h smartmontools-7.3/dev_areca.h --- smartmontools-7.1/dev_areca.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/dev_areca.h 2021-02-01 20:36:02.000000000 +0000 @@ -1,7 +1,7 @@ /* * dev_areca.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2012 Hank Wu * @@ -11,7 +11,7 @@ #ifndef DEV_ARECA_H #define DEV_ARECA_H -#define DEV_ARECA_H_CVSID "$Id: dev_areca.h 4760 2018-08-19 18:45:53Z chrfranke $" +#define DEV_ARECA_H_CVSID "$Id: dev_areca.h 5198 2021-02-01 20:36:02Z chrfranke $" ///////////////////////////////////////////////////////////////////////////// /// Areca RAID support @@ -92,7 +92,7 @@ { public: generic_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - ~generic_areca_device() throw(); + ~generic_areca_device(); ///////////////////////////////////////////////////////////////////// // OS-dependent functions @@ -140,10 +140,10 @@ { public: areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - ~areca_ata_device() throw(); - bool arcmsr_lock() { return true; } - bool arcmsr_unlock() { return true; } - int arcmsr_do_scsi_io(struct scsi_cmnd_io * /* iop */) + ~areca_ata_device(); + bool arcmsr_lock() override { return true; } + bool arcmsr_unlock() override { return true; } + int arcmsr_do_scsi_io(struct scsi_cmnd_io * /* iop */) override { return -1; } @@ -151,7 +151,7 @@ areca_ata_device(): smart_device(never_called) { } - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; }; // SAS(SCSI) device behind Areca RAID Controller @@ -161,10 +161,10 @@ { public: areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - ~areca_scsi_device() throw(); - bool arcmsr_lock() { return true; } - bool arcmsr_unlock() { return true; } - int arcmsr_do_scsi_io(struct scsi_cmnd_io * /* iop */) + ~areca_scsi_device(); + bool arcmsr_lock() override { return true; } + bool arcmsr_unlock() override { return true; } + int arcmsr_do_scsi_io(struct scsi_cmnd_io * /* iop */) override { return -1; } @@ -172,7 +172,7 @@ areca_scsi_device(): smart_device(never_called) { } - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; }; #endif diff -Nru smartmontools-7.1/dev_ata_cmd_set.h smartmontools-7.3/dev_ata_cmd_set.h --- smartmontools-7.1/dev_ata_cmd_set.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/dev_ata_cmd_set.h 2021-02-01 20:36:02.000000000 +0000 @@ -1,9 +1,9 @@ /* * dev_ata_cmd_set.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2008 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,7 +11,7 @@ #ifndef DEV_ATA_CMD_SET_H #define DEV_ATA_CMD_SET_H -#define DEV_ATA_CMD_SET_H_CVSID "$Id: dev_ata_cmd_set.h 4760 2018-08-19 18:45:53Z chrfranke $" +#define DEV_ATA_CMD_SET_H_CVSID "$Id: dev_ata_cmd_set.h 5198 2021-02-01 20:36:02Z chrfranke $" #include "atacmds.h" // smart_command_set #include "dev_interface.h" @@ -26,7 +26,7 @@ { public: /// ATA pass through mapped to ata_command_interface(). - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; protected: /// Old ATA interface called by ata_pass_through() diff -Nru smartmontools-7.1/dev_intelliprop.cpp smartmontools-7.3/dev_intelliprop.cpp --- smartmontools-7.1/dev_intelliprop.cpp 2019-07-01 20:54:14.000000000 +0000 +++ smartmontools-7.3/dev_intelliprop.cpp 2021-02-01 20:36:02.000000000 +0000 @@ -12,12 +12,10 @@ #include "atacmds.h" // ATTR_PACKED, STATIC_ASSERT, ata_debugmode #include "dev_interface.h" -#include "dev_intelliprop.h" #include "dev_tunnelled.h" #include -const char * dev_intelliprop_cpp_cvsid = "$Id: dev_intelliprop.cpp 4934 2019-07-01 20:54:14Z chrfranke $" - DEV_INTELLIPROP_H_CVSID; +const char * dev_intelliprop_cpp_cvsid = "$Id: dev_intelliprop.cpp 5198 2021-02-01 20:36:02Z chrfranke $"; //Vendor Specific log addresses #define LOG_C0 0xc0 @@ -248,11 +246,11 @@ public: intelliprop_device(smart_interface * intf, unsigned phydrive, ata_device * atadev); - virtual ~intelliprop_device() throw(); + virtual ~intelliprop_device(); - virtual bool open(); + virtual bool open() override; - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; private: unsigned m_phydrive; @@ -267,7 +265,7 @@ set_info().info_name = strprintf("%s [intelliprop_disk_%u]", atadev->get_info_name(), phydrive); } -intelliprop_device::~intelliprop_device() throw() +intelliprop_device::~intelliprop_device() { } @@ -291,7 +289,20 @@ } }//namespace -ata_device * get_intelliprop_device(smart_interface * intf, unsigned phydrive, ata_device * atadev) +ata_device * smart_interface::get_intelliprop_device(const char * type, ata_device * atadev) { - return new intelliprop::intelliprop_device(intf, phydrive, atadev); + // Take temporary ownership of 'atadev' to delete it on error + ata_device_auto_ptr atadev_holder(atadev); + + unsigned phydrive = ~0; int n = -1; + sscanf(type, "intelliprop,%u%n", &phydrive, &n); + if (!(n == (int)strlen(type) && phydrive <= 3)) { + set_err(EINVAL, "Option '-d intelliprop,N' must have 0 <= N <= 3"); + return 0; + } + + ata_device * itldev = new intelliprop::intelliprop_device(this, phydrive, atadev); + // 'atadev' is now owned by 'itldev' + atadev_holder.release(); + return itldev; } diff -Nru smartmontools-7.1/dev_intelliprop.h smartmontools-7.3/dev_intelliprop.h --- smartmontools-7.1/dev_intelliprop.h 2018-09-02 13:11:48.000000000 +0000 +++ smartmontools-7.3/dev_intelliprop.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -/* - * dev_intelliprop.h - * - * Home page of code is: http://www.smartmontools.org - * - * Copyright (C) 2016 Casey Biemiller - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -#ifndef DEV_INTELLIPROP_H -#define DEV_INTELLIPROP_H - -#define DEV_INTELLIPROP_H_CVSID "$Id: dev_intelliprop.h 4763 2018-09-02 13:11:48Z chrfranke $" - -ata_device * get_intelliprop_device(smart_interface * intf, unsigned phydrive, ata_device * atadev); - -#endif diff -Nru smartmontools-7.1/dev_interface.cpp smartmontools-7.3/dev_interface.cpp --- smartmontools-7.1/dev_interface.cpp 2019-11-24 18:19:24.000000000 +0000 +++ smartmontools-7.3/dev_interface.cpp 2021-06-04 16:39:50.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,7 +11,6 @@ #include "config.h" #include "dev_interface.h" -#include "dev_intelliprop.h" #include "dev_tunnelled.h" #include "atacmds.h" // ATA_SMART_CMD/STATUS #include "scsicmds.h" // scsi_cmnd_io @@ -19,15 +18,10 @@ #include #include +#include // realpath() #include -#if defined(HAVE_GETTIMEOFDAY) -#include -#elif defined(HAVE_FTIME) -#include -#endif - -const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 4979 2019-11-24 18:19:24Z chrfranke $" +const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 5219 2021-06-04 16:39:50Z chrfranke $" DEV_INTERFACE_H_CVSID; ///////////////////////////////////////////////////////////////////////////// @@ -49,7 +43,7 @@ throw std::logic_error("smart_device: wrong constructor called in implementation class"); } -smart_device::~smart_device() throw() +smart_device::~smart_device() { s_num_objects--; } @@ -253,7 +247,7 @@ { } -tunnelled_device_base::~tunnelled_device_base() throw() +tunnelled_device_base::~tunnelled_device_base() { delete m_tunnel_base_dev; } @@ -309,8 +303,9 @@ // default std::string s = "ata, scsi[+TYPE], nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], " - "usbjmicron[,p][,x][,N], usbprolific, usbsunplus, sntjmicron[,NSID], " - "intelliprop,N[+TYPE], jmb39x,N[,sLBA][,force][+TYPE]"; + "usbjmicron[,p][,x][,N], usbprolific, usbsunplus, sntasmedia, sntjmicron[,NSID], " + "sntrealtek, intelliprop,N[+TYPE], jmb39x[-q],N[,sLBA][,force][+TYPE], " + "jms56x,N[,sLBA][,force][+TYPE]"; // append custom std::string s2 = get_valid_custom_dev_types_str(); if (!s2.empty()) { @@ -324,36 +319,6 @@ return ""; } -int64_t smart_interface::get_timer_usec() -{ -#if defined(HAVE_GETTIMEOFDAY) - #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) - { - static bool have_clock_monotonic = true; - if (have_clock_monotonic) { - struct timespec ts; - if (!clock_gettime(CLOCK_MONOTONIC, &ts)) - return ts.tv_sec * 1000000LL + ts.tv_nsec/1000; - have_clock_monotonic = false; - } - } - #endif - { - struct timeval tv; - gettimeofday(&tv, 0); - return tv.tv_sec * 1000000LL + tv.tv_usec; - } -#elif defined(HAVE_FTIME) - { - struct timeb tb; - ftime(&tb); - return tb.time * 1000000LL + tb.millitm * 1000; - } -#else - return -1; -#endif -} - bool smart_interface::disable_system_auto_standby(bool /*disable*/) { return set_err(ENOSYS); @@ -389,6 +354,38 @@ return strerror(no); } +std::string smart_interface::get_unique_dev_name(const char * name, const char * type) const +{ + std::string unique_name; +#if defined(HAVE_UNISTD_H) && !defined(_WIN32) && !defined(__OS2__) + char * p = realpath(name, (char *)0); // nullptr requires POSIX.1.2008 compatibility + if (p) { + unique_name = p; + free(p); + } + else +#endif + unique_name = name; + + if (*type && is_raid_dev_type(type)) { + // -d TYPE options must match if RAID drive number is specified + unique_name += " ["; unique_name += type; unique_name += ']'; + } + return unique_name; +} + +bool smart_interface::is_raid_dev_type(const char * type) const +{ + if (!strchr(type, ',')) + return false; + if (str_starts_with(type, "sat,")) + return false; + int i; + if (sscanf(type, "%*[^,],%d", &i) != 1) + return false; + return true; +} + ///////////////////////////////////////////////////////////////////////////// // Default device factory @@ -426,7 +423,7 @@ } dev = get_nvme_device(name, type, nsid); } - + // TODO: Unify handling of '-d TYPE...+BASETYPE...' else if ( (str_starts_with(type, "sat") && (!type[3] || strchr(",+", type[3]))) || str_starts_with(type, "scsi+") || str_starts_with(type, "usb") ) { @@ -461,7 +458,7 @@ return get_snt_device(type, basedev.release()->to_scsi()); } - else if (str_starts_with(type, "jmb39x")) { + else if (str_starts_with(type, "jmb39x") || str_starts_with(type, "jms56x")) { // Split "jmb39x...+base..." -> ("jmb39x...", "base...") unsigned jmblen = strcspn(type, "+"); std::string jmbtype(type, jmblen); @@ -479,14 +476,10 @@ } else if (str_starts_with(type, "intelliprop")) { - // Parse "intelliprop,N[+base...]" - unsigned phydrive = ~0; int n = -1; char c = 0; - sscanf(type, "intelliprop,%u%n%c", &phydrive, &n, &c); - if (!((n == (int)strlen(type) || c == '+') && phydrive <= 3)) { - set_err(EINVAL, "Option '-d intelliprop,N' requires N between 0 and 3"); - return 0; - } - const char * basetype = (type[n] ? type + n + 1 : ""); + // Split "intelliprop...+base..." -> ("intelliprop...", "base...") + unsigned itllen = strcspn(type, "+"); + std::string itltype(type, itllen); + const char * basetype = (type[itllen] ? type+itllen+1 : ""); // Recurse to allocate base device, default is standard ATA if (!*basetype) basetype = "ata"; @@ -500,7 +493,7 @@ set_err(EINVAL, "Type '%s': Device type '%s' is not ATA", type, basetype); return 0; } - return get_intelliprop_device(this, phydrive, basedev.release()->to_ata()); + return get_intelliprop_device(itltype.c_str(), basedev.release()->to_ata()); } else { diff -Nru smartmontools-7.1/dev_interface.h smartmontools-7.3/dev_interface.h --- smartmontools-7.1/dev_interface.h 2019-11-24 18:19:24.000000000 +0000 +++ smartmontools-7.3/dev_interface.h 2021-06-04 16:39:50.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,7 +11,7 @@ #ifndef DEV_INTERFACE_H #define DEV_INTERFACE_H -#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 4979 2019-11-24 18:19:24Z chrfranke $\n" +#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 5219 2021-06-04 16:39:50Z chrfranke $\n" #include "utility.h" @@ -75,7 +75,7 @@ explicit smart_device(do_not_use_in_implementation_classes); public: - virtual ~smart_device() throw(); + virtual ~smart_device(); // Attributes public: @@ -716,7 +716,7 @@ : m_dev(dev), m_base_dev(base_dev) { } /// Destructor deletes device object. - ~any_device_auto_ptr() throw() + ~any_device_auto_ptr() { reset(); } /// Assign a new pointer. @@ -801,7 +801,7 @@ smart_device_list() { } - ~smart_device_list() throw() + ~smart_device_list() { for (unsigned i = 0; i < m_list.size(); i++) delete m_list[i]; @@ -881,7 +881,7 @@ smart_interface() { } - virtual ~smart_interface() throw() + virtual ~smart_interface() { } /// Return info string about build host and/or OS version. @@ -900,12 +900,6 @@ /// TODO: Remove this hack. virtual std::string get_app_examples(const char * appname); - /// Get microseconds since some unspecified starting point. - /// Used only for command duration measurements in debug outputs. - /// Returns -1 if unsupported. - /// Default implementation uses clock_gettime(), gettimeofday() or ftime(). - virtual int64_t get_timer_usec(); - /// Disable/Enable system auto standby/sleep mode. /// Return false if unsupported or if system is running /// on battery. @@ -978,6 +972,16 @@ virtual bool scan_smart_devices(smart_device_list & devlist, const smart_devtype_list & types, const char * pattern = 0); + /// Return unique device name which is (only) suitable for duplicate detection. + /// Default implementation resolves symlinks on POSIX systems and appends + /// " [type]" if is_raid_dev_type(type)' returns true. + virtual std::string get_unique_dev_name(const char * name, const char * type) const; + + /// Return true if the 'type' string contains a RAID drive number. + /// Default implementation returns true if 'type' starts with '[^,]+,[0-9]' + /// but not with 'sat,'. + virtual bool is_raid_dev_type(const char * type) const; + protected: /// Return standard ATA device. virtual ata_device * get_ata_device(const char * name, const char * type) = 0; @@ -1021,6 +1025,10 @@ virtual nvme_device * get_snt_device(const char * type, scsi_device * scsidev); //{ implemented in scsinvme.cpp } + /// Return filter for Intelliprop controllers. + virtual ata_device * get_intelliprop_device(const char * type, ata_device * atadev); + //{ implemented in dev_intelliprop.cpp } + /// Return JMB93x->ATA filter. /// Device 'smartdev' is used for ATA or SCSI R/W access. /// Return 0 and delete 'scsidev' on error. diff -Nru smartmontools-7.1/dev_jmb39x_raid.cpp smartmontools-7.3/dev_jmb39x_raid.cpp --- smartmontools-7.1/dev_jmb39x_raid.cpp 2019-11-24 18:31:59.000000000 +0000 +++ smartmontools-7.3/dev_jmb39x_raid.cpp 2022-02-27 07:53:55.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2019 Christian Franke + * Copyright (C) 2019-21 Christian Franke * * Based on JMraidcon (same license): * Copyright (C) 2010 Werner Johansson @@ -25,7 +25,7 @@ #include -const char * dev_jmb39x_raid_cpp_svnid = "$Id: dev_jmb39x_raid.cpp 4981 2019-11-24 18:31:59Z chrfranke $"; +const char * dev_jmb39x_raid_cpp_svnid = "$Id: dev_jmb39x_raid.cpp 5337 2022-02-27 07:53:55Z dpgilbert $"; static void jmbassert_failed(int line, const char * expr) { @@ -169,18 +169,27 @@ jmb_put_crc(data, crc); } -static void jmb_set_request_sector(uint8_t (& data)[512], uint32_t cmd_id, +static void jmb_set_request_sector(uint8_t (& data)[512], uint8_t version, uint32_t cmd_id, const uint8_t * cmd, unsigned cmdsize) { jmbassert(4 <= cmdsize && cmdsize <= 24); memset(data, 0, sizeof(data)); - jmb_put_le32(data, 0, 0x197b0322); // SCRAMLED_CMD + + uint32_t scrambled_cmd_code; + switch (version) { + default: + case 0: scrambled_cmd_code = 0x197b0322; break; // JMB39x: various devices + case 1: scrambled_cmd_code = 0x197b0393; break; // JMB39x: QNAP TR-004 NAS + case 2: scrambled_cmd_code = 0x197b0562; break; // JMS562 + } + jmb_put_le32(data, 0, scrambled_cmd_code); + jmb_put_le32(data, 4, cmd_id); memcpy(data + 8, cmd, cmdsize); jmb_put_crc(data, jmb_crc(data)); } -static int jmb_get_sector_type(uint8_t (& data)[512]) +static int jmb_get_sector_type(const uint8_t (& data)[512]) { if (jmb_check_crc(data)) return 1; // Plain (wakeup) sector @@ -209,9 +218,15 @@ jmb_set_wakeup_sector(data, 3); jmbassert(jmb_check_crc(data)); uint8_t cmd[] = {1, 2, 3, 4, 5, 6, 7}; - jmb_set_request_sector(data, 42, cmd, sizeof(cmd)); + jmb_set_request_sector(data, 0, 42, cmd, sizeof(cmd)); jmbassert(jmb_get_crc(data) == 0xb1f765d7); jmbassert(jmb_check_crc(data)); + jmb_set_request_sector(data, 1, 42, cmd, sizeof(cmd)); + jmbassert(jmb_get_crc(data) == 0x388b2759); + jmbassert(jmb_check_crc(data)); + jmb_set_request_sector(data, 2, 42, cmd, sizeof(cmd)); + jmbassert(jmb_get_crc(data) == 0xde10952b); + jmbassert(jmb_check_crc(data)); jmb_xor(data); jmbassert(jmb_get_sector_type(data) == 2); } @@ -256,7 +271,8 @@ static bool scsi_read_lba8(scsi_device * scsidev, uint8_t lba8, uint8_t (& data)[512]) { - struct scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr)); + struct scsi_cmnd_io io_hdr = {}; + io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = 512; io_hdr.dxferp = data; @@ -273,7 +289,8 @@ static bool scsi_write_lba8(scsi_device * scsidev, uint8_t lba8, const uint8_t (& data)[512]) { - struct scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr)); + struct scsi_cmnd_io io_hdr = {}; + io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = 512; io_hdr.dxferp = const_cast(data); @@ -300,17 +317,18 @@ { public: jmb39x_device(smart_interface * intf, smart_device * smartdev, const char * req_type, - uint8_t port, uint8_t lba, bool force); + uint8_t version, uint8_t port, uint8_t lba, bool force); - virtual ~jmb39x_device() throw(); + virtual ~jmb39x_device(); - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; private: + uint8_t m_version; uint8_t m_port; uint8_t m_lba; bool m_force; @@ -328,17 +346,17 @@ }; jmb39x_device::jmb39x_device(smart_interface * intf, smart_device * smartdev, const char * req_type, - uint8_t port, uint8_t lba, bool force) + uint8_t version, uint8_t port, uint8_t lba, bool force) : smart_device(intf, smartdev->get_dev_name(), req_type, req_type), tunnelled_device(smartdev), - m_port(port), m_lba(lba), m_force(force), + m_version(version), m_port(port), m_lba(lba), m_force(force), m_blocked(false), m_orig_write_back(false), m_cmd_id(0) { set_info().info_name = strprintf("%s [jmb39x_disk_%u]", smartdev->get_info_name(), port); memset(m_orig_data, 0, sizeof(m_orig_data)); } -jmb39x_device::~jmb39x_device() throw() +jmb39x_device::~jmb39x_device() { if (m_orig_write_back) try { jmb39x_device::restore_orig_data(); @@ -384,7 +402,7 @@ { // Set up request uint8_t request[512]; - jmb_set_request_sector(request, m_cmd_id, cmd, cmdsize); + jmb_set_request_sector(request, m_version, m_cmd_id, cmd, cmdsize); if (ata_debugmode) { pout("JMB39x: Write request sector #%d\n", m_cmd_id); @@ -535,8 +553,11 @@ m_cmd_id = 1; // Run JMB identify disk command + uint8_t b = (m_version != 1 ? 0x02 : 0x01); uint8_t cmd[24]= { - 0x00, 0x02, 0x02, 0xff, + 0x00, + b, b, + 0xff, m_port, 0x00, 0x00, 0x00, m_port, @@ -673,6 +694,23 @@ return 0; } + int n1 = -1; + char prefix[15+1] = ""; + sscanf(type, "%15[^,],%n", prefix, &n1); + uint8_t version; + if (!strcmp(prefix, "jmb39x")) + version = 0; + else if (!strcmp(prefix, "jmb39x-q")) + version = 1; + else if (!strcmp(prefix, "jms56x")) + version = 2; + else + n1 = -1; + if (n1 < 0) { + set_err(EINVAL, "Unknown JMicron type '%s'", type); + return 0; + } + // Use default LBA 33, same as JMraidcon. // MBR disk: Zero filled if there is no boot code in boot area. // GPT disk: Zero filled if GPT entries 125-128 are empty. @@ -680,21 +718,23 @@ unsigned port = ~0; bool force = false; - int n1 = -1, n2 = -1, len = strlen(type); - sscanf(type, "jmb39x,%u%n", &port, &n1); - if (0 < n1 && n1 < len && sscanf(type + n1, ",s%u%n", &lba, &n2) == 1 && n2 > 0) + const char * args = type + n1; + n1 = -1; + sscanf(args, "%u%n", &port, &n1); + int n2 = -1, len = strlen(args); + if (0 < n1 && n1 < len && sscanf(args + n1, ",s%u%n", &lba, &n2) == 1 && n2 > 0) n1 += n2; n2 = -1; - if (0 < n1 && n1 < len && (sscanf(type + n1, ",force%n", &n2), n2) > 0) { + if (0 < n1 && n1 < len && (sscanf(args + n1, ",force%n", &n2), n2) > 0) { force = true; n1 += n2; } if (!(n1 == len && port <= 4 && 33 <= lba && lba <= 62)) { - set_err(EINVAL, "Option -d jmb39x,N[,sLBA][,force] must have 0 <= N <= 4 [, 33 <= LBA <= 62]"); + set_err(EINVAL, "Option -d %s,N[,sLBA][,force] must have 0 <= N <= 4 [, 33 <= LBA <= 62]", prefix); return 0; } - ata_device * jmbdev = new jmb39x::jmb39x_device(this, smartdev, type, port, lba, force); + ata_device * jmbdev = new jmb39x::jmb39x_device(this, smartdev, type, version, port, lba, force); // 'smartdev' is now owned by 'jmbdev' smartdev_holder.release(); return jmbdev; diff -Nru smartmontools-7.1/dev_legacy.cpp smartmontools-7.3/dev_legacy.cpp --- smartmontools-7.1/dev_legacy.cpp 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/dev_legacy.cpp 2021-02-01 20:36:02.000000000 +0000 @@ -1,9 +1,9 @@ /* * dev_legacy.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2008-18 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -18,7 +18,7 @@ #include -const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 4760 2018-08-19 18:45:53Z chrfranke $" +const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 5198 2021-02-01 20:36:02Z chrfranke $" DEV_INTERFACE_H_CVSID; ///////////////////////////////////////////////////////////////////////////// @@ -55,13 +55,13 @@ : smart_device(never_called), m_fd(-1), m_mode(mode) { } - virtual ~legacy_smart_device() throw(); + virtual ~legacy_smart_device(); - virtual bool is_open() const; + virtual bool is_open() const override; - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; protected: /// Return filedesc for derived classes. @@ -74,7 +74,7 @@ }; -legacy_smart_device::~legacy_smart_device() throw() +legacy_smart_device::~legacy_smart_device() { if (m_fd >= 0) ::deviceclose(m_fd); @@ -141,9 +141,9 @@ public: legacy_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual smart_device * autodetect_open(); + virtual smart_device * autodetect_open() override; - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; }; legacy_scsi_device::legacy_scsi_device(smart_interface * intf, @@ -221,17 +221,17 @@ : public /*implements*/ smart_interface { public: - virtual std::string get_app_examples(const char * appname); + virtual std::string get_app_examples(const char * appname) override; virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, - const char * pattern = 0); + const char * pattern = 0) override; protected: - virtual ata_device * get_ata_device(const char * name, const char * type); + virtual ata_device * get_ata_device(const char * name, const char * type) override; - virtual scsi_device * get_scsi_device(const char * name, const char * type); + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; - virtual smart_device * autodetect_smart_device(const char * name); + virtual smart_device * autodetect_smart_device(const char * name) override; }; diff -Nru smartmontools-7.1/dev_tunnelled.h smartmontools-7.3/dev_tunnelled.h --- smartmontools-7.1/dev_tunnelled.h 2018-12-05 18:30:46.000000000 +0000 +++ smartmontools-7.3/dev_tunnelled.h 2021-02-01 20:36:02.000000000 +0000 @@ -1,9 +1,9 @@ /* * dev_tunnelled.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2008 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,7 +11,7 @@ #ifndef DEV_TUNNELLED_H #define DEV_TUNNELLED_H -#define DEV_TUNNELLED_H_CVSID "$Id: dev_tunnelled.h 4848 2018-12-05 18:30:46Z chrfranke $" +#define DEV_TUNNELLED_H_CVSID "$Id: dev_tunnelled.h 5198 2021-02-01 20:36:02Z chrfranke $" #include "dev_interface.h" @@ -27,17 +27,17 @@ explicit tunnelled_device_base(smart_device * tunnel_dev); public: - virtual ~tunnelled_device_base() throw(); + virtual ~tunnelled_device_base(); - virtual bool is_open() const; + virtual bool is_open() const override; - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; - virtual bool owns(const smart_device * dev) const; + virtual bool owns(const smart_device * dev) const override; - virtual void release(const smart_device * dev); + virtual void release(const smart_device * dev) override; private: smart_device * m_tunnel_base_dev; @@ -73,7 +73,7 @@ { } public: - virtual void release(const smart_device * dev) + virtual void release(const smart_device * dev) override { if (m_tunnel_dev == dev) m_tunnel_dev = 0; diff -Nru smartmontools-7.1/drivedb.h smartmontools-7.3/drivedb.h --- smartmontools-7.1/drivedb.h 2019-12-28 21:40:37.000000000 +0000 +++ smartmontools-7.3/drivedb.h 2022-02-19 17:48:34.000000000 +0000 @@ -4,7 +4,7 @@ * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-11 Philip Williams, Bruce Allen - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-22 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -68,9 +68,9 @@ /* const drive_settings builtin_knowndrives[] = { */ - { "$Id: drivedb.h 5008 2019-12-28 21:40:37Z chrfranke $", + { "VERSION: 7.3 $Id: drivedb.h 5319 2022-02-19 17:48:34Z chrfranke $", "-", "-", - "This is a dummy entry to hold the SVN-Id of drivedb.h", + "Version information", "" }, { "DEFAULT", @@ -136,7 +136,7 @@ "-v 228,raw48,Power-off_Retract_Count " // 229 Unknown_Attribute "-v 230,raw48,Head_Amplitude,HDD " - "-v 231,raw48,Temperature_Celsius " + "-v 231,raw48,Temperature_Celsius,HDD " "-v 232,raw48,Available_Reservd_Space " "-v 233,raw48,Media_Wearout_Indicator,SSD " // 234-239 Unknown_Attribute @@ -242,6 +242,26 @@ "-v 231,raw48,Lifetime_Left " //"-v 241,raw48,Total_LBAs_Written " }, + { "Apacer SSDs", + "([1248]|1[056]|20|3[02]|40|60|64|80|12[08]|160|240|256|320|480|512|640|960|1280|1920|3840)(GB|TB) SATA Flash Drive|" + "S[GH]250-M2[48][02] 128GB SSD", // tested with 120GB SATA Flash Drive/SFMB6130, SH250-M242 128GB SSD/SFMB8120 + "SFM[BC][0-9A-Z][0-9A-Z][1-9A-Z][0-9A-Z]", + "", + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 163,raw48,Maximum_Erase_Count " + "-v 164,raw48,Average_Erase_Count " + "-v 166,raw48,Total_Later_Bad_Blk_Ct " + "-v 167,raw48,SSD_Protect_Mode " + "-v 168,raw48,SATA_PHY_Error_Count " + "-v 171,raw48,Program_Fail_Count " + "-v 172,raw48,Erase_Fail_Count " + "-v 175,raw48,Bad_Cluster_Table_Ct " + "-v 192,raw48,Unexpect_Power_Loss_Ct " + //"-v 194,tempminmax,Temperature_Celsius " + "-v 231,raw48,Lifetime_Left " + //"-v 241,raw48,Total_LBAs_Written " + }, { "Apple MacBook Air SSD", // probably Toshiba "APPLE SSD TS(064|128)E", // tested with APPLE SSD TS064E/TQAABBF0 "", "", @@ -251,7 +271,7 @@ }, { "Apple SD/SM/TS...E/F/G SSDs", // SanDisk/Samsung/Toshiba? "APPLE SSD (S[DM]|TS)0?(128|256|512|768|1024)[EFG]", // tested with APPLE SSD SD256E/1021AP, SD0128F/A223321 - // APPLE SSD SM768E/CXM90A1Q, SM0512F/UXM2JA1Q, TS0256F/109L0704, SM0512G/BXW1SA0Q, SM1024G/BXW1SA0Q + // APPLE SSD SM768E/CXM90A1Q, SM0512F/UXM2JA1Q, TS0256F/109L0704, SM0512G/BXW1SA0Q, SM1024G/BXW1SA0Q "", "", //"-v 1,raw48,Raw_Read_Error_Rate " //"-v 5,raw16(raw16),Reallocated_Sector_Ct " @@ -267,6 +287,40 @@ //"-v 199,raw48,UDMA_CRC_Error_Count " //"-v 240,raw48,Unknown_SSD_Attribute " }, + { "ATP SATA III aMLC M.2 2242 Embedded SSD", + "ATP I-Temp M\\.2 2242", // tested with ATP I-Temp M.2 2242/R0822A + "","", + "-v 1,raw48,Raw_Read_Error_Count " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 14,raw48,Device_Raw_Capacity " + "-v 15,raw48,Device_User_Capacity " + "-v 16,raw48,Initial_Spare_Blocks " + "-v 17,raw48,Remaining_Spare_Blocks " + "-v 100,raw48,Total_Erease_Count " + "-v 160,raw48,Uncorrectable_Sectors " + "-v 172,raw48,Block_Erase_Failure " + "-v 173,raw48,Max_Erase_Count " + "-v 174,raw48,Unexpected_Power_Cycle " + "-v 175,raw48,Average_Erase_Count " + "-v 181,raw48,Program_Fail_Blocks " + "-v 187,raw48,Reported_UE_Counts " + "-v 194,raw48,Device_Temperature " + //"-v 195,raw48,Hardware_ECC_Recovered " + //"-v 197,raw48,Current_Pending_Sector " + //"-v 198,raw48,Offline_Uncorrectable " + "-v 199,raw48,SATA_CRC_Error_Count " + "-v 202,raw48,Percent_Lifetime_Used " + "-v 205,raw48,Thermal_Asperity_Rate " + "-v 231,raw48,Controller_Temperature " + "-v 234,raw48,Nand_Sectors_Read " + "-v 235,raw48,Device_Sectors_Written " + "-v 241,raw48,Nand_Sectors_Written " + "-v 242,raw48,Device_Bytes_Read " + "-v 248,raw48,PCT_Life_Remaining " + "-v 249,raw48,Spare_Block_Remaining " + }, { "Crucial/Micron RealSSD C300/P300", // Marvell 88SS9174 "C300-CTFDDA[AC](064|128|256)MAG|" // tested with C300-CTFDDAC128MAG/0002, // C300-CTFDDAC064MAG/0006 @@ -298,11 +352,11 @@ }, { "Crucial/Micron RealSSD m4/C400/P400", // Marvell 9176, fixed firmware "C400-MTFDDA[ACK](064|128|256|512)MAM|" - // M4-CT032M4SSD3/04MH + // M4-CT032M4SSD3/04MH "M4-CT(032|064|128|256|512)M4SSD[123]|" // tested with M4-CT512M4SSD2/0309 "MTFDDA[AK](064|128|256|512|050|100|200|400)MA[MNR]-1[JKS]1.*", // tested with - // MTFDDAK256MAR-1K1AA/MA52, MTFDDAK256MAM-1K12/08TH, - // MTFDDAA064MAR-1J1AB 49Y5835 49Y5838IBM/MA49 (P400e) + // MTFDDAK256MAR-1K1AA/MA52, MTFDDAK256MAM-1K12/08TH, + // MTFDDAA064MAR-1J1AB 49Y5835 49Y5838IBM/MA49 (P400e) "030[9-Z]|03[1-Z].|0[4-Z]..|[1-Z]....*", // >= "0309" "", //"-v 1,raw48,Raw_Read_Error_Rate " @@ -352,36 +406,9 @@ "-v 202,raw48,Perc_Rated_Life_Used " "-v 206,raw48,Write_Error_Rate" }, - { "Crucial/Micron MX500 SSDs", - "CT(250|500|1000|2000)MX500SSD[14]", // tested with CT500MX500SSD1/M3CR023, - // .../M3CR020, .../M3CR022 - "M3CR02[0-3]", // Firmware with bogus attribute 197 (see ticket #1227) - "This firmware returns bogus raw values in attribute 197", - //"-v 1,raw48,Raw_Read_Error_Rate " - "-v 5,raw48,Reallocate_NAND_Blk_Cnt " - //"-v 9,raw24(raw8),Power_On_Hours " - //"-v 12,raw48,Power_Cycle_Count " - "-v 171,raw48,Program_Fail_Count " - "-v 172,raw48,Erase_Fail_Count " - "-v 173,raw48,Ave_Block-Erase_Count " - "-v 174,raw48,Unexpect_Power_Loss_Ct " - "-v 180,raw48,Unused_Reserve_NAND_Blk " - "-v 183,raw48,SATA_Interfac_Downshift " - "-v 184,raw48,Error_Correction_Count " - //"-v 187,raw48,Reported_Uncorrect " - //"-v 194,tempminmax,Temperature_Celsius " - //"-v 196,raw16(raw16),Reallocated_Event_Count " - "-v 197,raw48,Bogus_Current_Pend_Sect " // Randomly flips 0 <> 1 - //"-v 198,raw48,Offline_Uncorrectable " - //"-v 199,raw48,UDMA_CRC_Error_Count " - "-v 202,raw48,Percent_Lifetime_Remain " - "-v 206,raw48,Write_Error_Rate " - "-v 210,raw48,Success_RAIN_Recov_Cnt " - "-v 246,raw48,Total_LBAs_Written " - "-v 247,raw48,Host_Program_Page_Count " - "-v 248,raw48,FTL_Program_Page_Count" - }, - { "Crucial/Micron BX/MX1/2/3/500, M5/600, 1100 SSDs", + { "Crucial/Micron Client SSDs", // MX100, MX200, BX300, MX300, BX500, MX500, M500, M600, 1100, 1300 + // See also tnfd22_client_ssd_smart_attributes.pdf Rev. E from 2018-09-28 + // (covers M500 FW>=MU03, M510, M550, MX100, M600, MX200, 1100, MX300, 1300) "Crucial_CT(128|256|512)MX100SSD1|"// Marvell 88SS9189, tested with Crucial_CT256MX100SSD1/MU01 "Crucial_CT(200|250|256|500|512|1000|1024)MX200SSD[1346]|" // Marvell 88SS9189, tested with // Crucial_CT500MX200SSD1/MU01, Crucial_CT1024MX200SSD1/MU01, Crucial_CT250MX200SSD3/MU01, @@ -396,10 +423,12 @@ // Crucial_CT1024M550SSD1/MU01, Crucial_CT128M550SSD4/MU02 "CT(120|240|480)BX300SSD1|" // Silicon Motion SM2258, same attributes as Marvell-based Crucial SSDs, // tested with CT240BX300SSD1/M2CR010 - "CT(120|240|480|960)BX500SSD1|" // Silicon Motion SM2258XT, tested with CT120BX500SSD1/M6CR013 + "CT(120|240|480|960|[12]000)BX500SSD1|" // Silicon Motion SM2258XT, tested with CT120BX500SSD1/M6CR013, + // CT1000BX500SSD1/M6CR030, CT2000BX500SSD1/M6CR030 "CT(250|500|1000|2000)MX500SSD[14]|" // Silicon Motion SM2258, tested with CT250MX500SSD1/M3CR010 // CT500MX500SSD1/M3CR010, CT1000MX500SSD1/M3CR010, CT2000MX500SSD1/M3CR010, - // CT250MX500SSD4/M3CR022 (now handled by above entry) + // CT500MX500SSD1/M3CR020, CT250MX500SSD4/M3CR022, CT500MX500SSD1/M3CR022, + // CT500MX500SSD1/M3CR023, CT1000MX500SSD1/M3CR032 "Micron_M500_MTFDDA[KTV](120|240|480|960)MAV|"// tested with Micron_M500_MTFDDAK960MAV/MU05 "Micron_M500DC_(EE|MT)FDDA[AK](120|240|480|800)MBB|" // tested with Micron_M500DC_EEFDDAA120MBB/129, // Micron_M500DC_MTFDDAK800MBB/0129 @@ -407,10 +436,13 @@ "(Micron_)?M510[_-]MTFDDA[KTV](128|256)MAZ|" // tested with M510-MTFDDAK256MAZ/MU01 "MICRON_M510DC_(EE|MT)FDDAK(120|240|480|800|960)MBP|" // tested with Micron_M510DC_MTFDDAK240MBP/0005 "(Micron_)?M550[_-]MTFDDA[KTV](064|128|256|512|1T0)MAY|" // tested with M550-MTFDDAK256MAY/MU01 - "Micron_M600_(EE|MT)FDDA[KTV](128|256|512|1T0)MBF[25Z]?|" // tested with Micron_M600_MTFDDAK1T0MBF/MU01 - "(Micron_1100_)?MTFDDA[KV](256|512|1T0|2T0)TBN|" // Marvell 88SS1074, tested with - // Micron_1100_MTFDDAK256TBN/M0MU020, MTFDDAK256TBN/M0MA020 (OEM) - "Micron 1100 SATA (256G|512G|1T|2T)B", // tested with Micron 1100 SATA 256GB/M0DL022 + "(Micron_M600_)?(EE|MT)FDDA[KTV](128|256|512|1T0)MBF[25Z]?(-.*)?|" // tested with Micron_M600_MTFDDAK1T0MBF/MU01, + // MTFDDAK256MBF-1AN1ZABHA/M603 + "(Micron_1100_)?MTFDDA[KV](256|512|1T0|2T0)TBN(-.*)?|" // Marvell 88SS1074, tested with + // Micron_1100_MTFDDAK256TBN/M0MU020, MTFDDAK256TBN/M0MA020 (OEM), MTFDDAV256TBN-1AR15ABHA/HPC0T14 + "Micron 1100 SATA (256G|512G|1T|2T)B|" // tested with Micron 1100 SATA 256GB/M0DL022 + "(Micron_1300_)?(EE|MT)FDDA[KV](256|512|1T0|2T0)TDL(-.*)?", // tested with Micron_1300_MTFDDAK256TDL/M5MU000, + // Micron_1300_MTFDDAK1T0TDL/M5MU000, MTFDDAK2T0TDL/M5MU030, MTFDDAK256TDL-1AW1ZABFA/M5MA030 "", "", //"-v 1,raw48,Raw_Read_Error_Rate " "-v 5,raw48,Reallocate_NAND_Blk_Cnt " @@ -428,26 +460,65 @@ //"-v 194,tempminmax,Temperature_Celsius " "-v 195,raw48,Cumulativ_Corrected_ECC " //"-v 196,raw16(raw16),Reallocated_Event_Count " - //"-v 197,raw48,Current_Pending_Sector " + "-v 197,raw48,Current_Pending_ECC_Cnt " // MX500: May flip 0 <> 1 (ticket #1227) //"-v 198,raw48,Offline_Uncorrectable " //"-v 199,raw48,UDMA_CRC_Error_Count " - "-v 202,raw48,Percent_Lifetime_Remain " + "-v 202,raw48,Percent_Lifetime_Remain " // norm = max(100-raw,0); raw = percent_lifetime_used "-v 206,raw48,Write_Error_Rate " "-v 210,raw48,Success_RAIN_Recov_Cnt " + "-v 223,raw48,Unkn_CrucialMicron_Attr " // M6CR030 "-v 246,raw48,Total_LBAs_Written " "-v 247,raw48,Host_Program_Page_Count " - "-v 248,raw48,FTL_Program_Page_Count" + "-v 248,raw48,FTL_Program_Page_Count " + "-v 249,raw48,Unkn_CrucialMicron_Attr " // M6CR030 + //"-v 250,raw48,Read_Error_Retry_Rate " // M6CR030 + "-v 251,raw48,Unkn_CrucialMicron_Attr " // M6CR030 + "-v 252,raw48,Unkn_CrucialMicron_Attr " // M6CR030 + "-v 253,raw48,Unkn_CrucialMicron_Attr " // M6CR030 + "-v 254,raw48,Unkn_CrucialMicron_Attr" // M6CR030 + }, + { "Lexar 128GB SSD", // for other Lexar drives see ticket #1529 + "Lexar 128GB SSD", // Lexar 128GB SSD/H190117D + "", "", + "-v 5,raw48,New_Bad_Blk_Cnt " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 167,raw48,SSD_Protect_mode " + "-v 168,raw48,SATA_PHY_Error_Cnt " + "-v 169,raw48,Bad_Block_Cnt " + "-v 171,raw48,Program_Fail_Cnt " + "-v 172,raw48,Erase_Fail_Cnt " + "-v 173,raw48,Erase_Cnt " + "-v 175,raw48,Bad_Cluster_Cnt " + "-v 177,raw48,Read_Retry_Cnt " + "-v 180,raw48,Spare_Blk_Cnt_Left " + //"-v 187,raw48,Reported_Uncorrect " + //"-v 192,raw48,Power-Off_Retract_Count " + //"-v 194,tempminmax,Temperature_Celsius " + //"-v 199,raw48,UDMA_CRC_Error_Count " + "-v 206,raw48,Min_Erase_Cnt " + "-v 207,raw48,Max_Erase_Cnt " + "-v 208,raw48,Avg_Erase_Cnt " + "-v 209,raw48,SLC_Min_Erase_Cnt " + "-v 210,raw48,SLC_Max_Erase_Cnt " + "-v 211,raw48,SLC_Avg_Erase_Cnt " + "-v 231,raw48,SSD_Life_Left " + //"-v 241,raw48,Total_LBAs_Written " + //"-v 242,raw48,Total_LBAs_Read " + "-v 245,raw48,Bit_Error_Cnt " }, // Reference: https://www.micron.com/resource-details/feec878a-265e-49a7-8086-15137c5f9011 // TN-FD-34: 5100 SSD SMART Implementation - { - "Micron 5100 Pro / 5200 SSDs", + { "Micron 5100 Pro / 52x0 / 5300 SSDs", "(Micron_5100_)?(EE|MT)FDDA[KV](240|480|960|1T9|3T8|7T6)T(BY|CB|CC)|" // Matches both stock and Dell OEM // tested with Micron_5100_MTFDDAK3T8TCB/D0MU410, MTFDDAK3T8TCB/D0MU410 - "(Micron_5200_)?MTFDDAK(480|960|1T9|3T8|7T6)TD(C|D|N)", // tested with Micron_5200_MTFDDAK3T8TDD/D1MU505 + "(Micron_5200_)?MTFDDAK(480|960|1T9|3T8|7T6)TD(C|D|N)|" // tested with Micron_5200_MTFDDAK3T8TDD/D1MU505 + "Micron_5210_MTFDDAK(480|960|1T9|3T8|7T6)QDE|" // tested with Micron_5210_MTFDDAK7T6QDE/D2MU804 + "Micron_5300(HC)?_MTFDDA[KV](240|480|960|1T9|3T8|7T6)TD[ST]", // tested with Micron_5300_MTFDDAK1T9TDS/D3MU001, + // Micron_5300HC_MTFDDAK960TDS/D3MN010 "", "", //"-v 1,raw48,Raw_Read_Error_Rate " - //"-v 5,raw48,Reallocated_Block_Count " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " //"-v 9,raw24(raw8),Power_On_Hours " // raw24(raw8)?? //"-v 12,raw48,Power_Cycle_Count " "-v 170,raw48,Reserved_Block_Pct " // Percentage of remaining reserved blocks available @@ -455,14 +526,14 @@ "-v 172,raw48,Erase_Fail_Count " "-v 173,raw48,Avg_Block-Erase_Count " "-v 174,raw48,Unexpect_Power_Loss_Ct " - //"-v 180,raw48,Reserved_Block_Count " // absolute count of remaining reserved blocks available + //"-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot " // absolute count of remaining reserved blocks available "-v 183,raw48,SATA_Int_Downshift_Ct " // SATA speed downshift count - //"-v 184,raw48,Error_Correction_Count " + //"-v 184,raw48,End-to-End_Error " //"-v 187,raw48,Reported_Uncorrect " // Number of UECC correction failures - //"-v 188,raw48,Command_Timeouts " + //"-v 188,raw48,Command_Timeout " //"-v 194,tempminmax,Temperature_Celsius " // 100 - degrees C, wraps: 101 reported as 255 - //"-v 195,raw48,Cumulativ_Corrected_ECC " - //"-v 196,raw48,Reallocation_Event_Ct " + //"-v 195,raw48,Hardware_ECC_Recovered " + //"-v 196,raw16(raw16),Reallocated_Event_Count " //"-v 197,raw48,Current_Pending_Sector " // Use the raw value //"-v 198,raw48,Offline_Uncorrectable " // Use the raw value //"-v 199,raw48,UDMA_CRC_Error_Count " // Use the raw value @@ -472,6 +543,7 @@ "-v 211,raw48,Integ_Scan_Complete_Cnt " // Number of periodic data integrity scans completed "-v 212,raw48,Integ_Scan_Folding_Cnt " // Number of blocks reallocated by integrity scans "-v 213,raw48,Integ_Scan_Progress " // Current is percentage, raw is absolute number of superblocks scanned by the current integrity scan + "-v 246,raw48,Total_LBAs_Written " "-v 247,raw48,Host_Program_Page_Count " "-v 248,raw48,Bckgnd_Program_Page_Cnt" }, @@ -651,8 +723,7 @@ "-v 241,raw48,Lifetime_Writes_GiB " "-v 242,raw48,Lifetime_Reads_GiB" }, - { - "StorFly CFast SATA 6Gbps SSDs", + { "StorFly CFast SATA 6Gbps SSDs", // http://datasheet.octopart.com/VSFCS2CC060G-100-Virtium-datasheet-82287733.pdf // tested with StorFly VSFCS2CC060G-100/0409-000 "StorFly VSFCS2C[CI](016|030|060|120|240)G-...", @@ -661,7 +732,7 @@ "-v 192,raw48,Unsafe_Shutdown_Count " "-v 160,raw48,Uncorrectable_Error_Cnt " // 0729 - remaining in block life. In 0828 remaining is normalized to 100% then decreases - "-v 161,raw48,Spares_Remaining " + "-v 161,raw48,Spares_Remaining " "-v 241,raw48,Host_Writes_32MiB " "-v 242,raw48,Host_Reads_32MiB " "-v 169,raw48,Lifetime_Remaining% " @@ -670,41 +741,46 @@ }, { "Phison Driven SSDs", // see MKP_521_Phison_SMART_attribute.pdf "BP4 mSATA SSD|" // MyDigital BP4, tested with BP4 mSATA SSD/S8FM06.9 + "Corsair Force LE200 SSD|" // tested with Corsair Force LE200 SSD/SBFM10, .../SBFM60.9 + "GIGABYTE GP-GSTFS31((120|240|256|480)G|100T)NTD|" // tested with GIGABYTE GP-GSTFS31120GNTD/SBFM61.3 "GOODRAM IRIDIUM PRO|" // tested with GOODRAM IRIDIUM PRO/SAFM01.5 "IR-SSDPR-S25A-(120|240|480|960)|" // Goodram IRIDM, tested with IR-SSDPR-S25A-120/SBFM91.3, // IR-SSDPR-S25A-240/SBFM91.2 + "KINGSTON O(C|M[48S])P0S3(64|128|256|512)B-[0A]0|" // tested with KINGSTON OCP0S364B-A0/SBFK62A3, + // KINGSTON OM4P0S3256B-A0/SBFK62A3, KINGSTON OM8P0S364B-A0/SBFK62A3, + // KINGSTON OMSP0S3128B-00/SBFK62A3 "KINGSTON SEDC400S37(400|480|800|960|1600|1800)G|" // DC400, tested with // KINGSTON SEDC400S37480G/SAFM02.[GH], KINGSTON SEDC400S37960G/SAFM32.I - "KINGSTON SEDC(450R|500[MR])(480|960|1920|3840)G|" // DC450R, DC500M/R, tested with + "KINGSTON SEDC(450R|500[MR])(480|960|1920|3840|7680)G|" // DC450R, DC500M/R, tested with // KINGSTON SEDC450R480G/SCEKH3. KINGSTON SEDC500M1920G/SCEKJ2.3, - // KINGSTON SEDC500R480G/SCEKJ2.3 + // KINGSTON SEDC500R480G/SCEKJ2.3, KINGSTON SEDC450R7680G/SCEKH3.4 "KINGSTON SUV300S37A(120|240|480)G|" // UV300 SSD, tested with KINGSTON SUV300S37A120G/SAFM11.K "KINGSTON SKC310S3B?7A960G|" // SSDNow KC310, KINGSTON SKC310S37A960G/SAFM00.r "KINGSTON SKC400S37(128G|256G|512G|1T)|" // SSDNow KC400, KINGSTON SKC400S37128G "KINGSTON SV310S3(7A|D7|N7A|B7A)960G|" // SSDNow V310 "KINGSTON SHSS3B?7A(120|240|480|960)G|" // HyperX Savage - "KINGSTON ?SA400S37(120|240|480|960)G|" // Kingston A400 SSD, Phison S11 or + "KINGSTON ?SA400(M8|S37)(120|240|480|960)G|" // Kingston A400 SSD, Phison S11 or // Silicon Motion controller (see ticket #801), tested with // KINGSTON SA400S37240G/SBFK10D7, KINGSTON SA400S37120G/SBFK71E0, */SBFKB1D1 - // KINGSTON SA400S37480G/SBFK10D7 (two spaces) + // KINGSTON SA400S37480G/SBFK10D7 (two spaces), KINGSTON SA400M8240G/SBFK61E1 "Patriot (Flare|Blast|Blaze|Burst)|" // tested with Patriot Flare/SBFM91.2, // Patriot Blast/SAFM11.3, Patriot Blaze/S9FM02, Patriot Burst/SBFM11.2 - "PNY CS(13|22)11 (120|240|480|960)GB SSD|" // tested with PNY CS1311 120GB SSD/CS131122, - // PNY CS2211 240GB SSD/CS221016 - "SSD Smartbuy (60|120|240)GB|" // SSD Smartbuy 240GB/SBFM91.1 + "PNY CS(900|1311|2211) (120|240|480|960)GB SSD|" // tested with PNY CS900 120GB SSD/CS900612, + // PNY CS900 240GB SSD/CS900613, PNY CS1311 120GB SSD/CS131122, PNY CS2211 240GB SSD/CS221016 + "SSD Smartbuy (60|64|120|128|240|256|480|512|960|1024|2000)GB|" // PS3111-S11, tested with + // SSD Smartbuy 240GB/SBFM91.1, SSD Smartbuy 64GB/SBFM21.1 "SSD PHISON 256GB PS3110-S10C|" // tested with SSD PHISON 256GB PS3110-S10C/SAFM12.2 "SSDPR-CX400-(128|256|512|1024)|" // Goodram CX400, tested with SSDPR-CX400-512/SBFM61.3 + "TEAM L3 EVO SSD (120|240|480|960)GB|" // TEAM L3 EVO SSD 120GB/SBFM11.0 "SSM28(128|256|512)GPTCB3B-S11[24]61[123]", // tested with SSM28256GPTCB3B-S112612/SBFM61.2 "", "", //"-v 1,raw48,Raw_Read_Error_Rate " "-v 2,raw48,Not_In_Use " "-v 3,raw48,Not_In_Use " - "-v 5,raw48,Not_In_Use " + "-v 5,raw48,Retired_Block_Count " "-v 7,raw48,Not_In_Use " "-v 8,raw48,Not_In_Use " //"-v 9,raw24(raw8),Power_On_Hours " - "-v 5,raw48,Retired_Block_Count " - //"-v 9,raw24(raw8),Power_On_Hours " "-v 10,raw48,Not_In_Use " //"-v 12,raw48,Power_Cycle_Count " "-v 167,raw48,Write_Protect_Mode " // DC500 @@ -752,12 +828,10 @@ //"-v 1,raw48,Raw_Read_Error_Rate " "-v 2,raw48,Not_In_Use " "-v 3,raw48,Not_In_Use " - "-v 5,raw48,Not_In_Use " + "-v 5,raw48,Retired_Block_Count " "-v 7,raw48,Not_In_Use " "-v 8,raw48,Not_In_Use " //"-v 9,raw24(raw8),Power_On_Hours " - "-v 5,raw48,Retired_Block_Count " - //"-v 9,raw24(raw8),Power_On_Hours " "-v 10,raw48,Not_In_Use " //"-v 12,raw48,Power_Cycle_Count " "-v 168,raw48,SATA_Phy_Error_Count " @@ -822,6 +896,7 @@ { "Indilinx Barefoot_2/Everest/Martini based SSDs", "OCZ VERTEX[ -]PLUS|" // tested with OCZ VERTEX-PLUS/3.55, OCZ VERTEX PLUS/3.55 "OCZ-VERTEX PLUS R2|" // Barefoot 2, tested with OCZ-VERTEX PLUS R2/1.2 + "OCZ-OCTANE|" // Everest 1, tested with OCZ-OCTANE/1.13 "OCZ-PETROL|" // Everest 1, tested with OCZ-PETROL/3.12 "OCZ-AGILITY4|" // Everest 2, tested with OCZ-AGILITY4/1.5.2 "OCZ-VERTEX4", // Everest 2, tested with OCZ-VERTEX4/1.5 @@ -906,8 +981,7 @@ "-v 249,raw48,Total_NAND_Prog_Ct_GiB " "-v 251,raw48,Total_NAND_Read_Ct_GiB" }, - { - "OCZ/Toshiba Trion SSDs", + { "OCZ/Toshiba Trion SSDs", "OCZ-TRION1[05]0|" // tested with OCZ-TRION100/SAFM11.2A, TRION150/SAFZ72.2 "TOSHIBA-TR150|" // tested with TOSHIBA-TR150/SAFZ12.3 "TOSHIBA Q300( Pro\\.)?", // tested with TOSHIBA Q300 Pro./JYRA0101 @@ -932,7 +1006,7 @@ //"-v 5,raw16(raw16),Reallocated_Sector_Ct " //"-v 7,raw48,Seek_Error_Rate " // from InnoDisk iSMART Linux tool, useless for SSD //"-v 8,raw48,Seek_Time_Performance " - //"-v 9,raw48,Power_On_Hours " + //"-v 9,raw24(raw8),Power_On_Hours " //"-v 10,raw48,Spin_Retry_Count " //"-v 12,raw48,Power_Cycle_Count " "-v 168,raw48,SATA_PHY_Error_Count " @@ -954,7 +1028,7 @@ //"-v 1,raw48,Raw_Read_Error_Rate " //"-v 2,raw48,Throughput_Performance " //"-v 3,raw16(avg16),Spin_Up_Time " - //"-v 5,raw48,Reallocated_Sector_Count " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " "-v 7,raw48,Seek_Error_Rate " // ? "-v 8,raw48,Seek_Time_Performance " // ? //"-v 9,raw24(raw8),Power_On_Hours " @@ -1023,18 +1097,19 @@ "-v 248,raw48,Remaining_Life " "-v 249,raw48,Spare_Blocks_Remaining" }, - { "Innodisk 3IE3/3ME3/3ME4 SSDs", // tested with 2.5" SATA SSD 3ME3/S15A19, CFast 3ME3/S15A19 + { "Innodisk 1IE3/3IE3/3ME3/3IE4/3ME4 SSDs", // tested with 2.5" SATA SSD 3ME3/S15A19, // InnoDisk Corp. - mSATA 3ME3/S15A19, mSATA mini 3ME3/S15A19, M.2 (S42) 3ME3, // SATA Slim 3ME3/S15A19, SATADOM-MH 3ME3/S15A19, SATADOM-ML 3ME3/S15A19, // SATADOM-MV 3ME3/S15A19, SATADOM-SL 3ME3/S15A19, SATADOM-SV 3ME3/S15A19, // SATADOM-SL 3IE3/S151019N, 2.5" SATA SSD 3IE3/S15C14i, CFast 3IE3/S15C14i, - // InnoDisk Corp. - mSATA 3IE3/S15C14i, Mini PCIeDOM 1IE3/S15C14i, + // InnoDisk Corp. - mSATA 3IE3/S15C14i, Mini PCIeDOM 1IE3/S15C14i, CFast 3ME3/S15A19 // mSATA mini 3IE3/S15C14i, M.2 (S42) 3IE3/S15C14i, SATA Slim 3IE3/S15C14i, // SATADOM-SH 3IE3 V2/S15C14i, SATADOM-SL 3IE3 V2/S15A19i, SATADOM-SV 3IE3 V2/S15C14i // mSATA 3ME4/L16711, M.2 (S42) 3ME4/L16711, SATADOM-MH 3ME4/L16B01, - // SATADOM-SH 3ME4/L16B01, SATADOM-SH Type C 3ME4/L16B01, SATADOM-SH Type D 3ME4/L16B01 + // SATADOM-SH 3ME4/L16B01, SATADOM-SH Type C 3ME4/L16B01, SATADOM-SH Type D 3ME4/L16B01, + // mSATA 3IE4/L16B01Hi "(2.5\" SATA SSD|CFast|InnoDisk Corp\\. - mSATA|Mini PCIeDOM|mSATA( mini)?|" - "M\\.2 \\(S42\\)|SATA Slim|SATADOM-[MS][HLV]( Type [CD])?) 3([IM]E3|ME4)( V2)?", + "M\\.2 \\(S42\\)|SATA Slim|SATADOM-[MS][HLV]( Type [CD])?) (1IE3|3[IM]E[34])( V2)?", "", "", //"-v 1,raw48,Raw_Read_Error_Rate " //"-v 2,raw48,Throughput_Performance " @@ -1067,9 +1142,9 @@ "-v 241,raw48,Host_Writes_32MiB " "-v 242,raw48,Host_Reads_32MiB" }, - { "InnoDisk iCF 9000 CompactFlash Cards", // tested with InnoDisk Corp. - iCF9000 1GB/140808, - // ..., InnoDisk Corp. - iCF9000 64GB/140808 - "InnoDisk Corp\\. - iCF9000 (1|2|4|8|16|32|64)GB", + { "InnoDisk iCF 9000 / 1SE2 Cards", // tested with InnoDisk Corp. - iCF9000 1GB/140808, + // InnoDisk Corp. - iCF9000 64GB/140808, InnoDisk Corp. - EDC 1SE2 H 64GB/131216 + "InnoDisk Corp\\. - (iCF9000|EDC 1SE2 H) (1|2|4|8|16|32|64)GB", "", "", //"-v 1,raw48,Raw_Read_Error_Rate " //"-v 5,raw16(raw16),Reallocated_Sector_Ct " @@ -1092,8 +1167,9 @@ "-v 241,raw48,Host_Writes_32MiB " "-v 242,raw48,Host_Reads_32MiB" }, - { "Intel X25-E SSDs", - "SSDSA2SH(032|064)G1.* INTEL", // G1 = first generation + { "Intel X25-E SSDs", // tested with + // INTELSSDSA2SH064G1IB 43W7659 44E9163IBM/447C8860 + "(INTEL)?SSDSA2SH(032|064)G1.* (.*IBM|INTEL)", // G1 = first generation "", "", //"-v 3,raw16(avg16),Spin_Up_Time " //"-v 4,raw48,Start_Stop_Count " @@ -1184,9 +1260,10 @@ }, { "Intel 320 Series SSDs", // tested with INTEL SSDSA2CT040G3/4PC10362, // INTEL SSDSA2CW160G3/4PC10362, SSDSA2BT040G3/4PC10362, SSDSA2BW120G3A/4PC10362, - // INTEL SSDSA2BW300G3D/4PC10362, SSDSA2BW160G3L/4PC1LE04, SSDSA1NW160G3/4PC10362 - "INTEL SSDSA[12][BCN][WT](040|080|120|160|300|600)G3[ADL]?", - // 2B = 2.5" 7mm, 2C = 2.5" 9.5mm, 1N = 1.8" microSATA + // INTEL SSDSA2BW300G3D/4PC10362, SSDSA2BW160G3L/4PC1LE04, SSDSA1NW160G3/4PC10362, + // INTEL SSDSA2BW160G3H/4PC10365 + "INTEL SSDSA[12][BCN][WT](040|080|120|160|300|600)G3[ADHL]?", + // 2B = 2.5" 7mm, 2C = 2.5" 9.5mm, 1N = 1.8" microSATA, *H = HP OEM "", "", "-F nologdir " //"-v 3,raw16(avg16),Spin_Up_Time " @@ -1351,7 +1428,7 @@ // https://www.intel.com/content/www/us/en/solid-state-drives/ssd-540s-series-spec.html // https://www.intel.com/content/www/us/en/solid-state-drives/ssd-540s-series-m2-spec.html { "Intel 540 Series SSDs", // INTEL SSDSC2KW120H6/LSF036C, INTEL SSDSC2KW480H6/LSF036C - "INTEL SSDSC[K2]KW(120H|180H|240H|360H|480H|010X)6", + "INTEL SSDSC[K2]KW(120H|180H|240H|360H|480H|010X)6", "", "", "-v 9,msec24hour32,Power_On_Hours_and_Msec " "-v 170,raw48,Available_Reservd_Space " @@ -1368,7 +1445,8 @@ }, { "Intel 545s Series SSDs", // tested with INTEL SSDSCKKW512G8, INTEL SSDSC2KW512G8/LHF002C // SSDSCKKW128G8X1, SSDSCKKW256G8X1, SSDSCKKW512G8X1, SSDSCKKW010T8X1 - "INTEL SSDSC[2K]KW(128G|256G|512G|010T)8.*", + // INTEL SSDSCKKF512G8 SATA 512GB/LHFD05N + "INTEL SSDSC[2K]K[WF](128G|256G|512G|010T)8.*", "", "", //"-v 5,raw16(raw16),Reallocated_Sector_Ct " //"-v 9,raw24(raw8),Power_On_Hours " @@ -1398,8 +1476,9 @@ }, { "Intel 730 and DC S35x0/3610/3700 Series SSDs", // tested with INTEL SSDSC2BP480G4, SSDSC2BB120G4/D2010355, // INTEL SSDSC2BB800G4T, SSDSC2BA200G3/5DV10250, SSDSC2BB080G6/G2010130, SSDSC2BX200G4/G2010110, - // INTEL SSDSC2BB016T6/G2010140, SSDSC2BX016T4/G2010140, SSDSC2BB150G7/N2010101 - "INTEL SSDSC(1N|2B)[ABPX]((080|100|120|150|160|200|240|300|400|480|600|800)G[3467][RT]?|(012|016)T[46])", + // INTEL SSDSC2BB016T6/G2010140, SSDSC2BX016T4/G2010140, SSDSC2BB150G7/N2010101, + // INTEL SSDSC2BB480H4/D2010380 + "INTEL SSDSC(1N|2B)[ABPX]((080|100|120|150|160|200|240|300|400|480|600|800)[GH][3467][RT]?|(012|016)T[46])", // A = S3700, B*4 = S3500, B*6 = S3510, P = 730, X = S3610 // Dell ships drives with model of the form SSDSC2BB120G4R "", "", @@ -1453,31 +1532,31 @@ { "Intel DC S3110 Series SSDs", // Tested with INTEL SSDSCKKI256G8 "INTEL SSDSCKKI(128|256|512)G8", "", "", - //"-v 5,raw16(raw16),Reallocated_Sector_Ct " - //"-v 9,raw24(raw8),Power_On_Hours " - //"-v 12,raw48,Power_Cycle_Count " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " "-v 170,raw48,Available_Reservd_Space " "-v 171,raw48,Program_Fail_Count " "-v 172,raw48,Erase_Fail_Count " - //"-v 173 is missing in official Intel doc" + //"-v 173 is missing in official Intel doc" "-v 174,raw48,Unexpect_Power_Loss_Ct " "-v 183,raw48,SATA_Downshift_Count " - //"-v 184,raw48,End-to-End_Error_Count " + //"-v 184,raw48,End-to-End_Error " "-v 187,raw48,Uncorrectable_Error_Cnt " - //"-v 190,tempminmax,Airflow_Temperature_Cel " - //"-v 192,raw48,Power-Off_Retract_Count " - //"-v 199,raw48,UDMA_CRC_Error_Count " + //"-v 190,tempminmax,Airflow_Temperature_Cel " + //"-v 192,raw48,Power-Off_Retract_Count " + //"-v 199,raw48,UDMA_CRC_Error_Count " "-v 225,raw48,Host_Writes_32MiB " "-v 226,raw48,Workld_Media_Wear_Indic " "-v 227,raw48,Workld_Host_Reads_Perc " "-v 228,raw48,Workload_Minutes " - //"-v 232,raw48,Available_Reservd_Space " - //"-v 233,raw48,Media_Wearout_Indicator " - //"-v 236 is missing in official Intel doc" + //"-v 232,raw48,Available_Reservd_Space " + //"-v 233,raw48,Media_Wearout_Indicator " + //"-v 236 is missing in official Intel doc" "-v 241,raw48,Host_Writes_32MiB " "-v 242,raw48,Host_Reads_32MiB " "-v 249,raw48,NAND_Writes_1GiB " - //"-v 252 is missing in official Intel doc" + //"-v 252 is missing in official Intel doc" }, { "Intel 3710 Series SSDs", // INTEL SSDSC2BA200G4R/G201DL2B (dell) "INTEL SSDSC2BA(200G|400G|800G|012T)4.?", @@ -1546,7 +1625,8 @@ { "Intel S4510/S4610/S4500/S4600 Series SSDs", // INTEL SSDSC2KB480G7/SCV10100, // INTEL SSDSC2KB960G7/SCV10100, INTEL SSDSC2KB038T7/SCV10100, // INTEL SSDSC2KB038T7/SCV10121, INTEL SSDSC2KG240G7/SCV10100 - "INTEL SSDSC(2K|KK)(B|G)(240G|480G|960G|019T|038T)(7|8).?", + // INTEL SSDSC2KB480GZ/7CV10100 + "INTEL SSDSC(2K|KK)(B|G)(240G|480G|960G|019T|038T)(7|8|Z).?", "", "", //"-v 5,raw16(raw16),Reallocated_Sector_Ct " //"-v 9,raw24(raw8),Power_On_Hours " @@ -1617,36 +1697,43 @@ "-v 227,raw48,Workld_Host_Reads_Perc " "-v 228,raw48,Workload_Minutes" }, - { "Kingston SSDNow UV400", - "KINGSTON SUV400S37A?(120|240|480|960)G", // KINGSTON SUV400S37120G/0C3J96R9, - "", - "", - // "-v 1,raw48,Raw_Read_Error_Rate " - // "-v 5,raw16(raw16),Reallocated_Sector_Ct " - // "-v 9,raw24(raw8),Power_On_Hours " - // "-v 12,raw48,Power_Cycle_Count " + { "Kingston SSDNow UV400/500", + "KINGSTON SUV400S37A?(120|240|480|960)G|" // tested with KINGSTON SUV400S37120G/0C3J96R9, + // KINGSTON SUV400S37240G/0C3J96R9, KINGSTON SUV400S37240G/0C3K87RA, + // KINGSTON SUV400S37120G/0C3K87RA + "KINGSTON SUV500(M[8S])?(120|240|480|960)G", // tested with KINGSTON SUV500120G/003056R6, + // KINGSTON SUV500240G/003056R6, KINGSTON SUV500480G/003056RI, + // KINGSTON SUV500MS120G/003056RA, KINGSTON SUV500MS120G/003056RI, + // KINGSTON SUV500M8120G/003056RI + "", "", + //"-v 1,raw48,Raw_Read_Error_Rate " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 100,raw48,Unknown_Kingston_Attr " + "-v 101,raw48,Unknown_Kingston_Attr " "-v 170,raw48,Reserved_Block_Count " "-v 171,raw48,Program_Fail_Count " "-v 172,raw48,Erase_Fail_Count " "-v 174,raw48,Unexpect_Power_Loss_Ct " - // "-v 175,raw48,Program_Fail_Count_Chip,SSD " - // "-v 176,raw48,Erase_Fail_Count_Chip,SSD " - // "-v 177,raw48,Wear_Leveling_Count,SSD " - // "-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip,SSD " - // "-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot,SSD " - // "-v 183,raw48,Runtime_Bad_Block " - // "-v 187,raw48,Reported_Uncorrect " - // "-v 194,tempminmax,Temperature_Celsius " - // "-v 195,raw48,Hardware_ECC_Recovered " - // "-v 196,raw16(raw16),Reallocated_Event_Count " - // "-v 197,raw48,Current_Pending_Sector " - // "-v 199,raw48,UDMA_CRC_Error_Count " + //"-v 175,raw48,Program_Fail_Count_Chip " + //"-v 176,raw48,Erase_Fail_Count_Chip " + //"-v 177,raw48,Wear_Leveling_Count " + //"-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip " + //"-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot " + //"-v 183,raw48,Runtime_Bad_Block " + //"-v 187,raw48,Reported_Uncorrect " + //"-v 194,tempminmax,Temperature_Celsius " + //"-v 195,raw48,Hardware_ECC_Recovered " + //"-v 196,raw16(raw16),Reallocated_Event_Count " + //"-v 197,raw48,Current_Pending_Sector " + //"-v 199,raw48,UDMA_CRC_Error_Count " "-v 201,raw48,Unc_Read_Error_Rate " - // "-v 204,raw48,Soft_ECC_Correction " + //"-v 204,raw48,Soft_ECC_Correction " "-v 231,raw48,SSD_Life_Left " - // "-v 241,raw48,Total_LBAs_Written " - // "-v 242,raw48,Total_LBAs_Read " - "-v 250,raw48,Read_Retry_Count " + "-v 241,raw48,Host_Writes_GiB " + "-v 242,raw48,Host_Reads_GiB " + "-v 250,raw48,Read_Retry_Count" }, { "JMicron based SSDs", // JMicron JMF60x "Kingston SSDNow V Series [0-9]*GB|" // tested with Kingston SSDNow V Series 64GB/B090522a @@ -1663,12 +1750,13 @@ "-v 234,raw24/raw24:w01234,Avg/Max_Erase_Count " "-v 235,raw24/raw24:w01z23,Good/Sys_Block_Count" }, - { "JMicron based SSDs", // JMicron JMF61x, JMF66x, JMF670 + { "JMicron/Maxiotek based SSDs", // JMicron JMF61x, JMF66x, JMF670 "ADATA S596 Turbo|" // tested with ADATA S596 Turbo 256GB SATA SSD (JMicron JMF616) - "ADATA SP600|" // tested with ADATA SP600/2.4 (JMicron JMF661) "ADATA SP310|" // Premier Pro SP310 mSATA, JMF667, tested with ADATA SP310/3.04 + "ADATA SP600(NS34)?|" // tested with ADATA SP600/2.4 (JMicron JMF661) "ADATA SX930|" // tested with ADATA SX930/6.8SE "APPLE SSD TS(064|128|256|512)C|" // Toshiba?, tested with APPLE SSD TS064C/CJAA0201 + "IM2S3138E-(128|256)GM-B|" // ADATA OEM, tested with IM2S3138E-128GM-B/DA002 "KingSpec KDM-SA\\.51-008GMJ|" // tested with KingSpec KDM-SA.51-008GMJ/1.092.37 (JMF605?) "KINGSTON SNV425S2(64|128)GB|" // SSDNow V Series (2. Generation, JMF618), // tested with KINGSTON SNV425S264GB/C091126a @@ -1678,6 +1766,7 @@ "KINGSTON SVP?100S2B?(64|96|128|256|512)G|" // SSDNow V100/V+100 Series, // tested with KINGSTON SVP100S296G/CJR10202, KINGSTON SV100S2256G/D110225a "KINGSTON SV200S3(64|128|256)G|" // SSDNow V200 Series, tested with KINGSTON SV200S3128G/E120506a + "NT-(64|128|256|512|[12]T)|" // KingSpec NT, MAS0902A-B2C or CS1802A-B2C, tested with NT-512/T191212 "TOSHIBA THNS128GG4BBAA|" // Toshiba / Super Talent UltraDrive DX, // tested with Toshiba 128GB 2.5" SSD (built in MacBooks) "TOSHIBA THNSNC128GMLJ|" // tested with THNSNC128GMLJ/CJTA0202 (built in Toshiba Protege/Dynabook) @@ -1714,12 +1803,13 @@ //"-v 241,raw48,Total_LBAs_Written " // FW SVN423b //"-v 242,raw48,Total_LBAs_Read " // FW SVN423b }, - { "Plextor M3/M5/M6 Series SSDs", // Marvell 88SS9174 (M3, M5S), 88SS9187 (M5P, M5Pro), 88SS9188 (M6M/S), + { "Plextor M3/M5/M6/M7 Series SSDs", // Marvell 88SS9174 (M3, M5S), 88SS9187 (M5P, M5Pro), 88SS9188 (M6M/S), // tested with PLEXTOR PX-128M3/1.01, PX-128M3P/1.04, PX-256M3/1.05, PX-128M5S/1.02, PX-256M5S/1.03, // PX-128M5M/1.05, PX-128M5S/1.05, PX-128M5Pro/1.05, PX-512M5Pro/1.06, PX-256M5P/1.01, PX-128M6S/1.03 // (1.04/5 Firmware self-test log lifetime unit is bogus, possibly 1/256 hours) - // PLEXTOR PX-256M6S+/1.00 - "PLEXTOR PX-(64|128|256|512|768)M(3P?|5[MPS]|5Pro|6[MS])\\+?", + // PLEXTOR PX-256M6S+/1.00, PLEXTOR PX-128M3/1.00, PLEXTOR PX-128M3/1.07, PLEXTOR PX-128M6V/1.04, + // PLEXTOR PX-128M6G-2242/1.01, PLEXTOR PX-512M7VC/1.05, PLEXTOR PX-512M8VC +/1.00 + "PLEXTOR ?PX-(64|128|256|512|768)M(3P?|5[MPS]|5Pro|6[GMSV]|[78]VC)(\\+|-.*| )?", "", "", //"-v 1,raw48,Raw_Read_Error_Rate " //"-v 5,raw16(raw16),Reallocated_Sector_Ct " @@ -1768,27 +1858,33 @@ "MZ7PC(512|256|128|064)HA(GH|FU|DR)-000.*|" // probably PM830, tested with SAMSUNG MZ7PC128HAFU-000L1/CXM04L1Q "Samsung SSD 840 (PRO )?Series|" // tested with Samsung SSD 840 PRO Series 128GB/DXM04B0Q, // Samsung SSD 840 Series/DXT06B0Q - "Samsung SSD 8[456]0 EVO (mSATA |M\\.2 )?((120|250|500|750)G|[12]T)B|" // tested with + "Samsung SSD 8[4-7]0 EVO (mSATA |M\\.2 )?((120|250|500|750)G|[124]T)B|" // tested with // Samsung SSD 840 EVO (120|250|500|750)GB/EXT0AB0Q, // Samsung SSD 840 EVO (120|250)GB/EXT0BB6Q, 1TB/EXT0BB0Q, 120GB mSATA/EXT41B6Q, // Samsung SSD 850 EVO 250GB/EMT01B6Q, Samsung SSD 850 EVO M.2 250GB/EMT21B6Q, // Samsung SSD 850 EVO mSATA 120GB/EMT41B6Q, Samsung SSD 850 EVO 2TB/EMT02B6Q, // Samsung SSD 860 EVO 250GB/RVT01B6Q, Samsung SSD 860 EVO mSATA 250GB/RVT41B6Q, // Samsung SSD 860 EVO 500GB/RVT01B6Q, Samsung SSD 860 EVO mSATA 500GB/RVT41B6Q, - // Samsung SSD 860 EVO mSATA 1TB/RVT41B6Q, Samsung SSD 860 EVO 2TB/RVT01B6Q - "Samsung SSD 8[56]0 PRO ((128|256|512)G|1T)B|" // tested with Samsung SSD 850 PRO 128GB/EXM01B6Q, - // Samsung SSD 850 PRO 1TB/EXM01B6Q, Samsung SSD 860 PRO 256GB/RVM01B6Q, - // Samsung SSD 860 PRO 512GB/RVM01B6Q, Samsung SSD 860 PRO 1TB/RVM01B6Q - "SAMSUNG MZ7PA256HMDR-.*|" // PM810 (470 Series), tested with SAMSUNG MZ7PA256HMDR-010H1/AXM07H1Q + // Samsung SSD 860 EVO mSATA 1TB/RVT41B6Q, Samsung SSD 860 EVO 2TB/RVT01B6Q, + // Samsung SSD 860 EVO 4TB/RVT04B6Q, Samsung SSD 870 EVO 1TB/SVT01B6Q + "Samsung SSD 8[56]0 PRO ((128|256|512)G|[124]T)B|" // tested with Samsung SSD 850 PRO 128GB/EXM01B6Q, + // Samsung SSD 850 PRO 1TB/EXM01B6Q, Samsung SSD 850 PRO 2TB/EXM02B6Q, + // Samsung SSD 860 PRO 256GB/RVM01B6Q, Samsung SSD 860 PRO 512GB/RVM01B6Q, + // Samsung SSD 860 PRO 1TB/RVM01B6Q + "Samsung SSD 8[67]0 QVO [1248]TB|" // tested with Samsung SSD 860 QVO 1TB/RVQ02B6Q, + // Samsung SSD 860 QVO 2TB/RVQ01B6Q, Samsung SSD 870 QVO 4TB/SVQ01B6Q + "Samsung SSD 883 DCT ((240|480|960)G|(1\\.92|3\\.84)T)B|" // tested with + // Samsung SSD 883 DCT 480GB/HXT7404Q, Samsung SSD 883 DCT 3.84TB/HXT7404Q "Samsung SSD 845DC EVO .*|" // Samsung SSD 845DC EVO 960GB/EXT03X3Q + "SAMSUNG MZ7PA256HMDR-.*|" // PM810 (470 Series), tested with SAMSUNG MZ7PA256HMDR-010H1/AXM07H1Q "SAMSUNG MZ[7M]PC(032|064|128|256|512)HBCD-.*|" // PM830, tested with SAMSUNG MZMPC032HBCD-000L1/CXM12L1Q "SAMSUNG MZ7TD(128|256)HAFV-.*|" // 840 Series, tested with SAMSUNG MZ7TD256HAFV-000L7/DXT06L6Q - "SAMSUNG MZMTD(128|256|512)HAGL-.*|" // PM841, tested with SAMSUNG MZMTD512HAGL-00000/DXT4200Q - "SAMSUNG MZ7TD512HAGM-.*|" // Another PM841, SAMSUNG MZ7TD512HAGM-000L1/DXT06L0Q + "SAMSUNG MZ[7M]TD(128|256|512)HA[GF][LMV]-.*|" // PM841, tested with SAMSUNG MZMTD512HAGL-00000/DXT4200Q, + // SAMSUNG MZ7TD512HAGM-000L1/DXT06L0Q, SAMSUNG MZMTD128HAFV-000L1/DXT43L0Q "SAMSUNG MZ7WD((120|240)H[AC]FV|480HAGM|960HAGP)-00003|" // SM843T Series, tested with // SAMSUNG MZ7WD120HAFV-00003/DXM85W3Q, SAMSUNG MZ7WD120HCFV-00003/DXM9203Q - "SAMSUNG MZ[7N]TE(128|256|512)HMHP-.*|" // PM851, tested with SAMSUNG MZ7TE256HMHP-000L7/EXT09L6Q, - // SAMSUNG MZNTE256HMHP-000H1/EXT22H0Q + "SAMSUNG MZ[7N]TE(128|256|512)HM(HP|JH)-.*|" // PM851, tested with SAMSUNG MZ7TE256HMHP-000L7/EXT09L6Q, + // SAMSUNG MZNTE256HMHP-000H1/EXT22H0Q, SAMSUNG MZNTE512HMJH-000L2/EXT26L0Q "SAMSUNG MZMPF(032|064)HCFV-.*|" // CM851 mSATA, tested with SAMSUNG MZMPF032HCFV-000H1/FXM42H2Q "SAMSUNG MZ7GE(240HMGR|(480|960)HMHP)-00003|" // SM853T Series, tested with // SAMSUNG MZ7GE240HMGR-00003/EXT0303Q @@ -1801,11 +1897,11 @@ // SAMSUNG MZ7KM960HMJP-00005/GXM5304Q, MZ7KM960HMJP0D3/GD53 (Dell) "SAMSUNG MZ7LH(240|480|960|1T9|3T8|7T6)H[AM](HQ|JR|LT|LA)-.*|" //PM883, tested with SAMSUNG MZ7LH960HAJR-00005 "SAMSUNG MZ7KH(240|480|960|1T9|3T8)HA(HQ|JR|LS)-.*|" //SM883 - "SAMSUNG MZN(LF|TY)(128|256)H[CD]HP-.*|" // CM871/871a, tested with SAMSUNG MZNLF128HCHP-000H1/FXT21H1Q, - // SAMSUNG MZNTY256HDHP-000/MAT21K0Q - "SAMSUNG MZ[7N]LN(128|256|512|1T0)H[ACM](GR|HP|HQ|J[HPQ]|LR)-.*|" // PM871/871a/b, tested with + "SAMSUNG MZ[7N](LF|TY)(128|192|256)H[CD](GS|HP)-.*|" // CM871/871a, tested with SAMSUNG MZNLF128HCHP-000H1/FXT21H1Q, + // SAMSUNG MZNTY256HDHP-000/MAT21K0Q, SAMSUNG MZ7LF192HCGS-000L1/FXT03L1Q + "SAMSUNG MZ[7NY]LN(128|256|512|1T0)H[ACM](GR|HP|HQ|J[HPQ]|LR)-.*|" // PM871/871a/b, tested with // SAMSUNG MZ7LN128HCHP-00000/EMT0100Q, SAMSUNG MZ7LN256HAHQ-000H1/MVT03H6Q, - // SAMSUNG MZNLN256HMHQ-000H1/MAV21H3Q + // SAMSUNG MZNLN256HMHQ-000H1/MAV21H3Q, SAMSUNG MZYLN256HCHP-000L2/EMT63L0Q "SAMSUNG SSD PM871 .*|" // SAMSUNG SSD PM871 2.5 7mm 256GB/EMT02D0Q // SAMSUNG MZ7LN256HMJP-00000/MAV0100Q, SAMSUNG MZ7LN512HMJP-00000/MAV0100Q "SAMSUNG MZHPV(128|256|512)HDG(L|M)-.*|" // SM951, tested with SAMSUNG MZHPV512HDGL-00000/BXW2500Q, @@ -1840,7 +1936,7 @@ "-v 199,raw48,CRC_Error_Count " "-v 201,raw48,Supercap_Status " "-v 202,raw48,Exception_Mode_Status " - //"-v 233,raw48,Media_Wearout_Indicator // PM851, 840 + //"-v 233,raw48,Media_Wearout_Indicator " // PM851, 840 "-v 234,raw48,Unknown_Samsung_Attr " // PM851, 840 "-v 235,raw48,POR_Recovery_Count " // PM851, 830/840/850 "-v 236,raw48,Unknown_Samsung_Attr " // PM851, 840 @@ -1853,7 +1949,7 @@ "-v 245,raw48,Timed_Workld_Media_Wear " // PM863 "-v 246,raw48,Timed_Workld_RdWr_Ratio " // PM863 "-v 247,raw48,Timed_Workld_Timer " // PM863 - "-v 249,raw48,Unknown_Samsung_Attr " // CM871a + "-v 249,raw48,NAND_Writes_1GiB " // CM871a, PM871 "-v 250,raw48,SATA_Iface_Downshift " // from the spec "-v 251,raw48,NAND_Writes" // PM863 }, @@ -1864,17 +1960,22 @@ "SanDisk SD7S[BN]6S-?(128|256|512)G(1122|-1006)|" // X300 (88SS9189?), tested with // SanDisk SD7SB6S128G1122/X3310000, SanDisk SD7SN6S-512G-1006/X3511006 "SanDisk SD8S[BN]8U-?((128|256|512)G|1T00)(1122|-1006)|" // X400 (88SS1074), tested with SanDisk SD8SB8U128G1122/X4120000 - "SanDisk SD9S[BN]8W-?((128|256|512)G|[12]T00)1122|" // X600, tested with SanDisk SD9SB8W128G1122/X6107000 + "SanDisk SD9S[BN]8W-?((128|256|512)G|[12]T00)(1122|-1006)|" // X600, tested with SanDisk SD9SB8W128G1122/X6107000, SD9SB8W-512G-1006/X6103006 + // SanDisk SD9SB8W1T001122/X6107000, SD9SB8W256G1122/X6107000 + "SanDisk SDSSDA-((120|240|480)G|[12]T00)|" // Plus, tested with SanDisk SDSSDA-2T00/411040RL "SanDisk SDSSDHP[0-9]*G|" // Ultra Plus (88SS9175), tested with SanDisk SDSSDHP128G/X23[01]6RL "SanDisk (SDSSDHII|Ultra II )[0-9]*GB?|" // Ultra II (88SS9190/88SS9189), tested with // SanDisk SDSSDHII120G/X31200RL, SanDisk Ultra II 960GB/X41100RL "SanDisk SDSSDH2(128|256)G|" // SanDisk SDSSDH2128G/X211200 - "SanDisk SDSSDH3(250|500|1000|1024|2000)G|" // Ultra 3D, tested with SanDisk SDSSDH3250G/X61170RL, - // SanDisk SDSSDH3500G/X61110RL, SanDisk SDSSDH31024G/X6107000 + "SanDisk SDSSDH3((250|500|1000|1024|2000)G| [24]T00)|" // Ultra 3D, tested with SanDisk SDSSDH3250G/X61170RL, + // SanDisk SDSSDH3500G/X61110RL, SanDisk SDSSDH31024G/X6107000, SanDisk SDSSDH3 2T00/411040RL, + // SanDisk SDSSDH3 4T00/411040RL "SanDisk SDSSDXPS?[0-9]*G|" // Extreme II/Pro (88SS9187), tested with SanDisk SDSSDXP480G/R1311, // SanDisk SDSSDXPS480G/X21200RL - "SanDisk SSD PLUS (120|240|480|1000) ?GB|" // Plus (88SS1074), tested with SanDisk SSD PLUS 120 GB/UE3000RL, + "SanDisk SSD G5 BICS4|" // WD Blue SSD WDS100T2B0A (#1378), tested with SanDisk SSD G5 BICS4/415000WD + "SanDisk SSD PLUS (120|240|480|[12]000) ?GB|" // Plus (88SS1074), tested with SanDisk SSD PLUS 120 GB/UE3000RL, // SanDisk SSD PLUS 120 GB/UE4500RL, SanDisk SSD PLUS 1000GB/UH4400RL + // SanDisk SSD PLUS 2000GB/UP4504RL "SSD SATAIII 16GB", // SSD SATAIII 16GB/i221100 (see #923) "", "", //"-v 5,raw16(raw16),Reallocated_Sector_Ct " @@ -1885,6 +1986,7 @@ "-v 167,raw48,Min_Bad_Block/Die " "-v 168,raw48,Maximum_Erase_Cycle " "-v 169,raw48,Total_Bad_Block " + "-v 170,raw48,Unknown_Marvell_Attr " // SDSSDH3 4T00 "-v 171,raw48,Program_Fail_Count " "-v 172,raw48,Erase_Fail_Count " "-v 173,raw48,Avg_Write/Erase_Count " @@ -1902,7 +2004,7 @@ "-v 234,raw48,Perc_Write/Erase_Ct_BC " "-v 241,raw48,Total_Writes_GiB " "-v 242,raw48,Total_Reads_GiB " - //"-v 243,raw48,Unknown_Attribute " + "-v 243,raw48,Unknown_Marvell_Attr " "-v 244,raw48,Thermal_Throttle " "-v 249,raw48,TLC_NAND_GB_Writes" }, @@ -1914,7 +2016,7 @@ "SanDisk SSD i100 [0-9]*GB|" // tested with SanDisk SSD i100 8GB/11.56.04, 24GB/11.56.04 "SanDisk SSD U100 ([0-9]*GB|SMG2)|" // tested with SanDisk SSD U100 8GB/10.56.00, 256GB/10.01.02, SMG2/10.56.04 "SanDisk SSD U110 (8|16|24|32|64|128)GB|" // tested with SanDisk SSD U110 32GB/U221000 - "SanDisk SDSA6MM-.*|" // tested with SanDisk SDSA6MM-016G-1006/U221006 + "SanDisk SDSA6[GM]M-[0-9]*G-.*|" // tested with SanDisk SDSA6GM-016G-1006/U221006, SanDisk SDSA6MM-016G-1006/U221006 "SanDisk SD7[SU]B[23]Q(064|128|256|512)G.*", // tested with SD7SB3Q064G1122/SD7UB3Q256G1122/SD7SB3Q128G/SD7UB2Q512G1122 "", "", //"-v 5,raw16(raw16),Reallocated_Sector_Ct " @@ -1934,63 +2036,66 @@ //"-v 242,raw48,Total_LBAs_Read " "-v 244,raw48,Thermal_Throttle " }, - // SDLF1DAR-480G-1HAW/ZR07RE41 + // SDLF1DAR-480G-1HAW/ZR07RE41 // SDLF1DAR-480G-1JA1/RP41ZH06 { "Sandisk SATA Cloudspeed Max and GEN2 ESS SSDs", - "SD[A-Z0-9]{2}[1-3][A-Z]{3}-?[0-9]{3}[GT]-?1[A-Z0-9]{3}", - "","", - "-v 13,raw48,Lifetime_UECC_Ct " - "-v 32,raw48,Lifetime_Write_AmpFctr " - "-v 33,raw48,Write_AmpFctr " - "-v 170,raw48,Reserve_Erase_BlkCt " - "-v 171,raw48,Program_Fail_Ct " - "-v 172,raw48,Erase_Fail_Ct " - "-v 173,raw48,Percent_Life_Used " - "-v 174,raw48,Unexpect_Power_Loss " - "-v 175,raw48,Lifetime_Die_Failure_Ct " - "-v 177,raw48,Lifetime_Remaining% " - "-v 178,raw48,SSD_LifeLeft(0.01%) " - "-v 180,raw48,Undetected_Data_Err_Ct " - "-v 183,raw48,LT_Link_Rate_DwnGrd_Ct " - "-v 191,raw48,Clean_Shutdown_Ct " - "-v 192,raw48,Unclean_Shutdown_Ct " - "-v 196,raw48,Lifetime_Retried_Blk_Ct " - "-v 204,raw48,Average_Block-Erase_Ct " - "-v 205,raw48,Read_Retry_Enable_Ct " - "-v 206,raw48,Successful_RaidRecov_Ct " - "-v 207,raw48,Trimmed_Sector_Ct " - "-v 211,raw48,Read_Disturb_ReallocEvt " - "-v 233,raw48,Lifetime_Nand_Writes " - "-v 235,raw48,Capacitor_Health " - "-v 244,raw48,Therm_Throt_Activation " - "-v 245,raw48,Drive_Life_Remaining% " - "-v 253,raw48,SPI_Test_Remaining " - }, - { "Sandisk SATA CS1K GEN1 ESS SSDs", - "SD[A-Z0-9]{2}[NO][A-Z0-9]{3}-?[0-9]{3}[GT]-?1[A-Z0-9]{3}", - "","", - "-v 1,raw48,UECC_Ct " - "-v 2,raw48,Internal_File_Check " - "-v 5,raw16(raw16),Retried_Blk_Ct " - "-v 32,raw48,Write_Ampflication " - "-v 170,raw48,Reserve_Blk_Remaining " - "-v 171,raw48,Program_Fail_Ct " - "-v 172,raw48,Erase_Fail_Ct " - "-v 173,raw48,Drive_Life_Used% " - "-v 174,raw48,Unexpect_PwrLoss_Ct " - "-v 175,raw48,PwrLoss_ProtectionFail " - "-v 177,raw48,DriveLife_Remaining% " - "-v 178,raw48,SSD_Life_Left " - "-v 180,raw48,End_to_End_Err_Detect " - "-v 190,raw48,Drive_Temp_Warning " - "-v 195,raw48,Uncorrectable_Err_Ct " - "-v 202,raw48,Exception_Mode_Status " - "-v 233,raw48,Number_Of_Write_Ct " - "-v 245,raw48,DriveLife_Used% " - }, + "SD[A-Z0-9]{2}[1-3][A-Z]{3}-?[0-9]{3}[GT]-?1[A-Z0-9]{3}", + "","", + "-v 13,raw48,Lifetime_UECC_Ct " + "-v 32,raw48,Lifetime_Write_AmpFctr " + "-v 33,raw48,Write_AmpFctr " + "-v 170,raw48,Reserve_Erase_BlkCt " + "-v 171,raw48,Program_Fail_Ct " + "-v 172,raw48,Erase_Fail_Ct " + "-v 173,raw48,Percent_Life_Used " + "-v 174,raw48,Unexpect_Power_Loss " + "-v 175,raw48,Lifetime_Die_Failure_Ct " + "-v 177,raw48,Lifetime_Remaining% " + "-v 178,raw48,SSD_LifeLeft(0.01%) " + "-v 180,raw48,Undetected_Data_Err_Ct " + "-v 183,raw48,LT_Link_Rate_DwnGrd_Ct " + "-v 191,raw48,Clean_Shutdown_Ct " + "-v 192,raw48,Unclean_Shutdown_Ct " + "-v 196,raw48,Lifetime_Retried_Blk_Ct " + "-v 204,raw48,Average_Block-Erase_Ct " + "-v 205,raw48,Read_Retry_Enable_Ct " + "-v 206,raw48,Successful_RaidRecov_Ct " + "-v 207,raw48,Trimmed_Sector_Ct " + "-v 211,raw48,Read_Disturb_ReallocEvt " + "-v 233,raw48,Lifetime_Nand_Writes " + "-v 235,raw48,Capacitor_Health " + "-v 244,raw48,Therm_Throt_Activation " + "-v 245,raw48,Drive_Life_Remaining% " + "-v 253,raw48,SPI_Test_Remaining " + }, + { "Sandisk SATA CS1K GEN1 ESS SSDs", + "SD[A-Z0-9]{2}[NO][A-Z0-9]{3}-?[0-9]{3}[GT]-?1[A-Z0-9]{3}", + "","", + "-v 1,raw48,UECC_Ct " + "-v 2,raw48,Internal_File_Check " + "-v 5,raw16(raw16),Retried_Blk_Ct " + "-v 32,raw48,Write_Ampflication " + "-v 170,raw48,Reserve_Blk_Remaining " + "-v 171,raw48,Program_Fail_Ct " + "-v 172,raw48,Erase_Fail_Ct " + "-v 173,raw48,Drive_Life_Used% " + "-v 174,raw48,Unexpect_PwrLoss_Ct " + "-v 175,raw48,PwrLoss_ProtectionFail " + "-v 177,raw48,DriveLife_Remaining% " + "-v 178,raw48,SSD_Life_Left " + "-v 180,raw48,End_to_End_Err_Detect " + "-v 190,raw48,Drive_Temp_Warning " + "-v 195,raw48,Uncorrectable_Err_Ct " + "-v 202,raw48,Exception_Mode_Status " + "-v 233,raw48,Number_Of_Write_Ct " + "-v 245,raw48,DriveLife_Used% " + }, { "Silicon Motion based SSDs", - "ADATA (SP550|SU[89]00)|" // tested with ADATA SP550/O0803B5a, ADATA SU800/Q0913A, ADATA SU800/R0427A, - // ADATA SU800/R0918B, ADATA SU900/Q0125A, ADATA SU900/Q0710B + "ADATA_IMSS332-((008|016|032|064|128|256|512)G|001T)[AEMT]P?|" // tested with ADATA_IMSS332-128GTP/Q0810B + "ADATA (SP550|SU(650(NS38)?|655|[89]00))|" // tested with ADATA SP550/O0803B5a, ADATA SU650/S0212B0, + // ADATA SU650/V8X01c45, ADATA SU650/V8X21c64, ADATA SU650NS38/P191202a, ADATA SU655/V8X01c55, + // ADATA SU800/Q0913A, ADATA SU800/R0427A, ADATA SU800/R0918B, ADATA SU900/Q0125A, ADATA SU900/Q0710B + "CORSAIR FORCE LX SSD|" // tested with CORSAIR FORCE LX SSD/N0307A "CHN mSATAM3 (128|256|512)|" // Zheino M3, tested with CHN mSATAM3 128/Q1124A0 "CIS 2S M305 (16|32|64|128|256)GB|" // Ceroz M305, tested with CIS 2S M305 64GB/P0316B "CT(120|250|500|1000)BX100SSD1|" // Crucial BX100, tested with CT250BX100SSD1/MU02, @@ -1999,46 +2104,54 @@ "DREVO X1 SSD|" // tested with DREVO X1 SSD/Q0111A "Drevo X1 pro (64|128|256)G|" // tested with Drevo X1 pro 64G/Q0303B "JAJS500M(120|240|480|960)C-1|" // J&A LEVEN JS500, tested with JAJS500M120C-1/P0614D - "KingDian S(280|400) (120|240|480)GB|" // SM2256EN, tested with KingDian S280 120GB/Q0526A, - // KingDian S400 120GB/Q0607A + "JAJS600M1TB|" // Intenso, tested with JAJS600M1TB/T0529A0 + "KingDian S100 (32|64)GB|" // SM2244LT, tested with KingDian S100 32GB/0311A + "KingDian S(200|280|400) ((60|120|240|480)GB|1TB)|" // SM2256EN, tested with KingDian S200 60GB/R0724A0 + // KingDian S280 120GB/Q0526A, KingDian S280 1TB/S0509A0, KingDian S400 120GB/Q0607A "KingSpec KSD-[PS]A25\\.[1-9]-(016|032|064|128)(MS|SJ)|" // tested with KingSpec KSD-PA25.6-064MS/20140803 + "KINGSTON SKC600(256|512|1024|2048)G|" // SM2259, tested with KINGSTON SKC600256G/S4500105 "LITEON LMH-(128|256|512)V2M-.*|" // tested with LITEON LMH-256V2M-11 MSATA 256GB/FM8110C "LITEON LCH-(128|256V|512)2S-.*|" // tested with LITEON LCH-256V2S-HP/2C02 "MKNSSDRE(1TB|2TB|512GB|500GB|256GB|250GB)|" // tested with MKNSSDRE256GB/N1007C - "MKNSSDTR(240|500|250|120|480|240)GB(-LT)?|" // tested with MKNSSDTR500GB/O1126A + "MKNSSD(S2|TR)(120|2[45]0|480|500)GB(-LT)?|" // tested with MKNSSDS2500GB/T0818A0, MKNSSDTR500GB/O1126A + "NFN025SA31T-.*|"// Neo Forza (?), from HP Laptop, tested with NFN025SA31T-6000000/S0628A0 "OWC Envoy Pro|" // tested with OWC Envoy Pro/R0522A0 (0x1e91:0xa2a5) "Patriot P200 ((128|256|512)GB|[12]TB)|" // tested with Patriot P200 256GB/S1022A0 "R3SL(120|240|480|960)G|" // AMD Radeon SSDs, tested with R3SL240G/P0422C "Ramsta SSD S800 (120|240|480)GB|" // SM2258G, tested with Ramsta SSD S800 480GB/RS81V0 + "SED2QII-LP SATA SSD ((64|128|256|512)GB|[12]TB)|" // ACPI SED2QII-LP, tested with + // SED2QII-LP SATA SSD 64GB/S0410A "T60|" // KingSpec T60, tested with T60/20151120 "TCSUNBOW [MX]3 (60|120|240)GB|" // TC-Sunbow M3/X3, tested with TCSUNBOW M3 240GB/R0327B0, - // TCSUNBOW X3 120GB/R1211A0 + // TCSUNBOW X3 120GB/R1211A0 "TEAM( T253T|L5Lite3)D(120G|240G|480G|1T)|" // Team Group L5Lite 3D, tested with // TEAML5Lite3D240G/R0302A0, TEAM T253TD480G/Q0410A - "TS((16|32|64|128|256|512)G|1T)(SSD|MSA)(370S?|420[IK]?)|" // Transcend SSD370/420 SATA/mSATA, TS6500, - // tested with TS32GMSA370/20140402, TS16GMSA370/20140516, TS64GSSD370/20140516, - // TS256GSSD370/N0815B, TS256GSSD370S/N1114H, TS512GSSD370S/N1114H, TS32GSSD420I/N1114H, - // TS32GSSD420K/P1225CE + "TS((16|32|64|128|256|512)G|1T)(SSD|MSA)(230S?|370S?|420[IK]?)|" // Transcend SSD230/370/420 + // SATA/mSATA, TS6500, tested with TS128GMSA230S/02J0S86A, TS32GMSA370/20140402, + // TS16GMSA370/20140516, TS64GSSD370/20140516, TS256GSSD370/N0815B, TS256GSSD370S/N1114H, + // TS512GSSD370S/N1114H, TS32GSSD420I/N1114H, TS32GSSD420K/P1225CE "TS(16|32|64|128|512|256)GMTS4[03]0S?|" // TS256GMTS400, TS256GMTS430S/S0423A - "TS(120|240)GMTS420|" // Transcend MTS420 + "TS(120|240)GMTS420S?|" // Transcend MTS420, tested with TS120GMTS420S/R0510A0 "TS(128G|256G|512G|1T)SSD230S|" // TS128GSSD230S/P1025F8 "TS(120|240|480|960)GSSD220S|" // TS480GSSD220S/P0520AA "TS(16G|32G|64G|128G|256G|512G|1T)MTS800S?|" // MTS800, tested with TS1TMTS800/O1225H1 "TS(16|32|64)GMSA630|" // MSA630 mSATA SSD, tested with TS32GMSA630/N0113E1 "TS(32|64|128)GPSD330|" // Transcend PSD SSD, tested with TS64GPSD330/20140121 - "TS(16|32|64|96|128|256)GSSD630|" // Transcend 630, tested with TS16GSSD630/N0113E1 + "TS(16|32|64|96|128|256)GSSD(630|360S)|" // Transcend 630/360S, tested with TS16GSSD630/N0113E1, + // TS256GSSD360S/R0123A0 "TS(128G|256G|512G|1T)ESD400K", // Transcend ESD400 Portable, tested with // TS256GESD400K/R0605AS (0x2174:0x2000) "", "", //"-v 1,raw48,Raw_Read_Error_Rate " //"-v 2,raw48,Throughput_Performance " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " //"-v 9,raw24(raw8),Power_On_Hours " //"-v 12,raw48,Power_Cycle_Count " "-v 148,raw48,Total_SLC_Erase_Ct " "-v 149,raw48,Max_SLC_Erase_Ct " "-v 150,raw48,Min_SLC_Erase_Ct " "-v 151,raw48,Average_SLC_Erase_Ct " - "-v 159,raw48,Unkn_SiliconMotion_Attr " // SU800/R0427A, SU900/Q0710B, TS256GMTS430S/S0423A + "-v 159,raw48,DRAM_1_Bit_Error_Count " // KINGSTON SKC600256G/S4500105 "-v 160,raw48,Uncorrectable_Error_Cnt " "-v 161,raw48,Valid_Spare_Block_Cnt " "-v 163,raw48,Initial_Bad_Block_Count " @@ -2063,6 +2176,7 @@ //"-v 198,raw48,Offline_Uncorrectable " //"-v 199,raw48,UDMA_CRC_Error_Count " "-v 225,raw48,Host_Writes_32MiB " // FW 20140402 + "-v 231,raw48,SSD_Life_Left " // KINGSTON SKC600256G/S4500105 //"-v 232,raw48,Available_Reservd_Space " "-v 241,raw48,Host_Writes_32MiB " "-v 242,raw48,Host_Reads_32MiB " @@ -2070,16 +2184,44 @@ "-v 246,raw48,SLC_Writes_32MiB " "-v 247,raw48,Raid_Recoverty_Ct " "-v 248,raw48,Unkn_SiliconMotion_Attr " // ADATA SU900/Q0125A + "-v 249,raw48,Unkn_SiliconMotion_Attr " // ADATA SU650/V8X01c45 //"-v 250,raw48,Read_Error_Retry_Rate " // ADATA SU800/Q0913A "-v 251,raw48,Unkn_SiliconMotion_Attr" // ADATA SU800/Q0913A }, + // Supermicro SSD-DM032-SMCMVN1, tested with SuperMicro SSD/SOB20R, see (#1380) + { "Supermicro SATA DOM (SuperDOM)", + "SuperMicro SSD", + "", "", + "-v 1,raw48,Raw_Read_Error_Rate " + "-v 15,raw48,User_Cpcty_Sector_Cnt " + "-v 160,raw48,Not_In_Use " + "-v 161,raw48,Not_In_Use " + "-v 163,raw48,Not_In_Use " + "-v 164,raw48,Not_In_Use " + "-v 165,raw48,Not_In_Use " + "-v 166,raw48,Minimum_PE_Cycles_TLC " + "-v 167,raw48,Not_In_Use " + "-v 168,raw48,Maximum_PE_Cycles_TLC " + "-v 231,raw48,SSD_Life_Left " + "-v 233,raw48,NAND_Writes_1GiB " + "-v 241,raw48,Lifetime_Writes_GiB " + "-v 242,raw48,Lifetime_Reads_GiB " + }, { "Silicon Motion based OEM SSDs", // Like 'Silicon Motion based SSDs' but with FW detection + "240GB|" // from Lenovo T430 Thinkpad, tested with 240GB/P0510E + "Dogfish SSD (128|256|512)GB|" // tested with Dogfish SSD 128GB/S1211A0 + "INTENSO|" // tested with INTENSO/S1211A0 (Portable SSD 256GB premium edition) "Intenso SSD|" // tested with Intenso SSD/Q1107A0 - "Intenso SSD Sata III|" // Sata III High, tested with Intenso SSD Sata III/P0510E + "Intenso ?SSD Sata III|" // Sata III High, tested with Intenso SSD Sata III/P0510E, + // Intenso SSD Sata III/R0817B0 "KingFast|" // KingFast F6M, tested with KingFast/P0725A - "SPCC M\\.2 SSD|" // Silicon Power 2280 M55, tested with SPCC M.2 SSD/Q0627A0 - "SuperMicro SSD", // Supermicro SSD-DM032-SMCMVN1, tested with SuperMicro SSD/SOB20R - "P0510E|P0725A|Q0627A0|Q1107A0|SOB20R", + "LDLC|" // tested with LDLC/KFS03005 + "SATA3 ((12[08]|240|256|480)G|[12]T)B SSD|" // TCSUNBOW X3, tested with SATA3 240GB SSD/S0618A0, + // SATA3 1TB SSD/S1230A0, + // KingDian S370, tested with SATA3 128GB SSD/T0311A0, SATA3 256GB SSD/S1127B0 + // KingDian S280, tested with SATA3 240GB SSD/T0519A0 + "SPCC M\\.2 SSD", // Silicon Power 2280 M55, tested with SPCC M.2 SSD/Q0627A0 + "KFS03005|P0510E|P0725A|Q(0627|1107)A0|R0817B0|S(0618|1211|1230)A0|S1127B0|SOB20R|T0(311|519)A0", "", "-v 148,raw48,Total_SLC_Erase_Ct " "-v 149,raw48,Max_SLC_Erase_Ct " @@ -2192,6 +2334,32 @@ "-v 130,raw48:54321,Minimum_Spares_All_Zs" //"-v 194,tempminmax,Temperature_Celsius" }, + { "SSSTC ER2 GD/CD Series SSDs", // Marvel DEAN 2.1 + "SSSTC ER2-[CG]D(240|480|960|1920)A?", // tested with SSSTC ER2-GD480/E4N2302l, + // SSSTC ER2-CD1920A/E5MN401 + "","", + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 170,raw48,Available_Reservd_Space " + "-v 171,raw48,Program_Fail_Count " + "-v 172,raw48,Erase_Fail_Count " + "-v 173,raw48,Average_PE_Count " + "-v 174,raw48,Unexpect_Power_Loss_Ct " + "-v 175,raw48,PwrLoss_ProtectionFail " + "-v 183,raw48,SATA_Iface_Downshift " + //"-v 184,raw48,End-to-End_Error " + //"-v 187,raw48,Reported_Uncorrect " + //"-v 194,tempminmax,Temperature_Celsius " + //"-v 198,raw48,Offline_Uncorrectable " + //"-v 199,raw48,UDMA_CRC_Error_Count " + "-v 202,raw48,Percent_Lifetime_Remain " + //"-v 210,raw48,Raid_Success_Recover_Ct " // ] E4N2302: Missing + //"-v 234,raw48,Thermal_Throttle_Status " // ] + //"-v 241,raw48,Total_LBAs_Written " + //"-v 242,raw48,Total_LBAs_Read " + "-v 243,raw48,NAND_Writes_GiB " + }, { "STEC Mach2 CompactFlash Cards", // tested with STEC M2P CF 1.0.0/K1385MS "STEC M2P CF 1.0.0", "", "", @@ -2212,6 +2380,22 @@ "-v 7,raw48,Unknown_Attribute " "-v 8,raw48,Unknown_Attribute" }, + { "Xmore Industrial SATA SSDs", // tested with M2CA032GXAIMS-003Z/XP01.1GB + "(CFAST|M2[AC]A|MSATA|SSD)[0-9]{3}[GT]XA[CEI][MT][MST]-[0-9]{3}[TZ]", + "", "", + //"-v 1,raw48,Raw_Read_Error_Rate " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 168,raw48,SATA_Phy_Error_Count " + "-v 169,raw48,Bad_Block_Rate " + "-v 170,raw24/raw24:z54z10,Bad_Blk_Ct_Lat/Erl " // Later bad block/Early bad block + "-v 173,raw16(avg16),MaxAvgErase_Ct " + "-v 192,raw48,Unexpect_Power_Loss_Ct " + //"-v 194,tempminmax,Temperature_Celsius " // optional + "-v 218,raw48,SATA_CRC_Error_Count " + "-v 231,raw48,Percent_Lifetime_Remain " + "-v 241,raw48,Host_Writes_GiB" + }, { "Marvell SSD SD88SA024BA0 (SUN branded)", "MARVELL SD88SA024BA0 SUN24G 0902M0054V", "", "", "" @@ -2290,14 +2474,14 @@ "FUJITSU MHL2300AT", "", "This drive's firmware has a harmless Drive Identity Structure\n" - "checksum error bug.", + "checksum error bug.", "-v 9,seconds" }, { "", // MHM2200AT, MHM2150AT, MHM2100AT, MHM2060AT "FUJITSU MHM2(20|15|10|06)0AT", "", "This drive's firmware has a harmless Drive Identity Structure\n" - "checksum error bug.", + "checksum error bug.", "-v 9,seconds" }, { "Fujitsu MHN", @@ -2503,7 +2687,7 @@ "" }, { "Seagate Samsung SpinPoint F4 EG (AF)", // later sold as Barracuda Green, - // tested with ST2000DL004 HD204UI/1AQ10001 + // tested with ST2000DL004 HD204UI/1AQ10001 "ST2000DL004 HD204UI", "", "", "" }, @@ -2629,27 +2813,31 @@ "ST(1500|2000)LM0(03|04|06|07|10) HN-M[0-9]*RAD", "", "", "" }, - { "Seagate Mobile HDD", // tested with ST2000LM007-1R8174/WDZD1BYX - // ST1000LM035-1RK172/ACM1 + { "Seagate Mobile HDD", // tested with ST1000LM035-1RK172/ACM1, + // ST1000LM035-1RK172/ACM2, ST2000LM007-1R8174/SBK2 "ST(2000LM0(07|09|10)|1000LM03[578])-.*", "", "", "" }, // Flash accelerated, no SMART info in the specs // ST1000LX015-1U7172/SDM1 - { "Seagate FireCuda 2.5", // + { "Seagate FireCuda 2.5", "ST(500|1000|2000)LX0(01|15|25)-.*", "", "", "-v 240,msec24hour32 " }, - // ST1000DX002/CC41 { "Seagate FireCuda 3.5", // ST2000DX002-2DV164/CC41 "ST[12]000DX002-.*", "", "", "-v 240,msec24hour32 " }, { "Seagate Samsung SpinPoint M9TU (USB)", // tested with ST1500LM008 HN-M151AAD/2BC10001 - // (0x04e8:0x61b5), ST2000LM005 HN-M201AAD2BC10001 (0x04e8:0x61b4) + // (0x04e8:0x61b5), ST2000LM005 HN-M201AAD2BC10001 (0x04e8:0x61b4) "ST(1500|2000)LM00[58] HN-M[0-9]*AAD", "", "", "" }, + { "Seagate FreePlay", // tested with ST1500LM003-9YH148/CC94 + // from FreeAgent GoFlex Enclosure. + "ST(1500LM003|1000LM010|1000LM002)-.*", + "", "", "" + }, { "SAMSUNG SpinPoint MP5", // tested with HM250HJ/2AK10001 "SAMSUNG HM(250H|320H|500J|640J)J", "", "", "" @@ -2668,21 +2856,31 @@ "", "-v 9,halfminutes" }, - { "SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS)", // tested with HS25YJZ/3AU10-01 + { "SAMSUNG SpinPoint N3U-3 (USB)", // tested with + // SAMSUNG HS25YJZ/3AU10-01 (0x18a5:0x0227, reports 4KiB LPS/LLS. ticket #159), + // SAMSUNG HS20YJZ/3AU10-01 (0x04e8:0x2f06, reports 512B sectors, Debian Bug 964032) "SAMSUNG HS(122H|2[05]YJ)Z", "", "", "" }, { "SK hynix SATA SSDs", - "SK ?hynix SC(210|300|308|311|313).*|" // tested with + "SK ?hynix (SC(210|300|308|311|313|401)|SH920) .*|" // tested with // SK hynix SC210 mSATA 256GB/20002L00, // SKhynix SC300 HFS256G32MND-3210A/20131P00, // SK hynix SC308 SATA 128GB/30001P10, // SK hynix SC311 SATA 512GB/70000P10, - // SK hynix SC313 HFS256G32TNF-N3A0A/70000P10 - "HFS(128|256|512)G3[29]MND-(2200|3[23]10)A|" // HFS128G32MND-2200A/20200L00, - // HFS512G32MND-3210A/20100P00, HFS512G39MND-3310A/20002P00 + // SK hynix SC313 HFS256G32TNF-N3A0A/70000P10, + // SK hynix SC401 SATA 512GB/90000121, + // SK hynix SH920 mSATA 256GB/1010BL00 + "HFS(128|256|512)G3[29A]MN[BD]-(2200|3[23]10)A|" // SC210, tested with + // HFS128G32MND-2200A/20200L00, HFS512G32MND-3210A/20100P00, + // HFS512G39MND-3310A/20002P00, HFS256G3AMNB-2200A/1010BL00 + "HFS(128|256|512)G3[29]MND-3(312|510)A|" // SC300, tested with HFS256G32MND-3312A/20001P00, + // HFS512G39MND-3510A/20400P00 + "HFS(128|256|512)G39TND-N210A|" // SC308, tested with HFS128G39TND-N210A/30001P10 "HFS(120|250|500)G32TND-N1A2A|" // SL308, tested with HFS500G32TND-N1A2A/30000P10 - "HFS(128|256|512)G39TND-N210A", // SC308, tested with HFS128G39TND-N210A/30001P10 + "HFS(128|256|512)G39TND-N210A|" // SC308, tested with HFS128G39TND-N210A/30001P10 + "HFS(128|256|512)G32TNF-N3A0A|" // SC313, tested with HFS256G32TNF-N3A0A/70000P10 + "SHGS31-(250|500|1000)GS-2", // S31, tested with SHGS31-1000GS-2/90000Q00 "", "", //"-v 1,raw48,Raw_Read_Error_Rate " "-v 5,raw48,Retired_Block_Count " @@ -2691,6 +2889,7 @@ "-v 100,raw48,Total_Erase_Count " "-v 168,raw48,Min_Erase_Count " "-v 169,raw48,Max_Erase_Count " + "-v 170,raw48,Unknown_SK_hynix_Attrib " "-v 171,raw48,Program_Fail_Count " "-v 172,raw48,Erase_Fail_Count " "-v 173,raw48,Wear_Leveling_Count " @@ -2706,6 +2905,7 @@ //"-v 184,raw48,End-to-End_Error " //"-v 187,raw48,Reported_Uncorrect " //"-v 188,raw48,Command_Timeout " + "-v 191,raw48,Unknown_SK_hynix_Attrib " // SC210 //"-v 194,tempminmax,Temperature_Celsius " //"-v 195,raw48,Hardware_ECC_Recovered " //"-v 196,raw16(raw16),Reallocated_Event_Count " @@ -2716,9 +2916,12 @@ "-v 212,raw48,Phy_Error_Count " "-v 231,raw48,SSD_Life_Left " "-v 234,raw48,Unknown_SK_hynix_Attrib " - "-v 241,raw48,Total_Writes_GiB " - "-v 242,raw48,Total_Reads_GiB " + "-v 236,raw48,Unknown_SK_hynix_Attrib " // SC313 + "-v 238,raw48,Unknown_SK_hynix_Attrib " // SC401 + "-v 241,raw48,Total_Writes_GB " // SC31: ~GB, not GiB (#1517) + "-v 242,raw48,Total_Reads_GB " "-v 243,raw48,Total_Media_Writes " + "-v 249,raw48,Unknown_SK_hynix_Attrib " // SC313 "-v 250,raw48,Read_Retry_Count " }, { "SK hynix SATA SSDs", @@ -3141,8 +3344,9 @@ "(Hitachi|HGST) HT[ES]5432(16|25|32)A7A38[145]", "", "", "" }, - { "Hitachi Travelstar 5K500.B", // tested with Hitachi HTS545050B9SA00/PB4OC60X - "(Hitachi )?HT[ES]5450(12|16|25|32|40|50)B9(A30[01]|SA00)", + { "Hitachi Travelstar 5K500.B", // tested with Hitachi HTS545050B9SA00/PB4OC60X, + // Hitachi HTS545025B9SA02/PB2AC60W + "(Hitachi )?HT[ES]5450(12|16|25|32|40|50)B9(A30[01]|SA0[02])", "", "", "" }, { "Hitachi/HGST Travelstar Z5K500", // tested with HGST HTS545050A7E380/GG2OAC90, @@ -3152,7 +3356,7 @@ "", "", "" }, { "Hitachi/HGST Travelstar 5K750", // tested with Hitachi HTS547575A9E384/JE4OA60A, - // APPLE HDD HTS547550A9E384/JE3AD70F + // APPLE HDD HTS547550A9E384/JE3AD70F "(Hitachi|APPLE HDD) HT[ES]5475(50|64|75)A9E38[14]", "", "", "" }, @@ -3161,8 +3365,9 @@ "HGST HT[ES]5410(64|75|10)A9E68[01]", "", "", "" }, - { "HGST Travelstar Z5K1000", // tested with HGST HTS541010A7E630/SE0OA4A0 - "HGST HTS5410(75|10)A7E63[015]", + { "HGST Travelstar Z5K1000", // tested with HGST HTS541010A7E630/SE0OA4A0, + // HGST HTS541010B7E610/01.01A01 + "HGST HTS5410(75|10)[AB]7E6(10|3[015])", "", "", "" }, { "HGST Travelstar 5K1500", // tested with HGST HTS541515A9E630/KA0OA500 @@ -3189,9 +3394,9 @@ "(Hitachi |HITACHI )?HTS7220(80|10|12|16|20)K9(A3|SA)00", "", "", "" }, - { "Hitachi Travelstar 7K320", // tested with + { "Hitachi Travelstar 7K320", // tested with HITACHI HTS723216L9SA60/FC2ZC50B, // HTS723225L9A360/FCDOC30F, HTS723216L9A362/FC2OC39F - "(Hitachi )?HT[ES]7232(80|12|16|25|32)L9(A300|A36[02]|SA61)", + "(Hitachi |HITACHI )?HT[ES]7232(80|12|16|25|32)L9(A300|A36[02]|SA6[01])", "", "", "" }, { "Hitachi Travelstar Z7K320", // tested with HITACHI HTS723232A7A364/EC2ZB70B @@ -3247,12 +3452,13 @@ "", "", "" }, { "Hitachi Deskstar 5K3000", // tested with HDS5C3030ALA630/MEAOA5C0, - // Hitachi HDS5C3020BLE630/MZ4OAAB0 (OEM, Toshiba Canvio Desktop) + // Hitachi HDS5C3020BLE630/MZ4OAAB0 (OEM, Toshiba Canvio Desktop) "(Hitachi )?HDS5C30(15|20|30)(ALA|BLE)63[02].*", "", "", "" }, - { "Hitachi Deskstar 5K4000", // tested with HDS5C4040ALE630/MPAOA250 - "(Hitachi )?HDS5C40(30|40)ALE63[01].*", + { "Hitachi/HGST Deskstar 5K4000", // tested with HDS5C4040ALE630/MPAOA250 + // HGST HDS5C4040ALE630/MPAOA580 + "(Hitachi |HGST )?HDS5C40(30|40)ALE63[01].*", "", "", "" }, { "Hitachi Deskstar 7K80", @@ -3327,9 +3533,15 @@ "", "", "" }, { "HGST Deskstar NAS", // tested with HGST HDN724040ALE640/MJAOA5E0, - // HGST HDN726050ALE610/APGNT517, HGST HDN726060ALE610/APGNT517 - // HGST HDN726040ALE614/APGNW7JH, HGST HDN726060ALE614/K1HE594D - "HGST HDN72(4030|4040|6040|6050|6060)ALE6(10|14|40|04)", + // HGST HDN726050ALE610/APGNT517, HGST HDN726060ALE610/APGNT517 + // HGST HDN726040ALE614/APGNW7JH, HGST HDN726060ALE614/K1HE594D + // HGST HDN728080ALE604/A4GNW91X + "HGST HDN72(40[34]|60[456]|808)0ALE6(04|1[04]|40)", + "", "", + "-v 22,raw48,Helium_Level" // HDN728080ALE604 + }, + { "Hitachi/HGST Ultrastar 5K3000", // tested with Hitachi HUA5C3030ALA640/MEAOA800 + "(Hitachi |HGST )?HUA5C30(20|30)ALA64[01]", "", "", "" }, { "Hitachi Ultrastar A7K1000", // tested with @@ -3345,16 +3557,17 @@ "", "", "" }, { "Hitachi Ultrastar 7K3000", // tested with Hitachi HUA723030ALA640/MKAOA580, - // Hitachi HUA723020ALA641/MK7OA840 - "Hitachi HUA7230(20|30)ALA64[01]", + // Hitachi HUA723020ALA641/MK7OA840, HUA723020ALA640/MK7OAAA0 + "(Hitachi )?HUA7230(20|30)ALA64[01]", "", "", "" }, { "Hitachi/HGST Ultrastar 7K4000", // tested with Hitachi HUS724040ALE640/MJAOA3B0, - // HGST HUS724040ALE640/MJAOA580, HGST HUS724020ALA640/MF6OAA70 - "(Hitachi|HGST) HUS7240(20|30|40)AL[AE]64[01]", + // HGST HUS724040ALE640/MJAOA580, HGST HUS724020ALA640/MF6OAA70, + // HUS724030ALA640/MF8OAAZ0 + "(Hitachi |HGST )?HUS7240(20|30|40)AL[AE]64[01]", "", "", "" }, - { "Hitachi/HGST Ultrastar 7K2", // + { "Hitachi/HGST Ultrastar 7K2", "(Hitachi|HGST) HUS722T[12]TALA604", "", "", "-v 16,raw48,Gas_Gauge" @@ -3363,6 +3576,11 @@ "HGST HUS7260[2456]0AL[AEN]61[014]", "", "", "" }, + { "HGST Ultrastar HC310/320", // tested with HGST HUS726T6TALE6L4/VKGNW40H, + // HGST HUS728T8TALE6L4/V8GNW460 + "HGST HUS72(6T[46]|8T8)TALE6L4", + "", "", "" + }, { "HGST Ultrastar He6", // tested with HGST HUS726060ALA640/AHGNT1E2 "HGST HUS726060ALA64[01]", "", "", @@ -3378,10 +3596,11 @@ "", "", "-v 22,raw48,Helium_Level" }, - { "WDC HGST Ultrastar He10", // WD white label, tested with - // WDC WD80EMAZ-00WJTA0/83.H0A83, WDC WD80EZAZ-11TDBA0/83.H0A83, - // WDC WD100EMAZ-00WJTA0/83.H0A83, WDC WD100EZAZ-11TDBA0/83.H0A83 - "WDC WD(80|100)E[MZ]AZ-.*", + { "Western Digital Ultrastar He10/12", // WD white label, tested with + // WDC WD80EMAZ-00WJTA0/83.H0A83 (Easystore 0x1058:0x25fb), + // WDC WD80EZAZ-11TDBA0/83.H0A83, WDC WD100EMAZ-00WJTA0/83.H0A83, + // WDC WD100EZAZ-11TDBA0/83.H0A83, WDC WD120EMAZ-11BLFA0/81.00A81 + "WDC WD(80|100|120)E[MZ]AZ-.*", "", "", "-v 22,raw48,Helium_Level" }, @@ -3390,6 +3609,30 @@ "", "", "-v 22,raw48,Helium_Level" }, + { "Western Digital Ultrastar DC HC530", // tested with + // WDC WUH721414ALE604/LDAZW110, WDC WUH721414ALE6L4/LDGNW07G + "WDC ?WUH721414ALE6[0L]4", + "", "", + "-v 22,raw48,Helium_Level" + }, + { "Western Digital Ultrastar DC HC550", // tested with WDC WUH721818ALE6L4/PCGNW110, + // WUH721818ALE6L4/PCGAW232, WDC WUH721818ALN6L4/PCGNW088 + "(WDC ?)?WUH72181[68]AL[EN]6[0L][0146]", + "", "", + "-v 22,raw48,Helium_Level" + }, + { "Western Digital Ultrastar DC HC560", // tested with WDC WUH722020ALN604/PQGNW108 + "(WDC ?)?WUH722020AL[EN]6[0L][014]", + "", "", + "-v 22,raw48,Helium_Level " + "-v 82,raw16,Head_Health_Score " + "-v 90,hex48,NAND_Master" + }, + { "Western Digital Ultrastar DC HC650", // tested with WDC WSH722020ALE6L0/PCGMT421 + "(WDC ?)?WSH7220(20|VC)AL[EN]6[0L][0146]", + "", "", + "-v 22,raw48,Helium_Level" + }, { "HGST MegaScale 4000", // tested with HGST HMS5C4040ALE640/MPAOA580 "HGST HMS5C4040[AB]LE64[01]", // B = DC 4000.B "", "", "" @@ -3422,7 +3665,6 @@ "TOSHIBA MK(80|12|10)34GSX", "", "", "" }, - // { "Toshiba 2.5\" HDD MK..32GSX", // tested with TOSHIBA MK1032GSX/AS021G "TOSHIBA MK(10|80|60|40)32GSX", "", "", "" @@ -3433,7 +3675,7 @@ "", "-v 9,minutes" }, - { "Toshiba 2.5\" HDD MK..52GSX", + { "Toshiba 2.5\" HDD MK..52GSX", // tested with TOSHIBA MK3252GSX/LV010A "TOSHIBA MK(80|12|16|25|32)52GSX", "", "", "" }, @@ -3475,6 +3717,11 @@ "TOSHIBA MK(32|50|64|75)75GSX", "", "", "" }, + { "Toshiba 2.5\" HDD MK..76GSX/GS001A", // tested with TOSHIBA MK2576GSX/GS001A + "TOSHIBA MK(16|25|32|50|64)76GSX", + "GS001A", + "", "" + }, { "Toshiba 2.5\" HDD MK..76GSX", // tested with TOSHIBA MK3276GSX/GS002D "TOSHIBA MK(16|25|32|50|64)76GSX", "", @@ -3490,7 +3737,7 @@ "", "", "" }, { "Toshiba 2.5\" HDD MQ01ABD...", // tested with TOSHIBA MQ01ABD100/AX001U, - // TOSHIBA MQ01ABD100V/AX001Q + // TOSHIBA MQ01ABD100/AX1R4C, TOSHIBA MQ01ABD100V/AX001Q "TOSHIBA MQ01ABD(025|032|050|064|075|100)V?", "", "", "" }, @@ -3533,12 +3780,13 @@ "TOSHIBA MG03ACA[1234]00Y?", "", "", "" }, - { "Toshiba 3.5\" MD04ACA... Enterprise HDD", // tested with TOSHIBA MD04ACA500/FP1A - "TOSHIBA MD04ACA[2345]00", + { "Toshiba MG04ACA... Enterprise HDD", // tested with TOSHIBA MD04ACA500/FP1A, + // TOSHIBA MG04ACA600A/FS2B, TOSHIBA MG04ACA400NY/FK5D (Dell) + "TOSHIBA MG04ACA[23456]00([AEN].?)?", "", "", "" }, - { "Toshiba 3.5\" MG04ACA... Enterprise HDD", // tested with TOSHIBA MG04ACA600A/FS2B - "TOSHIBA MG04ACA[23456]00[AE].?", + { "Toshiba MG05ACA... Enterprise Capacity HDD", // tested with TOSHIBA MG05ACA800E/GX2A + "TOSHIBA MG05ACA800[AE]", "", "", "" }, { "Toshiba MG06ACA... Enterprise Capacity HDD", // tested with TOSHIBA MG06ACA800E/4303, @@ -3552,6 +3800,20 @@ "-v 23,raw48,Helium_Condition_Lower " "-v 24,raw48,Helium_Condition_Upper" }, + { "Toshiba MG08ACA... Enterprise Capacity HDD", // tested with TOSHIBA MG08ACA14TE/0102, + // TOSHIBA MG08ACA16TE/0102 + "TOSHIBA MG08ACA1[46]T[AE]Y?", + "", "", + "-v 23,raw48,Helium_Condition_Lower " + "-v 24,raw48,Helium_Condition_Upper" + }, + { "Toshiba MG09ACA... Enterprise Capacity HDD", // tested with TOSHIBA MG09ACA18TE/0102 + "TOSHIBA MG09ACA1[68]T[AE]Y?", + "", "", + "-v 23,raw48,Helium_Condition_Lower " + "-v 24,raw48,Helium_Condition_Upper " + "-v 27,raw48,MAMR_Health_Monitor" + }, { "Toshiba 3.5\" DT01ABA... Desktop HDD", // tested with TOSHIBA DT01ABA300/MZ6OABB0 "TOSHIBA DT01ABA(100|150|200|300)", "", "", "" @@ -3561,12 +3823,36 @@ "TOSHIBA DT01ACA(025|032|050|075|100|150|200|300)", "", "", "" }, - { "Toshiba X300", // tested with TOSHIBA HDWE160/FS2A - "TOSHIBA HDWE1[456]0", + { "Toshiba N300/MN NAS HDD", // tested with TOSHIBA HDWQ140/FJ1M, TOSHIBA HDWN160/FS1M, + // TOSHIBA HDWN180/GX2M, TOSHIBA HDWG480/0601 (8TB), TOSHIBA HDWG11A/0603 (10TB), + // TOSHIBA HDWG21C/0601 (12TB), TOSHIBA HDWG21E/0601 (14TB), + // TOSHIBA MN07ACA12T/0601, TOSHIBA MN08ACA14T/0601 + "TOSHIBA HDW([GNQ]1[468]0|G(480|11A|21[CE]|31G))|" // 31G: 16TB + "TOSHIBA MN0(4ACA400|6ACA([68]00|10T)|7ACA1[24]T|8ACA1[46]T)", + "", "", + "-v 23,raw48,Helium_Condition_Lower " // ] >= 12TB + "-v 24,raw48,Helium_Condition_Upper" // ] + }, + { "Toshiba P300 (CMR)", // tested with TOSHIBA HDWD120/MX4OACF0 + "TOSHIBA HDWD1(05|10|20|30)", + "", "", "" + }, + { "Toshiba P300 (SMR)", // tested with TOSHIBA HDWD240/KQ000A + "TOSHIBA HDWD2[246]0", + "", "", "" + }, + { "Toshiba X300", // tested with TOSHIBA HDWE160/FS2A, TOSHIBA HDWF180/GX0B + "TOSHIBA HDW(E1[456]0|[FR]180|R(11A|21[CE]|31G))", // 11A:10TB, 21C:12TB, 21E:14TB, 31G: 16TB + "", "", + "-v 23,raw48,Helium_Condition_Lower " // ] >= 12TB + "-v 24,raw48,Helium_Condition_Upper" // ] + }, + { "Toshiba L200 (CMR)", + "TOSHIBA HDW[JK]1(05|10)", "", "", "" }, - { "Toshiba P300", // tested with TOSHIBA HDWD120/MX4OACF0 - "TOSHIBA HDWD1(30|20|10|05)", + { "Toshiba L200 (SMR)", // tested with TOSHIBA HDWL110/JU000A. TOSHIBA HDWL120/JT000A + "TOSHIBA HDWL1[12]0", "", "", "" }, { "Toshiba 1.8\" HDD", @@ -3583,7 +3869,7 @@ }, { "Toshiba HK4R Series SSD", // TOSHIBA THNSN8960PCSE/8EET6101 "TOSHIBA THNSN8(120P|240P|480P|960P|1Q92)CSE", - "", "", + "", "", "-v 167,raw48,SSD_Protect_Mode " "-v 168,raw48,SATA_PHY_Error_Count " "-v 169,raw48,Bad_Block_Count " @@ -3594,7 +3880,7 @@ // TOSHIBA THNSFJ256GCSU/JULA1102 // TOSHIBA THNSFJ256GDNU A/JYLA1102 "TOSHIBA THNS[NF]J(060|128|256|512)G[BCAM8VD][SCN][TU].*", - "", "", + "", "", "-v 167,raw48,SSD_Protect_Mode " "-v 168,raw48,SATA_PHY_Error_Count " "-v 169,raw48,Bad_Block_Count " @@ -3901,28 +4187,26 @@ "", "", "-v 188,raw16 -v 240,msec24hour32" }, - // should be ST4000DM005, ST3000DM008,ST3000DM009,ST2000DM006,ST2000DM007 - // ST1000DM010, ST500DM009 - // tested: ST3000DM008-2DM166/CC26 - { "Seagate Barracuda 3.5", // tested on ST1000DM010-2EP102/Z9ACZM97 - "ST(4000DM00[45]|3000DM008|3000DM009|2000DM006|2000DM007|1000DM010|500DM009)-.*", + { "Seagate Barracuda 7200.14 (AF)", // < 1TB, tested with ST250DM000-1BC141 + "ST(250|320|500|750)DM00[0-3]-.*", "", "", "-v 188,raw16 -v 240,msec24hour32" }, - // ST8000DM004, ST6000DM003, ST4000DM004, ST3000DM007, ST2000DM005 - { "Seagate Barracuda Compute", // tested on ST8000DM004-2CX188/0001 - "ST(8000DM004|6000DM003|4000DM004|3000DM007|2000DM005)-.*", - "", "", - "" - }, - { "Seagate Barracuda Pro", // tested on ST8000DM004-2CX188/0001 - "ST(8000DM005|6000DM004|4000DM006|2000DM009)-.*", + { "Seagate BarraCuda 3.5 (CMR)", // tested with ST1000DM010-2EP102/CC43, + // ST3000DM008-2DM166/CC26, ST4000DM006-2G5107/DN02, ST10000DM0004-1ZC101/DN01, + // ST12000DM0007-2GR116/DN01 + "ST(500DM009|1000DM010|2000DM00[67]|3000DM00[89]|4000DM006|6000DM004|" + "8000DM005|10000DM0004|12000DM0007)-.*", "", "", + "-v 200,raw48,Pressure_Limit " "-v 188,raw16 -v 240,msec24hour32" }, - { "Seagate Barracuda 7200.14 (AF)", // < 1TB, tested with ST250DM000-1BC141 - "ST(250|320|500|750)DM00[0-3]-.*", + { "Seagate BarraCuda 3.5 (SMR)", // tested with ST2000DM008-2FR102/0001, + // ST4000DM004-2CV104/0001 (TRIM: no), ST4000DM005-2DP166/0001, ST8000DM004-2CX188/0001 + "ST(2000DM00[589]|3000DM007|4000DM00[45]|6000DM003|8000DM004)-.*", "", "", + "-v 9,msec24hour32 " // ST4000DM004-2CV104/0001 + "-v 200,raw48,Pressure_Limit " "-v 188,raw16 -v 240,msec24hour32" }, { "Seagate Desktop HDD.15", // tested with ST4000DM000-1CD168/CC43, ST5000DM000-1FK178/CC44, @@ -4049,8 +4333,10 @@ // ST4000NM0035-1V4107/TNC3 // ST1000NM0055-1V410C/TN02 // ST8000NM0055-1RM112/SN04 + // ST10000NM0156-2AA111/SS05 "ST([1234568]|10)000NM0[01][0-68][456]-.*", // *[069]4 = 4Kn - "", "", + "", "", + "-v 200,raw48,Pressure_Limit " "-v 188,raw16 -v 240,msec24hour32" }, { "Seagate Enterprise Capacity 3.5 HDD", // V5.1, ms in attribute 9 @@ -4063,14 +4349,37 @@ "", "", "-v 9,msec24hour32 -v 240,msec24hour32" }, + // ST1000NM000A, ST1000NM002A, ST2000NM000A, ST2000NM001A, ST2000NM002A, + // ST3000NM000A, ST3000NM004A, ST4000NM000A, ST4000NM001A, ST4000NM002A, + // ST4000NM006A, ST4000NM010A, ST4000NM012A, ST4000NM013A, ST6000NM002A, + // ST6000NM021A, ST6000NM022A, ST6000NM025A, ST6000NM026A, ST8000NM000A, + // ST8000NM002A, ST8000NM004A, ST8000NM008A, ST8000NM009A, ST8000NM016A + { "Seagate Exos 7E8", // tested with ST6000NM021A-2R7101/SN02, ST8000NM000A-2KE101/SN02 + "ST[123468]000NM0(0[01234689]|1[0236]|2[1256])A-.*", + "", "", + "-v 18,raw48,Head_Health " + "-v 240,msec24hour32" + }, { "Seagate Exos X12", // tested with ST12000NM0007-2A1101/SN02 "ST12000NM00[01]7-.*", // *17 = SED "", "", + "-v 200,raw48,Pressure_Limit " "-v 240,msec24hour32" }, - { "Seagate Exos X14", // ST12000NM0008-2H3101/SN02 - "ST(14000NM04[24]8|14000NM0(01|25)8|12000NM0(00|24)8|10000NM0(47|56)8)-.*", + { "Seagate Exos X14", // tested with ST12000NM0008-2H3101/SN02, + // ST12000NM0538-2K2101/CMA2 (OEM?) + "ST(14000NM04[24]8|14000NM0(01|25)8|12000NM0(00|24|53)8|10000NM0(47|56)8)-.*", "", "", + "-v 18,raw48,Head_Health " + "-v 200,raw48,Pressure_Limit " + "-v 240,msec24hour32" + }, + { "Seagate Exos X16", // tested with ST10000NM001G-2MW103/SN02 + // ST14000NM001G-2KJ103/SN02, ST16000NM001G-2KK103/SN02, ST16000NM001G-2KK103/SN03 + "ST1[0246]000NM00[13]G-.*", + "", "", + "-v 18,raw48,Head_Health " + "-v 200,raw48,Pressure_Limit " "-v 240,msec24hour32" }, // new models: ST8000VN0002, ST6000VN0021, ST4000VN000 @@ -4088,17 +4397,25 @@ "ST(8000NE|[65432]000VN)00[01]1-.*", "", "", "" }, - { "Seagate IronWolf", // tested with ST6000VN0033-2EE110/SC60, - // ST6000VN0041-2EL11C/SC61, ST12000VN0007-2GS116/SC60, ST12000VN0008-2JH101/SC60 - "ST(1|2|3|4|6|8|10|12)000VN00(0?[2478]|22|33|41)-.*", - "", "", "" + { "Seagate IronWolf", // tested with ST3000VN007-2E4166/SC60, ST4000VN008-2DR166/SC60, + // ST6000VN001-2BB186/SC60, ST6000VN0033-2EE110/SC60, ST6000VN0041-2EL11C/SC61, + // ST8000VN0022-2EL112/SC61, ST10000VN0004-1ZD101/SC60, + // ST12000VN0007-2GS116/SC60, ST12000VN0008-2JH101/SC60 + "ST(1|2|3|4|6|8|10|12)000VN00(0?[2478]|1|22|33|41)-.*", + "", "", + "-v 18,raw48,Head_Health " + "-v 200,raw48,Pressure_Limit " + "-v 240,msec24hour32" }, { "Seagate IronWolf Pro", // tested with ST4000NE0025-2EW107/EN02, - // ST8000NE0004-1ZF11G/EN01, ST8000NE0021-2EN112/EN02 - "ST([24]000NE0025|6000NE0023|8000NE00(04|08|21)|(10|12|14)000NE000[478])-.*", - "", "", "" + // ST8000NE0004-1ZF11G/EN01, ST8000NE0021-2EN112/EN02, ST16000NE000-2RW103/EN02 + "ST([24]000NE0025|4000NE001|6000NE0023|8000NE00(04|08|21)|(10|12|14)000NE000[478]|16000NE000)-.*", + "", "", + "-v 18,raw48,Head_Health " // ST16000NE000 + "-v 200,raw48,Pressure_Limit " + "-v 240,msec24hour32" }, - { "Seagate Archive HDD", // tested with ST8000AS0002-1NA17Z/AR13 + { "Seagate Archive HDD (SMR)", // tested with ST8000AS0002-1NA17Z/AR13 "ST[568]000AS00[01][12]-.*", "", "", "" }, @@ -4143,9 +4460,15 @@ // ST3000VX000, ST3000VX004, ST2000VX000, ST2000VX004, ST1000VX000 { "Seagate Surveillance", // tested with ST1000VX001-1HH162/CV11, ST2000VX000-9YW164/CV12, // ST4000VX000-1F4168/CV14, ST2000VX003-1HH164/CV12 - "ST([1-6]000VX00[01234]1?|31000526SV|3500411SV)(-.*)?", + "ST([1-5]000VX00[01234]1?|31000526SV|3500411SV)(-.*)?", "", "", "" }, + { "Seagate Skyhawk", // tested with ST3000VX010-2H916L/CV11, ST6000VX0023-2EF110/SC60 + "ST(1000VX005|2000VX008|3000VX0(09|10)|4000VX007|6000VX00(1|23)|8000VX00(4|22))-.*", + "", "", + "-v 9,msec24hour32 " // CV* Firmware only? + "-v 240,msec24hour32" + }, { "Seagate DB35", // tested with ST3250823ACE/3.03, ST3300831SCE/3.03 "ST3(200826|250823|300831|400832)[AS]CE", "", "", "" @@ -4168,7 +4491,7 @@ }, { "Seagate Nytro XF1230 SATA SSD", // tested with XF1230-1A0480/ST200354 "XF1230-1A(0240|0480|0960|1920)", - "", "", + "", "", "-v 174,raw48,Unexpect_Power_Loss_Ct " "-v 180,raw48,End_to_End_Err_Detect " "-v 183,raw48,SATA_Downshift_Count " @@ -4184,10 +4507,10 @@ { "Seagate IronWolf 110 SATA SSD", //Written to Seagate documentation "ZA(240|480|960|1920|3840)NM10001", "", "", - //"-v 1,raw48,Raw_Read_Error_Rate " - //"-v 5,raw48,Reallocated_Sector_Ct " - //"-v 9,raw48,Power_On_Hours " - //"-v 12,raw48,Drive_Power_Cycle_Ct " + //"-v 1,raw48,Raw_Read_Error_Rate " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " "-v 100,raw48,Flash_GB_Erased " "-v 102,raw48,Lifetime_PS4_Entry_Ct " "-v 103,raw48,Lifetime_PS3_Exit_Ct " @@ -4199,26 +4522,53 @@ "-v 177,raw16,Wear_Range_Delta " "-v 183,hex56,SATA_Downshift_Count " "-v 187,raw48,Uncorrectable_ECC_Ct " - //"-v 194,tempminmax,Primary_Temperature " + //"-v 194,tempminmax,Temperature_Celsius " "-v 195,raw16(raw16),RAISE_ECC_Cor_Ct " "-v 198,raw48,Uncor_Read_Error_Ct " - //"-v 199,raw48,SATA_R-Err_(CRC)_Err_Ct " + //"-v 199,raw48,UDMA_CRC_Error_Count " "-v 230,raw56,Drv_Life_Protect_Status " "-v 231,hex56,SSD_Life_Left " - //"-v 232,raw48,Available_Rsrvd_Space " + //"-v 232,raw48,Available_Reservd_Space " "-v 233,raw48,Lifetime_Wts_To_Flsh_GB " "-v 241,raw48,Lifetime_Wts_Frm_Hst_GB " "-v 242,raw48,Lifetime_Rds_Frm_Hst_GB " "-v 243,hex56,Free_Space " }, + { "Seagate IronWolf Pro 125 SSDs", // IronWolf_Pro_125_SSD_Product_Manual_100866982_A.pdf + "Seagate IronWolfPro ZA(240|480|960|1920|3840)NX10001-.*", // tested with + // Seagate IronWolfPro ZA3840NX10001-2ZH104/SU4SC01B + "", "", + //"-v 1,raw48,Raw_Read_Error_Rate " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " + "-v 16,raw48,Spare_Blocks_Available " + "-v 17,raw48,Spare_Blocks_Remaining " + "-v 168,raw48,SATA_PHY_Error_Count " + "-v 170,raw16,Early/Later_Bad_Blck_Ct " + "-v 173,raw16,Max/Avg/Min_Erase_Ct " + "-v 174,raw48,Unexpect_Power_Loss_Ct " + "-v 177,raw16,Wear_Range_Delta " + //"-v 192,raw48,Power-Off_Retract_Count " + //"-v 194,tempminmax,Temperature_Celsius " + "-v 218,raw48,SATA_CRC_Error_Count " + "-v 231,raw48,SSD_Life_Left " + "-v 232,hex48,Read_Failure_Blk_Ct " + "-v 233,raw48,Flash_Writes_GiB " + "-v 234,raw48,NAND_Reads_Sectors " + "-v 235,raw48,Flash_Writes_Sectors " + "-v 241,raw48,Host_Writes_GiB " + "-v 242,raw48,Host_Reads_GiB " + "-v 246,hex64,Write_Protect_Detail " // prevents interpretation of bogus threshold 255 (ticket #1396) + "-v 247,raw48,Health_Check_Timer " + }, { "Seagate Nytro SATA SSD", //Written to Seagate documentation // tested with XA960LE10063, XA960LE10063 "XA(240|480|960|1920|3840)[LM]E10(00|02|04|06|08|10)3", "", "", - //"-v 1,raw48,Raw_Read_Error_Rate " - //"-v 5,raw48,Reallocated_Sector_Ct " - //"-v 9,raw48,Power_On_Hours " - //"-v 12,raw48,Drive_Power_Cycle_Ct " + //"-v 1,raw48,Raw_Read_Error_Rate " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " + //"-v 9,raw24(raw8),Power_On_Hours " + //"-v 12,raw48,Power_Cycle_Count " "-v 100,raw48,Flash_GB_Erased " "-v 102,raw48,Lifetime_PS4_Entry_Ct " "-v 103,raw48,Lifetime_PS3_Exit_Ct " @@ -4230,28 +4580,32 @@ "-v 177,raw16,Wear_Range_Delta " "-v 183,hex56,SATA_Downshift_Count " "-v 187,raw48,Uncorrectable_ECC_Ct " - //"-v 194,tempminmax,Primary_Temperature " + //"-v 194,tempminmax,Temperature_Celsius " "-v 195,raw16(raw16),RAISE_ECC_Cor_Ct " "-v 198,raw48,Uncor_Read_Error_Ct " - //"-v 199,raw48,SATA_R-Err_(CRC)_Err_Ct " + //"-v 199,raw48,UDMA_CRC_Error_Count " "-v 230,raw56,Drv_Life_Protect_Status " "-v 231,hex56,SSD_Life_Left " - //"-v 232,raw48,Available_Rsrvd_Space " + //"-v 232,raw48,Available_Reservd_Space " "-v 233,raw48,Lifetime_Wts_To_Flsh_GB " "-v 241,raw48,Lifetime_Wts_Frm_Hst_GB " "-v 242,raw48,Lifetime_Rds_Frm_Hst_GB " "-v 243,hex56,Free_Space " }, - { "WD Blue and Green SSDs", // tested with WDC WDS250G1B0A-00H9H0/X41000WD, + { "WD Blue / Red / Green SSDs", // tested with WDC WDS250G1B0A-00H9H0/X41000WD, // WDC WDS250G1B0A-00H9H0/X41100WD, WDC WDS100T1B0A-00H9H0, // WDC WDS120G2G0A-00JH30/UE360000, WDC WDS240G2G0A-00JH30/UF300000, // WDC WDS500G2B0A-00SM50/X61130WD, WDC WDS200T2B0A-00SM50/X61130WD, // WDC WDS200T2B0A/X61190WD, WDC WDS120G1G0A-00SS50/Z3311000 - // WDC WDS500G2B0A-00SM50/401000WD - "WDC ?WDS((120|240|250|480|500)G|[12]00T)(1B|2B|1G|2G)0[AB](-.*)?", // *B* = Blue, *G* = Green, *2B* = Blue 3D NAND + // WDC WDS500G2B0A-00SM50/401000WD, + // WDC WDBNCE2500PNC/X61130WD, WDC WDBNCE0010PNC-WRSN/X41110WD, + // WDC WDS200T1R0A-68A4W0/411000WR + "WDC WDBNCE(250|500|00[124])0PNC(-.*)?|" // Blue 3D + "WDC ?WDS((120|240|250|480|500)G|[12]00T)(1B|2B|1G|2G|1R)0[AB](-.*)?", + // *B* = Blue, *G* = Green, *2B* = Blue 3D NAND, *1R* = Red SA500 "", "", - //"-v 5,raw48,Reallocated_Sector_Ct " // Reassigned Block Count - //"-v 9,raw48,Power_On_Hours " + //"-v 5,raw16(raw16),Reallocated_Sector_Ct " // Reassigned Block Count + //"-v 9,raw24(raw8),Power_On_Hours " //"-v 12,raw48,Power_Cycle_Count " "-v 165,raw48,Block_Erase_Count " "-v 166,raw48,Minimum_PE_Cycles_TLC " @@ -4263,13 +4617,13 @@ "-v 172,raw48,Erase_Fail_Count " "-v 173,raw48,Average_PE_Cycles_TLC " "-v 174,raw48,Unexpected_Power_Loss " - //"-v 184,raw48,End-to-end_Error " // Detection/Correction Count + //"-v 184,raw48,End-to-End_Error " // Detection/Correction Count //"-v 187,raw48,Reported_Uncorrect " // Uncorrectable Errors - //"-v 188,raw48,Command_Timeout - //"-v 194,tempminmax,Temperature_Celsius " - //"-v 199,raw48,UDMA_CRC_Error_Count // SATA CRC Errors + //"-v 188,raw48,Command_Timeout " + //"-v 194,tempminmax,Temperature_Celsius " + //"-v 199,raw48,UDMA_CRC_Error_Count " // SATA CRC Errors "-v 230,hex48,Media_Wearout_Indicator " // Maybe hex16 - //"-v 232,raw48,Available_Reserve_Space" + //"-v 232,raw48,Available_Reservd_Space" "-v 233,raw48,NAND_GB_Written_TLC " "-v 234,raw48,NAND_GB_Written_SLC " "-v 241,raw48,Host_Writes_GiB " @@ -4348,6 +4702,10 @@ "WDC WD(12|16|25|32)00SB-.*", "", "", "" }, + { "Western Digital PiDrive Foundation Edition", // WDC WD3750LMCW-11D9GS3 + "WDC WD(3750|2500)LMCW-.*", + "", "", "" + }, { "Western Digital Caviar Serial ATA", "WDC WD(4|8|20|32)00BD-.*", "", "", "" @@ -4375,8 +4733,13 @@ "", "", "" }, { "Western Digital Blue", // tested with WDC WD5000AZLX-00K4KA0/80.00A80, - // WDC WD10EZEX-00RKKA0/80.00A80, WDC WD10EZEX-75M2NA0/01.01A01, WDC WD40EZRZ-00WN9B0/80.00A80 - "WDC WD((25|32|50)00AAKX|5000AZ(LX|RZ)|7500A(AL|ZE)X|10E(AL|ZE)X|[1-6]0EZRZ)-.*", + // WDC WD10EZEX-00RKKA0/80.00A80, WDC WD10EZEX-75M2NA0/01.01A01, WDC WD40EZRZ-00WN9B0/80.00A80, + // APPLE HDD WDC WD10EALX-408EA0/07.01D03 + "(APPLE HDD )?WDC WD((25|32|50)00AAKX|5000AZ(LX|RZ)|7500A(AL|ZE)X|10E(AL|ZE)X|[1-6]0EZRZ)-.*", + "", "", "" + }, + { "Western Digital Blue (SMR)", // tested with WDC WD40EZAZ-00SF3B0/80.00A80 (TRIM: zeroed) + "WDC WD(20|40|60)EZAZ-.*", "", "", "" }, { "Western Digital RE Serial ATA", @@ -4391,8 +4754,9 @@ "WDC WD(5000AB|7500AY|1000FY)PS-.*", "", "", "" }, - { "Western Digital RE3 Serial ATA", // tested with WDC WD7502ABYS-02A6B0/03.00C06 - "WDC WD((25|32|50|75)02A|(75|10)02F)BYS-.*", + { "Western Digital RE3 Serial ATA", // tested with WDC WD7502ABYS-02A6B0/03.00C06, + // WD1002FBYS-12/03.M0300 + "(WDC )?WD((25|32|50|75)02A|(75|10)02F)BYS-.*", "", "", "" }, { "Western Digital RE4", // tested with WDC WD2003FYYS-18W0B0/01.01D02, @@ -4422,7 +4786,7 @@ "", "", "" }, { "Western Digital Caviar Green", // tested with WDC WD7500AADS-00M2B0/01.00A01, - // WDC WD10EADX/77.04D77 + // WDC WD10EADX/77.04D77 "WDC WD((50|64|75)00AA[CV]S|(50|64|75)00AADS|10EA[CV]S|(10|15|20)EAD[SX])-.*", "", "", @@ -4435,15 +4799,15 @@ { "Western Digital Green", // tested with // WDC WD10EZRX-00A8LB0/01.01A01, WDC WD20EZRX-00DC0B0/80.00A80, // WDC WD30EZRX-00MMMB0/80.00A80, WDC WD40EZRX-00SPEB0/80.00A80, - // WDC WD60EZRX-00MVLB1/80.00A80 - "WDC WD(7500AA|(10|15|20)EA|(10|20|25|30|40|50|60)EZ)RX-.*", + // WDC WD60EZRX-00MVLB1/80.00A80, WDC WD5000AZRX-00A8LB0/01.01A01 + "WDC WD(5000AZ|7500AA|(10|15|20)EA|(10|20|25|30|40|50|60)EZ)RX-.*", "", "", "" }, { "Western Digital Caviar Black", // tested with WDC WD7501AAES/06.01D06 "WDC WD((500|640)1AAL|7501AA[EL]|1001FA[EL]|2001FAS)S-.*|" "WDC WD(2002|7502|1502|5003|1002|5002)(FAE|AAE|AZE|AAL)X-.*", // could be // WD2002FAEX, WD7502AAEX, WD1502FAEX, WD5003AZEX, WD1002FAEX, WD5002AALX - "", "", "" + "", "", "-F xerrorlba" // WDC WD6401AALS-00L3B2/01.03B01 (ticket #1558) }, { "Western Digital Black", // tested with // WDC WD1003FZEX-00MK2A0/01.01A01, WDC WD3001FAEX-00MJRA0/01.01L01, @@ -4457,6 +4821,10 @@ // old series: WD4001FAEX WD3001FAEX WD2002FAEX WD1002FAEX WD5003AZEX "", "", "" }, + { "Western Digital Black (SMR)", // ticket #1313 + "WDC WD10SPSX-.*", + "", "", "" + }, { "Western Digital AV ATA", // tested with WDC WD3200AVJB-63J5A0/01.03E01 "WDC WD(8|16|25|32|50)00AV[BJ]B-.*", "", "", "" @@ -4506,8 +4874,8 @@ "WDC WD(4|6|8|10|12|16|25)00BEAS-.*", "", "", "" }, - { "Western Digital Scorpio Blue Serial ATA", - "WDC WD((4|6|8|10|12|16|25)00BEVS|(8|12|16|25|32|40|50|64)00BEVT|7500KEVT|10TEVT)-.*", + { "Western Digital Scorpio Blue Serial ATA", // tested with WDC WD3200BEVS-08VAT2/14.01A14 + "WDC WD((4|6|8|10|12|16|25|32)00BEVS|(8|12|16|25|32|40|50|64)00BEVT|7500KEVT|10TEVT)-.*", "", "", "" }, { "Western Digital Scorpio Blue Serial ATA (AF)", // tested with @@ -4528,32 +4896,49 @@ // WDC WD40EFRX-68WT0N0/80.00A80, WDC WD60EFRX-68MYMN1/82.00A82, // WDC WD80EFAX-68LHPN0/83.H0A83, WDC WD80EFZX-68UW8N0/83.H0A83, // WDC WD80EZZX-11CSGA0/83.H0A03 (My Book 0x1058:0x25ee), - // WDC WD60EFAX-68SHWN0/82.00A82, WDC WD100EFAX-68LHPN0/83.H0A83 - "WDC WD(7500BFC|10JFC|[1-6]0EFR|[68]0E[FZ][AZ]|100EFA)X-.*", + // WDC WD100EFAX-68LHPN0/83.H0A83, + // WDC WD120EMFZ-11A6JA0/81.00A81 (Easystore 0x1058:0x25fb) + "WDC WD(7500BFCX|10JFCX|[1-6]0EFRX|[68]0E[FZ]ZX|(8|10)0EFAX|120EMFZ)-.*", "", "", - "-v 22,raw48,Helium_Level" // WD80EFZX, WD100EFAX + "-v 22,raw48,Helium_Level" // WD80EFAX, WD80EFZX, WD100EFAX, WD120EMFZ }, - { "Western Digital Red Pro", // tested with WDC WD2001FFSX-68JNUN0/81.00A81, - // WDC WD6002FFWX-68TZ4N0/83.H0A83, WDC WD101KFBX-68R56N0/83.H0A03 - "WDC WD([2-68]00[123]FF[BSW]|101KFB)X-.*", - "", "", - "-v 22,raw48,Helium_Level" // WD101KFBX + { "Western Digital Red (SMR)", // ticket #1313, tested with WDC WD60EFAX-68SHWN0/82.00A82 + "WDC WD[2346]0EFAX-.*", + "", "", "" }, - { "Western Digital Purple", // tested with WDC WD40PURX-64GVNY0/80.00A80 - "WDC WD[123456]0PURX-.*", + { "Western Digital Red Pro", // tested with WDC WD2001FFSX-68JNUN0/81.00A81, + // WDC WD6002FFWX-68TZ4N0/83.H0A83, WDC WD101KFBX-68R56N0/83.H0A03, + // WDC WD102KFBX-68M95N0/83.00A83 + "WDC WD([2-68]00[123]FF[BSW]|10[12]KFB)X-.*", + "", "", + "-v 22,raw48,Helium_Level" // WD101KFBX (but not WD102KFBX) + }, + { "Western Digital Purple", // tested with WDC WD40PURX-64GVNY0/80.00A80, + // WDC WD40PURZ-85TTDY0/80.00A80 + // WDC WD80PUZX-64NEAY0/80.H0A80 + "WDC WD[1234568]0PU[RZ][XZ]-.*", "", "", "" }, { "Western Digital Gold", // tested with WDC WD1005FBYZ-01YCBB2/RR07, // WDC WD2005FBYZ-01YCBB2/RR07, WDC WD4002FYYZ-01B7CB0/01.01M02, - // WDC WD8003FRYZ-01JPDB1/01.01H02, WDC WD121KRYZ-01W0RB0/01.01H01 - "WDC WD([12]005FB|4002FY|6002FR|800[23]FR|1[02]1KR)YZ-.*", + // WDC WD4003FRYZ-01F0DB0/01.01H01, WDC WD6003FRYZ-01F0DB0/01.01H01, + // WDC WD8003FRYZ-01JPDB1/01.01H02, WDC WD8004FRYZ-01VAEB0/01.01H01, + // WDC WD102KRYZ-01A5AB0/01.01H01, WDC WD121KRYZ-01W0RB0/01.01H01, + // WDC WD141KRYZ-01C66B0/01.01H01 + "WDC WD([12]005FB|4002FY|4003FR|600[23]FR|800[234]FR|(1[024]1|102)KR)YZ-.*", "", "", - "-v 22,raw48,Helium_Level" // WD121KRYZ + "-v 22,raw48,Helium_Level" // WD121KRYZ, WD141KRYZ }, - { "Western Digital Blue", // tested with WDC WD5000LPVX-08V0TT2/03.01A03, + { "Western Digital Blue Mobile", // tested with WDC WD5000LPVX-08V0TT2/03.01A03, + // WDC WD10JPVX-75JC3T0/0301A03, WDC WD10JPVX-22JC3T0/01.01A01, // WDC WD20NPVZ-00WFZT0/01.01A01 - // WDC WD10SPZX-22Z10T0/01.01A01 - "WDC WD(20SPZX|20NPVZ|15NPVZ|10[SJ]PZX|7500BPVX|5000[BL]PVX|5000LPCX|3200LPCX)-.*", + "WDC WD(3200LPCX|5000[BL]P[CV]X|7500BPVX|10JP[VZ]X|(15|20)NPVZ)-.*", + "", "", "" + }, + { "Western Digital Blue Mobile (SMR)", // ticket #1313, tested with + // WDC WD10SPZX-22Z10T0/01.01A01, WDC WD10SPZX-21Z10T0/02.01A02, + // WDC WD20SPZX-22CRAT0/01.01A01, WDC WD20SPZX-22UA7T0/01.01A01 + "WDC WD[12]0SPZX-.*", "", "", "" }, { "Western Digital Green Mobile", // tested with WDC WD20NPVX-00EA4T0/01.01A01 @@ -4577,6 +4962,7 @@ // WDC WD10JMVW-11AJGS2/01.01A01 (0x1058:0x10b8), // WDC WD10JMVW-11AJGS4/01.01A01 (0x1058:0x25a0/25a2), // WDC WD10JMVW-11S5XS1/01.01A01, + // WDC WD10SMZW-11Y0TS0/01.01A01, // WDC WD10TMVW-11ZSMS5/01.01A01, // WDC WD20NMVW-11AV3S2/01.01A01 (0x1058:0x0822), // WDC WD20NMVW-11AV3S3/01.01A01 (0x1058:0x0837), @@ -4586,7 +4972,11 @@ // WDC WD20NMVW-59AV3S3/01.01A01 (0x1058:0x107d), // WDC WD30NMVW-11C3NS4/01.01A01, // WDC WD40NMZW-11GX6S1/01.01A01 (0x1058:0x2599/25e2/25fa) - "WDC WD(5000[LK]|7500[BK]|10[JT]|[234]0N)M[VZ][VW]-.*", // *W-* = USB 3.0 + // WDC WD50NDZW-11A8JS1/01.01A01 (0x1058:0x2627) + // WDC WD50NDZW-11MR8S1/02.01A02 + // WDC WD40NDZM-59A8KS1/01.01A01 + "WDC WD((5000[LK]|7500[BK]|10[JST]|[234]0N)M|50ND|40ND)[VZ][VWM]-.*", // *W-* = USB 3.0 + // Model numbers with "M" suffix denote the use of USB-C receptacles instead of Micro-B. "", "", "" }, { "Quantum Bigfoot", // tested with TS10.0A/A21.0G00, TS12.7A/A21.0F00 @@ -4785,8 +5175,8 @@ "", "-d usbjmicron" // 0x1f0a: works also with "-d sat" }, - { "USB: Samsung S1 Portable; JMicron", - "0x04e8:0x2f03", + { "USB: Samsung S1; JMicron", + "0x04e8:0x2f0[36]", // 0x2f03: S1 Portable, 0x2f06: S1 Mini (SAMSUNG HS20YJZ/3AU10-01) "", "", "-d usbjmicron" @@ -4857,6 +5247,12 @@ "", "-d sat" }, + { "USB: Sony HD-E1; ", + "0x054c:0x05bf", // Sony HD-E1B - 1TB USB3.0 + "", // 0x6610 + "", + "-d sat" + }, // Sunplus { "USB: ; SunPlus", "0x04fc:0x0c05", @@ -5030,8 +5426,8 @@ "-d sat" }, { "USB: LaCie; ", // 0x1070: ASMedia 1053 ? - "0x059f:0x10(6f|7[05])", - "", // 6f/70=0x0001, 75=0x0000 + "0x059f:0x10(6f|7[05]|b8)", // 0x0x10b8: d2 PROFESSIONAL + "", // 6f/70/b8=0x0001, 75=0x0000 "", "-d sat" }, @@ -5170,6 +5566,13 @@ "", "-d sat" }, + // 0x0860 (?) + { "USB: ; ", + "0x0860:0x0001", + "", // 0x0100 + "", + "-d sat" + }, // Oxford Semiconductor, Ltd { "USB: ; Oxford", "0x0928:0x0000", @@ -5214,6 +5617,12 @@ "", "-d sat" }, + { "USB: Toshiba; Sunplus", + "0x0930:0xa002", + "", // 0x0103 + "", + "-d usbsunplus" + }, // Lumberg, Inc. { "USB: Toshiba Stor.E; Sunplus", "0x0939:0x0b1[56]", @@ -5229,8 +5638,8 @@ }, // Apricorn { "USB: Apricorn SATA Wire; ", - "0x0984:0x0040", - "", + "0x0984:0x0(040|301)", // 0x0040: Apricorn SATA Wire + "", // 0x0301 (0x0201): Corsair SSD & HDD Cloning Kit "", "-d sat" }, @@ -5260,6 +5669,25 @@ "", "-d sat" }, + // Realtek + { "USB: ; Realtek RTL9210", // USB->PCIe (NVMe) + "0x0bda:0x9210", + "", // 0x2100 + "", + "-d sntrealtek" + }, + { "USB: ; Realtek RTL9211", // USB->PCIe (NVMe) or SATA + "0x(0bda|2eb9):0x9211", // 0x0bda: guessed, 0x2eb9: Sabrent EC-WPTF + ".*", // fall through to next entry and report ambiguous result + "", + "-d sntrealtek" // NVMe or ... + }, + { "USB: ; Realtek RTL9211", + "0x(0bda|2eb9):0x9211", + "", + "", + "" // ... SATA (unsupported) + }, // Addonics { "USB: Addonics HDMU3; ", // (ticket #609) "0x0bf6:0x1001", @@ -5386,9 +5814,10 @@ }, // ADATA { "USB: ADATA; ", - "0x125f:0xa(11|13|15|31|35|37|75)a", // 0xa11a: Classic CH11 1TB, 0xa13a: NH13 1TB, - "", // 0xa15a: HD710 1TB, 0xa31a: HV620 2TB (0x0100), 0xa35a: HD650 2TB (0x6503), - "", // 0xa37a: Silverstone MS10 M.2 (0x3103), 0xa75a: HD710P 4TB + "0x125f:0xa(11|13|15|21|31|35|37|75|83)a", // 0xa11a: Classic CH11 1TB, 0xa13a: NH13 1TB, + "", // 0xa15a: HD710 1TB, 0xa21a: HV610 (0x4504), 0xa31a: HV620 2TB (0x0100), + "", // 0xa35a: HD650 2TB (0x6503), 0xa37a: Silverstone MS10 M.2 (0x3103), 0xa75a: HD710P 4TB, + // 0xa83a: HD330 (0x0100) "-d sat" }, { "USB: ADATA; Cypress", @@ -5469,7 +5898,7 @@ }, { "USB: ; JMicron JMS578", // USB->SATA "0x152d:0x0578", - "", // 0x0100 + "", // 0x0100, 0x0204 "", "-d sat" }, @@ -5491,6 +5920,12 @@ "", "" // unsupported }, + { "USB: ; JMicron", + "0x152d:0x1337", + "", // 0x0508, Digitus DA-71106 + "", + "-d sat" + }, { "USB: ; JMicron JMS561", // USB2/3->2xSATA "0x152d:0x[19]561", // 0x1561(0x0106), Sabrent USB 3.0 Dual Bay SATA Dock "", // 0x9561(0x0105), Orico 6629US3-C USB 3.0 Dual Bay SATA Dock @@ -5498,7 +5933,7 @@ "-d sat" }, { "USB: ; JMicron JMS576", // USB3.1->SATA - "0x152d:0x1576", + "0x152d:0x[01]576", "", // 0x0204, ICY BOX IB-223U3a-B "", "-d sat" @@ -5601,6 +6036,12 @@ "-d sat" }, // ASMedia + { "USB: ; ASMedia ASM2362", // USB->PCIe (NVMe) + "0x174c:0x2362", + "", + "", + "-d sntasmedia" + }, { "USB: ; ASMedia", "0x174c:0x....", "", @@ -5639,7 +6080,7 @@ "", "-d usbsunplus" }, - { "USB: Verbatim Pocket Hard Drive; JMicron", // SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS) + { "USB: Verbatim Pocket Hard Drive; JMicron", // SAMSUNG HS25YJZ/3AU10-01 "0x18a5:0x0227", "", "", @@ -5704,6 +6145,12 @@ "", "-d sat" }, + { "USB: OWC Mercury Elite Pro Quad; ", + "0x1e91:0xa4a7", + "", // 0x0100 + "", + "-d sat" + }, // Innostor { "USB: ; Innostor IS611", // USB3->SATA+PATA "0x1f75:0x0611", // SMART access via PATA does not work @@ -5756,6 +6203,14 @@ "", "-d sat" }, + // 0x2eb9 (?): See Realtek (0x0bda) above + // AKiTiO (?) + { "USB: AkiTio NT2 U3.1C; ", + "0x2ce5:0x0014", + "", // 0x0100 + "", + "-d sat" + }, // Power Quotient International { "USB: PQI H560; ", "0x3538:0x0902", @@ -5772,10 +6227,10 @@ }, // Sharkoon { "USB: Sharkoon QuickPort XT USB 3.0; ", - "0x357d:0x7788", - "", - "", - "-d sat" + "0x357d:0x7788", + "", + "", + "-d sat" }, // Hitachi/SimpleTech { "USB: Hitachi Touro Desk; JMicron", // 3TB diff -Nru smartmontools-7.1/install-sh smartmontools-7.3/install-sh --- smartmontools-7.1/install-sh 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/install-sh 2022-02-28 16:34:38.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2018-03-11.20; # UTC +scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -69,6 +69,11 @@ # Desired mode of installed file. mode=0755 +# Create dirs (including intermediate dirs) using mode 755. +# This is like GNU 'install' as of coreutils 8.32 (2020). +mkdir_umask=22 + +backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= @@ -99,18 +104,28 @@ --version display version info and exit. -c (ignored) - -C install only if different (preserve the last data modification time) + -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. + -p pass -p to $cpprog. -s $stripprog installed files. + -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG + +By default, rm is invoked with -f; when overridden with RMPROG, +it's up to you to specify -f if you want it. + +If -S is not specified, no backups are attempted. + +Email bug reports to bug-automake@gnu.org. +Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do @@ -137,8 +152,13 @@ -o) chowncmd="$chownprog $2" shift;; + -p) cpprog="$cpprog -p";; + -s) stripcmd=$stripprog;; + -S) backupsuffix="$2" + shift;; + -t) is_target_a_directory=always dst_arg=$2 @@ -255,6 +275,10 @@ dstdir=$dst test -d "$dstdir" dstdir_status=$? + # Don't chown directories that already exist. + if test $dstdir_status = 0; then + chowncmd="" + fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command @@ -301,22 +325,6 @@ if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then @@ -326,52 +334,49 @@ fi posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - # Note that $RANDOM variable is not portable (e.g. dash); Use it - # here however when possible just to lower collision chance. - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - - trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 - - # Because "mkdir -p" follows existing symlinks and we likely work - # directly in world-writeable /tmp, make sure that the '$tmpdir' - # directory is successfully created first before we actually test - # 'mkdir -p' feature. - if (umask $mkdir_umask && - $mkdirprog $mkdir_mode "$tmpdir" && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - test_tmpdir="$tmpdir/a" - ls_ld_tmpdir=`ls -ld "$test_tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null - fi - trap '' 0;; - esac;; + # The $RANDOM variable is not portable (e.g., dash). Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap ' + ret=$? + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null + exit $ret + ' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p'. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; esac if @@ -382,7 +387,7 @@ then : else - # The umask is ridiculous, or mkdir does not conform to POSIX, + # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. @@ -411,7 +416,7 @@ prefixes= else if $posix_mkdir; then - (umask=$mkdir_umask && + (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 @@ -451,7 +456,18 @@ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -477,6 +493,13 @@ then rm -f "$dsttmp" else + # If $backupsuffix is set, and the file being installed + # already exists, attempt a backup. Don't worry if it fails, + # e.g., if mv doesn't support -f. + if test -n "$backupsuffix" && test -f "$dst"; then + $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null + fi + # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || @@ -491,9 +514,9 @@ # file should still install successfully. { test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || + $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 diff -Nru smartmontools-7.1/json.cpp smartmontools-7.3/json.cpp --- smartmontools-7.1/json.cpp 2019-08-08 19:01:13.000000000 +0000 +++ smartmontools-7.3/json.cpp 2022-01-06 17:13:25.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2017-19 Christian Franke + * Copyright (C) 2017-22 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -13,11 +13,11 @@ #include "json.h" -const char * json_cvsid = "$Id: json.cpp 4942 2019-08-08 19:01:13Z chrfranke $" +const char * json_cvsid = "$Id: json.cpp 5292 2022-01-06 17:13:25Z chrfranke $" JSON_H_CVSID; #include "sg_unaligned.h" -#include "utility.h" // uint128_*() +#include "utility.h" // regular_expression, uint128_*() #include #include @@ -32,27 +32,37 @@ #define jassert(expr) (!(expr) ? jassert_failed(__LINE__, #expr) : (void)0) -static void check_key(const char * key) +std::string json::str2key(const char * str) +{ + std::string key = str; + for (char & c : key) { + if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || c == '_') + continue; + if ('A' <= c && c <= 'Z') + c += 'a' - 'A'; + else + c = '_'; + } + return key; +} + +json::ref::ref(json & js) +: m_js(js) { - // Limit: object keys should be valid identifiers (lowercase only) - char c = key[0]; - jassert('a' <= c && c <= 'z'); - for (int i = 1; (c = key[i]); i++) - jassert(('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_')); } -json::ref::ref(json & js, const char * key) +json::ref::ref(json & js, const char * keystr) : m_js(js) { - check_key(key); - m_path.push_back(node_info(key)); + jassert(keystr && *keystr); + m_path.push_back(node_info(keystr)); } -json::ref::ref(const ref & base, const char * key) +json::ref::ref(const ref & base, const char * keystr) : m_js(base.m_js), m_path(base.m_path) { - check_key(key); - m_path.push_back(node_info(key)); + jassert(keystr && *keystr); + m_path.push_back(node_info(keystr)); } json::ref::ref(const ref & base, int index) @@ -198,31 +208,41 @@ sg_get_unaligned_le64( pvalue )); } +void json::ref::operator+=(std::initializer_list ilist) +{ + for (const initlist_key_value_pair & kv : ilist) { + jassert(kv.keystr && *kv.keystr); + switch (kv.value.type) { + default: operator[](kv.keystr) = kv.value; break; + case nt_object: operator[](kv.keystr) += kv.object; break; + case nt_array: operator[](kv.keystr) += kv.array; break; + } + } +} + +void json::ref::operator+=(std::initializer_list ilist) +{ + int i = 0; + for (const initlist_value & v : ilist) + operator[](i++) = v; +} + json::node::node() -: type(nt_unset), - intval(0), - intval_hi(0) { } json::node::node(const std::string & key_) -: type(nt_unset), - intval(0), - intval_hi(0), - key(key_) +: key(key_) { } json::node::~node() { - for (size_t i = 0; i < childs.size(); i++) - delete childs[i]; } json::node::const_iterator::const_iterator(const json::node * node_p, bool sorted) : m_node_p(node_p), - m_use_map(sorted && node_p->type == nt_object), - m_child_idx(0) + m_use_map(sorted && node_p->type == nt_object) { if (m_use_map) m_key_iter = node_p->key2index.begin(); @@ -253,9 +273,9 @@ const json::node * json::node::const_iterator::operator*() const { if (m_use_map) - return m_node_p->childs[m_key_iter->second]; + return m_node_p->childs[m_key_iter->second].get(); else - return m_node_p->childs[m_child_idx]; + return m_node_p->childs[m_child_idx].get(); } json::node * json::find_or_create_node(const json::node_path & path, node_type type) @@ -274,13 +294,12 @@ node * p2; if (ni != p->key2index.end()) { // Object element exists - p2 = p->childs[ni->second]; + p2 = p->childs[ni->second].get(); } else { // Create new object element p->key2index[pi.key] = (unsigned)p->childs.size(); - p2 = new node(pi.key); - p->childs.push_back(p2); + p->childs.push_back(std::unique_ptr(p2 = new node(pi.key))); } jassert(p2 && p2->key == pi.key); p = p2; @@ -296,14 +315,14 @@ // Existing or new array element? if (pi.index < (int)p->childs.size()) { // Array index exists - p2 = p->childs[pi.index]; + p2 = p->childs[pi.index].get(); if (!p2) // Already created ? - p->childs[pi.index] = p2 = new node; + p->childs[pi.index].reset(p2 = new node); } else { // Grow array, fill gap, create new element p->childs.resize(pi.index + 1); - p->childs[pi.index] = p2 = new node; + p->childs[pi.index].reset(p2 = new node); } jassert(p2 && p2->key.empty()); p = p2; @@ -319,13 +338,6 @@ return p; } -json::json() -: m_enabled(false), - m_verbose(false), - m_uint128_output(false) -{ -} - void json::set_bool(const node_path & path, bool value) { if (!m_enabled) @@ -360,7 +372,7 @@ { if (!m_enabled) return; - jassert(value != 0); // Limit: nullptr not supported + jassert(value != nullptr); // Limit: nullptr not supported find_or_create_node(path, nt_string)->strval = value; } @@ -371,7 +383,19 @@ find_or_create_node(path, nt_string)->strval = value; } -static void print_string(FILE * f, const char * s) +void json::set_initlist_value(const node_path & path, const initlist_value & val) +{ + if (!m_enabled) + return; + node * p = find_or_create_node(path, val.type); + switch (p->type) { + case nt_bool: case nt_int: case nt_uint: p->intval = val.intval; break; + case nt_string: p->strval = val.strval; break; + default: jassert(false); + } +} + +static void print_quoted_string(FILE * f, const char * s) { putc('"', f); for (int i = 0; s[i]; i++) { @@ -388,15 +412,48 @@ putc('"', f); } -void json::print_json(FILE * f, bool pretty, bool sorted, const node * p, int level) +static char yaml_string_needs_quotes(const char * s) { - if (!p->key.empty()) - fprintf(f, "\"%s\":%s", p->key.c_str(), (pretty ? " " : "")); + if (!*s) + return '\''; // empty string + bool need = false; char quotes = '\''; + for (int i = 0; s[i]; i++) { + char c = s[i]; + if (!(' ' <= c && c <= '~')) + return '"'; // non-ascii char + if ( ('0' <= c && c <= '9') || ('A' <= c && c <= 'Z') + || ('a' <= c && c <= 'z') || c == '_' ) + continue; + if (c == '\'') // if string contains any single quote + quotes = '"'; // use double quotes + if (i == 0) + need = true; // space or special char except '_' at BOL + else if (c == ' ' && (s[i-1] == ':' || s[i+1] == '#')) + need = true; // ": " or " #" + else if ((c == ' ' || c == ':') && !s[i+1]) + need = true; // space or : at EOL + } + if (need) + return quotes; + + static const regular_expression special( + "[0-9]+[,0-9]*(\\.[0-9]*)?([eE][-+]?[0-9]+)?|" // decimal ('^[-+.]' handled above) + "0x[0-7A-Fa-f]+|" // hex + "[Ff][Aa][Ll][Ss][Ee]|[Tt][Rr][Uu][Ee]|[Nn][Oo]|[Yy][Ee][Ss]|" // boolean + "[Nn][Uu][Ll][Ll]" // null + ); + if (special.full_match(s)) + return quotes; // special token + return 0; // none of the above +} +void json::print_json(FILE * f, bool pretty, bool sorted, const node * p, int level) +{ + bool is_obj = (p->type == nt_object); switch (p->type) { case nt_object: case nt_array: - putc((p->type == nt_object ? '{' : '['), f); + putc((is_obj ? '{' : '['), f); if (!p->childs.empty()) { bool first = true; for (node::const_iterator it(p, sorted); !it.at_end(); ++it) { @@ -407,10 +464,13 @@ const node * p2 = *it; if (!p2) { // Unset element of sparse array - jassert(p->type == nt_array); + jassert(!is_obj); fputs("null", f); } else { + jassert(is_obj == !p2->key.empty()); + if (is_obj) + fprintf(f, "\"%s\":%s", p2->key.c_str(), (pretty ? " " : "")); // Recurse print_json(f, pretty, sorted, p2, level + 1); } @@ -419,7 +479,7 @@ if (pretty) fprintf(f, "\n%*s", level * 2, ""); } - putc((p->type == nt_object ? '}' : ']'), f); + putc((is_obj ? '}' : ']'), f); break; case nt_bool: @@ -442,7 +502,78 @@ break; case nt_string: - print_string(f, p->strval.c_str()); + print_quoted_string(f, p->strval.c_str()); + break; + + default: jassert(false); + } +} + +void json::print_yaml(FILE * f, bool pretty, bool sorted, const node * p, int level_o, + int level_a, bool cont) +{ + bool is_obj = (p->type == nt_object); + switch (p->type) { + case nt_object: + case nt_array: + if (!p->childs.empty()) { + if (!cont) + fputs("\n", f); + for (node::const_iterator it(p, sorted); !it.at_end(); ++it) { + int spaces = (cont ? 1 : (is_obj ? level_o : level_a) * 2); + if (spaces > 0) + fprintf(f, "%*s", spaces, ""); + const node * p2 = *it; + if (!p2) { + // Unset element of sparse array + jassert(!is_obj); + fputs("-" /*" null"*/ "\n", f); + } + else { + jassert(is_obj == !p2->key.empty()); + if (is_obj) + fprintf(f, "%s:", p2->key.c_str()); + else + putc('-', f); + // Recurse + print_yaml(f, pretty, sorted, p2, (is_obj ? level_o : level_a) + 1, + (is_obj ? level_o + (pretty ? 1 : 0) : level_a + 1), !is_obj); + } + cont = false; + } + } + else { + fputs((is_obj ? "{}\n" : "[]\n"), f); + } + break; + + case nt_bool: + fputs((p->intval ? " true\n" : " false\n"), f); + break; + + case nt_int: + fprintf(f, " %" PRId64 "\n", (int64_t)p->intval); + break; + + case nt_uint: + fprintf(f, " %" PRIu64 "\n", p->intval); + break; + + case nt_uint128: + { + char buf[64]; + fprintf(f, " %s\n", uint128_hilo_to_str(buf, p->intval_hi, p->intval)); + } + break; + + case nt_string: + putc(' ', f); + switch (yaml_string_needs_quotes(p->strval.c_str())) { + default: print_quoted_string(f, p->strval.c_str()); break; + case '\'': fprintf(f, "'%s'", p->strval.c_str()); break; + case 0: fputs(p->strval.c_str(), f); break; + } + putc('\n', f); break; default: jassert(false); @@ -452,15 +583,16 @@ void json::print_flat(FILE * f, const char * assign, bool sorted, const node * p, std::string & path) { + bool is_obj = (p->type == nt_object); switch (p->type) { case nt_object: case nt_array: - fprintf(f, "%s%s%s;\n", path.c_str(), assign, (p->type == nt_object ? "{}" : "[]")); + fprintf(f, "%s%s%s;\n", path.c_str(), assign, (is_obj ? "{}" : "[]")); if (!p->childs.empty()) { unsigned len = path.size(); for (node::const_iterator it(p, sorted); !it.at_end(); ++it) { const node * p2 = *it; - if (p->type == nt_array) { + if (!is_obj) { char buf[10]; snprintf(buf, sizeof(buf), "[%u]", it.array_index()); path += buf; } @@ -469,7 +601,7 @@ } if (!p2) { // Unset element of sparse array - jassert(p->type == nt_array); + jassert(!is_obj); fprintf(f, "%s%snull;\n", path.c_str(), assign); } else { @@ -503,7 +635,7 @@ case nt_string: fprintf(f, "%s%s", path.c_str(), assign); - print_string(f, p->strval.c_str()); + print_quoted_string(f, p->strval.c_str()); fputs(";\n", f); break; @@ -517,13 +649,20 @@ return; jassert(m_root_node.type == nt_object); - if (!options.flat) { - print_json(f, options.pretty, options.sorted, &m_root_node, 0); - if (options.pretty) - putc('\n', f); - } - else { - std::string path("json"); - print_flat(f, (options.pretty ? " = " : "="), options.sorted, &m_root_node, path); + switch (options.format) { + default: + print_json(f, options.pretty, options.sorted, &m_root_node, 0); + if (options.pretty) + putc('\n', f); + break; + case 'y': + fputs("---", f); + print_yaml(f, options.pretty, options.sorted, &m_root_node, 0, 0, false); + break; + case 'g': { + std::string path("json"); + print_flat(f, (options.pretty ? " = " : "="), options.sorted, &m_root_node, path); + } + break; } } diff -Nru smartmontools-7.1/json.h smartmontools-7.3/json.h --- smartmontools-7.1/json.h 2019-08-08 19:01:13.000000000 +0000 +++ smartmontools-7.3/json.h 2022-01-06 17:13:25.000000000 +0000 @@ -3,47 +3,103 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2017-19 Christian Franke + * Copyright (C) 2017-22 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef JSON_H_CVSID -#define JSON_H_CVSID "$Id: json.h 4942 2019-08-08 19:01:13Z chrfranke $" +#define JSON_H_CVSID "$Id: json.h 5292 2022-01-06 17:13:25Z chrfranke $" #include #include +#include +#include +#include #include #include -#include /// Create and print JSON output. class json { +public: + /// Return true if value is a safe JSON integer. + /// Same as Number.isSafeInteger(value) in JavaScript. + static bool is_safe_uint(unsigned long long value) + { return (value < (1ULL << 53)); } + + /// Replace space and non-alphanumerics with '_', upper to lower case. + static std::string str2key(const char * str); + + /// Replace space and non-alphanumerics with '_', upper to lower case + /// (std::string variant). + static std::string str2key(const std::string & str) + { return str2key(str.c_str()); } + + enum node_type { + nt_unset, nt_object, nt_array, + nt_bool, nt_int, nt_uint, nt_uint128, nt_string + }; + + // initializer_list<> elements. + struct initlist_value { + // cppcheck-suppress noExplicitConstructor + initlist_value(node_type t) : type(t) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(bool v) : type(nt_bool), intval(v ? 1 : 0) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(int v) : initlist_value((long long)v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(unsigned v) : initlist_value((unsigned long long)v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(long v) : initlist_value((long long)v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(unsigned long v) : initlist_value((unsigned long long)v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(long long v) : type(nt_int), intval((uint64_t)(int64_t)v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(unsigned long long v) : type(nt_uint), intval((uint64_t)v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(const char * v) : type(nt_string), strval(v) {} + // cppcheck-suppress noExplicitConstructor + initlist_value(const std::string & v) : type(nt_string), strval(v.c_str()) {} + node_type type; + uint64_t intval = 0; + const char * strval = nullptr; + }; + + struct initlist_key_value_pair { + initlist_key_value_pair(const char * k, const initlist_value & v) : keystr(k), value(v) {} + initlist_key_value_pair(const std::string & k, const initlist_value & v) + : keystr(k.c_str()), value(v) {} + initlist_key_value_pair(const char * k, const std::initializer_list & ilist) + : keystr(k), value(nt_object), object(ilist) {} + initlist_key_value_pair(const std::string & k, const std::initializer_list & ilist) + : keystr(k.c_str()), value(nt_object), object(ilist) {} + initlist_key_value_pair(const char * k, const std::initializer_list & ilist) + : keystr(k), value(nt_array), array(ilist) {} + initlist_key_value_pair(const std::string & k, const std::initializer_list & ilist) + : keystr(k.c_str()), value(nt_array), array(ilist) {} + const char * keystr; + initlist_value value; + std::initializer_list object; + std::initializer_list array; + }; + private: struct node_info { std::string key; - int index; + int index = 0; - node_info() - : index(0) { } - explicit node_info(const char * key_) - : key(key_), index(0) { } - explicit node_info(int index_) - : index(index_) { } + node_info() = default; + explicit node_info(const char * keystr) : key(str2key(keystr)) { } + explicit node_info(int index_) : index(index_) { } }; typedef std::vector node_path; public: - /// Return true if value is a safe JSON integer. - /// Same as Number.isSafeInteger(value) in JavaScript. - static bool is_safe_uint(unsigned long long value) - { return (value < (1ULL << 53)); } - - json(); - /// Reference to a JSON element. class ref { @@ -51,8 +107,12 @@ ~ref(); /// Return reference to object element. - ref operator[](const char * key) const - { return ref(*this, key); } + ref operator[](const char * keystr) const + { return ref(*this, keystr); } + + /// Return reference to object element (std::string variant). + ref operator[](const std::string & keystr) const + { return ref(*this, keystr.c_str()); } /// Return reference to array element. ref operator[](int index) const @@ -87,20 +147,37 @@ void set_unsafe_uint128(uint64_t value_hi, uint64_t value_lo); void set_unsafe_le128(const void * pvalue); + /// Braced-init-list support for nested objects. + void operator+=(std::initializer_list ilist); + /// Braced-init-list support for simple arrays. + void operator+=(std::initializer_list ilist); + private: friend class json; - ref(json & js, const char * key); - ref(const ref & base, const char * key); + explicit ref(json & js); + ref(json & js, const char * keystr); + ref(const ref & base, const char * keystr); ref(const ref & base, int index); ref(const ref & base, const char * /*dummy*/, const char * key_suffix); + void operator=(const initlist_value & value) + { m_js.set_initlist_value(m_path, value); } + json & m_js; node_path m_path; }; /// Return reference to element of top level object. - ref operator[](const char * key) - { return ref(*this, key); } + ref operator[](const char * keystr) + { return ref(*this, keystr); } + + /// Return reference to element of top level object (std::string variant). + ref operator[](const std::string & keystr) + { return ref(*this, keystr.c_str()); } + + /// Braced-init-list support for top level object. + void operator+=(std::initializer_list ilist) + { ref(*this) += ilist; } /// Enable/disable JSON output. void enable(bool yes = true) @@ -120,35 +197,30 @@ /// Options for print(). struct print_options { - bool pretty; //< Pretty-print output. - bool sorted; //< Sort object keys. - bool flat; //< Print flat format. - print_options() - : pretty(false), sorted(false), flat(false) { } + bool pretty = false; //< Pretty-print output. + bool sorted = false; //< Sort object keys. + char format = 0; //< 'y': YAML, 'g': flat(grep, gron), other: JSON }; /// Print JSON tree to a file. void print(FILE * f, const print_options & options) const; private: - enum node_type { - nt_unset, nt_object, nt_array, - nt_bool, nt_int, nt_uint, nt_uint128, nt_string - }; - struct node { node(); + node(const node &) = delete; explicit node(const std::string & key_); ~node(); + void operator=(const node &) = delete; - node_type type; + node_type type = nt_unset; - uint64_t intval, intval_hi; + uint64_t intval = 0, intval_hi = 0; std::string strval; std::string key; - std::vector childs; + std::vector< std::unique_ptr > childs; typedef std::map keymap; keymap key2index; @@ -164,21 +236,14 @@ private: const node * m_node_p; bool m_use_map; - unsigned m_child_idx; + unsigned m_child_idx = 0; keymap::const_iterator m_key_iter; }; - -#if __cplusplus >= 201103 - node(const node &) = delete; - void operator=(const node &) = delete; -#else - private: node(const node &); void operator=(const node &); -#endif }; - bool m_enabled; - bool m_verbose; - bool m_uint128_output; + bool m_enabled = false; + bool m_verbose = false; + bool m_uint128_output = false; node m_root_node; @@ -190,8 +255,11 @@ void set_uint128(const node_path & path, uint64_t value_hi, uint64_t value_lo); void set_cstring(const node_path & path, const char * value); void set_string(const node_path & path, const std::string & value); + void set_initlist_value(const node_path & path, const initlist_value & value); static void print_json(FILE * f, bool pretty, bool sorted, const node * p, int level); + static void print_yaml(FILE * f, bool pretty, bool sorted, const node * p, int level_o, + int level_a, bool cont); static void print_flat(FILE * f, const char * assign, bool sorted, const node * p, std::string & path); }; diff -Nru smartmontools-7.1/knowndrives.cpp smartmontools-7.3/knowndrives.cpp --- smartmontools-7.1/knowndrives.cpp 2018-12-02 16:07:26.000000000 +0000 +++ smartmontools-7.3/knowndrives.cpp 2021-02-09 20:25:13.000000000 +0000 @@ -1,10 +1,10 @@ /* * knowndrives.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-11 Philip Williams, Bruce Allen - * Copyright (C) 2008-18 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -25,7 +25,7 @@ #include -const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 4842 2018-12-02 16:07:26Z chrfranke $" +const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 5207 2021-02-09 20:25:13Z chrfranke $" KNOWNDRIVES_H_CVSID; #define MODEL_STRING_LENGTH 40 @@ -135,6 +135,7 @@ enum dbentry_type { + DBENTRY_VERSION, DBENTRY_ATA_DEFAULT, DBENTRY_ATA, DBENTRY_USB @@ -143,9 +144,11 @@ // Return type of entry static dbentry_type get_modelfamily_type(const char * modelfamily) { - if (modelfamily[0] == 'D' && !strcmp(modelfamily, "DEFAULT")) + if (modelfamily[0] == 'V' && str_starts_with(modelfamily, "VERSION:")) + return DBENTRY_VERSION; + else if (modelfamily[0] == 'D' && !strcmp(modelfamily, "DEFAULT")) return DBENTRY_ATA_DEFAULT; - else if(modelfamily[0] == 'U' && str_starts_with(modelfamily, "USB:")) + else if (modelfamily[0] == 'U' && str_starts_with(modelfamily, "USB:")) return DBENTRY_USB; else return DBENTRY_ATA; @@ -156,6 +159,23 @@ return get_modelfamily_type(dbentry->modelfamily); } +// Extract "BRANCH/REV" from "VERSION: ..." string. +static void parse_version(std::string & dbversion, const char * verstr) +{ + static const regular_expression regex( + "^VERSION: ([0-9]+\\.[0-9]+)(/([0-9]+) | \\$[^0-9]* ([0-9]+) )" + // (1 )( (3 ) (4 ) ) + ); + const int nmatch = 1+4; + regular_expression::match_range match[nmatch]; + if (!regex.execute(verstr, nmatch, match)) + return; + dbversion.assign(verstr + match[1].rm_so, match[1].rm_eo - match[1].rm_so); + int i = (match[3].rm_so >= 0 ? 3 : 4); // "BRANCH/REV" or "BRANCH ... SVN-REV" + dbversion += '/'; + dbversion.append(verstr + match[i].rm_so, match[i].rm_eo - match[i].rm_so); +} + // Compile regular expression, print message on failure. static bool compile(regular_expression & regex, const char *pattern) { @@ -181,7 +201,8 @@ // string. If either the drive's model or firmware strings are not set by the // manufacturer then values of NULL may be used. Returns the entry of the // first match in knowndrives[] or 0 if no match if found. -static const drive_settings * lookup_drive(const char * model, const char * firmware) +static const drive_settings * lookup_drive(const char * model, const char * firmware, + std::string * dbversion = nullptr) { if (!model) model = ""; @@ -189,8 +210,16 @@ firmware = ""; for (unsigned i = 0; i < knowndrives.size(); i++) { + dbentry_type t = get_dbentry_type(&knowndrives[i]); + // Get version if requested + if (t == DBENTRY_VERSION) { + if (dbversion) + parse_version(*dbversion, knowndrives[i].modelfamily); + continue; + } + // Skip DEFAULT and USB entries - if (get_dbentry_type(&knowndrives[i]) != DBENTRY_ATA) + if (t != DBENTRY_ATA) continue; // Check whether model matches the regular expression in knowndrives[i]. @@ -554,7 +583,7 @@ // Returns pointer to database entry or nullptr if none found const drive_settings * lookup_drive_apply_presets( const ata_identify_device * drive, ata_vendor_attr_defs & defs, - firmwarebug_defs & firmwarebugs) + firmwarebug_defs & firmwarebugs, std::string & dbversion) { // get the drive's model/firmware strings char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; @@ -562,7 +591,7 @@ ata_format_id_string(firmware, drive->fw_rev, sizeof(firmware)-1); // Look up the drive in knowndrives[]. - const drive_settings * dbentry = lookup_drive(model, firmware); + const drive_settings * dbentry = lookup_drive(model, firmware, &dbversion); if (!dbentry) return 0; diff -Nru smartmontools-7.1/knowndrives.h smartmontools-7.3/knowndrives.h --- smartmontools-7.1/knowndrives.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/knowndrives.h 2021-02-09 20:25:13.000000000 +0000 @@ -1,10 +1,10 @@ /* * knowndrives.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-11 Philip Williams, Bruce Allen - * Copyright (C) 2008-15 Christian Franke + * Copyright (C) 2008-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -12,7 +12,7 @@ #ifndef KNOWNDRIVES_H_ #define KNOWNDRIVES_H_ -#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 4760 2018-08-19 18:45:53Z chrfranke $\n" +#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 5207 2021-02-09 20:25:13Z chrfranke $\n" // Structure to store drive database entries, see drivedb.h for a description. struct drive_settings { @@ -52,7 +52,7 @@ // Returns pointer to database entry or nullptr if none found. const drive_settings * lookup_drive_apply_presets( const ata_identify_device * drive, ata_vendor_attr_defs & defs, - firmwarebug_defs & firmwarebugs); + firmwarebug_defs & firmwarebugs, std::string & dbversion); // Get path for additional database file const char * get_drivedb_path_add(); diff -Nru smartmontools-7.1/Makefile.am smartmontools-7.3/Makefile.am --- smartmontools-7.1/Makefile.am 2019-11-24 18:19:24.000000000 +0000 +++ smartmontools-7.3/Makefile.am 2022-02-18 17:23:14.000000000 +0000 @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in # -# $Id: Makefile.am 4979 2019-11-24 18:19:24Z chrfranke $ +# $Id: Makefile.am 5318 2022-02-18 17:23:14Z chrfranke $ # @SET_MAKE@ @@ -64,7 +64,6 @@ dev_ata_cmd_set.cpp \ dev_ata_cmd_set.h \ dev_intelliprop.cpp \ - dev_intelliprop.h \ dev_interface.cpp \ dev_interface.h \ dev_jmb39x_raid.cpp \ @@ -143,7 +142,6 @@ dev_ata_cmd_set.cpp \ dev_ata_cmd_set.h \ dev_intelliprop.cpp \ - dev_intelliprop.h \ dev_interface.cpp \ dev_interface.h \ dev_jmb39x_raid.cpp \ @@ -197,6 +195,14 @@ netbsd_nvme_ioctl.h \ megaraid.h +if OS_POSIX + +smartd_SOURCES += \ + popen_as_ugid.cpp \ + popen_as_ugid.h + +endif + if OS_WIN32_MINGW smartd_SOURCES += \ @@ -419,7 +425,7 @@ os_win32/smartd_mailer.conf.sample.ps1 \ os_win32/smartd_warning.cmd \ os_win32/syslogevt.mc \ - os_win32/update-smart-drivedb.nsi \ + os_win32/update-smart-drivedb.ps1.in \ os_win32/versioninfo.rc.in \ os_win32/wtssendmsg.c \ $(docs_DATA) \ @@ -502,7 +508,7 @@ if ENABLE_DRIVEDB -drivedb_DATA = drivedb.h +drivedbinst_DATA = drivedb.h endif update-smart-drivedb: update-smart-drivedb.in config.status @@ -585,7 +591,7 @@ # Create empty directories if configured. # Default install rules no longer create empty directories since automake 1.11. installdirs-local: - @for d in '$(smartdplugindir)' '$(savestatesdir)' '$(attributelogdir)'; do \ + @for d in '$(smartdplugindir)' '$(drivedbdir)' '$(savestatesdir)' '$(attributelogdir)'; do \ test -n "$$d" || continue; \ echo " $(MKDIR_P) '$(DESTDIR)$$d'"; \ $(MKDIR_P) "$(DESTDIR)$$d" || exit 1; \ @@ -613,10 +619,16 @@ -e 's|/usr/bin/mail|/usr/bin/$(os_mailer)|g' \ -e 's|RELEASE_6_0_DRIVEDB|$(DRIVEDB_BRANCH)|g' | \ if test -n '$(drivedbdir)'; then \ - sed 's|/usr/local/share/smartmontools/drivedb\.h|$(drivedbdir)/drivedb.h|g' ; \ + sed -e 's|/usr/local/share/smartmontools/drivedb\.h|$(drivedbinstdir)/drivedb.h|g' \ + -e 's|/usr/local/var/lib/smartmontools/drivedb\.h|$(drivedbdir)/drivedb.h|g' ; \ else \ sed '/^\.\\" %IF ENABLE_DRIVEDB/,/^\.\\" %ENDIF ENABLE_DRIVEDB/ s,^,.\\"\# ,' ; \ fi | \ + if test '$(drivedbinstdir)' != '$(drivedbdir)'; then \ + cat; \ + else \ + sed '/^\.\\" %IF ENABLE_DB_INSTALL/,/^\.\\" %ENDIF ENABLE_DB_INSTALL/ s,^,.\\"\# ,' ; \ + fi | \ if test '$(with_update_smart_drivedb)' = 'yes'; then \ cat; \ else \ @@ -757,7 +769,8 @@ # Check drive database syntax check: - @if ./smartctl -B $(srcdir)/drivedb.h -P showall >/dev/null; then \ + @if ./smartctl -P showall >/dev/null && \ + ./smartctl -B $(srcdir)/drivedb.h -P showall >/dev/null; then \ echo "$(srcdir)/drivedb.h: OK"; \ else \ echo "$(srcdir)/drivedb.h: Syntax check failed"; exit 1; \ @@ -864,10 +877,8 @@ $(exedir_win32)/wtssendmsg.exe if ENABLE_DRIVEDB -if OS_WIN32_NSIS EXEFILES_WIN32 += \ - $(exedir_win32)/update-smart-drivedb.exe -endif + $(exedir_win32)/update-smart-drivedb.ps1 endif FILES_WIN32 = \ @@ -904,7 +915,7 @@ smartctl_res.rc smartd_res.rc \ syslogevt.h \ syslogevt.rc syslogevt_*.bin \ - update-smart-drivedb.exe \ + update-smart-drivedb.ps1 \ wtssendmsg.exe wtssendmsg_res.rc # Note: Only use without options to be compatible with all variants @@ -945,10 +956,6 @@ sha1sum $@ > $@.sha1 sha256sum $@ > $@.sha256 -# Build drivedb.h update tool -update-smart-drivedb.exe: os_win32/update-smart-drivedb.nsi - "$(MAKENSIS)" -V2 -NOCD -DBRANCH=$(DRIVEDB_BRANCH) $< - else $(distinst_win32): @echo "makensis: command not found. Please install NSIS from http://nsis.sourceforge.net/" 1>&2 @@ -968,10 +975,6 @@ if test -n '$(STRIP)'; then $(STRIP) -s $@; else strip -s $@; fi touch -r $< $@ -# strip would break NSIS integrity check -$(exedir_win32)/update-smart-drivedb.exe: update-smart-drivedb.exe - cp -p $< $@ - $(exedir_win32)/%.h: $(srcdir)/%.h $(UNIX2DOS) < $< > $@ touch -r $< $@ @@ -984,6 +987,10 @@ $(UNIX2DOS) < $< > $@ touch -r $< $@ +$(exedir_win32)/%.ps1: %.ps1 + $(UNIX2DOS) < $< > $@ + touch -r $< $@ + $(docdir_win32)/%.html: %.html $(UNIX2DOS) < $< > $@ touch -r $< $@ @@ -1032,9 +1039,24 @@ wtssendmsg.exe: os_win32/wtssendmsg.c wtssendmsg_res.o $(CC) -Os -o $@ $^ -lwtsapi32 -# Build os_win32/vc14/{config.h,smart*.rc,svnversion.h} for MSVC14 from MinGW files +# Build drivedb.h update script +update-smart-drivedb.ps1: os_win32/update-smart-drivedb.ps1.in config.status + $(SHELL) ./config.status --file=$@:$< + +# MSVC Version to change in make command line +vc = 16 +vcver = $(vc) + +.PHONY: check-vc-version clean-vc config-vc distclean-vc maintainer-clean-vc + +check-vc-version: + @case '$(vcver)' in \ + 14|15|16) test -d '$(srcdir)/os_win32/vc$(vcver)' || \ + { echo '$(srcdir)/os_win32/vc$(vcver): Not found (not included in src tarball)' >&2; exit 1; } ;; \ + *) echo 'Usage: $(MAKE) vc=14|15|16 config-vc clean-vc distclean-vc maintainer-clean-vc'; exit 1 ;; \ + esac -vcver = 14 +# Build os_win32/vcNN/{config.h,smart*.rc,svnversion.h} for MSVC14/15/16 from MinGW files CONFIG_VC_FILES = \ $(srcdir)/os_win32/vc$(vcver)/config.h \ @@ -1042,11 +1064,11 @@ $(srcdir)/os_win32/vc$(vcver)/smartd_res.rc \ $(srcdir)/os_win32/vc$(vcver)/svnversion.h -config-vc$(vcver): $(CONFIG_VC_FILES) +config-vc: check-vc-version $(CONFIG_VC_FILES) $(srcdir)/os_win32/vc$(vcver)/config.h: config.h Makefile sed -e '1i/* os_win32/vc$(vcver)/config.h. Generated from config.h by Makefile. */' \ - -e 's,^#define HAVE_\(ATTR_PACKED\|GETTIMEOFDAY\|[DK_]*NTDDDISK_H\|LONG_DOUBLE_WIDER\|STRINGS_H\|UNISTD_H\) 1$$,/* #undef HAVE_\1 */ /* VC$(vcver) */,' \ + -e 's,^#define HAVE_\(ATTR_PACKED\|CLOCK_GETTIME\|GETTIMEOFDAY\|LONG_DOUBLE_WIDER\|STRINGS_H\|UNISTD_H\) 1$$,/* #undef HAVE_\1 */ /* VC$(vcver) */,' \ -e 's,^\(#define SMARTMONTOOLS_BUILD_HOST "[^-]*\)[^"]*,\1-pc-w32vc$(vcver),' $< > $@ $(srcdir)/os_win32/vc$(vcver)/svnversion.h: svnversion.h @@ -1058,18 +1080,23 @@ $(srcdir)/os_win32/vc$(vcver)/smartd_res.rc: smartd_res.rc sed '/^1 24 /d' $< > $@ -clean-vc$(vcver): +# VC14: smartmontools.VC.*, VC15/16: .vs/smartmontools/vNN/* +clean-vc: check-vc-version rm -f $(srcdir)/os_win32/vc$(vcver)/smartmontools.VC.VC.opendb rm -f $(srcdir)/os_win32/vc$(vcver)/smartmontools.VC.db + rm -f $(srcdir)/os_win32/vc$(vcver)/.vs/smartmontools/v$(vcver)/Browse.VC.opendb + rm -f $(srcdir)/os_win32/vc$(vcver)/.vs/smartmontools/v$(vcver)/*.VC.db* + rm -rf $(srcdir)/os_win32/vc$(vcver)/.vs/smartmontools/v$(vcver)/ipch rm -f $(srcdir)/os_win32/vc$(vcver)/syslogevt.h rm -rf $(srcdir)/os_win32/vc$(vcver)/Debug rm -rf $(srcdir)/os_win32/vc$(vcver)/Release rm -rf $(srcdir)/os_win32/vc$(vcver)/x64 -distclean-vc$(vcver): clean-vc$(vcver) +distclean-vc: clean-vc rm -f $(CONFIG_VC_FILES) -maintainer-clean-vc$(vcver): distclean-vc$(vcver) +maintainer-clean-vc: distclean-vc + rm -f $(srcdir)/os_win32/vc$(vcver)/*.vcxproj.user rm -rf $(srcdir)/os_win32/vc$(vcver)/.vs endif diff -Nru smartmontools-7.1/Makefile.in smartmontools-7.3/Makefile.in --- smartmontools-7.1/Makefile.in 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/Makefile.in 2022-02-28 16:34:38.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,7 @@ @SET_MAKE@ # -# $Id: Makefile.am 4979 2019-11-24 18:19:24Z chrfranke $ +# $Id: Makefile.am 5318 2022-02-18 17:23:14Z chrfranke $ # @@ -107,7 +107,11 @@ @OS_WIN32_MINGW_TRUE@am__append_8 = smartctl_res.o @OS_WIN32_MINGW_TRUE@am__append_9 = smartctl_res.o -@OS_WIN32_MINGW_TRUE@am__append_10 = \ +@OS_POSIX_TRUE@am__append_10 = \ +@OS_POSIX_TRUE@ popen_as_ugid.cpp \ +@OS_POSIX_TRUE@ popen_as_ugid.h + +@OS_WIN32_MINGW_TRUE@am__append_11 = \ @OS_WIN32_MINGW_TRUE@ os_win32/daemon_win32.cpp \ @OS_WIN32_MINGW_TRUE@ os_win32/daemon_win32.h \ @OS_WIN32_MINGW_TRUE@ os_win32/popen_win32.cpp \ @@ -115,9 +119,9 @@ @OS_WIN32_MINGW_TRUE@ os_win32/syslog_win32.cpp \ @OS_WIN32_MINGW_TRUE@ os_win32/syslog.h -@OS_WIN32_MINGW_TRUE@am__append_11 = smartd_res.o @OS_WIN32_MINGW_TRUE@am__append_12 = smartd_res.o -@NEED_GETOPT_LONG_TRUE@am__append_13 = \ +@OS_WIN32_MINGW_TRUE@am__append_13 = smartd_res.o +@NEED_GETOPT_LONG_TRUE@am__append_14 = \ @NEED_GETOPT_LONG_TRUE@ getopt/getopt.c \ @NEED_GETOPT_LONG_TRUE@ getopt/getopt.h \ @NEED_GETOPT_LONG_TRUE@ getopt/getopt1.c \ @@ -125,7 +129,7 @@ @NEED_GETOPT_LONG_TRUE@ getopt/bits/getopt_core.h \ @NEED_GETOPT_LONG_TRUE@ getopt/bits/getopt_ext.h -@NEED_GETOPT_LONG_TRUE@am__append_14 = \ +@NEED_GETOPT_LONG_TRUE@am__append_15 = \ @NEED_GETOPT_LONG_TRUE@ getopt/getopt.c \ @NEED_GETOPT_LONG_TRUE@ getopt/getopt.h \ @NEED_GETOPT_LONG_TRUE@ getopt/getopt1.c \ @@ -133,49 +137,49 @@ @NEED_GETOPT_LONG_TRUE@ getopt/bits/getopt_core.h \ @NEED_GETOPT_LONG_TRUE@ getopt/bits/getopt_ext.h -@NEED_REGEX_TRUE@am__append_15 = \ +@NEED_REGEX_TRUE@am__append_16 = \ @NEED_REGEX_TRUE@ regex/regex.c \ @NEED_REGEX_TRUE@ regex/regex.h \ @NEED_REGEX_TRUE@ regex/regex_internal.h -@NEED_REGEX_TRUE@am__append_16 = \ +@NEED_REGEX_TRUE@am__append_17 = \ @NEED_REGEX_TRUE@ regex/regex.c \ @NEED_REGEX_TRUE@ regex/regex.h \ @NEED_REGEX_TRUE@ regex/regex_internal.h # Included by regex.c: -@NEED_REGEX_TRUE@am__append_17 = \ +@NEED_REGEX_TRUE@am__append_18 = \ @NEED_REGEX_TRUE@ regex/regcomp.c \ @NEED_REGEX_TRUE@ regex/regexec.c \ @NEED_REGEX_TRUE@ regex/regex_internal.c -@NEED_REGEX_TRUE@am__append_18 = \ +@NEED_REGEX_TRUE@am__append_19 = \ @NEED_REGEX_TRUE@ regex/regcomp.c \ @NEED_REGEX_TRUE@ regex/regexec.c \ @NEED_REGEX_TRUE@ regex/regex_internal.c -@OS_WIN32_TRUE@am__append_19 = \ +@OS_WIN32_TRUE@am__append_20 = \ @OS_WIN32_TRUE@ csmisas.h \ @OS_WIN32_TRUE@ os_win32/wmiquery.cpp \ @OS_WIN32_TRUE@ os_win32/wmiquery.h -@OS_WIN32_TRUE@am__append_20 = \ +@OS_WIN32_TRUE@am__append_21 = \ @OS_WIN32_TRUE@ csmisas.h \ @OS_WIN32_TRUE@ os_win32/wmiquery.cpp \ @OS_WIN32_TRUE@ os_win32/wmiquery.h -@OS_WIN32_TRUE@am__append_21 = -lole32 -loleaut32 @OS_WIN32_TRUE@am__append_22 = -lole32 -loleaut32 -@ENABLE_UPDATE_SMART_DRIVEDB_TRUE@@OS_SOLARIS_TRUE@am__append_23 = update-smart-drivedb.1m -@ENABLE_UPDATE_SMART_DRIVEDB_TRUE@@OS_SOLARIS_FALSE@am__append_24 = update-smart-drivedb.8 -@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@am__append_25 = \ -@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ $(exedir_win32)/update-smart-drivedb.exe - +@OS_WIN32_TRUE@am__append_23 = -lole32 -loleaut32 +@ENABLE_UPDATE_SMART_DRIVEDB_TRUE@@OS_SOLARIS_TRUE@am__append_24 = update-smart-drivedb.1m +@ENABLE_UPDATE_SMART_DRIVEDB_TRUE@@OS_SOLARIS_FALSE@am__append_25 = update-smart-drivedb.8 @ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@am__append_26 = \ +@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@ $(exedir_win32)/update-smart-drivedb.ps1 + +@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@am__append_27 = \ @ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@ $(exedir_win32)/drivedb.h -@OS_WIN32_MINGW_TRUE@am__append_27 = \ +@OS_WIN32_MINGW_TRUE@am__append_28 = \ @OS_WIN32_MINGW_TRUE@ $(FILES_WIN32) \ @OS_WIN32_MINGW_TRUE@ defadmin.manifest \ @OS_WIN32_MINGW_TRUE@ distdir.mkdir \ @@ -185,7 +189,7 @@ @OS_WIN32_MINGW_TRUE@ smartctl_res.rc smartd_res.rc \ @OS_WIN32_MINGW_TRUE@ syslogevt.h \ @OS_WIN32_MINGW_TRUE@ syslogevt.rc syslogevt_*.bin \ -@OS_WIN32_MINGW_TRUE@ update-smart-drivedb.exe \ +@OS_WIN32_MINGW_TRUE@ update-smart-drivedb.ps1 \ @OS_WIN32_MINGW_TRUE@ wtssendmsg.exe wtssendmsg_res.rc subdir = . @@ -205,25 +209,24 @@ am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(examplesdir)" \ "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(smartdscriptdir)" \ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" \ - "$(DESTDIR)$(docsdir)" "$(DESTDIR)$(drivedbdir)" \ + "$(DESTDIR)$(docsdir)" "$(DESTDIR)$(drivedbinstdir)" \ "$(DESTDIR)$(examplesdir)" "$(DESTDIR)$(initddir)" \ "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(systemdsystemunitdir)" PROGRAMS = $(sbin_PROGRAMS) am__smartctl_SOURCES_DIST = smartctl.cpp smartctl.h atacmdnames.cpp \ atacmdnames.h atacmds.cpp atacmds.h ataidentify.cpp \ ataidentify.h ataprint.cpp ataprint.h dev_ata_cmd_set.cpp \ - dev_ata_cmd_set.h dev_intelliprop.cpp dev_intelliprop.h \ - dev_interface.cpp dev_interface.h dev_jmb39x_raid.cpp \ - dev_tunnelled.h drivedb.h json.cpp json.h knowndrives.cpp \ - knowndrives.h nvmecmds.cpp nvmecmds.h nvmeprint.cpp \ - nvmeprint.h scsicmds.cpp scsicmds.h scsiata.cpp scsinvme.cpp \ - scsiprint.cpp scsiprint.h static_assert.h utility.cpp \ - utility.h sg_unaligned.h os_win32/popen_win32.cpp \ - os_win32/popen.h getopt/getopt.c getopt/getopt.h \ - getopt/getopt1.c getopt/getopt_int.h getopt/bits/getopt_core.h \ - getopt/bits/getopt_ext.h regex/regex.c regex/regex.h \ - regex/regex_internal.h csmisas.h os_win32/wmiquery.cpp \ - os_win32/wmiquery.h + dev_ata_cmd_set.h dev_intelliprop.cpp dev_interface.cpp \ + dev_interface.h dev_jmb39x_raid.cpp dev_tunnelled.h drivedb.h \ + json.cpp json.h knowndrives.cpp knowndrives.h nvmecmds.cpp \ + nvmecmds.h nvmeprint.cpp nvmeprint.h scsicmds.cpp scsicmds.h \ + scsiata.cpp scsinvme.cpp scsiprint.cpp scsiprint.h \ + static_assert.h utility.cpp utility.h sg_unaligned.h \ + os_win32/popen_win32.cpp os_win32/popen.h getopt/getopt.c \ + getopt/getopt.h getopt/getopt1.c getopt/getopt_int.h \ + getopt/bits/getopt_core.h getopt/bits/getopt_ext.h \ + regex/regex.c regex/regex.h regex/regex_internal.h csmisas.h \ + os_win32/wmiquery.cpp os_win32/wmiquery.h @OS_WIN32_MINGW_TRUE@am__objects_1 = popen_win32.$(OBJEXT) @NEED_GETOPT_LONG_TRUE@am__objects_2 = getopt.$(OBJEXT) \ @NEED_GETOPT_LONG_TRUE@ getopt1.$(OBJEXT) @@ -250,11 +253,11 @@ am__DEPENDENCIES_1 = am__smartd_SOURCES_DIST = smartd.cpp atacmdnames.cpp atacmdnames.h \ atacmds.cpp atacmds.h dev_ata_cmd_set.cpp dev_ata_cmd_set.h \ - dev_intelliprop.cpp dev_intelliprop.h dev_interface.cpp \ - dev_interface.h dev_jmb39x_raid.cpp dev_tunnelled.h drivedb.h \ - knowndrives.cpp knowndrives.h nvmecmds.cpp nvmecmds.h \ - scsicmds.cpp scsicmds.h scsiata.cpp scsinvme.cpp \ - static_assert.h utility.cpp utility.h sg_unaligned.h \ + dev_intelliprop.cpp dev_interface.cpp dev_interface.h \ + dev_jmb39x_raid.cpp dev_tunnelled.h drivedb.h knowndrives.cpp \ + knowndrives.h nvmecmds.cpp nvmecmds.h scsicmds.cpp scsicmds.h \ + scsiata.cpp scsinvme.cpp static_assert.h utility.cpp utility.h \ + sg_unaligned.h popen_as_ugid.cpp popen_as_ugid.h \ os_win32/daemon_win32.cpp os_win32/daemon_win32.h \ os_win32/popen_win32.cpp os_win32/popen.h \ os_win32/syslog_win32.cpp os_win32/syslog.h getopt/getopt.c \ @@ -262,7 +265,8 @@ getopt/bits/getopt_core.h getopt/bits/getopt_ext.h \ regex/regex.c regex/regex.h regex/regex_internal.h csmisas.h \ os_win32/wmiquery.cpp os_win32/wmiquery.h -@OS_WIN32_MINGW_TRUE@am__objects_5 = daemon_win32.$(OBJEXT) \ +@OS_POSIX_TRUE@am__objects_5 = popen_as_ugid.$(OBJEXT) +@OS_WIN32_MINGW_TRUE@am__objects_6 = daemon_win32.$(OBJEXT) \ @OS_WIN32_MINGW_TRUE@ popen_win32.$(OBJEXT) \ @OS_WIN32_MINGW_TRUE@ syslog_win32.$(OBJEXT) am_smartd_OBJECTS = smartd.$(OBJEXT) atacmdnames.$(OBJEXT) \ @@ -271,7 +275,8 @@ dev_jmb39x_raid.$(OBJEXT) knowndrives.$(OBJEXT) \ nvmecmds.$(OBJEXT) scsicmds.$(OBJEXT) scsiata.$(OBJEXT) \ scsinvme.$(OBJEXT) utility.$(OBJEXT) $(am__objects_5) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) + $(am__objects_6) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) am__EXTRA_smartd_SOURCES_DIST = os_darwin.cpp os_darwin.h os_linux.cpp \ os_linux.h os_freebsd.cpp os_freebsd.h os_netbsd.cpp \ os_netbsd.h os_openbsd.cpp os_openbsd.h os_os2.cpp os_os2.h \ @@ -339,14 +344,14 @@ ./$(DEPDIR)/os_linux.Po ./$(DEPDIR)/os_netbsd.Po \ ./$(DEPDIR)/os_openbsd.Po ./$(DEPDIR)/os_os2.Po \ ./$(DEPDIR)/os_qnxnto.Po ./$(DEPDIR)/os_solaris.Po \ - ./$(DEPDIR)/os_win32.Po ./$(DEPDIR)/popen_win32.Po \ - ./$(DEPDIR)/regcomp.Po ./$(DEPDIR)/regex.Po \ - ./$(DEPDIR)/regex_internal.Po ./$(DEPDIR)/regexec.Po \ - ./$(DEPDIR)/scsiata.Po ./$(DEPDIR)/scsicmds.Po \ - ./$(DEPDIR)/scsinvme.Po ./$(DEPDIR)/scsiprint.Po \ - ./$(DEPDIR)/smartctl.Po ./$(DEPDIR)/smartd.Po \ - ./$(DEPDIR)/syslog_win32.Po ./$(DEPDIR)/utility.Po \ - ./$(DEPDIR)/wmiquery.Po + ./$(DEPDIR)/os_win32.Po ./$(DEPDIR)/popen_as_ugid.Po \ + ./$(DEPDIR)/popen_win32.Po ./$(DEPDIR)/regcomp.Po \ + ./$(DEPDIR)/regex.Po ./$(DEPDIR)/regex_internal.Po \ + ./$(DEPDIR)/regexec.Po ./$(DEPDIR)/scsiata.Po \ + ./$(DEPDIR)/scsicmds.Po ./$(DEPDIR)/scsinvme.Po \ + ./$(DEPDIR)/scsiprint.Po ./$(DEPDIR)/smartctl.Po \ + ./$(DEPDIR)/smartd.Po ./$(DEPDIR)/syslog_win32.Po \ + ./$(DEPDIR)/utility.Po ./$(DEPDIR)/wmiquery.Po am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -397,10 +402,10 @@ man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) -DATA = $(docs_DATA) $(drivedb_DATA) $(examples_DATA) $(initd_DATA) \ +DATA = $(docs_DATA) $(drivedbinst_DATA) $(examples_DATA) $(initd_DATA) \ $(sysconf_DATA) $(systemdsystemunit_DATA) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)config.h.in +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -417,9 +422,6 @@ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ COPYING ChangeLog INSTALL NEWS README TODO compile \ @@ -437,6 +439,8 @@ DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' @@ -457,8 +461,9 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CXX = @CXX@ -CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -468,9 +473,8 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ -EGREP = @EGREP@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -528,6 +532,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ drivedbdir = @drivedbdir@ +drivedbinstdir = @drivedbinstdir@ dvidir = @dvidir@ exampledir = @exampledir@ exec_prefix = @exec_prefix@ @@ -603,16 +608,16 @@ smartctl_SOURCES = smartctl.cpp smartctl.h atacmdnames.cpp \ atacmdnames.h atacmds.cpp atacmds.h ataidentify.cpp \ ataidentify.h ataprint.cpp ataprint.h dev_ata_cmd_set.cpp \ - dev_ata_cmd_set.h dev_intelliprop.cpp dev_intelliprop.h \ - dev_interface.cpp dev_interface.h dev_jmb39x_raid.cpp \ - dev_tunnelled.h drivedb.h json.cpp json.h knowndrives.cpp \ - knowndrives.h nvmecmds.cpp nvmecmds.h nvmeprint.cpp \ - nvmeprint.h scsicmds.cpp scsicmds.h scsiata.cpp scsinvme.cpp \ - scsiprint.cpp scsiprint.h static_assert.h utility.cpp \ - utility.h sg_unaligned.h $(am__append_7) $(am__append_13) \ - $(am__append_15) $(am__append_19) + dev_ata_cmd_set.h dev_intelliprop.cpp dev_interface.cpp \ + dev_interface.h dev_jmb39x_raid.cpp dev_tunnelled.h drivedb.h \ + json.cpp json.h knowndrives.cpp knowndrives.h nvmecmds.cpp \ + nvmecmds.h nvmeprint.cpp nvmeprint.h scsicmds.cpp scsicmds.h \ + scsiata.cpp scsinvme.cpp scsiprint.cpp scsiprint.h \ + static_assert.h utility.cpp utility.h sg_unaligned.h \ + $(am__append_7) $(am__append_14) $(am__append_16) \ + $(am__append_20) smartctl_LDADD = $(os_deps) $(os_libs) $(am__append_8) \ - $(am__append_21) + $(am__append_22) smartctl_DEPENDENCIES = $(os_deps) $(am__append_9) EXTRA_smartctl_SOURCES = os_darwin.cpp os_darwin.h os_linux.cpp \ os_linux.h os_freebsd.cpp os_freebsd.h os_netbsd.cpp \ @@ -620,19 +625,18 @@ os_qnxnto.cpp os_qnxnto.h os_solaris.cpp os_solaris.h \ os_win32.cpp os_generic.cpp os_generic.h aacraid.h cciss.cpp \ cciss.h cissio_freebsd.h dev_areca.cpp dev_areca.h \ - dev_legacy.cpp linux_nvme_ioctl.h megaraid.h $(am__append_17) + dev_legacy.cpp linux_nvme_ioctl.h megaraid.h $(am__append_18) smartd_SOURCES = smartd.cpp atacmdnames.cpp atacmdnames.h atacmds.cpp \ atacmds.h dev_ata_cmd_set.cpp dev_ata_cmd_set.h \ - dev_intelliprop.cpp dev_intelliprop.h dev_interface.cpp \ - dev_interface.h dev_jmb39x_raid.cpp dev_tunnelled.h drivedb.h \ - knowndrives.cpp knowndrives.h nvmecmds.cpp nvmecmds.h \ - scsicmds.cpp scsicmds.h scsiata.cpp scsinvme.cpp \ - static_assert.h utility.cpp utility.h sg_unaligned.h \ - $(am__append_10) $(am__append_14) $(am__append_16) \ - $(am__append_20) + dev_intelliprop.cpp dev_interface.cpp dev_interface.h \ + dev_jmb39x_raid.cpp dev_tunnelled.h drivedb.h knowndrives.cpp \ + knowndrives.h nvmecmds.cpp nvmecmds.h scsicmds.cpp scsicmds.h \ + scsiata.cpp scsinvme.cpp static_assert.h utility.cpp utility.h \ + sg_unaligned.h $(am__append_10) $(am__append_11) \ + $(am__append_15) $(am__append_17) $(am__append_21) smartd_LDADD = $(os_deps) $(os_libs) $(CAPNG_LDADD) $(SYSTEMD_LDADD) \ - $(am__append_11) $(am__append_22) -smartd_DEPENDENCIES = $(os_deps) $(am__append_12) + $(am__append_12) $(am__append_23) +smartd_DEPENDENCIES = $(os_deps) $(am__append_13) EXTRA_smartd_SOURCES = os_darwin.cpp os_darwin.h os_linux.cpp \ os_linux.h os_freebsd.cpp os_freebsd.h os_netbsd.cpp \ os_netbsd.h os_openbsd.cpp os_openbsd.h os_os2.cpp os_os2.h \ @@ -640,7 +644,7 @@ os_win32.cpp os_generic.cpp os_generic.h aacraid.h cciss.cpp \ cciss.h cissio_freebsd.h dev_areca.cpp dev_areca.h \ dev_legacy.cpp linux_nvme_ioctl.h freebsd_nvme_ioctl.h \ - netbsd_nvme_ioctl.h megaraid.h $(am__append_18) + netbsd_nvme_ioctl.h megaraid.h $(am__append_19) # Exclude from source tarball nodist_EXTRA_smartctl_SOURCES = os_solaris_ata.s @@ -652,10 +656,10 @@ # section 5). Automake can deal cleanly with man page sections 1-8 # and n, but NOT with sections of the form 1m. @OS_SOLARIS_TRUE@extra_MANS = smartd.conf.4 smartctl.1m smartd.1m \ -@OS_SOLARIS_TRUE@ $(am__append_23) +@OS_SOLARIS_TRUE@ $(am__append_24) # For systems that adopts traditional manner @OS_SOLARIS_FALSE@man_MANS = smartd.conf.5 smartctl.8 smartd.8 \ -@OS_SOLARIS_FALSE@ $(am__append_24) +@OS_SOLARIS_FALSE@ $(am__append_25) docsdir = $(docdir) docs_DATA = \ AUTHORS \ @@ -713,7 +717,7 @@ os_win32/smartd_mailer.conf.sample.ps1 \ os_win32/smartd_warning.cmd \ os_win32/syslogevt.mc \ - os_win32/update-smart-drivedb.nsi \ + os_win32/update-smart-drivedb.ps1.in \ os_win32/versioninfo.rc.in \ os_win32/wtssendmsg.c \ $(docs_DATA) \ @@ -730,7 +734,7 @@ update-smart-drivedb update-smart-drivedb.8 \ update-smart-drivedb.1m update-smart-drivedb.8.html \ update-smart-drivedb.8.html.tmp update-smart-drivedb.8.pdf \ - update-smart-drivedb.8.txt SMART $(am__append_27) + update-smart-drivedb.8.txt SMART $(am__append_28) # 'make maintainer-clean' also removes files generated by './autogen.sh' MAINTAINERCLEANFILES = \ @@ -747,7 +751,7 @@ $(srcdir)/missing \ $(srcdir)/m4/pkg.m4 -@ENABLE_DRIVEDB_TRUE@drivedb_DATA = drivedb.h +@ENABLE_DRIVEDB_TRUE@drivedbinst_DATA = drivedb.h @INSTALL_INITSCRIPT_TRUE@@OS_DARWIN_FALSE@initd_DATA = $(initdfile) @INSTALL_INITSCRIPT_TRUE@@OS_DARWIN_TRUE@initd_DATA = com.smartmontools.smartd.plist @INSTALL_INITSCRIPT_FALSE@initd_DATA_install = install-initdDATA-null @@ -779,10 +783,16 @@ -e 's|/usr/bin/mail|/usr/bin/$(os_mailer)|g' \ -e 's|RELEASE_6_0_DRIVEDB|$(DRIVEDB_BRANCH)|g' | \ if test -n '$(drivedbdir)'; then \ - sed 's|/usr/local/share/smartmontools/drivedb\.h|$(drivedbdir)/drivedb.h|g' ; \ + sed -e 's|/usr/local/share/smartmontools/drivedb\.h|$(drivedbinstdir)/drivedb.h|g' \ + -e 's|/usr/local/var/lib/smartmontools/drivedb\.h|$(drivedbdir)/drivedb.h|g' ; \ else \ sed '/^\.\\" %IF ENABLE_DRIVEDB/,/^\.\\" %ENDIF ENABLE_DRIVEDB/ s,^,.\\"\# ,' ; \ fi | \ + if test '$(drivedbinstdir)' != '$(drivedbdir)'; then \ + cat; \ + else \ + sed '/^\.\\" %IF ENABLE_DB_INSTALL/,/^\.\\" %ENDIF ENABLE_DB_INSTALL/ s,^,.\\"\# ,' ; \ + fi | \ if test '$(with_update_smart_drivedb)' = 'yes'; then \ cat; \ else \ @@ -900,7 +910,7 @@ @OS_WIN32_MINGW_TRUE@ $(exedir_win32)/runcmda.exe \ @OS_WIN32_MINGW_TRUE@ $(exedir_win32)/runcmdu.exe \ @OS_WIN32_MINGW_TRUE@ $(exedir_win32)/wtssendmsg.exe \ -@OS_WIN32_MINGW_TRUE@ $(am__append_25) +@OS_WIN32_MINGW_TRUE@ $(am__append_26) @OS_WIN32_MINGW_TRUE@FILES_WIN32 = $(EXEFILES_WIN32) \ @OS_WIN32_MINGW_TRUE@ $(docdir_win32)/AUTHORS.txt \ @OS_WIN32_MINGW_TRUE@ $(docdir_win32)/ChangeLog.txt \ @@ -918,13 +928,16 @@ @OS_WIN32_MINGW_TRUE@ $(docdir_win32)/smartd.8.pdf \ @OS_WIN32_MINGW_TRUE@ $(docdir_win32)/smartd.conf.5.html \ @OS_WIN32_MINGW_TRUE@ $(docdir_win32)/smartd.conf.5.pdf \ -@OS_WIN32_MINGW_TRUE@ $(am__append_26) +@OS_WIN32_MINGW_TRUE@ $(am__append_27) # Note: Only use without options to be compatible with all variants @OS_WIN32_MINGW_TRUE@UNIX2DOS = unix2dos -# Build os_win32/vc14/{config.h,smart*.rc,svnversion.h} for MSVC14 from MinGW files -@OS_WIN32_MINGW_TRUE@vcver = 14 +# MSVC Version to change in make command line +@OS_WIN32_MINGW_TRUE@vc = 16 +@OS_WIN32_MINGW_TRUE@vcver = $(vc) + +# Build os_win32/vcNN/{config.h,smart*.rc,svnversion.h} for MSVC14/15/16 from MinGW files @OS_WIN32_MINGW_TRUE@CONFIG_VC_FILES = \ @OS_WIN32_MINGW_TRUE@ $(srcdir)/os_win32/vc$(vcver)/config.h \ @OS_WIN32_MINGW_TRUE@ $(srcdir)/os_win32/vc$(vcver)/smartctl_res.rc \ @@ -1179,6 +1192,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_qnxnto.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_solaris.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_win32.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popen_as_ugid.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popen_win32.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Po@am__quote@ # am--include-marker @@ -1480,27 +1494,27 @@ @list='$(docs_DATA)'; test -n "$(docsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docsdir)'; $(am__uninstall_files_from_dir) -install-drivedbDATA: $(drivedb_DATA) +install-drivedbinstDATA: $(drivedbinst_DATA) @$(NORMAL_INSTALL) - @list='$(drivedb_DATA)'; test -n "$(drivedbdir)" || list=; \ + @list='$(drivedbinst_DATA)'; test -n "$(drivedbinstdir)" || list=; \ if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(drivedbdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(drivedbdir)" || exit 1; \ + echo " $(MKDIR_P) '$(DESTDIR)$(drivedbinstdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(drivedbinstdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(drivedbdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(drivedbdir)" || exit $$?; \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(drivedbinstdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(drivedbinstdir)" || exit $$?; \ done -uninstall-drivedbDATA: +uninstall-drivedbinstDATA: @$(NORMAL_UNINSTALL) - @list='$(drivedb_DATA)'; test -n "$(drivedbdir)" || list=; \ + @list='$(drivedbinst_DATA)'; test -n "$(drivedbinstdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(drivedbdir)'; $(am__uninstall_files_from_dir) + dir='$(DESTDIR)$(drivedbinstdir)'; $(am__uninstall_files_from_dir) install-examplesDATA: $(examples_DATA) @$(NORMAL_INSTALL) @list='$(examples_DATA)'; test -n "$(examplesdir)" || list=; \ @@ -1602,7 +1616,6 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files - distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -1661,6 +1674,10 @@ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @@ -1703,6 +1720,8 @@ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) @@ -1718,7 +1737,7 @@ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ @@ -1775,7 +1794,7 @@ all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) config.h \ all-local installdirs: installdirs-local - for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(examplesdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(smartdscriptdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docsdir)" "$(DESTDIR)$(drivedbdir)" "$(DESTDIR)$(examplesdir)" "$(DESTDIR)$(initddir)" "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \ + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(examplesdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(smartdscriptdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docsdir)" "$(DESTDIR)$(drivedbinstdir)" "$(DESTDIR)$(examplesdir)" "$(DESTDIR)$(initddir)" "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -1844,6 +1863,7 @@ -rm -f ./$(DEPDIR)/os_qnxnto.Po -rm -f ./$(DEPDIR)/os_solaris.Po -rm -f ./$(DEPDIR)/os_win32.Po + -rm -f ./$(DEPDIR)/popen_as_ugid.Po -rm -f ./$(DEPDIR)/popen_win32.Po -rm -f ./$(DEPDIR)/regcomp.Po -rm -f ./$(DEPDIR)/regex.Po @@ -1875,7 +1895,7 @@ info-am: install-data-am: install-data-local install-docsDATA \ - install-drivedbDATA install-examplesDATA \ + install-drivedbinstDATA install-examplesDATA \ install-examplesSCRIPTS install-initdDATA install-man \ install-smartdscriptSCRIPTS install-systemdsystemunitDATA @@ -1937,6 +1957,7 @@ -rm -f ./$(DEPDIR)/os_qnxnto.Po -rm -f ./$(DEPDIR)/os_solaris.Po -rm -f ./$(DEPDIR)/os_win32.Po + -rm -f ./$(DEPDIR)/popen_as_ugid.Po -rm -f ./$(DEPDIR)/popen_win32.Po -rm -f ./$(DEPDIR)/regcomp.Po -rm -f ./$(DEPDIR)/regex.Po @@ -1966,7 +1987,7 @@ ps-am: -uninstall-am: uninstall-docsDATA uninstall-drivedbDATA \ +uninstall-am: uninstall-docsDATA uninstall-drivedbinstDATA \ uninstall-examplesDATA uninstall-examplesSCRIPTS \ uninstall-initdDATA uninstall-man uninstall-sbinPROGRAMS \ uninstall-sbinSCRIPTS uninstall-smartdscriptSCRIPTS \ @@ -1980,23 +2001,23 @@ check check-am clean clean-cscope clean-generic \ clean-sbinPROGRAMS cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ - dist-xz dist-zip distcheck distclean distclean-compile \ - distclean-generic distclean-hdr distclean-tags distcleancheck \ - distdir distuninstallcheck dvi dvi-am html html-am info \ - info-am install install-am install-data install-data-am \ - install-data-local install-docsDATA install-drivedbDATA \ - install-dvi install-dvi-am install-examplesDATA \ - install-examplesSCRIPTS install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-initdDATA install-man install-man5 install-man8 \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-sbinPROGRAMS install-sbinSCRIPTS \ - install-smartdscriptSCRIPTS install-strip install-sysconfDATA \ - install-systemdsystemunitDATA installcheck installcheck-am \ - installdirs installdirs-local maintainer-clean \ + dist-xz dist-zip dist-zstd distcheck distclean \ + distclean-compile distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-data-local \ + install-docsDATA install-drivedbinstDATA install-dvi \ + install-dvi-am install-examplesDATA install-examplesSCRIPTS \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-initdDATA install-man \ + install-man5 install-man8 install-pdf install-pdf-am \ + install-ps install-ps-am install-sbinPROGRAMS \ + install-sbinSCRIPTS install-smartdscriptSCRIPTS install-strip \ + install-sysconfDATA install-systemdsystemunitDATA installcheck \ + installcheck-am installdirs installdirs-local maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-docsDATA uninstall-drivedbDATA \ + uninstall-am uninstall-docsDATA uninstall-drivedbinstDATA \ uninstall-examplesDATA uninstall-examplesSCRIPTS \ uninstall-initdDATA uninstall-man uninstall-man5 \ uninstall-man8 uninstall-sbinPROGRAMS uninstall-sbinSCRIPTS \ @@ -2141,7 +2162,7 @@ # Create empty directories if configured. # Default install rules no longer create empty directories since automake 1.11. installdirs-local: - @for d in '$(smartdplugindir)' '$(savestatesdir)' '$(attributelogdir)'; do \ + @for d in '$(smartdplugindir)' '$(drivedbdir)' '$(savestatesdir)' '$(attributelogdir)'; do \ test -n "$$d" || continue; \ echo " $(MKDIR_P) '$(DESTDIR)$$d'"; \ $(MKDIR_P) "$(DESTDIR)$$d" || exit 1; \ @@ -2212,7 +2233,8 @@ # Check drive database syntax check: - @if ./smartctl -B $(srcdir)/drivedb.h -P showall >/dev/null; then \ + @if ./smartctl -P showall >/dev/null && \ + ./smartctl -B $(srcdir)/drivedb.h -P showall >/dev/null; then \ echo "$(srcdir)/drivedb.h: OK"; \ else \ echo "$(srcdir)/drivedb.h: Syntax check failed"; exit 1; \ @@ -2302,10 +2324,6 @@ @OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ sha1sum $@ > $@.sha1 @OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ sha256sum $@ > $@.sha256 -# Build drivedb.h update tool -@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@update-smart-drivedb.exe: os_win32/update-smart-drivedb.nsi -@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ "$(MAKENSIS)" -V2 -NOCD -DBRANCH=$(DRIVEDB_BRANCH) $< - @OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_FALSE@$(distinst_win32): @OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_FALSE@ @echo "makensis: command not found. Please install NSIS from http://nsis.sourceforge.net/" 1>&2 @OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_FALSE@ @exit 1 @@ -2323,10 +2341,6 @@ @OS_WIN32_MINGW_TRUE@ if test -n '$(STRIP)'; then $(STRIP) -s $@; else strip -s $@; fi @OS_WIN32_MINGW_TRUE@ touch -r $< $@ -# strip would break NSIS integrity check -@OS_WIN32_MINGW_TRUE@$(exedir_win32)/update-smart-drivedb.exe: update-smart-drivedb.exe -@OS_WIN32_MINGW_TRUE@ cp -p $< $@ - @OS_WIN32_MINGW_TRUE@$(exedir_win32)/%.h: $(srcdir)/%.h @OS_WIN32_MINGW_TRUE@ $(UNIX2DOS) < $< > $@ @OS_WIN32_MINGW_TRUE@ touch -r $< $@ @@ -2339,6 +2353,10 @@ @OS_WIN32_MINGW_TRUE@ $(UNIX2DOS) < $< > $@ @OS_WIN32_MINGW_TRUE@ touch -r $< $@ +@OS_WIN32_MINGW_TRUE@$(exedir_win32)/%.ps1: %.ps1 +@OS_WIN32_MINGW_TRUE@ $(UNIX2DOS) < $< > $@ +@OS_WIN32_MINGW_TRUE@ touch -r $< $@ + @OS_WIN32_MINGW_TRUE@$(docdir_win32)/%.html: %.html @OS_WIN32_MINGW_TRUE@ $(UNIX2DOS) < $< > $@ @OS_WIN32_MINGW_TRUE@ touch -r $< $@ @@ -2387,11 +2405,24 @@ @OS_WIN32_MINGW_TRUE@wtssendmsg.exe: os_win32/wtssendmsg.c wtssendmsg_res.o @OS_WIN32_MINGW_TRUE@ $(CC) -Os -o $@ $^ -lwtsapi32 -@OS_WIN32_MINGW_TRUE@config-vc$(vcver): $(CONFIG_VC_FILES) +# Build drivedb.h update script +@OS_WIN32_MINGW_TRUE@update-smart-drivedb.ps1: os_win32/update-smart-drivedb.ps1.in config.status +@OS_WIN32_MINGW_TRUE@ $(SHELL) ./config.status --file=$@:$< + +@OS_WIN32_MINGW_TRUE@.PHONY: check-vc-version clean-vc config-vc distclean-vc maintainer-clean-vc + +@OS_WIN32_MINGW_TRUE@check-vc-version: +@OS_WIN32_MINGW_TRUE@ @case '$(vcver)' in \ +@OS_WIN32_MINGW_TRUE@ 14|15|16) test -d '$(srcdir)/os_win32/vc$(vcver)' || \ +@OS_WIN32_MINGW_TRUE@ { echo '$(srcdir)/os_win32/vc$(vcver): Not found (not included in src tarball)' >&2; exit 1; } ;; \ +@OS_WIN32_MINGW_TRUE@ *) echo 'Usage: $(MAKE) vc=14|15|16 config-vc clean-vc distclean-vc maintainer-clean-vc'; exit 1 ;; \ +@OS_WIN32_MINGW_TRUE@ esac + +@OS_WIN32_MINGW_TRUE@config-vc: check-vc-version $(CONFIG_VC_FILES) @OS_WIN32_MINGW_TRUE@$(srcdir)/os_win32/vc$(vcver)/config.h: config.h Makefile @OS_WIN32_MINGW_TRUE@ sed -e '1i/* os_win32/vc$(vcver)/config.h. Generated from config.h by Makefile. */' \ -@OS_WIN32_MINGW_TRUE@ -e 's,^#define HAVE_\(ATTR_PACKED\|GETTIMEOFDAY\|[DK_]*NTDDDISK_H\|LONG_DOUBLE_WIDER\|STRINGS_H\|UNISTD_H\) 1$$,/* #undef HAVE_\1 */ /* VC$(vcver) */,' \ +@OS_WIN32_MINGW_TRUE@ -e 's,^#define HAVE_\(ATTR_PACKED\|CLOCK_GETTIME\|GETTIMEOFDAY\|LONG_DOUBLE_WIDER\|STRINGS_H\|UNISTD_H\) 1$$,/* #undef HAVE_\1 */ /* VC$(vcver) */,' \ @OS_WIN32_MINGW_TRUE@ -e 's,^\(#define SMARTMONTOOLS_BUILD_HOST "[^-]*\)[^"]*,\1-pc-w32vc$(vcver),' $< > $@ @OS_WIN32_MINGW_TRUE@$(srcdir)/os_win32/vc$(vcver)/svnversion.h: svnversion.h @@ -2403,18 +2434,23 @@ @OS_WIN32_MINGW_TRUE@$(srcdir)/os_win32/vc$(vcver)/smartd_res.rc: smartd_res.rc @OS_WIN32_MINGW_TRUE@ sed '/^1 24 /d' $< > $@ -@OS_WIN32_MINGW_TRUE@clean-vc$(vcver): +# VC14: smartmontools.VC.*, VC15/16: .vs/smartmontools/vNN/* +@OS_WIN32_MINGW_TRUE@clean-vc: check-vc-version @OS_WIN32_MINGW_TRUE@ rm -f $(srcdir)/os_win32/vc$(vcver)/smartmontools.VC.VC.opendb @OS_WIN32_MINGW_TRUE@ rm -f $(srcdir)/os_win32/vc$(vcver)/smartmontools.VC.db +@OS_WIN32_MINGW_TRUE@ rm -f $(srcdir)/os_win32/vc$(vcver)/.vs/smartmontools/v$(vcver)/Browse.VC.opendb +@OS_WIN32_MINGW_TRUE@ rm -f $(srcdir)/os_win32/vc$(vcver)/.vs/smartmontools/v$(vcver)/*.VC.db* +@OS_WIN32_MINGW_TRUE@ rm -rf $(srcdir)/os_win32/vc$(vcver)/.vs/smartmontools/v$(vcver)/ipch @OS_WIN32_MINGW_TRUE@ rm -f $(srcdir)/os_win32/vc$(vcver)/syslogevt.h @OS_WIN32_MINGW_TRUE@ rm -rf $(srcdir)/os_win32/vc$(vcver)/Debug @OS_WIN32_MINGW_TRUE@ rm -rf $(srcdir)/os_win32/vc$(vcver)/Release @OS_WIN32_MINGW_TRUE@ rm -rf $(srcdir)/os_win32/vc$(vcver)/x64 -@OS_WIN32_MINGW_TRUE@distclean-vc$(vcver): clean-vc$(vcver) +@OS_WIN32_MINGW_TRUE@distclean-vc: clean-vc @OS_WIN32_MINGW_TRUE@ rm -f $(CONFIG_VC_FILES) -@OS_WIN32_MINGW_TRUE@maintainer-clean-vc$(vcver): distclean-vc$(vcver) +@OS_WIN32_MINGW_TRUE@maintainer-clean-vc: distclean-vc +@OS_WIN32_MINGW_TRUE@ rm -f $(srcdir)/os_win32/vc$(vcver)/*.vcxproj.user @OS_WIN32_MINGW_TRUE@ rm -rf $(srcdir)/os_win32/vc$(vcver)/.vs # build darwin installer diff -Nru smartmontools-7.1/missing smartmontools-7.3/missing --- smartmontools-7.1/missing 2019-12-30 15:01:06.000000000 +0000 +++ smartmontools-7.3/missing 2022-02-28 16:34:38.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify diff -Nru smartmontools-7.1/NEWS smartmontools-7.3/NEWS --- smartmontools-7.1/NEWS 2019-12-30 15:00:49.000000000 +0000 +++ smartmontools-7.3/NEWS 2022-02-28 16:34:27.000000000 +0000 @@ -1,10 +1,119 @@ smartmontools NEWS ------------------ -$Id: NEWS 5022 2019-12-30 15:00:49Z chrfranke $ +$Id: NEWS 5338 2022-02-28 16:34:26Z chrfranke $ The most up-to-date version of this file is: https://www.smartmontools.org/browser/trunk/smartmontools/NEWS +Date 2022-02-28 +Summary: smartmontools release 7.3 +----------------------------------------------------------- +- smartctl '-j': Many additions to the JSON output for SCSI/SAS devices. +- smartctl '-j': JSON output always includes timestamp, regardless of '-i'. +- smartctl '-i' and '--identify': ATA ACS-5 enhancements. +- smartctl '-l defects': additionally works for SCSI Pending Defects log + subpage. +- smartctl '-l envrep': Prints SCSI Environmental Reporting log subpage. +- smartctl '-l scterc[,R,W],p': Gets/sets the persistent power-on values. +- smartctl '-l scterc,reset': Restores to manufacturer's default values. +- smartctl '-l tapedevstat': Prints SCSI Tape Device Statistics log page. +- smartctl '-l tapealert': Prints SCSI Tape Alert log page. +- smartctl '-l zdevstat': Prints SCSI Zoned Block Device Statistics log + subpage. +- smartctl '-H': No longer checks and clears the SCSI Tape Alert log page + unless the option is given twice. +- smartctl '-H': No longer sets bit 2 of exit status if ATA attributes are + available. +- smartctl '-H': Checks new NVME 1.4 status bit. +- smartctl '-n POWERMODE': ATA: Optionally exits immediately if unsupported. +- smartctl: Support for Zoned block device characteristics and statistics. +- smartctl: Various fixes related to SCSI supported log pages and subpages. +- smartd: Fixed code execution vulnerability in conjunction with + GNU mailutils < 3.13. +- smartd '-u USER[:GROUP]': Runs the warning script as a non-privileged user. +- smartd '--capabilities': No longer suppresses mail notification. +- smartd '--capabilities=mail': Adds capabilities required for exim MTA. +- smartd '-q *nodev0*': Three new options to change the exit status to 0 if + there are no devices to monitor. +- smartd '-s' and '-A': Allows one to disable preconfigured files with '-'. +- smartd: Fixed handling of multiple email addresses in conjunction with + plugin scripts. Added new environment variable SMARTD_ADDRESS_ORIG. +- smartd: No longer writes 'smartd -D' output to syslog on syntax error. +- smartd.conf '-c i=N': Allows one to specify device specific check intervals. +- SCSI: Retry on UNIT ATTENTION when fetching capacity. +- NVMe/USB: Device type '-d sntasmedia' for ASMedia ASM2362 USB to + NVMe bridges. +- VERSION information in drive database files of all branches. +- smartctl and smartd print drive database VERSION information. +- HDD, SSD and USB additions to drive database. +- update-smart-drivedb: Now checks VERSION information to prevent downgrades. +- update-smart-drivedb '--force': Overrides the VERSION check. +- update-smart-drivedb '--file' and '--url': Updates from local files or + other URLs. +- update-smart-drivedb '-q': Suppresses info messages. +- update-smart-drivedb: Added long option variants for all short options. +- update-smart-drivedb: Prevents dangling gpg-agents and temp directories. +- update-smart-drivedb '--install': Installs runtime drivedb.h from location + specified by ... +- configure '--with-drivedbinstdir: drivedb.h package install location. +- configure: SOURCE_DATE_EPOCH prevents inclusion of configure arguments + in executables. +- configure: Check for '-fstack-protector' now includes the required libs. +- Dropped restriction to C++98, a C++11 compiler is now required. +- Linux: Device scan range enhanced to '/dev/sdzz'. +- Linux: Fixed access to '-d aacraid' and '-d megaraid' devices from smartd + if '--capabilities' is used. +- Linux: '-d cciss,N' is no longer required for non-RAID hpsa devices. +- Darwin: smartctl '-s apm,N' is now supported. +- OpenBSD: Fixed too short command timeouts. +- OpenBSD: Fixed device name used for autodetection. +- OpenBSD: Fixed SAT autodetection of sd* devices. +- FreeBSD: Added direct access ('-d megaraid,N') and scanning for LSI RAID on + 'mfi' and 'mrsas' controllers. +- Windows: smartd '-u restricted': Runs the warning script with a restricted + access token. +- Windows: New script 'update-smartd-drivedb.ps1' provides gpg verification + and replaces 'update-smartd-drivedb.exe'. +- Windows: Disabled '-d aacraid' support due to unresolved bugs. + Added '-d accraid,...,force' flag to try anyway. + +Date 2020-12-30 +Summary: smartmontools release 7.2 +----------------------------------------------------------- +- smartctl: New option '--json=y[c]' selects YAML output. +- smartctl '-i': Prints ATA TRIM and Zoned Device capabilities. +- smartctl '-j': Fixed 'scsi_grown_defect_list' value. +- smartctl '-a': Prints SCSI 'Accumulated power on time'. +- smartctl '-n POWERMODE': SCSI support. +- smartctl '-s standby,now' and '-s standby,off': SCSI support. +- smartctl '-c': NVMe 1.4 additions. +- smartd: Support for staggered self-tests. +- smartd: No longer writes attribute log if no attributes were read + due to standby mode or other error. +- smartd: Now resolves symlinks before device names are checked for + duplicates. +- smartd: Fixed SMARTD_DEVICETYPE environment variable if DEVICESCAN is + used without '-d TYPE'. +- ATA: Device type '-d jmb39x-q,N' for JMB39x protocol variant used by + some QNAP NAS devices. +- ATA: Device type '-d jms56x,N' for JMS562 USB to SATA RAID bridges. +- SCSI: Improved heuristics for log subpages of new and very old disks. +- NVMe: Log transfer size limited to avoid device or kernel crashes. +- NVMe/USB: Device type '-d sntrealtek' for Realtek RTL9210 USB to + NVMe bridges. +- update-smart-drivedb: New option '--branch X.Y'. +- HDD, SSD and USB additions to drive database. +- Dropped support for pre-C99 snprintf(). +- configure: Dropped option '--without-working-snprintf'. +- configure: Fixed '-fstack-protector*' detection. +- Linux: Various fixes of smartd.service file. +- Darwin: NVMe log support. +- FreeBSD: Device scan does no longer include T_ENCLOSURE devices. +- NetBSD: Fixed timeout handling. +- NetBSD big endian: Fixed ATA register handling. +- OpenBSD: Fixed timeout handling. +- Windows: Dropped backward compatibility fixes for very old compilers. + Date 2019-12-30 Summary: smartmontools release 7.1 ----------------------------------------------------------- @@ -154,7 +263,7 @@ - Optional NVMe device scanning support on Linux and Windows. - configure option '--with-nvme-devicescan' to include NVMe in default device scanning result. -- Device scanning now allows to specify multiple '-d TYPE' options. +- Device scanning now allows one to specify multiple '-d TYPE' options. - ATA: Added new POWER MODE values introduced in ATA ACS-2. - ATA: SCT commands are no longer issued if ATA Security is locked. - SCSI: LB provisioning improvements. @@ -264,7 +373,7 @@ - smartctl '-s/-g wcache' for SCSI devices to control write cache. - smartctl '-s/-g rcache' for SCSI devices to control read cache. - smartctl prints more info for SCSI devices: media rotation rate, - form factor, physical block size, lowest LBA alignement, + form factor, physical block size, lowest LBA alignment, logical block provisioning, disk protection type and selftest progress status. - smartctl '--identify' updated for latest ATA ACS-3 spec. @@ -400,7 +509,7 @@ Summary: smartmontools release 5.40 ----------------------------------------------------------- - Other config entries may precede smartd DEVICESCAN. -- Option '-v' allows to specify byte order of attribute raw value +- Option '-v' allows one to specify byte order of attribute raw value - configure: New default value for '--with-docdir'. - configure: '--enable-drivedb' is now the default. - Improved support for Intel SSDs. @@ -730,8 +839,8 @@ ----------------------------------- This is the first release of smartmontools based on autoconf/automake. For this reason, it is a very experimental release. Please let us -know in particular about documenation errors/omissions, missing or -unneccesary files, and similar oversights. The major changes are: +know in particular about documentation errors/omissions, missing or +unnecessary files, and similar oversights. The major changes are: [1] installation scripts based on autoconfig/automake [2] ./configure [options] lets you set arbitrary paths [3] supports FHS with ./configure --prefix=/usr/local diff -Nru smartmontools-7.1/nvmecmds.cpp smartmontools-7.3/nvmecmds.cpp --- smartmontools-7.1/nvmecmds.cpp 2019-07-01 20:54:14.000000000 +0000 +++ smartmontools-7.3/nvmecmds.cpp 2021-06-04 16:39:50.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2016-19 Christian Franke + * Copyright (C) 2016-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,7 +11,7 @@ #include "config.h" #include "nvmecmds.h" -const char * nvmecmds_cvsid = "$Id: nvmecmds.cpp 4934 2019-07-01 20:54:14Z chrfranke $" +const char * nvmecmds_cvsid = "$Id: nvmecmds.cpp 5219 2021-06-04 16:39:50Z chrfranke $" NVMECMDS_H_CVSID; #include "dev_interface.h" @@ -19,6 +19,8 @@ #include "scsicmds.h" // dStrHex() #include "utility.h" +#include + using namespace smartmontools; // Print NVMe debug messages? @@ -51,8 +53,6 @@ static bool nvme_pass_through(nvme_device * device, const nvme_cmd_in & in, nvme_cmd_out & out) { - int64_t start_usec = -1; - if (nvme_debugmode) { pout(" [NVMe call: opcode=0x%02x, size=0x%04x, nsid=0x%08x, cdw10=0x%08x", in.opcode, in.size, in.nsid, in.cdw10); @@ -60,12 +60,18 @@ pout(",\n cdw1x=0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x", in.cdw11, in.cdw12, in.cdw13, in.cdw14, in.cdw15); pout("]\n"); - - start_usec = smi()->get_timer_usec(); } + auto start_usec = (nvme_debugmode ? get_timer_usec() : -1); + bool ok = device->nvme_pass_through(in, out); + if (start_usec >= 0) { + auto duration_usec = get_timer_usec() - start_usec; + if (duration_usec > 0) + pout(" [Duration: %.6fs]\n", duration_usec / 1000000.0); + } + if ( dont_print_serial_number && ok && in.opcode == nvme_admin_identify && in.cdw10 == 0x01) { // Invalidate serial number @@ -74,12 +80,6 @@ } if (nvme_debugmode) { - if (start_usec >= 0) { - int64_t duration_usec = smi()->get_timer_usec() - start_usec; - if (duration_usec >= 500) - pout(" [Duration: %.3fs]\n", duration_usec / 1000000.0); - } - if (!ok) { pout(" [NVMe call failed: "); if (out.status_valid) @@ -132,6 +132,7 @@ swapx(&id_ctrl.vid); swapx(&id_ctrl.ssvid); swapx(&id_ctrl.cntlid); + swapx(&id_ctrl.ver); swapx(&id_ctrl.oacs); swapx(&id_ctrl.wctemp); swapx(&id_ctrl.cctemp); @@ -181,30 +182,54 @@ return true; } -// Read NVMe log page with identifier LID. -bool nvme_read_log_page(nvme_device * device, unsigned char lid, void * data, - unsigned size, bool broadcast_nsid) +static bool nvme_read_log_page_1(nvme_device * device, unsigned nsid, + unsigned char lid, void * data, unsigned size, unsigned offset = 0) { - if (!(4 <= size && size <= 0x4000 && (size % 4) == 0)) - throw std::logic_error("nvme_read_log_page(): invalid size"); + if (!(4 <= size && size <= 0x1000 && !(size % 4) && !(offset % 4))) + return device->set_err(EINVAL, "Invalid NVMe log size %u or offset %u", size, offset); memset(data, 0, size); nvme_cmd_in in; in.set_data_in(nvme_admin_get_log_page, data, size); - in.nsid = broadcast_nsid ? 0xffffffff : device->get_nsid(); + in.nsid = nsid; in.cdw10 = lid | (((size / 4) - 1) << 16); + in.cdw12 = offset; // LPOL, NVMe 1.2.1 return nvme_pass_through(device, in); } +// Read NVMe log page with identifier LID. +unsigned nvme_read_log_page(nvme_device * device, unsigned nsid, unsigned char lid, + void * data, unsigned size, bool lpo_sup, unsigned offset /* = 0 */) +{ + unsigned n, bs; + for (n = 0; n < size; n += bs) { + if (!lpo_sup && offset + n > 0) { + device->set_err(ENOSYS, "Log Page Offset not supported"); + break; + } + + // Limit transfer size to one page to avoid problems with + // limits of NVMe pass-through layer or too low MDTS values. + bs = size - n; + if (bs > 0x1000) + bs = 0x1000; + if (!nvme_read_log_page_1(device, nsid, lid, (char *)data + n, bs, offset + n)) + break; + } + + return n; +} + // Read NVMe Error Information Log. -bool nvme_read_error_log(nvme_device * device, nvme_error_log_page * error_log, unsigned num_entries) +unsigned nvme_read_error_log(nvme_device * device, nvme_error_log_page * error_log, + unsigned num_entries, bool lpo_sup) { - if (!nvme_read_log_page(device, 0x01, error_log, num_entries * sizeof(*error_log), true)) - return false; + unsigned n = nvme_read_log_page(device, 0xffffffff, 0x01, error_log, + num_entries * sizeof(*error_log), lpo_sup); if (isbigendian()) { - for (unsigned i = 0; i < num_entries; i++) { + for (unsigned i = 0; i < n; i++) { swapx(&error_log[i].error_count); swapx(&error_log[i].sqid); swapx(&error_log[i].cmdid); @@ -215,13 +240,13 @@ } } - return true; + return n / sizeof(*error_log); } // Read NVMe SMART/Health Information log. bool nvme_read_smart_log(nvme_device * device, nvme_smart_log & smart_log) { - if (!nvme_read_log_page(device, 0x02, &smart_log, sizeof(smart_log), true)) + if (!nvme_read_log_page_1(device, 0xffffffff, 0x02, &smart_log, sizeof(smart_log))) return false; if (isbigendian()) { diff -Nru smartmontools-7.1/nvmecmds.h smartmontools-7.3/nvmecmds.h --- smartmontools-7.1/nvmecmds.h 2019-07-01 20:54:14.000000000 +0000 +++ smartmontools-7.3/nvmecmds.h 2020-12-04 20:40:43.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2016-19 Christian Franke + * Copyright (C) 2016-20 Christian Franke * * Original code from : * Copyright (C) 2011-2014 Intel Corporation @@ -14,7 +14,7 @@ #ifndef NVMECMDS_H #define NVMECMDS_H -#define NVMECMDS_H_CVSID "$Id: nvmecmds.h 4934 2019-07-01 20:54:14Z chrfranke $" +#define NVMECMDS_H_CVSID "$Id: nvmecmds.h 5124 2020-12-04 20:40:43Z chrfranke $" #include "static_assert.h" @@ -236,12 +236,12 @@ bool nvme_read_id_ns(nvme_device * device, unsigned nsid, smartmontools::nvme_id_ns & id_ns); // Read NVMe log page with identifier LID. -bool nvme_read_log_page(nvme_device * device, unsigned char lid, void * data, - unsigned size, bool broadcast_nsid); +unsigned nvme_read_log_page(nvme_device * device, unsigned nsid, unsigned char lid, + void * data, unsigned size, bool lpo_sup, unsigned offset = 0); // Read NVMe Error Information Log. -bool nvme_read_error_log(nvme_device * device, smartmontools::nvme_error_log_page * error_log, - unsigned num_entries); +unsigned nvme_read_error_log(nvme_device * device, smartmontools::nvme_error_log_page * error_log, + unsigned num_entries, bool lpo_sup); // Read NVMe SMART/Health Information log. bool nvme_read_smart_log(nvme_device * device, smartmontools::nvme_smart_log & smart_log); diff -Nru smartmontools-7.1/nvmeprint.cpp smartmontools-7.3/nvmeprint.cpp --- smartmontools-7.1/nvmeprint.cpp 2018-12-16 18:09:44.000000000 +0000 +++ smartmontools-7.3/nvmeprint.cpp 2021-06-04 15:46:36.000000000 +0000 @@ -1,9 +1,9 @@ /* * nvmeprint.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2016-18 Christian Franke + * Copyright (C) 2016-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -13,7 +13,7 @@ #include "nvmeprint.h" -const char * nvmeprint_cvsid = "$Id: nvmeprint.cpp 4859 2018-12-16 18:09:44Z chrfranke $" +const char * nvmeprint_cvsid = "$Id: nvmeprint.cpp 5218 2021-06-04 15:46:36Z chrfranke $" NVMEPRINT_H_CVSID; #include "utility.h" @@ -57,6 +57,7 @@ else { // More than 64-bit, prepend '~' flag on low precision int i = 0; + // cppcheck-suppress knownConditionTrueFalse if (uint128_to_str_precision_bits() < 128) str[i++] = '~'; uint128_hilo_to_str(str + i, (int)sizeof(str) - i, hi, lo); @@ -144,6 +145,17 @@ jout("Controller ID: %d\n", id_ctrl.cntlid); jglb["nvme_controller_id"] = id_ctrl.cntlid; + if (id_ctrl.ver) { // NVMe 1.2 + int i = snprintf(buf, sizeof(buf), "%u.%u", id_ctrl.ver >> 16, (id_ctrl.ver >> 8) & 0xff); + if (i > 0 && (id_ctrl.ver & 0xff)) + snprintf(buf+i, sizeof(buf)-i, ".%u", id_ctrl.ver & 0xff); + } + else + snprintf(buf, sizeof(buf), "<1.2"); + jout("NVMe Version: %s\n", buf); + jglb["nvme_version"]["string"] = buf; + jglb["nvme_version"]["value"] = id_ctrl.ver; + // Print namespace info if available jout("Number of Namespaces: %u\n", id_ctrl.nn); jglb["nvme_number_of_namespaces"] = id_ctrl.nn; @@ -189,11 +201,10 @@ } } - time_t now = time(0); - char td[DATEANDEPOCHLEN]; dateandtimezoneepoch(td, now); - jout("Local Time is: %s\n", td); - jglb["local_time"]["time_t"] = now; - jglb["local_time"]["asctime"] = td; + // SMART/Health Information is mandatory + jglb["smart_support"] += { {"available", true}, {"enabled", true} }; + + jout_startup_datetime("Local Time is: "); } // Format scaled power value. @@ -221,30 +232,42 @@ ((id_ctrl.frmw & 0x10) ? ", no Reset required" : "")); if (show_all || id_ctrl.oacs) - pout("Optional Admin Commands (0x%04x): %s%s%s%s%s%s%s%s%s%s%s\n", id_ctrl.oacs, + pout("Optional Admin Commands (0x%04x): %s%s%s%s%s%s%s%s%s%s%s%s\n", id_ctrl.oacs, (!id_ctrl.oacs ? " -" : ""), ((id_ctrl.oacs & 0x0001) ? " Security" : ""), ((id_ctrl.oacs & 0x0002) ? " Format" : ""), ((id_ctrl.oacs & 0x0004) ? " Frmw_DL" : ""), - ((id_ctrl.oacs & 0x0008) ? " NS_Mngmt" : ""), + ((id_ctrl.oacs & 0x0008) ? " NS_Mngmt" : ""), // NVMe 1.2 ((id_ctrl.oacs & 0x0010) ? " Self_Test" : ""), // NVMe 1.3 ... ((id_ctrl.oacs & 0x0020) ? " Directvs" : ""), ((id_ctrl.oacs & 0x0040) ? " MI_Snd/Rec" : ""), ((id_ctrl.oacs & 0x0080) ? " Vrt_Mngmt" : ""), ((id_ctrl.oacs & 0x0100) ? " Drbl_Bf_Cfg" : ""), - ((id_ctrl.oacs & ~0x01ff) ? " *Other*" : "")); + ((id_ctrl.oacs & 0x0200) ? " Get_LBA_Sts" : ""), // NVMe 1.4 + ((id_ctrl.oacs & ~0x03ff) ? " *Other*" : "")); if (show_all || id_ctrl.oncs) - pout("Optional NVM Commands (0x%04x): %s%s%s%s%s%s%s%s%s\n", id_ctrl.oncs, + pout("Optional NVM Commands (0x%04x): %s%s%s%s%s%s%s%s%s%s\n", id_ctrl.oncs, (!id_ctrl.oncs ? " -" : ""), ((id_ctrl.oncs & 0x0001) ? " Comp" : ""), ((id_ctrl.oncs & 0x0002) ? " Wr_Unc" : ""), ((id_ctrl.oncs & 0x0004) ? " DS_Mngmt" : ""), - ((id_ctrl.oncs & 0x0008) ? " Wr_Zero" : ""), + ((id_ctrl.oncs & 0x0008) ? " Wr_Zero" : ""), // NVMe 1.1 ... ((id_ctrl.oncs & 0x0010) ? " Sav/Sel_Feat" : ""), ((id_ctrl.oncs & 0x0020) ? " Resv" : ""), ((id_ctrl.oncs & 0x0040) ? " Timestmp" : ""), // NVMe 1.3 - ((id_ctrl.oncs & ~0x007f) ? " *Other*" : "")); + ((id_ctrl.oncs & 0x0080) ? " Verify" : ""), // NVMe 1.4 + ((id_ctrl.oncs & ~0x00ff) ? " *Other*" : "")); + + if (show_all || id_ctrl.lpa) + pout("Log Page Attributes (0x%02x): %s%s%s%s%s%s%s\n", id_ctrl.lpa, + (!id_ctrl.lpa ? " -" : ""), + ((id_ctrl.lpa & 0x01) ? " S/H_per_NS" : ""), + ((id_ctrl.lpa & 0x02) ? " Cmd_Eff_Lg" : ""), // NVMe 1.2 + ((id_ctrl.lpa & 0x04) ? " Ext_Get_Lg" : ""), // NVMe 1.2.1 + ((id_ctrl.lpa & 0x08) ? " Telmtry_Lg" : ""), // NVMe 1.3 + ((id_ctrl.lpa & 0x10) ? " Pers_Ev_Lg" : ""), // NVMe 1.4 + ((id_ctrl.lpa & ~0x001f) ? " *Other*" : "")); if (id_ctrl.mdts) pout("Maximum Data Transfer Size: %u Pages\n", (1U << id_ctrl.mdts)); @@ -260,13 +283,14 @@ if (nsid && (show_all || id_ns.nsfeat)) { const char * align = &(" "[nsid < 10 ? 0 : (nsid < 100 ? 1 : 2)]); - pout("Namespace %u Features (0x%02x): %s%s%s%s%s%s%s\n", nsid, id_ns.nsfeat, align, + pout("Namespace %u Features (0x%02x): %s%s%s%s%s%s%s%s\n", nsid, id_ns.nsfeat, align, (!id_ns.nsfeat ? " -" : ""), ((id_ns.nsfeat & 0x01) ? " Thin_Prov" : ""), - ((id_ns.nsfeat & 0x02) ? " NA_Fields" : ""), + ((id_ns.nsfeat & 0x02) ? " NA_Fields" : ""), // NVMe 1.2 ... ((id_ns.nsfeat & 0x04) ? " Dea/Unw_Error" : ""), ((id_ns.nsfeat & 0x08) ? " No_ID_Reuse" : ""), // NVMe 1.3 - ((id_ns.nsfeat & ~0x0f) ? " *Other*" : "")); + ((id_ns.nsfeat & 0x10) ? " NP_Fields" : ""), // NVMe 1.4 + ((id_ns.nsfeat & ~0x1f) ? " *Other*" : "")); } // Print Power States @@ -322,9 +346,12 @@ if (w & 0x10) jout("- volatile memory backup device has failed\n"); jref["volatile_memory_backup_failed"] = !!(w & 0x10); - if (w & ~0x1f) - jout("- unknown critical warning(s) (0x%02x)\n", w & ~0x1f); - jref["other"] = w & ~0x1f; + if (w & 0x20) + jout("- persistent memory region has become read-only or unreliable\n"); + jref["persistent_memory_region_unreliable"] = !!(w & 0x20); + if (w & ~0x3f) + jout("- unknown critical warning(s) (0x%02x)\n", w & ~0x3f); + jref["other"] = w & ~0x3f; } jout("\n"); @@ -387,7 +414,7 @@ // Temperature sensors are optional for (int i = 0; i < 8; i++) { - int k = smart_log.temp_sensor[i]; + k = smart_log.temp_sensor[i]; if (show_all || k) { jout("Temperature Sensor %d: %s\n", i + 1, kelvin_to_str(buf, k)); @@ -407,20 +434,34 @@ } static void print_error_log(const nvme_error_log_page * error_log, - unsigned num_entries, unsigned print_entries) + unsigned read_entries, unsigned max_entries) { - pout("Error Information (NVMe Log 0x01, max %u entries)\n", num_entries); + pout("Error Information (NVMe Log 0x01, %u of %u entries)\n", + read_entries, max_entries); + + // Search last valid entry + unsigned valid_entries = read_entries; + while (valid_entries && !error_log[valid_entries-1].error_count) + valid_entries--; - unsigned cnt = 0; - for (unsigned i = 0; i < num_entries; i++) { + if (!valid_entries) { + pout("No Errors Logged\n\n"); + return; + } + + pout("Num ErrCount SQId CmdId Status PELoc LBA NSID VS\n"); + int unused = 0; + for (unsigned i = 0; i < valid_entries; i++) { const nvme_error_log_page & e = error_log[i]; - if (!e.error_count) - continue; // unused or invalid entry - if (++cnt > print_entries) + if (!e.error_count) { + // unused or invalid entry + unused++; continue; - - if (cnt == 1) - pout("Num ErrCount SQId CmdId Status PELoc LBA NSID VS\n"); + } + if (unused) { + pout(" - [%d unused entr%s]\n", unused, (unused == 1 ? "y" : "ies")); + unused = 0; + } char sq[16] = "-", cm[16] = "-", st[16] = "-", pe[16] = "-"; char lb[32] = "-", ns[16] = "-", vs[8] = "-"; @@ -443,10 +484,8 @@ i, e.error_count, sq, cm, st, pe, lb, ns, vs); } - if (!cnt) - pout("No Errors Logged\n"); - else if (cnt > print_entries) - pout("... (%u entries not shown)\n", cnt - print_entries); + if (valid_entries == read_entries && read_entries < max_entries) + pout("... (%u entries not read)\n", max_entries - read_entries); pout("\n"); } @@ -524,46 +563,61 @@ } } + // Check for Log Page Offset support + bool lpo_sup = !!(id_ctrl.lpa & 0x04); + // Print Error Information Log if (options.error_log_entries) { - unsigned num_entries = id_ctrl.elpe + 1; // 0-based value - raw_buffer error_log_buf(num_entries * sizeof(nvme_error_log_page)); + unsigned max_entries = id_ctrl.elpe + 1; // 0's based value + unsigned want_entries = options.error_log_entries; + if (want_entries > max_entries) + want_entries = max_entries; + raw_buffer error_log_buf(want_entries * sizeof(nvme_error_log_page)); nvme_error_log_page * error_log = reinterpret_cast(error_log_buf.data()); - if (!nvme_read_error_log(device, error_log, num_entries)) { - jerr("Read Error Information Log failed: %s\n\n", device->get_errmsg()); + unsigned read_entries = nvme_read_error_log(device, error_log, want_entries, lpo_sup); + if (!read_entries) { + jerr("Read %u entries from Error Information Log failed: %s\n\n", + want_entries, device->get_errmsg()); return retval | FAILSMART; } + if (read_entries < want_entries) + jerr("Read Error Information Log failed, %u entries missing: %s\n", + want_entries - read_entries, device->get_errmsg()); - print_error_log(error_log, num_entries, options.error_log_entries); + print_error_log(error_log, read_entries, max_entries); } // Dump log page if (options.log_page_size) { // Align size to dword boundary unsigned size = ((options.log_page_size + 4-1) / 4) * 4; - bool broadcast_nsid; raw_buffer log_buf(size); + unsigned nsid; switch (options.log_page) { case 1: case 2: case 3: - broadcast_nsid = true; + nsid = 0xffffffff; break; default: - broadcast_nsid = false; + nsid = device->get_nsid(); break; } - if (!nvme_read_log_page(device, options.log_page, log_buf.data(), - size, broadcast_nsid)) { + unsigned read_bytes = nvme_read_log_page(device, nsid, options.log_page, log_buf.data(), + size, lpo_sup); + if (!read_bytes) { jerr("Read NVMe Log 0x%02x failed: %s\n\n", options.log_page, device->get_errmsg()); return retval | FAILSMART; } + if (read_bytes < size) + jerr("Read NVMe Log 0x%02x failed, 0x%x bytes missing: %s\n", + options.log_page, size - read_bytes, device->get_errmsg()); - pout("NVMe Log 0x%02x (0x%04x bytes)\n", options.log_page, size); - dStrHex(log_buf.data(), size, 0); + pout("NVMe Log 0x%02x (0x%04x bytes)\n", options.log_page, read_bytes); + dStrHex(log_buf.data(), read_bytes, 0); pout("\n"); } diff -Nru smartmontools-7.1/nvmeprint.h smartmontools-7.3/nvmeprint.h --- smartmontools-7.1/nvmeprint.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/nvmeprint.h 2021-01-24 16:40:20.000000000 +0000 @@ -1,9 +1,9 @@ /* * nvmeprint.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2016 Christian Franke + * Copyright (C) 2016-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,30 +11,20 @@ #ifndef NVMEPRINT_H #define NVMEPRINT_H -#define NVMEPRINT_H_CVSID "$Id: nvmeprint.h 4760 2018-08-19 18:45:53Z chrfranke $" +#define NVMEPRINT_H_CVSID "$Id: nvmeprint.h 5183 2021-01-24 16:40:20Z chrfranke $" #include "nvmecmds.h" // options for nvmePrintMain struct nvme_print_options { - bool drive_info; - bool drive_capabilities; - bool smart_check_status; - bool smart_vendor_attrib; - unsigned error_log_entries; - unsigned char log_page; - unsigned log_page_size; - - nvme_print_options() - : drive_info(false), - drive_capabilities(false), - smart_check_status(false), - smart_vendor_attrib(false), - error_log_entries(0), - log_page(0), - log_page_size(0) - { } + bool drive_info = false; + bool drive_capabilities = false; + bool smart_check_status = false; + bool smart_vendor_attrib = false; + unsigned error_log_entries = 0; + unsigned char log_page = 0; + unsigned log_page_size = 0; }; int nvmePrintMain(nvme_device * device, const nvme_print_options & options); diff -Nru smartmontools-7.1/os_darwin.cpp smartmontools-7.3/os_darwin.cpp --- smartmontools-7.1/os_darwin.cpp 2018-11-09 07:18:23.000000000 +0000 +++ smartmontools-7.3/os_darwin.cpp 2021-02-14 18:02:51.000000000 +0000 @@ -1,7 +1,7 @@ /* * os_darwin.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2004-8 Geoffrey Keating * Copyright (C) 2014 Alex Samorukov @@ -38,7 +38,7 @@ #define ARGUSED(x) ((void)(x)) // Needed by '-V' option (CVS versioning) of smartd/smartctl -const char *os_darwin_cpp_cvsid="$Id: os_darwin.cpp 4831 2018-11-09 07:18:23Z samm2 $" \ +const char *os_darwin_cpp_cvsid="$Id: os_darwin.cpp 5209 2021-02-14 18:02:51Z samm2 $" \ ATACMDS_H_CVSID CONFIG_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; // examples for smartctl @@ -65,7 +65,7 @@ IONVMeSMARTInterface **smartIfNVMe; } devices[20]; -const char * dev_darwin_cpp_cvsid = "$Id: os_darwin.cpp 4831 2018-11-09 07:18:23Z samm2 $" +const char * dev_darwin_cpp_cvsid = "$Id: os_darwin.cpp 5209 2021-02-14 18:02:51Z samm2 $" DEV_INTERFACE_H_CVSID; ///////////////////////////////////////////////////////////////////////////// @@ -83,13 +83,13 @@ : smart_device(never_called), m_fd(-1), m_mode(mode) { } - virtual ~darwin_smart_device() throw(); + virtual ~darwin_smart_device(); - virtual bool is_open() const; + virtual bool is_open() const override; - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; protected: /// Return filedesc for derived classes. @@ -102,7 +102,7 @@ }; -darwin_smart_device::~darwin_smart_device() throw() +darwin_smart_device::~darwin_smart_device() { if (m_fd >= 0) darwin_smart_device::close(); @@ -372,7 +372,7 @@ { public: darwin_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; protected: // virtual int ata_command_interface(smart_command_set command, int select, char * data); @@ -398,6 +398,7 @@ int fd = get_fd(); IOATASMARTInterface **ifp = devices[fd].smartIf; IOATASMARTInterface *smartIf; + io_object_t disk = devices[fd].ioob; IOReturn err; int timeoutCount = 5; int rc = 0; @@ -429,6 +430,32 @@ errno = ENOTSUP; err = -1; break; + case ATA_SET_FEATURES: + switch(in.in_regs.features) { + case ATA_ENABLE_APM: + if (in.in_regs.sector_count) { + int l = (int) in.in_regs.sector_count; + CFNumberRef cfLevel = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &l); + kern_return_t r = IORegistryEntrySetCFProperty(disk, CFSTR("APM Level"), cfLevel); + CFRelease(cfLevel); + if (r) { + switch(r) { + case kIOReturnNotPrivileged: + return set_err(ENOSYS, "Use superuser to manage APM"); + break; + case kIOReturnUnsupported: + return set_err(ENOSYS, "APM not supported"); + break; + default: + return set_err(ENOSYS, "APM error: %u", r); + } + } + break; + } + default: + return set_err(ENOSYS, "Unsupported ATA feature"); + } + break; case ATA_SMART_CMD: switch (in.in_regs.features) { case ATA_SMART_READ_VALUES: @@ -507,22 +534,22 @@ : public /*implements*/ smart_interface { public: - virtual std::string get_os_version_str(); + virtual std::string get_os_version_str() override; - virtual std::string get_app_examples(const char * appname); + virtual std::string get_app_examples(const char * appname) override; virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, - const char * pattern = 0); + const char * pattern = 0) override; protected: - virtual ata_device * get_ata_device(const char * name, const char * type); + virtual ata_device * get_ata_device(const char * name, const char * type) override; - virtual scsi_device * get_scsi_device(const char * name, const char * type); + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; virtual nvme_device * get_nvme_device(const char * name, const char * type, - unsigned nsid); + unsigned nsid) override; - virtual smart_device * autodetect_smart_device(const char * name); + virtual smart_device * autodetect_smart_device(const char * name) override; }; @@ -537,7 +564,7 @@ darwin_nvme_device(smart_interface * intf, const char * dev_name, const char * req_type, unsigned nsid); - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; }; darwin_nvme_device::darwin_nvme_device(smart_interface * intf, const char * dev_name, @@ -560,17 +587,19 @@ if (! ifp) return false; smartIfNVMe = *ifp; - // currently only GetIdentifyData and SMARTReadData are supported + // currently only GetIdentifyData and GetLogPage are supported switch (in.opcode) { case smartmontools::nvme_admin_identify: - err = smartIfNVMe->GetIdentifyData(ifp, (struct nvme_id_ctrl *) in.buffer, in.nsid); // FIXME + err = smartIfNVMe->GetIdentifyData(ifp, (struct nvme_id_ctrl *) in.buffer, in.nsid); + if (err) + return set_err(ENOSYS, "GetIdentifyData failed: system=0x%x, sub=0x%x, code=%d", + err_get_system(err), err_get_sub(err), err_get_code(err)); break; case smartmontools::nvme_admin_get_log_page: - if(page == 0x02) - err = smartIfNVMe->SMARTReadData(ifp, (struct nvme_smart_log *) in.buffer); - else /* GetLogPage() is not working yet */ - return set_err(ENOSYS, "NVMe admin command:0x%02x/page:0x%02x is not supported", - in.opcode, page); + err = smartIfNVMe->GetLogPage(ifp, in.buffer, page, in.size / 4 - 1); + if (err) + return set_err(ENOSYS, "GetLogPage failed: system=0x%x, sub=0x%x, code=%d", + err_get_system(err), err_get_sub(err), err_get_code(err)); break; default: return set_err(ENOSYS, "NVMe admin command 0x%02x is not supported", in.opcode); diff -Nru smartmontools-7.1/os_darwin.h smartmontools-7.3/os_darwin.h --- smartmontools-7.1/os_darwin.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/os_darwin.h 2020-06-24 08:08:38.000000000 +0000 @@ -11,7 +11,7 @@ #ifndef OS_DARWIN_H_ #define OS_DARWIN_H_ -#define OS_DARWIN_H_CVSID "$Id: os_darwin.h 4760 2018-08-19 18:45:53Z chrfranke $\n" +#define OS_DARWIN_H_CVSID "$Id: os_darwin.h 5073 2020-06-24 08:08:38Z samm2 $\n" #define kIOATABlockStorageDeviceClass "IOATABlockStorageDevice" @@ -21,7 +21,7 @@ #define kIOPropertySMARTCapableKey "SMART Capable" #endif -// NVMe definitions, non documented, experimental +// NVMe definitions based on Xcode SDK, see NVMeSMARTLibExternal.h #define kIOPropertyNVMeSMARTCapableKey "NVMe SMART Capable" // Constant to init driver @@ -34,7 +34,6 @@ 0xcc, 0xd1, 0xdb, 0x19, 0xfd, 0x9a, 0x4d, 0xaf, 0xbf, 0x95, \ 0x12, 0x45, 0x4b, 0x23, 0xa, 0xb6) -// interface structure, obtained using lldb, could be incomplete or wrong typedef struct IONVMeSMARTInterface { IUNKNOWN_C_GUTS; @@ -50,65 +49,31 @@ IOReturn ( *GetIdentifyData )( void * interface, struct nvme_id_ctrl * NVMeIdentifyControllerStruct, unsigned int ns ); + UInt64 reserved0; + UInt64 reserved1; - // Always getting kIOReturnDeviceError - IOReturn ( *GetFieldCounters )( void * interface, - char * FieldCounters ); - // Returns 0 - IOReturn ( *ScheduleBGRefresh )( void * interface); - - // Always returns kIOReturnDeviceError, probably expects pointer to some - // structure as an argument - IOReturn ( *GetLogPage )( void * interface, void * data, unsigned int, unsigned int); - - - /* GetSystemCounters Looks like a table with an attributes. Sample result: - - 0x101022200: 0x01 0x00 0x08 0x00 0x00 0x00 0x00 0x00 - 0x101022208: 0x00 0x00 0x00 0x00 0x02 0x00 0x08 0x00 - 0x101022210: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x101022218: 0x03 0x00 0x08 0x00 0xf1 0x74 0x26 0x01 - 0x101022220: 0x00 0x00 0x00 0x00 0x04 0x00 0x08 0x00 - 0x101022228: 0x0a 0x91 0xb1 0x00 0x00 0x00 0x00 0x00 - 0x101022230: 0x05 0x00 0x08 0x00 0x24 0x9f 0xfe 0x02 - 0x101022238: 0x00 0x00 0x00 0x00 0x06 0x00 0x08 0x00 - 0x101022240: 0x9b 0x42 0x38 0x02 0x00 0x00 0x00 0x00 - 0x101022248: 0x07 0x00 0x08 0x00 0xdd 0x08 0x00 0x00 - 0x101022250: 0x00 0x00 0x00 0x00 0x08 0x00 0x08 0x00 - 0x101022258: 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x101022260: 0x09 0x00 0x08 0x00 0x00 0x00 0x00 0x00 - 0x101022268: 0x00 0x00 0x00 0x00 0x0a 0x00 0x04 0x00 - ......... - 0x101022488: 0x74 0x00 0x08 0x00 0x00 0x00 0x00 0x00 - 0x101022490: 0x00 0x00 0x00 0x00 0x75 0x00 0x40 0x02 - 0x101022498: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - */ - IOReturn ( *GetSystemCounters )( void * interface, char *, unsigned int *); - - - /* GetAlgorithmCounters returns mostly 0 - 0x102004000: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004008: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004018: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004020: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004028: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004038: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004040: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004048: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004050: 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 - 0x102004058: 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004060: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004068: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004070: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004078: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004080: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004088: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004090: 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 - 0x102004098: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + // NumDWords Number of dwords for log page data, zero based. + IOReturn ( *GetLogPage )( void * interface, void * data, unsigned int logPageId, unsigned int numDWords); + + UInt64 reserved2; + UInt64 reserved3; + UInt64 reserved4; + UInt64 reserved5; + UInt64 reserved6; + UInt64 reserved7; + UInt64 reserved8; + UInt64 reserved9; + UInt64 reserved10; + UInt64 reserved11; + UInt64 reserved12; + UInt64 reserved13; + UInt64 reserved14; + UInt64 reserved15; + UInt64 reserved16; + UInt64 reserved17; + UInt64 reserved18; + UInt64 reserved19; - */ - IOReturn ( *GetAlgorithmCounters )( void * interface, char *, unsigned int *); } IONVMeSMARTInterface; diff -Nru smartmontools-7.1/os_freebsd.cpp smartmontools-7.3/os_freebsd.cpp --- smartmontools-7.1/os_freebsd.cpp 2019-01-02 22:09:00.000000000 +0000 +++ smartmontools-7.3/os_freebsd.cpp 2021-11-24 08:31:31.000000000 +0000 @@ -1,7 +1,7 @@ /* - * os_freebsd.c + * os_freebsd.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-10 Eduard Martinescu * @@ -26,6 +26,7 @@ #endif #include #include +#include #include #include #include @@ -75,7 +76,7 @@ #define PATHINQ_SETTINGS_SIZE 128 #endif -const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 4888 2019-01-02 22:09:00Z samm2 $" \ +const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 5253 2021-11-24 08:31:31Z samm2 $" \ ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; #define NO_RETURN 0 @@ -139,7 +140,7 @@ : smart_device(never_called), m_fd(-1) { } - virtual ~freebsd_smart_device() throw(); + virtual ~freebsd_smart_device(); virtual bool is_open() const; @@ -168,7 +169,7 @@ } #endif -freebsd_smart_device::~freebsd_smart_device() throw() +freebsd_smart_device::~freebsd_smart_device() { if (m_fd >= 0) os_freebsd::freebsd_smart_device::close(); @@ -199,6 +200,9 @@ " smartctl -a --device=areca,3/1 /dev/arcmsr0\n" " (Prints all SMART information for 3rd disk in the 1st enclosure \n" " on first ARECA RAID controller)\n" + " smartctl -a --device=megaraid,3 /dev/mrsas0\n" + " (Prints all SMART information for 3rd disk\n" + " on first LSI RAID controller)\n" ; @@ -240,7 +244,7 @@ { public: freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; protected: virtual int do_cmd(struct ata_ioc_request* request, bool is_48bit_cmd); @@ -279,7 +283,7 @@ } struct ata_ioc_request request; - bzero(&request,sizeof(struct ata_ioc_request)); + memset(&request, 0, sizeof(struct ata_ioc_request)); request.timeout=SCSI_TIMEOUT_DEFAULT; request.u.ata.command=in.in_regs.command; @@ -446,9 +450,9 @@ freebsd_nvme_device(smart_interface * intf, const char * dev_name, const char * req_type, unsigned nsid); - virtual bool open(); + virtual bool open() override; - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; }; freebsd_nvme_device::freebsd_nvme_device(smart_interface * intf, const char * dev_name, @@ -522,7 +526,6 @@ #else pt.cmd.opc = in.opcode; #endif - pt.cmd.opc = in.opcode; pt.cmd.nsid = htole32(in.nsid); pt.buf = in.buffer; pt.len = in.size; @@ -563,8 +566,8 @@ int escalade_type, int disknum); protected: - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); - virtual bool open(); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; + virtual bool open() override; private: int m_escalade_type; ///< Type string for escalade_command_interface(). @@ -762,6 +765,239 @@ return true; } +///////////////////////////////////////////////////////////////////////////// +/// LSI MegaRAID support + +class freebsd_megaraid_device +: public /* implements */ scsi_device, + public /* extends */ freebsd_smart_device +{ +public: + freebsd_megaraid_device(smart_interface *intf, const char *name, + unsigned int tgt); + + virtual ~freebsd_megaraid_device(); + + virtual smart_device * autodetect_open() override; + + virtual bool open() override; + virtual bool close() override; + + virtual bool scsi_pass_through(scsi_cmnd_io *iop) override; + +private: + unsigned int m_disknum; + unsigned int m_hba; + int m_fd; + + bool (freebsd_megaraid_device::*pt_cmd)(int cdblen, void *cdb, int dataLen, void *data, + int senseLen, void *sense, int report, int direction, int timeout); + bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data, + int senseLen, void *sense, int report, int direction, int timeout); +}; + +freebsd_megaraid_device::freebsd_megaraid_device(smart_interface *intf, + const char *dev_name, unsigned int tgt) + : smart_device(intf, dev_name, "megaraid", "megaraid"), + freebsd_smart_device(), + m_disknum(tgt), m_hba(0), + m_fd(-1), pt_cmd(0) +{ + set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum); + set_info().dev_type = strprintf("megaraid,%d", tgt); +} + +freebsd_megaraid_device::~freebsd_megaraid_device() +{ + if (m_fd >= 0) + ::close(m_fd); +} + +smart_device * freebsd_megaraid_device::autodetect_open() +{ + int report = scsi_debugmode; + + // Open device + if (!open()) + return this; + + // The code below is based on smartd.cpp:SCSIFilterKnown() + if (strcmp(get_req_type(), "megaraid")) + return this; + + // Get INQUIRY + unsigned char req_buff[64] = {0, }; + int req_len = 36; + if (scsiStdInquiry(this, req_buff, req_len)) { + close(); + set_err(EIO, "INQUIRY failed"); + return this; + } + + int avail_len = req_buff[4] + 5; + int len = (avail_len < req_len ? avail_len : req_len); + if (len < 36) + return this; + + if (report) + pout("Got MegaRAID inquiry.. %s\n", req_buff+8); + + // Use INQUIRY to detect type + { + // SAT? + ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); + if (newdev) // NOTE: 'this' is now owned by '*newdev' + return newdev; + } + + // Nothing special found + return this; +} + +bool freebsd_megaraid_device::open() +{ + /* Open Device IOCTL node */ + if ((m_fd = ::open(get_dev_name(), O_RDWR)) >= 0) { + pt_cmd = &freebsd_megaraid_device::megasas_cmd; + } + else { + int err = errno; + freebsd_smart_device::close(); + return set_err(err, "cannot open %s",get_dev_name()); + } + set_fd(m_fd); + return true; +} + +bool freebsd_megaraid_device::close() +{ + if (m_fd >= 0) + ::close(m_fd); + m_fd = -1; m_hba = 0; pt_cmd = 0; + set_fd(m_fd); + return true; +} + +bool freebsd_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop) +{ + int report = scsi_debugmode; + + if (report > 0) { + int k, j; + const unsigned char * ucp = iop->cmnd; + const char * np; + char buff[256]; + const int sz = (int)sizeof(buff); + + np = scsi_get_opcode_name(ucp[0]); + j = snprintf(buff, sz, " [%s: ", np ? np : ""); + for (k = 0; k < (int)iop->cmnd_len; ++k) + j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]); + if ((report > 1) && + (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { + int trunc = (iop->dxfer_len > 256) ? 1 : 0; + + snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing " + "data, len=%d%s:\n", (int)iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); + } + else + snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); + pout("%s", buff); + } + + // Controller rejects Test Unit Ready + if (iop->cmnd[0] == 0x00) + return true; + + if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) { + // Controller does not return ATA output registers in SAT sense data + if (iop->cmnd[2] & (1 << 5)) // chk_cond + return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware"); + } + // SMART WRITE LOG SECTOR causing media errors + if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 // SAT16 WRITE LOG + && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || + (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 // SAT12 WRITE LOG + && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) + { + if(!failuretest_permissive) + return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force"); + } + if (pt_cmd == NULL) + return false; + return (this->*pt_cmd)(iop->cmnd_len, iop->cmnd, + iop->dxfer_len, iop->dxferp, + iop->max_sense_len, iop->sensep, report, iop->dxfer_dir, iop->timeout); +} + +bool freebsd_megaraid_device::megasas_cmd(int cdbLen, void *cdb, + int dataLen, void *data, + int senseLen, void * sense, int /*report*/, int dxfer_dir, int timeout) +{ + struct mfi_pass_frame * pthru; + struct mfi_ioc_packet uio; + + pthru = (struct mfi_pass_frame *)&uio.mfi_frame.raw; + memset(&uio, 0, sizeof(uio)); + + pthru->header.cmd = MFI_CMD_PD_SCSI_IO; + pthru->header.cmd_status = 0; + pthru->header.scsi_status = 0x0; + pthru->header.target_id = m_disknum; + pthru->header.lun_id = 0; // FIXME, should be bus number? + + pthru->header.sense_len = senseLen; + pthru->sense_addr_lo = (uintptr_t)sense ; + pthru->sense_addr_hi = (uintptr_t)((uint64_t)sense >> 32); + + pthru->header.cdb_len = cdbLen; + pthru->header.timeout = timeout; + switch (dxfer_dir) { + case DXFER_FROM_DEVICE: + pthru->header.flags = MFI_FRAME_DIR_READ; + break; + case DXFER_TO_DEVICE: + pthru->header.flags = MFI_FRAME_DIR_WRITE; + break; + case DXFER_NONE: + pthru->header.flags = MFI_FRAME_DIR_NONE; + break; + } + + if (dataLen > 0) { + uio.mfi_sge_count = 1; + uio.mfi_sgl_off = offsetof(struct mfi_pass_frame,sgl); + uio.mfi_sgl[0].iov_base = data; + uio.mfi_sgl[0].iov_len = dataLen; + + pthru->header.sg_count = 1; + pthru->header.data_len = dataLen; + // tested on amd64 kernel in native and 32bit mode + pthru->sgl.sg64[0].addr = (intptr_t)data; + pthru->sgl.sg64[0].len = (uint32_t)dataLen; + } + memcpy(pthru->cdb, cdb, cdbLen); + + uio.mfi_adapter_no = m_hba; + uio.mfi_sense_len = senseLen; + uio.mfi_sense_off = offsetof(struct mfi_pass_frame, sense_addr_lo); + + errno = 0; + int rc = ioctl(m_fd, MFI_CMD, &uio); + + if (pthru->header.cmd_status || rc != 0) { + if (pthru->header.cmd_status == 12) { + return set_err(EIO, "megasas_cmd: Device %d does not exist\n", m_disknum); + } + return set_err((errno ? errno : EIO), "megasas_cmd result: %d.%d = %d/%d", + m_hba, m_disknum, errno, + pthru->header.cmd_status); + } + return true; +} + ///////////////////////////////////////////////////////////////////////////// /// Implement Highpoint RAID support with old functions @@ -775,8 +1011,8 @@ unsigned char controller, unsigned char channel, unsigned char port); protected: - virtual int ata_command_interface(smart_command_set command, int select, char * data); - virtual bool open(); + virtual int ata_command_interface(smart_command_set command, int select, char * data) override; + virtual bool open() override; private: unsigned char m_hpt_data[3]; ///< controller/channel/port @@ -837,7 +1073,7 @@ } // perform smart action - memset(buff, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER)); + memset(buff, 0, sizeof(buff)); pide_pt_hdr = (PHPT_PASS_THROUGH_HEADER)buff; pide_pt_hdr->lbamid = 0x4f; @@ -970,13 +1206,13 @@ public: freebsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual smart_device * autodetect_open(); + virtual smart_device * autodetect_open() override; - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; private: struct cam_device *m_camdev; @@ -1064,8 +1300,7 @@ } } // clear out structure, except for header that was filled in for us - bzero(&(&ccb->ccb_h)[1], - sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); + memset(&(&ccb->ccb_h)[1], 0, sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); cam_fill_csio(&ccb->csio, /* retries */ 1, @@ -1174,10 +1409,10 @@ { public: freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - virtual smart_device * autodetect_open(); - virtual bool arcmsr_lock(); - virtual bool arcmsr_unlock(); - virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); + virtual smart_device * autodetect_open() override; + virtual bool arcmsr_lock() override; + virtual bool arcmsr_unlock() override; + virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override; }; /////////////////////////////////////////////////////////////////// @@ -1188,10 +1423,10 @@ { public: freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - virtual smart_device * autodetect_open(); - virtual bool arcmsr_lock(); - virtual bool arcmsr_unlock(); - virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); + virtual smart_device * autodetect_open() override; + virtual bool arcmsr_lock() override; + virtual bool arcmsr_unlock() override; + virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override; }; @@ -1246,8 +1481,7 @@ // errors found return -1; } - - return ioctlreturn; + return 0; } bool freebsd_areca_ata_device::arcmsr_lock() @@ -1292,7 +1526,7 @@ return -1; } - return ioctlreturn; + return 0; } bool freebsd_areca_scsi_device::arcmsr_lock() @@ -1317,8 +1551,8 @@ public: freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum); - virtual bool scsi_pass_through(scsi_cmnd_io * iop); - virtual bool open(); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; + virtual bool open() override; private: unsigned char m_disknum; ///< Disk number. @@ -1402,6 +1636,15 @@ return this; } + // DELL? + if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8) + || !memcmp(req_buff + 16, "PERC ", 5) || !memcmp(req_buff + 8, "LSI\0",4) + ) { + close(); + set_err(EINVAL, "DELL or MegaRaid controller, use '-d megaraid,N'"); + return this; + } + // SAT or USB, skip MFI controllers because of bugs { smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); @@ -1428,32 +1671,36 @@ : public /*implements*/ smart_interface { public: - virtual std::string get_os_version_str(); + virtual std::string get_os_version_str() override; - virtual std::string get_app_examples(const char * appname); + virtual std::string get_app_examples(const char * appname) override; virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, - const char * pattern = 0); + const char * pattern = 0) override; protected: - virtual ata_device * get_ata_device(const char * name, const char * type); + virtual ata_device * get_ata_device(const char * name, const char * type) override; #if FREEBSDVER > 800100 virtual ata_device * get_atacam_device(const char * name, const char * type); #endif - virtual scsi_device * get_scsi_device(const char * name, const char * type); + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; virtual nvme_device * get_nvme_device(const char * name, const char * type, - unsigned nsid); + unsigned nsid) override; - virtual smart_device * autodetect_smart_device(const char * name); + virtual smart_device * autodetect_smart_device(const char * name) override; - virtual smart_device * get_custom_smart_device(const char * name, const char * type); + virtual smart_device * get_custom_smart_device(const char * name, const char * type) override; - virtual std::string get_valid_custom_dev_types_str(); + virtual std::string get_valid_custom_dev_types_str() override; private: bool get_nvme_devlist(smart_device_list & devlist, const char * type); + bool get_dev_megaraid(smart_device_list & devlist); + int megaraid_pd_add_list(const char * devname, smart_device_list & devlist); + int megaraid_dcmd_cmd(const char * devname, uint32_t opcode, void *buf, + size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp); }; @@ -1523,7 +1770,7 @@ } union ccb ccb; - bzero(&ccb, sizeof(union ccb)); + memset(&ccb, 0, sizeof(union ccb)); ccb.ccb_h.path_id = CAM_XPT_PATH_ID; ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; @@ -1534,7 +1781,7 @@ ccb.cdm.match_buf_len = bufsize; // TODO: Use local buffer instead of malloc() if possible ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); - bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure + memset(ccb.cdm.matches, 0, bufsize); // clear ccb.cdm.matches structure if (ccb.cdm.matches == NULL) { close(fd); @@ -1591,6 +1838,10 @@ skip_device = 1; else skip_device = 0; + + // skip ses devices + if (dev_result->inq_data.device == T_ENCLOSURE) + skip_device = 1; // /* Shall we skip non T_DIRECT devices ? */ // if (dev_result->inq_data.device != T_DIRECT) @@ -1772,6 +2023,9 @@ } } + // add devices from LSI MegaRaid controllers + get_dev_megaraid(devlist); + if (scan_nvme) get_nvme_devlist(devlist, type); return true; @@ -1797,6 +2051,114 @@ return true; } +// getting devices from LSI SAS MegaRaid, if available +bool freebsd_smart_interface::get_dev_megaraid(smart_device_list & devlist) +{ + /* Scanning of disks on MegaRaid device */ + char ctrlpath[64]; + + // trying to add devices on first 32 buses, same as StorCLI does + for(unsigned i = 0; i <=32; i++) { + sprintf(ctrlpath, "%s%u", MFI_CTRLR_PREFIX, i); + megaraid_pd_add_list(ctrlpath, devlist); + sprintf(ctrlpath, "%s%u", MRSAS_CTRLR_PREFIX, i); + megaraid_pd_add_list(ctrlpath, devlist); + } + return true; +} + +int +freebsd_smart_interface::megaraid_dcmd_cmd(const char * devname, uint32_t opcode, void *buf, + size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp) +{ + struct mfi_ioc_packet ioc; + struct mfi_dcmd_frame * dcmd; + + if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) || + (mbox == NULL && mboxlen != 0)) + { + errno = EINVAL; + return (-1); + } + + memset(&ioc, 0, sizeof(ioc)); + dcmd = (struct mfi_dcmd_frame *)&ioc.mfi_frame.raw; + + if (mbox) + memcpy(dcmd->mbox, mbox, mboxlen); + dcmd->header.cmd = MFI_CMD_DCMD; + dcmd->header.data_len = bufsize; + dcmd->opcode = opcode; + + if (bufsize > 0) { + ioc.mfi_sge_count = 1; + ioc.mfi_sgl_off = offsetof(struct mfi_dcmd_frame,sgl); + ioc.mfi_sgl[0].iov_base = buf; + ioc.mfi_sgl[0].iov_len = bufsize; + dcmd->header.sg_count = 1; + dcmd->header.data_len = bufsize; + // tested on amd64 kernel in native and 32bit mode + dcmd->sgl.sg64[0].addr = (intptr_t)buf; + dcmd->sgl.sg64[0].len = (uint32_t)bufsize; + } + + int fd; + if ((fd = ::open(devname, O_RDWR)) < 0) { + return (errno); + } + // We are using MFI_CMD as it seems to be supported by all LSI BSD drivers + int r = ioctl(fd, MFI_CMD, &ioc); + ::close(fd); + if (r < 0) { + return (r); + } + + if (statusp != NULL) + *statusp = dcmd->header.cmd_status; + else if (dcmd->header.cmd_status != MFI_STAT_OK) { + fprintf(stderr, "command %x returned error status %x\n", + opcode, dcmd->header.cmd_status); + errno = EIO; + return (-1); + } + return (0); +} + +int +freebsd_smart_interface::megaraid_pd_add_list(const char * devname, smart_device_list & devlist) +{ + /* + * Keep fetching the list in a loop until we have a large enough + * buffer to hold the entire list. + */ + mfi_pd_list * list = 0; + for (unsigned list_size = 1024; ; ) { + list = reinterpret_cast(realloc(list, list_size)); + if (!list) + throw std::bad_alloc(); + memset(list, 0, list_size); + if (megaraid_dcmd_cmd(devname, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0, + NULL) < 0) + { + free(list); + return (-1); + } + if (list->size <= list_size) + break; + list_size = list->size; + } + + // adding all SCSI devices + for (unsigned i = 0; i < list->count; i++) { + if(list->addr[i].scsi_dev_type) + continue; /* non disk device found */ + smart_device * dev = new freebsd_megaraid_device(this, devname, list->addr[i].device_id); + devlist.push_back(dev); + } + free(list); + return (0); +} + #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8 static char done[USB_MAX_DEVICES]; @@ -1936,7 +2298,6 @@ unsigned short vendor_id = 0, product_id = 0, version = 0; struct cam_device *cam_dev; union ccb ccb; - int bus=-1; int i; const char * test_name = name; @@ -1971,7 +2332,7 @@ } else free(atanames[i]); } - if(numata) free(atanames); + free(atanames); } else { if (numata < 0) @@ -1998,7 +2359,7 @@ return 0; } // zero the payload - bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE); + memset(&(&ccb.ccb_h)[1], 0, PATHINQ_SETTINGS_SIZE); ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) { warn("Get Transfer Settings CCB failed\n" @@ -2008,7 +2369,6 @@ } // now check if we are working with USB device, see umass.c if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found - usbdevlist(bus,vendor_id, product_id, version); int bus=ccb.cpi.unit_number; // unit_number will match umass number cam_close_device(cam_dev); if(usbdevlist(bus,vendor_id, product_id, version)){ @@ -2033,8 +2393,15 @@ } } // device is LSI raid supported by mfi driver - if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid"))) - set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information"); + if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid"))) { + set_err(EINVAL, "To access disks on LSI RAID load mfip.ko and use /dev/passX or use -d 'megaraid,N' with /dev/mfiX devices"); + return 0; + } + + if(!strncmp(MFI_CTRLR_PREFIX, test_name, strlen(MFI_CTRLR_PREFIX)) || !strncmp(MRSAS_CTRLR_PREFIX, test_name, strlen(MRSAS_CTRLR_PREFIX))) { + set_err(EINVAL, "To access disks on %s use '-d megaraid,N' device type", test_name); + return 0; + } // form /dev/nvme* or nvme* if(!strncmp("/dev/nvme", test_name, strlen("/dev/nvme"))) @@ -2141,12 +2508,16 @@ return new freebsd_areca_ata_device(this, name, disknum, encnum); } + if (sscanf(type, "megaraid,%d", &disknum) == 1) { + return new freebsd_megaraid_device(this, name, disknum); + } + return 0; } std::string freebsd_smart_interface::get_valid_custom_dev_types_str() { - return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E" + return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E, megaraid,N" #if FREEBSDVER > 800100 ", atacam" #endif diff -Nru smartmontools-7.1/os_freebsd.h smartmontools-7.3/os_freebsd.h --- smartmontools-7.1/os_freebsd.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/os_freebsd.h 2021-11-23 12:08:56.000000000 +0000 @@ -69,7 +69,7 @@ #ifndef OS_FREEBSD_H_ #define OS_FREEBSD_H_ -#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 4760 2018-08-19 18:45:53Z chrfranke $" +#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 5247 2021-11-23 12:08:56Z samm2 $" #define MAX_NUM_DEV 26 @@ -606,4 +606,164 @@ #define __unused __attribute__ ((__unused__)) #endif +// MFI definition from the kernel sources, see sys/dev/mfi + +#define MFI_STAT_OK 0x00 +#define MFI_DCMD_PD_GET_LIST 0x02010000 + +#define MFI_CTRLR_PREFIX "/dev/mfi" +#define MRSAS_CTRLR_PREFIX "/dev/mrsas" + +/* + * MFI Frame flags + */ +#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000 +#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001 +#define MFI_FRAME_SGL32 0x0000 +#define MFI_FRAME_SGL64 0x0002 +#define MFI_FRAME_SENSE32 0x0000 +#define MFI_FRAME_SENSE64 0x0004 +#define MFI_FRAME_DIR_NONE 0x0000 +#define MFI_FRAME_DIR_WRITE 0x0008 +#define MFI_FRAME_DIR_READ 0x0010 +#define MFI_FRAME_DIR_BOTH 0x0018 +#define MFI_FRAME_IEEE_SGL 0x0020 +#define MFI_FRAME_FMT "\20" \ + "\1NOPOST" \ + "\2SGL64" \ + "\3SENSE64" \ + "\4WRITE" \ + "\5READ" \ + "\6IEEESGL" + +/* MFI Commands */ +typedef enum { + MFI_CMD_INIT = 0x00, + MFI_CMD_LD_READ, + MFI_CMD_LD_WRITE, + MFI_CMD_LD_SCSI_IO, + MFI_CMD_PD_SCSI_IO, + MFI_CMD_DCMD, + MFI_CMD_ABORT, + MFI_CMD_SMP, + MFI_CMD_STP +} mfi_cmd_t; + +/* Scatter Gather elements */ +struct mfi_sg32 { + uint32_t addr; + uint32_t len; +} __packed; + +struct mfi_sg64 { + uint64_t addr; + uint32_t len; +} __packed; + +struct mfi_sg_skinny { + uint64_t addr; + uint32_t len; + uint32_t flag; +} __packed; + +union mfi_sgl { + struct mfi_sg32 sg32[1]; + struct mfi_sg64 sg64[1]; + struct mfi_sg_skinny sg_skinny[1]; +} __packed; + +/* Message frames. All messages have a common header */ +struct mfi_frame_header { + uint8_t cmd; + uint8_t sense_len; + uint8_t cmd_status; + uint8_t scsi_status; + uint8_t target_id; + uint8_t lun_id; + uint8_t cdb_len; + uint8_t sg_count; + uint32_t context; + /* + * pad0 is MSI Specific. Not used by Driver. Zero the value before + * sending the command to f/w. + */ + uint32_t pad0; + uint16_t flags; +#define MFI_FRAME_DATAOUT 0x08 +#define MFI_FRAME_DATAIN 0x10 + uint16_t timeout; + uint32_t data_len; +} __packed; + +#define MFI_PASS_FRAME_SIZE 48 +struct mfi_pass_frame { + struct mfi_frame_header header; + uint32_t sense_addr_lo; + uint32_t sense_addr_hi; + uint8_t cdb[16]; + union mfi_sgl sgl; +} __packed; + +#define MFI_DCMD_FRAME_SIZE 40 +#define MFI_MBOX_SIZE 12 + +struct mfi_dcmd_frame { + struct mfi_frame_header header; + uint32_t opcode; + uint8_t mbox[MFI_MBOX_SIZE]; + union mfi_sgl sgl; +} __packed; + +#define MAX_IOCTL_SGE 16 +struct mfi_ioc_packet { + uint16_t mfi_adapter_no; + uint16_t mfi_pad1; + uint32_t mfi_sgl_off; + uint32_t mfi_sge_count; + uint32_t mfi_sense_off; + uint32_t mfi_sense_len; + union { + uint8_t raw[128]; + struct mfi_frame_header hdr; + } mfi_frame; + + struct iovec mfi_sgl[MAX_IOCTL_SGE]; +} __packed; + +#ifdef COMPAT_FREEBSD32 +struct mfi_ioc_packet32 { + uint16_t mfi_adapter_no; + uint16_t mfi_pad1; + uint32_t mfi_sgl_off; + uint32_t mfi_sge_count; + uint32_t mfi_sense_off; + uint32_t mfi_sense_len; + union { + uint8_t raw[128]; + struct mfi_frame_header hdr; + } mfi_frame; + + struct iovec32 mfi_sgl[MAX_IOCTL_SGE]; +} __packed; +#endif + +struct mfi_pd_address { + uint16_t device_id; + uint16_t encl_device_id; + uint8_t encl_index; + uint8_t slot_number; + uint8_t scsi_dev_type; /* 0 = disk */ + uint8_t connect_port_bitmap; + uint64_t sas_addr[2]; +} __packed; + +#define MAX_SYS_PDS 240 +struct mfi_pd_list { + uint32_t size; + uint32_t count; + struct mfi_pd_address addr[MAX_SYS_PDS]; +} __packed; + +#define MFI_CMD _IOWR('M', 1, struct mfi_ioc_packet) + #endif /* OS_FREEBSD_H_ */ diff -Nru smartmontools-7.1/os_linux.cpp smartmontools-7.3/os_linux.cpp --- smartmontools-7.1/os_linux.cpp 2019-08-08 19:19:58.000000000 +0000 +++ smartmontools-7.3/os_linux.cpp 2022-02-02 17:34:26.000000000 +0000 @@ -1,11 +1,11 @@ /* - * os_linux.cpp + * os_linux.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-11 Bruce Allen * Copyright (C) 2003-11 Doug Gilbert - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-22 Christian Franke * * Original AACRaid code: * Copyright (C) 2014 Raghava Aditya @@ -37,11 +37,6 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -// This file contains the linux-specific IOCTL parts of -// smartmontools. It includes one interface routine for ATA devices, -// one for SCSI devices, and one for ATA devices behind escalade -// controllers. - #include "config.h" #include @@ -94,7 +89,7 @@ #define ARGUSED(x) ((void)(x)) -const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 4943 2019-08-08 19:19:58Z chrfranke $" +const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 5314 2022-02-02 17:34:26Z chrfranke $" OS_LINUX_H_CVSID; extern unsigned char failuretest_permissive; @@ -113,13 +108,13 @@ m_flags(flags), m_retry_flags(retry_flags) { } - virtual ~linux_smart_device() throw(); + virtual ~linux_smart_device(); - virtual bool is_open() const; + virtual bool is_open() const override; - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; protected: /// Return filedesc for derived classes. @@ -135,7 +130,7 @@ int m_retry_flags; ///< Flags to retry ::open(), -1 if no retry }; -linux_smart_device::~linux_smart_device() throw() +linux_smart_device::~linux_smart_device() { if (m_fd >= 0) ::close(m_fd); @@ -219,7 +214,7 @@ linux_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); protected: - virtual int ata_command_interface(smart_command_set command, int select, char * data); + virtual int ata_command_interface(smart_command_set command, int select, char * data) override; }; linux_ata_device::linux_ata_device(smart_interface * intf, const char * dev_name, const char * req_type) @@ -923,9 +918,9 @@ linux_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type, bool scanning = false); - virtual smart_device * autodetect_open(); + virtual smart_device * autodetect_open() override; - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; private: bool m_scanning; ///< true if created within scan_smart_devices @@ -960,11 +955,11 @@ linux_aacraid_device(smart_interface *intf, const char *dev_name, unsigned int host, unsigned int channel, unsigned int device); - virtual ~linux_aacraid_device() throw(); + virtual ~linux_aacraid_device(); - virtual bool open(); + virtual bool open() override; - virtual bool scsi_pass_through(scsi_cmnd_io *iop); + virtual bool scsi_pass_through(scsi_cmnd_io *iop) override; private: //Device Host number @@ -988,7 +983,7 @@ set_info().dev_type = strprintf("aacraid,%d,%d,%d",aHost,aLun,aId); } -linux_aacraid_device::~linux_aacraid_device() throw() +linux_aacraid_device::~linux_aacraid_device() { } @@ -1027,7 +1022,7 @@ return set_err(ENOENT, "aac entry not found in /proc/devices"); //Create misc device file in /dev/ used for communication with driver - if(mknod(dev_name,S_IFCHR,makedev(mjr,aHost))) + if(mknod(dev_name, S_IFCHR|0600, makedev(mjr,aHost))) return set_err(errno,"cannot create %s:%s",dev_name,strerror(errno)); afd = ::open(dev_name,O_RDWR); @@ -1196,14 +1191,14 @@ linux_megaraid_device(smart_interface *intf, const char *name, unsigned int tgt); - virtual ~linux_megaraid_device() throw(); + virtual ~linux_megaraid_device(); - virtual smart_device * autodetect_open(); + virtual smart_device * autodetect_open() override; - virtual bool open(); - virtual bool close(); + virtual bool open() override; + virtual bool close() override; - virtual bool scsi_pass_through(scsi_cmnd_io *iop); + virtual bool scsi_pass_through(scsi_cmnd_io *iop) override; private: unsigned int m_disknum; @@ -1229,7 +1224,7 @@ set_info().dev_type = strprintf("megaraid,%d", tgt); } -linux_megaraid_device::~linux_megaraid_device() throw() +linux_megaraid_device::~linux_megaraid_device() { if (m_fd >= 0) ::close(m_fd); @@ -1303,14 +1298,14 @@ while (fgets(line, sizeof(line), fp) != NULL) { int n1 = 0; if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) { - n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0)); + n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR|0600, makedev(mjr, 0)); if(report > 0) pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno); if (n1 >= 0 || errno == EEXIST) break; } else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) { - n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0)); + n1=mknod("/dev/megadev0", S_IFCHR|0600, makedev(mjr, 0)); if(report > 0) pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno); if (n1 >= 0 || errno == EEXIST) @@ -1516,7 +1511,7 @@ public: linux_cciss_device(smart_interface * intf, const char * name, unsigned char disknum); - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; private: unsigned char m_disknum; ///< Disk number. @@ -1559,9 +1554,9 @@ linux_escalade_device(smart_interface * intf, const char * dev_name, escalade_type_t escalade_type, int disknum); - virtual bool open(); + virtual bool open() override; - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; private: escalade_type_t m_escalade_type; ///< Controller type @@ -1991,10 +1986,10 @@ { public: linux_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - virtual smart_device * autodetect_open(); - virtual bool arcmsr_lock(); - virtual bool arcmsr_unlock(); - virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); + virtual smart_device * autodetect_open() override; + virtual bool arcmsr_lock() override; + virtual bool arcmsr_unlock() override; + virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override; }; /////////////////////////////////////////////////////////////////// @@ -2005,10 +2000,10 @@ { public: linux_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - virtual smart_device * autodetect_open(); - virtual bool arcmsr_lock(); - virtual bool arcmsr_unlock(); - virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); + virtual smart_device * autodetect_open() override; + virtual bool arcmsr_lock() override; + virtual bool arcmsr_unlock() override; + virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override; }; // Looks in /proc/scsi to suggest correct areca devices @@ -2624,7 +2619,7 @@ // DELL? if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8) - || !memcmp(req_buff + 16, "PERC H700", 9) || !memcmp(req_buff + 8, "LSI\0",4) + || !memcmp(req_buff + 16, "PERC ", 5) || !memcmp(req_buff + 8, "LSI\0",4) ) { close(); set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'"); @@ -2672,9 +2667,9 @@ linux_nvme_device(smart_interface * intf, const char * dev_name, const char * req_type, unsigned nsid); - virtual bool open(); + virtual bool open() override; - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; }; linux_nvme_device::linux_nvme_device(smart_interface * intf, const char * dev_name, @@ -2804,29 +2799,30 @@ : public /*implements*/ smart_interface { public: - virtual std::string get_os_version_str(); + virtual std::string get_os_version_str() override; - virtual std::string get_app_examples(const char * appname); + virtual std::string get_app_examples(const char * appname) override; virtual bool scan_smart_devices(smart_device_list & devlist, - const smart_devtype_list & types, const char * pattern = 0); + const smart_devtype_list & types, const char * pattern = 0) override; protected: - virtual ata_device * get_ata_device(const char * name, const char * type); + virtual ata_device * get_ata_device(const char * name, const char * type) override; - virtual scsi_device * get_scsi_device(const char * name, const char * type); + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; virtual nvme_device * get_nvme_device(const char * name, const char * type, - unsigned nsid); + unsigned nsid) override; - virtual smart_device * autodetect_smart_device(const char * name); + virtual smart_device * autodetect_smart_device(const char * name) override; - virtual smart_device * get_custom_smart_device(const char * name, const char * type); + virtual smart_device * get_custom_smart_device(const char * name, const char * type) override; - virtual std::string get_valid_custom_dev_types_str(); + virtual std::string get_valid_custom_dev_types_str() override; private: - static const int devxy_to_n_max = 103; // Max value of devxy_to_n() below + static constexpr int devxy_to_n_max = 701; // "/dev/sdzz" + static int devxy_to_n(const char * name, bool debug); void get_dev_list(smart_device_list & devlist, const char * pattern, bool scan_scsi, bool (* p_dev_sdxy_seen)[devxy_to_n_max+1], @@ -2855,10 +2851,10 @@ return ""; } -// "/dev/sdXY" -> 0-103 -// "/dev/disk/by-id/NAME" -> "../../sdXY" -> 0-103 +// "/dev/sdXY" -> 0-devxy_to_n_max +// "/dev/disk/by-id/NAME" -> "../../sdXY" -> 0-devxy_to_n_max // Other -> -1 -static int devxy_to_n(const char * name, bool debug) +int linux_smart_interface::devxy_to_n(const char * name, bool debug) { const char * xy; char dest[256]; @@ -2887,9 +2883,10 @@ // "[a-z]" -> 0-25 return x - 'a'; - if (!(x <= 'c' && 'a' <= y && y <= 'z' && !xy[2])) + if (!('a' <= y && y <= 'z' && !xy[2])) return -1; - // "[a-c][a-z]" -> 26-103 + // "[a-z][a-z]" -> 26-701 + STATIC_ASSERT((('z' - 'a' + 1) * ('z' - 'a' + 1) + ('z' - 'a')) == devxy_to_n_max); return (x - 'a' + 1) * ('z' - 'a' + 1) + (y - 'a'); } @@ -2975,7 +2972,7 @@ n1=0; if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) { scan_megasas = true; - n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0)); + n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR|0600, makedev(mjr, 0)); if(scsi_debugmode > 0) pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno); if (n1 >= 0 || errno == EEXIST) @@ -3068,7 +3065,7 @@ } get_dev_list(devlist, "/dev/sd[a-z]", true, p_dev_sdxy_seen, false, type_scsi_sat, autodetect); - get_dev_list(devlist, "/dev/sd[a-c][a-z]", true, p_dev_sdxy_seen, false, type_scsi_sat, autodetect); + get_dev_list(devlist, "/dev/sd[a-z][a-z]", true, p_dev_sdxy_seen, false, type_scsi_sat, autodetect); // get device list from the megaraid device get_dev_megasas(devlist); @@ -3117,11 +3114,11 @@ return (-1); } - bzero(&ioc, sizeof(ioc)); + memset(&ioc, 0, sizeof(ioc)); struct megasas_dcmd_frame * dcmd = &ioc.frame.dcmd; ioc.host_no = bus_no; if (mbox) - bcopy(mbox, dcmd->mbox.w, mboxlen); + memcpy(dcmd->mbox.w, mbox, mboxlen); dcmd->cmd = MFI_CMD_DCMD; dcmd->timeout = 0; dcmd->flags = 0; @@ -3173,7 +3170,7 @@ list = reinterpret_cast(realloc(list, list_size)); if (!list) throw std::bad_alloc(); - bzero(list, list_size); + memset(list, 0, list_size); if (megasas_dcmd_cmd(bus_no, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0, NULL) < 0) { @@ -3211,8 +3208,8 @@ return x * 100000 + y * 1000 + z; } -// Check for SCSI host proc_name "hpsa" -static bool is_hpsa(const char * name) +// Check for SCSI host proc_name "hpsa" and HPSA raid_level +static bool is_hpsa_in_raid_mode(const char * name) { char path[128]; snprintf(path, sizeof(path), "/sys/block/%s/device", name); @@ -3252,7 +3249,23 @@ if (strcmp(proc_name, "hpsa")) return false; - return true; + // See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/scsi/hpsa.c?id=6417f03132a6952cd17ddd8eaddbac92b61b17e0#n693 + snprintf(path, sizeof(path), "/sys/block/%s/device/raid_level", name); + fd = open(path, O_RDONLY); + if (fd < 0) + return false; + + char raid_level[4]; + n = read(fd, raid_level, sizeof(raid_level) - 1); + close(fd); + if (n < 3) + return false; + raid_level[n] = 0; + + if (strcmp(raid_level, "N/A")) + return true; + + return false; } // Guess device type (ata or scsi) based on device name (Linux @@ -3307,8 +3320,8 @@ return get_scsi_passthrough_device(usbtype, new linux_scsi_device(this, name, "")); } - // Fail if hpsa driver - if (is_hpsa(test_name)) + // Fail if hpsa driver and device is using RAID + if (is_hpsa_in_raid_mode(test_name)) return missing_option("-d cciss,N"); // No USB bridge or hpsa driver found, assume regular SCSI device diff -Nru smartmontools-7.1/os_netbsd.cpp smartmontools-7.3/os_netbsd.cpp --- smartmontools-7.1/os_netbsd.cpp 2019-06-12 20:29:55.000000000 +0000 +++ smartmontools-7.3/os_netbsd.cpp 2021-02-01 20:36:02.000000000 +0000 @@ -1,7 +1,7 @@ /* * os_netbsd.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-8 Sergey Svishchev * Copyright (C) 2016 Kimihiro Nonaka @@ -25,7 +25,7 @@ // based on "sys/dev/ic/nvmeio.h" from NetBSD kernel sources #include "netbsd_nvme_ioctl.h" // NVME_PASSTHROUGH_CMD, nvme_completion_is_error -const char * os_netbsd_cpp_cvsid = "$Id: os_netbsd.cpp 4919 2019-06-12 20:29:55Z chrfranke $" +const char * os_netbsd_cpp_cvsid = "$Id: os_netbsd.cpp 5198 2021-02-01 20:36:02Z chrfranke $" OS_NETBSD_H_CVSID; #define ARGUSED(x) ((void)(x)) @@ -52,7 +52,7 @@ : smart_device(never_called), m_fd(-1) { } - virtual ~netbsd_smart_device() throw(); + virtual ~netbsd_smart_device(); virtual bool is_open() const; @@ -72,7 +72,7 @@ int m_fd; ///< filedesc, -1 if not open. }; -netbsd_smart_device::~netbsd_smart_device() throw() +netbsd_smart_device::~netbsd_smart_device() { if (m_fd >= 0) os_netbsd::netbsd_smart_device::close(); @@ -131,7 +131,7 @@ { public: netbsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; protected: virtual int do_cmd(struct atareq* request, bool is_48bit_cmd); @@ -168,7 +168,7 @@ struct atareq req; memset(&req, 0, sizeof(req)); - req.timeout = 1000; + req.timeout = SCSI_TIMEOUT_DEFAULT * 1000; req.command = in.in_regs.command; req.features = in.in_regs.features; req.sec_count = in.in_regs.sector_count; @@ -227,9 +227,9 @@ netbsd_nvme_device(smart_interface * intf, const char * dev_name, const char * req_type, unsigned nsid); - virtual bool open(); + virtual bool open() override; - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; }; netbsd_nvme_device::netbsd_nvme_device(smart_interface * intf, const char * dev_name, @@ -331,9 +331,9 @@ public: netbsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type, bool scanning = false); - virtual smart_device * autodetect_open(); + virtual smart_device * autodetect_open() override; - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; private: bool m_scanning; ///< true if created within scan_smart_devices @@ -492,26 +492,26 @@ : public /*implements*/ smart_interface { public: - virtual std::string get_os_version_str(); + virtual std::string get_os_version_str() override; - virtual std::string get_app_examples(const char * appname); + virtual std::string get_app_examples(const char * appname) override; virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, - const char * pattern = 0); + const char * pattern = 0) override; protected: - virtual ata_device * get_ata_device(const char * name, const char * type); + virtual ata_device * get_ata_device(const char * name, const char * type) override; - virtual scsi_device * get_scsi_device(const char * name, const char * type); + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; virtual nvme_device * get_nvme_device(const char * name, const char * type, - unsigned nsid); + unsigned nsid) override; - virtual smart_device * autodetect_smart_device(const char * name); + virtual smart_device * autodetect_smart_device(const char * name) override; - virtual smart_device * get_custom_smart_device(const char * name, const char * type); + virtual smart_device * get_custom_smart_device(const char * name, const char * type) override; - virtual std::string get_valid_custom_dev_types_str(); + virtual std::string get_valid_custom_dev_types_str() override; private: int get_dev_names(char ***, const char *); diff -Nru smartmontools-7.1/os_openbsd.cpp smartmontools-7.3/os_openbsd.cpp --- smartmontools-7.1/os_openbsd.cpp 2018-12-02 16:07:26.000000000 +0000 +++ smartmontools-7.3/os_openbsd.cpp 2021-04-07 06:42:07.000000000 +0000 @@ -1,7 +1,7 @@ /* - * os_openbsd.c + * os_openbsd.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2004-10 David Snyder * @@ -17,71 +17,424 @@ #include "utility.h" #include "os_openbsd.h" +#include #include +#include +#include -const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 4842 2018-12-02 16:07:26Z chrfranke $" +const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 5215 2021-04-07 06:42:07Z samm2 $" OS_OPENBSD_H_CVSID; -enum warnings { - BAD_SMART, MAX_MSG -}; +#define ARGUSED(x) ((void)(x)) -/* Utility function for printing warnings */ -void -printwarning(int msgNo, const char *extra) -{ - static int printed[] = {0, 0}; - static const char *message[] = { - "Error: SMART Status command failed.\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n", - PACKAGE_STRING " does not currently support twe(4) devices (3ware Escalade)\n", - }; - - if (msgNo >= 0 && msgNo <= MAX_MSG) { - if (!printed[msgNo]) { - printed[msgNo] = 1; - pout("%s", message[msgNo]); - if (extra) - pout("%s", extra); - } - } - return; -} +///////////////////////////////////////////////////////////////////////////// + +namespace os_openbsd { // No need to publish anything, name provided for Doxygen static const char *net_dev_prefix = "/dev/"; static const char *net_dev_ata_disk = "wd"; static const char *net_dev_scsi_disk = "sd"; static const char *net_dev_scsi_tape = "st"; -/* Guess device type(ata or scsi) based on device name */ -int -guess_device_type(const char *dev_name) +///////////////////////////////////////////////////////////////////////////// +/// Implement shared open/close routines with old functions. + +class openbsd_smart_device +: virtual public /*implements*/ smart_device +{ +public: + explicit openbsd_smart_device() + : smart_device(never_called), + m_fd(-1) { } + + virtual ~openbsd_smart_device(); + + virtual bool is_open() const; + + virtual bool open(); + + virtual bool close(); + +protected: + /// Return filedesc for derived classes. + int get_fd() const + { return m_fd; } + + void set_fd(int fd) + { m_fd = fd; } + +private: + int m_fd; ///< filedesc, -1 if not open. +}; + +openbsd_smart_device::~openbsd_smart_device() +{ + if (m_fd >= 0) + os_openbsd::openbsd_smart_device::close(); +} + +bool openbsd_smart_device::is_open() const +{ + return (m_fd >= 0); +} + + +bool openbsd_smart_device::open() +{ + const char *dev = get_dev_name(); + int fd; + + if (is_scsi()) { + fd = ::open(dev,O_RDWR|O_NONBLOCK); + + if (fd < 0 && errno == EROFS) + fd = ::open(dev,O_RDONLY|O_NONBLOCK); + if (fd < 0) { + set_err(errno); + return false; + } + } else if (is_ata()) { + if ((fd = ::open(dev,O_RDWR|O_NONBLOCK))<0) { + set_err(errno); + return false; + } + } else + return false; + + set_fd(fd); + return true; +} + +bool openbsd_smart_device::close() +{ + int failed = 0; + // close device, if open + if (is_open()) + failed=::close(get_fd()); + + set_fd(-1); + + if(failed) return false; + else return true; +} + +///////////////////////////////////////////////////////////////////////////// +/// Implement standard ATA support + +class openbsd_ata_device +: public /*implements*/ ata_device, + public /*extends*/ openbsd_smart_device +{ +public: + openbsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; + +protected: + virtual int do_cmd(struct atareq* request, bool is_48bit_cmd); +}; + +openbsd_ata_device::openbsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type) +: smart_device(intf, dev_name, "ata", req_type), + openbsd_smart_device() +{ +} + +int openbsd_ata_device::do_cmd( struct atareq* request, bool is_48bit_cmd) +{ + int fd = get_fd(), ret; + ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the ATAIOCCOMMAND + ret = ioctl(fd, ATAIOCCOMMAND, request); + if (ret) set_err(errno); + return ret; +} + +bool openbsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) +{ + bool ata_48bit = false; // no ata_48bit_support via ATAIOCCOMMAND + + if (!ata_cmd_is_ok(in, + true, // data_out_support + true, // multi_sector_support + ata_48bit) + ) { + set_err(ENOSYS, "48-bit ATA commands not implemented"); + return false; + } + + struct atareq req; + + memset(&req, 0, sizeof(req)); + req.command = in.in_regs.command; + req.features = in.in_regs.features; + req.sec_count = in.in_regs.sector_count; + req.sec_num = in.in_regs.lba_low; + req.head = in.in_regs.device; + req.cylinder = in.in_regs.lba_mid | (in.in_regs.lba_high << 8); + req.timeout = SCSI_TIMEOUT_DEFAULT * 1000; + + switch (in.direction) { + case ata_cmd_in::no_data: + req.flags = ATACMD_READREG; + break; + case ata_cmd_in::data_in: + req.flags = ATACMD_READ | ATACMD_READREG; + req.databuf = (char *)in.buffer; + req.datalen = in.size; + break; + case ata_cmd_in::data_out: + req.flags = ATACMD_WRITE | ATACMD_READREG; + req.databuf = (char *)in.buffer; + req.datalen = in.size; + break; + default: + return set_err(ENOSYS); + } + + clear_err(); + errno = 0; + if (do_cmd(&req, in.in_regs.is_48bit_cmd())) + return false; + if (req.retsts != ATACMD_OK) + return set_err(EIO, "request failed, error code 0x%02x", req.retsts); + + out.out_regs.error = req.error; + out.out_regs.sector_count = req.sec_count; + out.out_regs.lba_low = req.sec_num; + out.out_regs.device = req.head; + out.out_regs.lba_mid = req.cylinder; + out.out_regs.lba_high = req.cylinder >> 8; + out.out_regs.status = req.command; + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +/// Standard SCSI support + +class openbsd_scsi_device +: public /*implements*/ scsi_device, + public /*extends*/ openbsd_smart_device +{ +public: + openbsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type, bool scanning = false); + + virtual smart_device * autodetect_open() override; + + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; + +private: + bool m_scanning; ///< true if created within scan_smart_devices +}; + +openbsd_scsi_device::openbsd_scsi_device(smart_interface * intf, + const char * dev_name, const char * req_type, bool scanning /* = false */) +: smart_device(intf, dev_name, "scsi", req_type), + openbsd_smart_device(), + m_scanning(scanning) { - int len; - int dev_prefix_len = strlen(net_dev_prefix); +} + +bool openbsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop) +{ + struct scsireq sc; + int fd = get_fd(); - if (!dev_name || !(len = strlen(dev_name))) - return CONTROLLER_UNKNOWN; + if (scsi_debugmode) { + unsigned int k; + const unsigned char * ucp = iop->cmnd; + const char * np; - if (!strncmp(net_dev_prefix, dev_name, dev_prefix_len)) { - if (len <= dev_prefix_len) - return CONTROLLER_UNKNOWN; - else - dev_name += dev_prefix_len; + np = scsi_get_opcode_name(ucp[0]); + pout(" [%s: ", np ? np : ""); + for (k = 0; k < iop->cmnd_len; ++k) + pout("%02x ", ucp[k]); + if ((scsi_debugmode > 1) && + (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { + int trunc = (iop->dxfer_len > 256) ? 1 : 0; + + pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); + } + else + pout("]\n"); } - if (!strncmp(net_dev_ata_disk, dev_name, strlen(net_dev_ata_disk))) - return CONTROLLER_ATA; - if (!strncmp(net_dev_scsi_disk, dev_name, strlen(net_dev_scsi_disk))) - return CONTROLLER_SCSI; + memset(&sc, 0, sizeof(sc)); + memcpy(sc.cmd, iop->cmnd, iop->cmnd_len); + sc.cmdlen = iop->cmnd_len; + sc.databuf = (char *)iop->dxferp; + sc.datalen = iop->dxfer_len; + sc.senselen = iop->max_sense_len; + sc.timeout = (iop->timeout == 0 ? 60 : iop->timeout) * 1000; + sc.flags = + (iop->dxfer_dir == DXFER_NONE ? SCCMD_READ : + (iop->dxfer_dir == DXFER_FROM_DEVICE ? SCCMD_READ : SCCMD_WRITE)); - if (!strncmp(net_dev_scsi_tape, dev_name, strlen(net_dev_scsi_tape))) - return CONTROLLER_SCSI; + if (ioctl(fd, SCIOCCOMMAND, &sc) < 0) { + if (scsi_debugmode) { + pout(" error sending SCSI ccb\n"); + } + return set_err(EIO); + } + iop->resid = sc.datalen - sc.datalen_used; + iop->scsi_status = sc.status; + if (iop->sensep) { + memcpy(iop->sensep, sc.sense, sc.senselen_used); + iop->resp_sense_len = sc.senselen_used; + } + if (scsi_debugmode) { + int trunc; - return CONTROLLER_UNKNOWN; + pout(" status=0\n"); + trunc = (iop->dxfer_len > 256) ? 1 : 0; + + pout(" Incoming data, len=%d%s:\n", (int) iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len), 1); + } + // XXX we probably need error handling here + return true; } -int -get_dev_names(char ***names, const char *prefix) +///////////////////////////////////////////////////////////////////////////// +///// SCSI open with autodetection support + +smart_device * openbsd_scsi_device::autodetect_open() +{ + // Open device + if (!open()) + return this; + + // No Autodetection if device type was specified by user + bool sat_only = false; + if (*get_req_type()) { + // Detect SAT if device object was created by scan_smart_devices(). + if (!(m_scanning && !strcmp(get_req_type(), "sat"))) + return this; + sat_only = true; + } + + // The code below is based on smartd.cpp:SCSIFilterKnown() + + // Get INQUIRY + unsigned char req_buff[64] = {0, }; + int req_len = 36; + if (scsiStdInquiry(this, req_buff, req_len)) { + // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices + // watch this spot ... other devices could lock up here + req_len = 64; + if (scsiStdInquiry(this, req_buff, req_len)) { + // device doesn't like INQUIRY commands + close(); + set_err(EIO, "INQUIRY failed"); + return this; + } + } + + int avail_len = req_buff[4] + 5; + int len = (avail_len < req_len ? avail_len : req_len); + if (len < 36) { + if (sat_only) { + close(); + set_err(EIO, "INQUIRY too short for SAT"); + } + return this; + } + + // Use INQUIRY to detect type + + // SAT or USB, skip MFI controllers because of bugs + { + smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); + if (newdev) { + // NOTE: 'this' is now owned by '*newdev' + return newdev; + } + } + + // Nothing special found + + if (sat_only) { + close(); + set_err(EIO, "Not a SAT device"); + } + return this; +} + +///////////////////////////////////////////////////////////////////////////// +/// Implement platform interface with old functions. + +class openbsd_smart_interface +: public /*implements*/ smart_interface +{ +public: + virtual std::string get_os_version_str() override; + + virtual std::string get_app_examples(const char * appname) override; + + virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, + const char * pattern = 0) override; + +protected: + virtual ata_device * get_ata_device(const char * name, const char * type) override; + + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; + + virtual smart_device * autodetect_smart_device(const char * name) override; + + virtual smart_device * get_custom_smart_device(const char * name, const char * type) override; + + virtual std::string get_valid_custom_dev_types_str() override; + +private: + int get_dev_names(char ***, const char *); +}; + + +////////////////////////////////////////////////////////////////////// + +std::string openbsd_smart_interface::get_os_version_str() +{ + struct utsname osname; + uname(&osname); + return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine); +} + +std::string openbsd_smart_interface::get_app_examples(const char * appname) +{ + if (!strcmp(appname, "smartctl")) { + char p; + + p = 'a' + getrawpartition(); + return strprintf( + "=================================================== SMARTCTL EXAMPLES =====\n\n" + " smartctl -a /dev/wd0%c (Prints all SMART information)\n\n" + " smartctl --smart=on --offlineauto=on --saveauto=on /dev/wd0%c\n" + " (Enables SMART on first disk)\n\n" + " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n\n" + " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/wd0%c\n" + " (Prints Self-Test & Attribute errors)\n" + " smartctl -a /dev/wd0%c (Prints all SMART information)\n" + " smartctl -s on -o on -S on /dev/wd0%c (Enables SMART on first disk)\n" + " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n" + " smartctl -A -l selftest -q errorsonly /dev/wd0%c" + " (Prints Self-Test & Attribute errors)\n", + p, p, p, p, p, p, p, p); + } + return ""; +} +ata_device * openbsd_smart_interface::get_ata_device(const char * name, const char * type) +{ + return new openbsd_ata_device(this, name, type); +} + +scsi_device * openbsd_smart_interface::get_scsi_device(const char * name, const char * type) +{ + return new openbsd_scsi_device(this, name, type); +} + +int openbsd_smart_interface::get_dev_names(char ***names, const char *prefix) { char *disknames, *p, **mp; int n = 0; @@ -108,6 +461,7 @@ pout("Out of memory constructing scan device list\n"); return -1; } + for (p = strtok(disknames, ","); p; p = strtok(NULL, ",")) { if (strncmp(p, prefix, strlen(prefix))) { continue; @@ -136,291 +490,134 @@ return n; } -int -make_device_names(char ***devlist, const char *name) -{ - if (!strcmp(name, "SCSI")) - return get_dev_names(devlist, net_dev_scsi_disk); - else if (!strcmp(name, "ATA")) - return get_dev_names(devlist, net_dev_ata_disk); - else - return 0; -} -int -deviceopen(const char *pathname, char *type) -{ - if (!strcmp(type, "SCSI")) { - int fd = open(pathname, O_RDWR | O_NONBLOCK); - if (fd < 0 && errno == EROFS) - fd = open(pathname, O_RDONLY | O_NONBLOCK); - return fd; - } else if (!strcmp(type, "ATA")) - return open(pathname, O_RDWR | O_NONBLOCK); - else - return -1; -} +bool openbsd_smart_interface::scan_smart_devices(smart_device_list & devlist, + const char * type, const char * pattern /*= 0*/) + { + if (pattern) { + set_err(EINVAL, "DEVICESCAN with pattern not implemented yet"); + return false; + } -int -deviceclose(int fd) -{ - return close(fd); -} + if (type == NULL) + type = ""; -int -ata_command_interface(int fd, smart_command_set command, int select, char *data) -{ - struct atareq req; - unsigned char inbuf[DEV_BSIZE]; - int retval, copydata = 0; - - memset(&req, 0, sizeof(req)); - memset(&inbuf, 0, sizeof(inbuf)); + bool scan_ata = !*type || !strcmp(type, "ata"); + bool scan_scsi = !*type || !strcmp(type, "scsi") || !strcmp(type, "sat"); - switch (command) { - case READ_VALUES: - req.flags = ATACMD_READ; - req.features = ATA_SMART_READ_VALUES; - req.command = ATAPI_SMART; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.cylinder = htole16(WDSMART_CYL); - req.timeout = 1000; - copydata = 1; - break; - case READ_THRESHOLDS: - req.flags = ATACMD_READ; - req.features = ATA_SMART_READ_THRESHOLDS; - req.command = ATAPI_SMART; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.cylinder = htole16(WDSMART_CYL); - req.timeout = 1000; - copydata = 1; - break; - case READ_LOG: - req.flags = ATACMD_READ; - req.features = ATA_SMART_READ_LOG_SECTOR; /* XXX missing from wdcreg.h */ - req.command = ATAPI_SMART; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.cylinder = htole16(WDSMART_CYL); - req.sec_num = select; - req.sec_count = 1; - req.timeout = 1000; - copydata = 1; - break; - case WRITE_LOG: - memcpy(inbuf, data, 512); - req.flags = ATACMD_WRITE; - req.features = ATA_SMART_WRITE_LOG_SECTOR; /* XXX missing from wdcreg.h */ - req.command = ATAPI_SMART; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.cylinder = htole16(WDSMART_CYL); - req.sec_num = select; - req.sec_count = 1; - req.timeout = 1000; - break; - case IDENTIFY: - req.flags = ATACMD_READ; - req.command = WDCC_IDENTIFY; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.timeout = 1000; - copydata = 1; - break; - case PIDENTIFY: - req.flags = ATACMD_READ; - req.command = ATAPI_IDENTIFY_DEVICE; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.timeout = 1000; - copydata = 1; - break; - case ENABLE: - req.flags = ATACMD_READ; - req.features = ATA_SMART_ENABLE; - req.command = ATAPI_SMART; - req.cylinder = htole16(WDSMART_CYL); - req.timeout = 1000; - break; - case DISABLE: - req.flags = ATACMD_READ; - req.features = ATA_SMART_DISABLE; - req.command = ATAPI_SMART; - req.cylinder = htole16(WDSMART_CYL); - req.timeout = 1000; - break; - case AUTO_OFFLINE: - /* NOTE: According to ATAPI 4 and UP, this command is obsolete */ - req.flags = ATACMD_READ; - req.features = ATA_SMART_AUTO_OFFLINE; /* XXX missing from wdcreg.h */ - req.command = ATAPI_SMART; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.cylinder = htole16(WDSMART_CYL); - req.sec_num = select; - req.sec_count = 1; - req.timeout = 1000; - break; - case AUTOSAVE: - req.flags = ATACMD_READ; - req.features = ATA_SMART_AUTOSAVE; /* XXX missing from wdcreg.h */ - req.command = ATAPI_SMART; - req.cylinder = htole16(WDSMART_CYL); - req.sec_count = 0xf1; - /* to enable autosave */ - req.timeout = 1000; - break; - case IMMEDIATE_OFFLINE: - /* NOTE: According to ATAPI 4 and UP, this command is obsolete */ - req.flags = ATACMD_READ; - req.features = ATA_SMART_IMMEDIATE_OFFLINE; /* XXX missing from wdcreg.h */ - req.command = ATAPI_SMART; - req.databuf = (caddr_t) inbuf; - req.datalen = sizeof(inbuf); - req.cylinder = htole16(WDSMART_CYL); - req.sec_num = select; - req.sec_count = 1; - req.timeout = 1000; - break; - case STATUS_CHECK: - /* same command, no HDIO in NetBSD */ - case STATUS: - req.flags = ATACMD_READ; - req.features = ATA_SMART_STATUS; - req.command = ATAPI_SMART; - req.cylinder = htole16(WDSMART_CYL); - req.timeout = 1000; - break; - case CHECK_POWER_MODE: - req.flags = ATACMD_READREG; - req.command = WDCC_CHECK_PWR; - req.timeout = 1000; - break; - default: - pout("Unrecognized command %d in ata_command_interface()\n", command); - errno = ENOSYS; - return -1; - } + // Make namelists + char * * atanames = 0; int numata = 0; + if (scan_ata) { + numata = get_dev_names(&atanames, net_dev_ata_disk); + if (numata < 0) { + set_err(ENOMEM); + return false; + } + } - if (command == STATUS_CHECK) { - char buf[512]; + char * * scsinames = 0; int numscsi = 0; + char * * scsitapenames = 0; int numscsitape = 0; + if (scan_scsi) { + numscsi = get_dev_names(&scsinames, net_dev_scsi_disk); + if (numscsi < 0) { + set_err(ENOMEM); + return false; + } + numscsitape = get_dev_names(&scsitapenames, net_dev_scsi_tape); + if (numscsitape < 0) { + set_err(ENOMEM); + return false; + } + } - unsigned const short normal = WDSMART_CYL, failed = 0x2cf4; + // Add to devlist + int i; + for (i = 0; i < numata; i++) { + ata_device * atadev = get_ata_device(atanames[i], type); + if (atadev) + devlist.push_back(atadev); + free(atanames[i]); + } + if(numata) free(atanames); - retval = ioctl(fd, ATAIOCCOMMAND, &req); - if (retval < 0) { - perror("Failed command"); - return -1; + for (i = 0; i < numscsi; i++) { + scsi_device * scsidev = new openbsd_scsi_device(this, scsinames[i], type, true /*scanning*/); + if (scsidev) + devlist.push_back(scsidev); + free(scsinames[i]); } - /* Cyl low and Cyl high unchanged means "Good SMART status" */ - if (letoh16(req.cylinder) == normal) - return 0; - - /* These values mean "Bad SMART status" */ - if (letoh16(req.cylinder) == failed) - return 1; - - /* We haven't gotten output that makes sense; - * print out some debugging info */ - snprintf(buf, sizeof(buf), - "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n", - (int) req.command, (int) req.features, (int) req.sec_count, (int) req.sec_num, - (int) (letoh16(req.cylinder) & 0xff), (int) ((letoh16(req.cylinder) >> 8) & 0xff), - (int) req.error); - printwarning(BAD_SMART, buf); - return 0; - } - if ((retval = ioctl(fd, ATAIOCCOMMAND, &req))) { - perror("Failed command"); - return -1; - } - if (command == CHECK_POWER_MODE) - data[0] = req.sec_count; + if(numscsi) free(scsinames); - if (copydata) - memcpy(data, inbuf, 512); + for (i = 0; i < numscsitape; i++) { + scsi_device * scsidev = get_scsi_device(scsitapenames[i], type); + if (scsidev) + devlist.push_back(scsidev); + free(scsitapenames[i]); + } + if(numscsitape) free(scsitapenames); - return 0; + return true; } -int -do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) +smart_device * openbsd_smart_interface::autodetect_smart_device(const char * name) { - struct scsireq sc; - - if (report > 0) { - size_t k; + const char * test_name = name; - const unsigned char *ucp = iop->cmnd; - const char *np; - - np = scsi_get_opcode_name(ucp[0]); - pout(" [%s: ", np ? np : ""); - for (k = 0; k < iop->cmnd_len; ++k) - pout("%02x ", ucp[k]); - if ((report > 1) && - (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { - int trunc = (iop->dxfer_len > 256) ? 1 : 0; + // if dev_name null, or string length zero + if (!name || !*name) + return 0; - pout("]\n Outgoing data, len=%d%s:\n", (int) iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len), 1); - } else - pout("]"); + // Dereference symlinks + struct stat st; + std::string pathbuf; + if (!lstat(name, &st) && S_ISLNK(st.st_mode)) { + char * p = realpath(name, (char *)0); + if (p) { + pathbuf = p; + free(p); + test_name = pathbuf.c_str(); + } } - memset(&sc, 0, sizeof(sc)); - memcpy(sc.cmd, iop->cmnd, iop->cmnd_len); - sc.cmdlen = iop->cmnd_len; - sc.databuf = (char *)iop->dxferp; - sc.datalen = iop->dxfer_len; - sc.senselen = iop->max_sense_len; - sc.timeout = iop->timeout == 0 ? 60000 : iop->timeout; /* XXX */ - sc.flags = - (iop->dxfer_dir == DXFER_NONE ? SCCMD_READ : - (iop->dxfer_dir == DXFER_FROM_DEVICE ? SCCMD_READ : SCCMD_WRITE)); - if (ioctl(fd, SCIOCCOMMAND, &sc) < 0) { - warn("error sending SCSI ccb"); - return -1; - } - iop->resid = sc.datalen - sc.datalen_used; - iop->scsi_status = sc.status; - if (iop->sensep) { - memcpy(iop->sensep, sc.sense, sc.senselen_used); - iop->resp_sense_len = sc.senselen_used; + if (str_starts_with(test_name, net_dev_prefix)) { + test_name += strlen(net_dev_prefix); + if (!strncmp(net_dev_ata_disk, test_name, strlen(net_dev_ata_disk))) + return get_ata_device(name, "ata"); + if (!strncmp(net_dev_scsi_disk, test_name, strlen(net_dev_scsi_disk))) { + // XXX Try to detect possible USB->(S)ATA bridge + // XXX get USB vendor ID, product ID and version from sd(4)/umass(4). + // XXX check sat device via get_usb_dev_type_by_id(). + + // No USB bridge found, assume regular SCSI or SAT device + return get_scsi_device(name, ""); + } + if (!strncmp(net_dev_scsi_tape, test_name, strlen(net_dev_scsi_tape))) + return get_scsi_device(name, "scsi"); } - if (report > 0) { - int trunc; + // device type unknown + return 0; +} - pout(" status=0\n"); - trunc = (iop->dxfer_len > 256) ? 1 : 0; - pout(" Incoming data, len=%d%s:\n", (int) iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len), 1); - } +smart_device * openbsd_smart_interface::get_custom_smart_device(const char * name, const char * type) +{ + ARGUSED(name); + ARGUSED(type); return 0; } -/* print examples for smartctl */ -void -print_smartctl_examples() -{ - char p; - - p = 'a' + getrawpartition(); - printf( - "=================================================== SMARTCTL EXAMPLES =====\n\n" - " smartctl -a /dev/wd0%c (Prints all SMART information)\n\n" - " smartctl --smart=on --offlineauto=on --saveauto=on /dev/wd0%c\n" - " (Enables SMART on first disk)\n\n" - " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n\n" - " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/wd0%c\n" - " (Prints Self-Test & Attribute errors)\n", - p, p, p, p - ); - return; +std::string openbsd_smart_interface::get_valid_custom_dev_types_str() +{ + return ""; +} + +} // namespace + +///////////////////////////////////////////////////////////////////////////// +/// Initialize platform interface and register with smi() + +void smart_interface::init() +{ + static os_openbsd::openbsd_smart_interface the_interface; + smart_interface::set(&the_interface); } diff -Nru smartmontools-7.1/os_solaris.cpp smartmontools-7.3/os_solaris.cpp --- smartmontools-7.1/os_solaris.cpp 2018-10-09 19:34:46.000000000 +0000 +++ smartmontools-7.3/os_solaris.cpp 2020-06-20 13:47:36.000000000 +0000 @@ -1,7 +1,7 @@ /* - * os_solaris.c + * os_solaris.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2003-08 SAWADA Keiji * Copyright (C) 2003-15 Casper Dik @@ -29,36 +29,8 @@ #define ARGUSED(x) ((void)(x)) -const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp 4805 2018-10-09 19:34:46Z chrfranke $" \ -ATACMDS_H_CVSID CONFIG_H_CVSID OS_SOLARIS_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; - -// The printwarning() function warns about unimplemented functions -int printedout[2]; -char *unimplemented[2]={ - "ATA command routine ata_command_interface()", - "3ware Escalade Controller command routine escalade_command_interface()", -}; - -int printwarning(int which){ - if (!unimplemented[which]) - return 0; - - if (printedout[which]) - return 1; - - printedout[which]=1; - - pout("\n" - "#######################################################################\n" - "%s NOT IMPLEMENTED under Solaris.\n" - "Please contact " PACKAGE_BUGREPORT " if\n" - "you want to help in porting smartmontools to Solaris.\n" - "#######################################################################\n" - "\n", - unimplemented[which]); - - return 1; -} +const char *os_XXXX_cpp_cvsid = "$Id: os_solaris.cpp 5065 2020-06-20 13:47:36Z chrfranke $" + OS_SOLARIS_H_CVSID; // print examples for smartctl void print_smartctl_examples(){ @@ -300,7 +272,7 @@ case STATUS_CHECK: return smart_status_check(fd); default: - pout("Unrecognized command %d in ata_command_interface() of os_solaris.c\n", command); + pout("Unrecognized command %d in ata_command_interface() of os_solaris.cpp\n", command); errno = EINVAL; return -1; } @@ -309,10 +281,10 @@ /* Above smart_* routines uses undocumented ioctls of "dada" * driver, which is specific to SPARC Solaris. See - * os_solaris_ata.s for further details. x86 Solaris seems not to - * provide similar or alternative interface... */ - if (printwarning(0)) - return -1; + * os_solaris_ata.s for further details. */ + + pout("Device type 'ata' not implemented, try '-d sat' or '-d sat,12' instead.\n"); + errno = ENOSYS; #endif return -1; } diff -Nru smartmontools-7.1/os_win32/installer.nsi smartmontools-7.3/os_win32/installer.nsi --- smartmontools-7.1/os_win32/installer.nsi 2019-12-29 14:27:48.000000000 +0000 +++ smartmontools-7.3/os_win32/installer.nsi 2022-02-01 18:15:00.000000000 +0000 @@ -3,11 +3,11 @@ ; ; Home page of code is: https://www.smartmontools.org ; -; Copyright (C) 2006-19 Christian Franke +; Copyright (C) 2006-22 Christian Franke ; ; SPDX-License-Identifier: GPL-2.0-or-later ; -; $Id: installer.nsi 5020 2019-12-29 14:27:48Z chrfranke $ +; $Id: installer.nsi 5310 2022-02-01 18:15:00Z chrfranke $ ; @@ -188,7 +188,8 @@ SetOutPath "$INSTDIR\bin" File "${INPDIR}\bin\drivedb.h" - File "${INPDIR}\bin\update-smart-drivedb.exe" + Delete "$INSTDIR\bin\update-smart-drivedb.exe" ; TODO: Remove after smartmontools 7.3 + File "${INPDIR}\bin\update-smart-drivedb.ps1" SectionEnd @@ -201,7 +202,6 @@ SetOutPath "$INSTDIR\doc" File "${INPDIR}\doc\AUTHORS.txt" File "${INPDIR}\doc\ChangeLog.txt" - Delete "$INSTDIR\doc\ChangeLog-5.0-6.0.txt" ; TODO: Remove after smartmontools 7.1 File "${INPDIR}\doc\ChangeLog-6.0-7.0.txt" File "${INPDIR}\doc\COPYING.txt" File "${INPDIR}\doc\INSTALL.txt" @@ -234,10 +234,6 @@ CreateDirectory "$INSTDIR" - ; Remove old "Install_Dir" registry entry (smartmontools < r3911/6.3) - ; No longer needed for GSmartControl - DeleteRegKey HKLM "Software\smartmontools" ; TODO: Remove after smartmontools 7.0 - ; Write uninstall keys and program WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "DisplayName" "smartmontools" !ifdef VERSTR @@ -349,9 +345,13 @@ CreateShortCut "$SMPROGRAMS\smartmontools\smartmontools Daily Builds.lnk" "https://builds.smartmontools.org/" ; drivedb.h update - ${If} ${FileExists} "$INSTDIR\bin\update-smart-drivedb.exe" + Delete "$SMPROGRAMS\smartmontools\drivedb.h update.lnk" ; TODO: Remove after smartmontools 7.3 + ${If} ${FileExists} "$INSTDIR\bin\update-smart-drivedb.ps1" SetOutPath "$INSTDIR\bin" - !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\drivedb.h update.lnk" "$INSTDIR\bin\update-smart-drivedb.exe" "" + !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\drivedb.h update (ps1).lnk" "$INSTDIR\bin\runcmdu.exe" "powershell -NoProfile -ExecutionPolicy Bypass .\update-smart-drivedb.ps1" + ${If} ${FileExists} "$INSTDIR\doc\README.TXT" + CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\drivedb.h update help (ps1).lnk" "$INSTDIR\bin\runcmdu.exe" 'powershell -NoProfile -ExecutionPolicy Bypass "Get-Help .\update-smart-drivedb.ps1 -Detail | more"' + ${EndIf} ${EndIf} ; Uninstall @@ -463,13 +463,13 @@ Delete "$INSTDIR\bin\drivedb.h.error" Delete "$INSTDIR\bin\drivedb.h.lastcheck" Delete "$INSTDIR\bin\drivedb.h.old" - Delete "$INSTDIR\bin\update-smart-drivedb.exe" + Delete "$INSTDIR\bin\update-smart-drivedb.exe" ; TODO: Remove after smartmontools 7.3 + Delete "$INSTDIR\bin\update-smart-drivedb.ps1" Delete "$INSTDIR\bin\runcmda.exe" Delete "$INSTDIR\bin\runcmdu.exe" Delete "$INSTDIR\bin\wtssendmsg.exe" Delete "$INSTDIR\doc\AUTHORS.txt" Delete "$INSTDIR\doc\ChangeLog.txt" - Delete "$INSTDIR\doc\ChangeLog-5.0-6.0.txt" ; TODO: Remove after smartmontools 7.1 Delete "$INSTDIR\doc\ChangeLog-6.0-7.0.txt" Delete "$INSTDIR\doc\COPYING.txt" Delete "$INSTDIR\doc\INSTALL.txt" diff -Nru smartmontools-7.1/os_win32/popen.h smartmontools-7.3/os_win32/popen.h --- smartmontools-7.1/os_win32/popen.h 2018-10-17 05:32:17.000000000 +0000 +++ smartmontools-7.3/os_win32/popen.h 2021-12-18 15:55:35.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2018 Christian Franke + * Copyright (C) 2018-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -11,7 +11,7 @@ #ifndef POPEN_H #define POPEN_H -#define POPEN_H_CVSID "$Id: popen.h 4818 2018-10-17 05:32:17Z chrfranke $" +#define POPEN_H_CVSID "$Id: popen.h 5272 2021-12-18 15:55:35Z chrfranke $" #include @@ -42,6 +42,17 @@ } #endif +// Enhanced version of popen() with ability to modify the access token. +// If 'restricted' is set, the child process is run with a restricted access +// token. The local Administrator group and most privileges (all except +// SeChangeNotifyPrivilege) are removed. +FILE * popen_as_restr_user(const char * cmd, const char * mode, bool restricted); + +// Check whether the access token of the current user could be effectively +// restricted. +// Returns false if the current user is the local SYSTEM or Administrator account. +bool popen_as_restr_check(); + // wait(3) macros from #ifndef WIFEXITED #define WIFEXITED(status) (((status) & 0xff) == 0x00) diff -Nru smartmontools-7.1/os_win32/popen_win32.cpp smartmontools-7.3/os_win32/popen_win32.cpp --- smartmontools-7.1/os_win32/popen_win32.cpp 2018-10-17 05:32:17.000000000 +0000 +++ smartmontools-7.3/os_win32/popen_win32.cpp 2021-12-18 15:55:35.000000000 +0000 @@ -3,14 +3,14 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2018 Christian Franke + * Copyright (C) 2018-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "popen.h" -const char * popen_win32_cpp_cvsid = "$Id: popen_win32.cpp 4818 2018-10-17 05:32:17Z chrfranke $" +const char * popen_win32_cpp_cvsid = "$Id: popen_win32.cpp 5272 2021-12-18 15:55:35Z chrfranke $" POPEN_H_CVSID; #include @@ -20,14 +20,107 @@ #include #include -#define WIN32_LEAN_AND_MEAN #include +static HANDLE create_restricted_token() +{ + // Create SIDs for SYSTEM and Local Adminstrator + union { + SID sid; + char sid_space[32]; // 16 + } adm, sys; // "S-1-5-18", "S-1-5-32-544" + DWORD adm_size = sizeof(adm), sys_size = sizeof(sys); + if (!( CreateWellKnownSid(WinBuiltinAdministratorsSid, (PSID)0, &adm.sid, &adm_size) + && CreateWellKnownSid(WinLocalSystemSid, (PSID)0, &sys.sid, &sys_size) )) { + errno = ENOMEM; + return (HANDLE)0; + } + + // Open token of current process + HANDLE proc_token; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &proc_token)) { + errno = EPERM; + return (HANDLE)0; + } + + // Get Owner of current process: S-1-5-21-SYSTEM-GUID-USERID + union { + TOKEN_USER user; + char user_space[128]; // TODO: Max size? + } usr; + DWORD size = 0; + if (!GetTokenInformation(proc_token, TokenUser, &usr, sizeof(usr), &size)) { + CloseHandle(proc_token); + errno = EPERM; + return (HANDLE)0; + } + + // Restricting token from SYSTEM or local Administrator is not effective + if (EqualSid(usr.user.User.Sid, &sys.sid) || EqualSid(usr.user.User.Sid, &adm.sid)) { + CloseHandle(proc_token); + errno = EINVAL; + return (HANDLE)0; + } + + // The default DACL of an elevated process may not contain the user itself: + // D:(A;;GA;;;BA)(A;;GA;;;SY)[(A;;GXGR;;;S-1-5-5-0-LOGON_ID)] + // The restricted process then fails to start because the hidden + // console cannot be accessed. Use a standard default DACL instead: + // D:(A;;GA;;;S-1-5-21-SYSTEM-GUID-USERID)(A;;GA;;;BA)(A;;GA;;;SY) + union { + ACL acl; + char acl_space[256]; // 236 + } dacl; + if (!( InitializeAcl(&dacl.acl, sizeof(dacl), ACL_REVISION) + && AddAccessAllowedAce(&dacl.acl, ACL_REVISION, GENERIC_ALL, usr.user.User.Sid) + && AddAccessAllowedAce(&dacl.acl, ACL_REVISION, GENERIC_ALL, &adm.sid) + && AddAccessAllowedAce(&dacl.acl, ACL_REVISION, GENERIC_ALL, &sys.sid) )) { + CloseHandle(proc_token); + errno = ENOMEM; + return (HANDLE)0; + } + + // Create new token with local Administrator and most Privileges dropped + SID_AND_ATTRIBUTES sid_to_disable = {&adm.sid, 0}; + HANDLE restr_token; + BOOL ok = CreateRestrictedToken(proc_token, + DISABLE_MAX_PRIVILEGE, // Keep only "SeChangeNotifyPrivilege" + 1, &sid_to_disable, // Disable "S-1-5-32-544" (changes group to deny only) + 0, (LUID_AND_ATTRIBUTES *)0, // No further privileges + 0, (SID_AND_ATTRIBUTES *)0, // No restricted SIDs + &restr_token + ); + CloseHandle(proc_token); + + if (!ok) { + errno = EPERM; + return (HANDLE)0; + } + + // Set new Default DACL + TOKEN_DEFAULT_DACL tdacl = { &dacl.acl }; + if (!SetTokenInformation(restr_token, TokenDefaultDacl, &tdacl, sizeof(tdacl))) { + CloseHandle(restr_token); + errno = EPERM; + return (HANDLE)0; + } + + return restr_token; +} + +bool popen_as_restr_check() +{ + HANDLE restr_token = create_restricted_token(); + if (!restr_token) + return false; + CloseHandle(restr_token); + return true; +} + static FILE * s_popen_file; static HANDLE s_popen_process; -extern "C" -FILE * popen(const char * command, const char * mode) +FILE * popen_as_restr_user(const char * cmd, const char * mode, bool restricted) { // Fail if previous run is still in progress if (s_popen_file) { @@ -89,7 +182,7 @@ } // Build command line "cmd /c COMMAND" - int cmdlen = strlen(command); + int cmdlen = strlen(cmd); char * shellcmd = (char *)malloc(7 + cmdlen + 1); if (!shellcmd) { fclose(f); // CloseHandle(pipe_out_r) @@ -98,16 +191,29 @@ return (FILE *)0; } memcpy(shellcmd, "cmd /c ", 7); - memcpy(shellcmd + 7, command, cmdlen + 1); + memcpy(shellcmd + 7, cmd, cmdlen + 1); + + // Create a restricted token if requested + HANDLE restr_token = 0; + if (restricted) { + restr_token = create_restricted_token(); + if (!restr_token) { + int err = errno; + fclose(f); // CloseHandle(pipe_out_r) + CloseHandle(pipe_out_w); + errno = err; + return (FILE *)0; + } + } // Redirect stdin stderr to null device // Don't inherit parent's stdin, script may hang if parent has no console. SECURITY_ATTRIBUTES sa_inherit = { sizeof(sa_inherit), (SECURITY_DESCRIPTOR *)0, TRUE }; - HANDLE null_in = CreateFile("nul", GENERIC_READ , 0, &sa_inherit, OPEN_EXISTING, 0, (HANDLE)0); - HANDLE null_err = CreateFile("nul", GENERIC_WRITE, 0, &sa_inherit, OPEN_EXISTING, 0, (HANDLE)0); + HANDLE null_in = CreateFileA("nul", GENERIC_READ , 0, &sa_inherit, OPEN_EXISTING, 0, (HANDLE)0); + HANDLE null_err = CreateFileA("nul", GENERIC_WRITE, 0, &sa_inherit, OPEN_EXISTING, 0, (HANDLE)0); // Set stdio handles - STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); + STARTUPINFO si{}; si.cb = sizeof(si); si.hStdInput = null_in; si.hStdOutput = pipe_out_w; si.hStdError = null_err; @@ -115,19 +221,36 @@ // Create process PROCESS_INFORMATION pi; - BOOL ok = CreateProcessA( - getenv("COMSPEC"), // "C:\WINDOWS\system32\cmd.exe" or nullptr - shellcmd, // "cmd /c COMMAND" ("cmd" searched in PATH if COMSPEC not set) - (SECURITY_ATTRIBUTES *)0, (SECURITY_ATTRIBUTES *)0, - TRUE, // inherit - CREATE_NO_WINDOW, // DETACHED_PROCESS would open new console(s) - (void *)0, (char *)0, &si, &pi - ); + BOOL ok; + const char * shell = getenv("COMSPEC"); + if (restr_token) { + ok = CreateProcessAsUserA( + restr_token, + shell, // "C:\Windows\System32\cmd.exe" or nullptr + shellcmd, // "cmd /c COMMAND" ("cmd" searched in PATH if COMSPEC not set) + (SECURITY_ATTRIBUTES *)0, (SECURITY_ATTRIBUTES *)0, + TRUE, // inherit + CREATE_NO_WINDOW, // DETACHED_PROCESS would open new console(s) + (void *)0, (char *)0, &si, &pi + ); + } + else { + ok = CreateProcessA( + shell, // "C:\Windows\System32\cmd.exe" or nullptr + shellcmd, // "cmd /c COMMAND" ("cmd" searched in PATH if COMSPEC not set) + (SECURITY_ATTRIBUTES *)0, (SECURITY_ATTRIBUTES *)0, + TRUE, // inherit + CREATE_NO_WINDOW, // DETACHED_PROCESS would open new console(s) + (void *)0, (char *)0, &si, &pi + ); + } free(shellcmd); // Close inherited handles CloseHandle(null_err); CloseHandle(null_in); + if (restr_token) + CloseHandle(restr_token); CloseHandle(pipe_out_w); if (!ok) { @@ -145,6 +268,12 @@ } extern "C" +FILE * popen(const char * cmd, const char * mode) +{ + return popen_as_restr_user(cmd, mode, false); +} + +extern "C" int pclose(FILE * f) { if (f != s_popen_file) { @@ -174,3 +303,46 @@ else return exitcode << 8; } + +// Test program +#ifdef TEST + +int main(int argc, char **argv) +{ + bool restricted = false; + int ai = 1; + if (argc > 1 && !strcmp(argv[ai], "-r")) { + restricted = true; + ai++; + } + if (ai + 1 != argc) { + printf("Usage: %s [-r] \"COMMAND ARG...\"\n", argv[0]); + return 1; + } + const char * cmd = argv[ai]; + + printf("popen_as_restr_check() = %s\n", (popen_as_restr_check() ? "true" : "false")); + printf("popen_as_restr_user(\"%s\", \"r\", %s):\n", cmd, (restricted ? "true" : "false")); + FILE * f = popen_as_restr_user(cmd, "r", restricted); + if (!f) { + perror("popen_as_restr_user"); + return 1; + } + + int cnt, c; + for (cnt = 0; (c = getc(f)) != EOF; cnt++) + putchar(c); + printf("[EOF]\nread %d bytes\n", cnt); + + int status = pclose(f); + + if (status == -1) { + perror("pclose"); + return 1; + } + printf("pclose() = 0x%04x (exit = %d, sig = %d)\n", + status, WEXITSTATUS(status), WTERMSIG(status)); + return status; +} + +#endif diff -Nru smartmontools-7.1/os_win32/update-smart-drivedb.nsi smartmontools-7.3/os_win32/update-smart-drivedb.nsi --- smartmontools-7.1/os_win32/update-smart-drivedb.nsi 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/os_win32/update-smart-drivedb.nsi 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -; -; smartmontools drive database update NSIS script -; -; Home page of code is: http://www.smartmontools.org -; -; Copyright (C) 2011-13 Christian Franke -; -; SPDX-License-Identifier: GPL-2.0-or-later -; -; $Id: update-smart-drivedb.nsi 4760 2018-08-19 18:45:53Z chrfranke $ -; - - -;-------------------------------------------------------------------- -; Command line arguments: -; makensis -DBRANCH= update-smart-drivedb.nsi - -!include "FileFunc.nsh" - -Name "update-smart-drivedb" -Caption "Update smartmontools drivedb.h" -OutFile "update-smart-drivedb.exe" - -SetCompressor /solid lzma - -XPStyle on -InstallColors /windows - -Page instfiles - -Section "" - - SetOutPath $INSTDIR - -!ifdef BRANCH - StrCpy $0 "branches/${BRANCH}" - Push $0 - Call Download - IfErrors 0 endload -!endif - - StrCpy $0 "trunk" - Push $0 - Call Download - IfErrors 0 endload - MessageBox MB_OK "Download failed" /SD IDOK - Abort "Download failed" - endload: - - ; Check syntax - Delete "drivedb.h.error" - IfFileExists "smartctl-nc.exe" 0 endsyntax - ExecWait '.\smartctl-nc.exe -B drivedb.h.new -P showall' $1 - StrCmp $1 "0" endsyntax - Rename "drivedb.h.new" "drivedb.h.error" - MessageBox MB_OK "drivedb.h.error: rejected by smartctl, probably no longer compatible" /SD IDOK - Abort "drivedb.h.error: rejected by smartctl, probably no longer compatible" - endsyntax: - - ; Keep old file if identical - Delete "drivedb.h.lastcheck" - IfFileExists "drivedb.h" 0 endcomp - Call Cmp - IfErrors changed 0 - DetailPrint "drivedb.h is already up to date" - MessageBox MB_OK "$INSTDIR\drivedb.h is already up to date" /SD IDOK - Delete "drivedb.h.new" - DetailPrint "Create file: drivedb.h.lastcheck" - FileOpen $1 "drivedb.h.lastcheck" w - FileClose $1 - Return - changed: - Delete "drivedb.h.old" - Rename "drivedb.h" "drivedb.h.old" - - endcomp: - Rename "drivedb.h.new" "drivedb.h" - MessageBox MB_OK "$INSTDIR\drivedb.h updated from $0" /SD IDOK - -SectionEnd - -Function .onInit - ; Install in same directory - ${GetExePath} $INSTDIR -FunctionEnd - -; Download from branch or trunk on stack, SetErrors on error -Function Download - Pop $R0 - DetailPrint "Download from $R0" - - ; SVN repository read-only URL - ; (SF code browser does not return ContentLength required for NSISdl::download) - StrCpy $R1 "http://svn.code.sf.net/p/smartmontools/code/$R0/smartmontools/drivedb.h" - - DetailPrint "($R1)" - - NSISdl::download $R1 "drivedb.h.new" - Pop $R0 - DetailPrint "Download: $R0" - ClearErrors - StrCmp $R0 "success" 0 err - - ; File must start with comment - FileOpen $R0 "drivedb.h.new" r - FileReadByte $R0 $R1 - FileClose $R0 - ClearErrors - StrCmp $R1 "47" 0 +2 - Return - DetailPrint "drivedb.h.new: syntax error ($R1)" - -err: - Delete "drivedb.h.new" - SetErrors -FunctionEnd - -; Compare drivedb.h drivedb.h.new, SetErrors if different -; TODO: ignore differences in Id string -Function Cmp - ClearErrors - FileOpen $R0 "drivedb.h" r - FileOpen $R1 "drivedb.h.new" r - readloop: - FileRead $R0 $R2 - FileRead $R1 $R3 - StrCmp $R2 $R3 0 +2 - IfErrors 0 readloop - FileClose $R0 - FileClose $R1 - ClearErrors - StrCmp $R2 $R3 0 +2 - Return - SetErrors -FunctionEnd diff -Nru smartmontools-7.1/os_win32/update-smart-drivedb.ps1.in smartmontools-7.3/os_win32/update-smart-drivedb.ps1.in --- smartmontools-7.1/os_win32/update-smart-drivedb.ps1.in 1970-01-01 00:00:00.000000000 +0000 +++ smartmontools-7.3/os_win32/update-smart-drivedb.ps1.in 2022-02-23 21:47:28.000000000 +0000 @@ -0,0 +1,840 @@ +# +# smartmontools drive database update script for Windows +# +# Home page of code is: https://www.smartmontools.org +# +# Copyright (C) 2022 Christian Franke +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# $Id: update-smart-drivedb.ps1.in 5332 2022-02-23 21:47:28Z chrfranke $ +# + +<# + .SYNOPSIS + Update smartmontools @VERSION@ drive database. + + .DESCRIPTION + update-smart-drivedb.ps1 updates SCRIPTDIR/drivedb.h from + branches/@DRIVEDB_BRANCH@ of smartmontools SVN repository. + + The downloaded file is verified with OpenPGP/GPG key ID 721042C5. + The public key block is included in the script. + + .PARAMETER Smartctl + Use this smartctl executable for syntax check ('-Smartctl -' to + disable). The default is smartctl.exe in script directory. + + .PARAMETER UrlOf + Use the URL of one of the following locations for download: + github (GitHub mirror of SVN repository) + sf (Sourceforge code browser) + svn (SVN repository) + svni (SVN repository via HTTP instead of HTTPS) + trac (Trac code browser) + The default is 'svn'. + + .PARAMETER Url + Download from this URL. A valid OpenPGP/GPG signature with '.raw.asc' + extension must also exist unless '-NoVerify' is also specified. + + .PARAMETER File + Copy from local file. A valid OpenPGP/GPG signature 'FILE.raw.asc' + must also exist unless '-NoVerify' is also specified. + + .PARAMETER Trunk + Download from SVN trunk. This requires '-NoVerify' because the trunk + versions are not signed. + + .PARAMETER Branch + If '-Branch X.Y' is specified, download from + branches/RELEASE_X_Y_DRIVEDB. This also selects the OpenPGP/GPG key + for older branches (5.40 to 6.6: Key ID DFD22559). + + .PARAMETER Insecure + Don't abort download if certificate verification fails. This option + is also required if a HTTP URL is selected with '-UrlOf' option. + + .PARAMETER NoVerify + Don't verify signature with GnuPG. + + .PARAMETER Force + Allow downgrades. By default, the database is not replaced with an + older version of the same branch. + + .PARAMETER ExportKey + Print the OpenPGP/GPG public key block. + + .PARAMETER DryRun + Print download commands only. + + .PARAMETER Quiet + Suppress info messages. + + .PARAMETER Drivedb + Destination drive database file. + The default is drivedb.h in script directory. + + .EXAMPLE + update-smart-drivedb.ps1 + /INSTALLPATH/drivedb.h 7.2/5225 updated to 7.2/5237 + + (Regular update) + + .EXAMPLE + update-smart-drivedb.ps1 -Force -File /INSTALLPATH/drivedb.h.old + /INSTALLPATH/drivedb.h 7.2/5237 downgraded to 7.2/5225 + + (Revert to previous version) + + .EXAMPLE + update-smart-drivedb -Trunk -NoVerify -Smartctl - drivedb-trunk.h + drivedb-trunk.h 7.3/5254 newly installed (NOT VERIFIED) + + (Download the database from SVN trunk to current directory) + + .LINK + https://www.smartmontools.org/ +#> + +param ( + [string]$Smartctl, + [string]$UrlOf, + [string]$Url, + [string]$File, + [switch]$Trunk, + [string]$Branch, + [switch]$Insecure, + [switch]$NoVerify, + [switch]$Force, + [switch]$ExportKey, + [switch]$DryRun, + [switch]$Quiet, + #[switch]$Verbose, # Common parameter + [Parameter(Position=0)][string]$Drivedb +) + +$ErrorActionPreference = "Stop" + +# Set by config.status +# Default drivedb.h update branch +$default_branch="@DRIVEDB_BRANCH@" + +# GnuPG used to verify signature (disabled if empty) +$gpg = "@gnupg@" + +# Name and Directory of this script +$myname = $MyInvocation.MyCommand.Name +$mydir = Split-Path -Path $MyInvocation.MyCommand.Source +if (!$mydir) { + throw "Unknown script directory" +} + +# Default drivedb location +$default_drivedb = "$mydir\drivedb.h" + +# Default command used for syntax check +$default_smartctl = "$mydir\smartctl" + +function error($message) +{ + # Echo error messages to stdout because 'Write-Error' + # always writes a full 'ErrorRecord' to stderr. + echo "${myname}: $message" + exit 1 +} + +function warning($message) +{ + echo "${myname}: (Warning) $message" +} + +function iecho($message) +{ + if (!$script:Quiet) { + echo $message + } +} + +function vecho($message) +{ + $message | Write-Verbose +} + +function test_f($file) +{ + return Test-Path -PathType Leaf -LiteralPath $file +} + +function touch($file) +{ + if (Test-Path -PathType Leaf -LiteralPath $file) { + (Get-Item $file).LastWriteTime = Get-Date + } else { + New-Item -ItemType File -Path $file | Out-Null + } +} + +function cmp($file1, $file2) +{ + if (!( (Test-Path -PathType Leaf -LiteralPath $file1) ` + -and (Test-Path -PathType Leaf -LiteralPath $file2))) { + return $false + } + return (Get-FileHash $file1).hash -eq (Get-FileHash $file2).hash +} + +function rm_f # FILE... +{ + foreach ($file in $args) { + if (Test-Path -PathType Leaf -LiteralPath $file) { + Remove-Item $file + } + } +} + +function rm_rf($dir) +{ + if (Test-Path -PathType Container -LiteralPath $dir) { + Remove-Item -Recurse $dir + } +} + +function mv_f($oldfile, $newfile) +{ + rm_f $newfile + Rename-Item $oldfile $newfile +} + +function selecturl($url_of, [ref]$url) +{ + switch ($url_of) { + 'github' { + # https://github.com/smartmontools/smartmontools/raw/origin/$branch/smartmontools/drivedb.h + # https://github.com/smartmonto ols/smartmontools/raw/master/smartmontools/drivedb.h + # redirected to: + $u = 'https://raw.githubusercontent.com/smartmontools/smartmontools/master/smartmontools/drivedb.h' + } + 'sf' { $u = 'https://sourceforge.net/p/smartmontools/code/HEAD/tree/trunk/smartmontools/drivedb.h?format=raw' } + 'svn' { $u = 'https://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools/drivedb.h' } + 'svni' { $u = 'http://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools/drivedb.h' } + 'trac' { $u = 'https://www.smartmontools.org/export/HEAD/trunk/smartmontools/drivedb.h' } + default { error "${url_of}: is none of 'github sf svn svni trac'" } + } + $url.Value = $u +} + +function vcopy($src, $dest) +{ + if ($script:DryRun) { + echo "Copy-Item $src $dest" + } else { + vecho "Copy-Item $src $dest" + Copy-Item $src $dest + } +} + +function download($url, $file, [ref]$errmsg) +{ + $req = @{ Uri = $url; OutFile = $file; MaximumRedirection = 0 } + if ($script:Insecure) { + # #Requires -Version 6 + $req += @{ SkipCertificateCheck = $true } + } + + $errmsg.Value = "" + if ($script:DryRun) { + echo "Invoke-WebRequest $(echo @req)" + } else { + try { + Invoke-WebRequest @req + } catch { + if ($_.Exception.Message) { + $errmsg.Value = $_.Exception.Message + } else { + $errmsg.Value = "Unknown error" + } + } + } +} + +function check_file($file, $firstchar, $minsize, $maxsize) +{ + # Check file size + $size = (Get-Item -LiteralPath $file).Length + if ($size -lt $minsize) { + return "too small file size $size bytes" + } + if ($size -gt $maxsize) { + return "too large file size $size bytes" + } + + # Check first chars + switch ((Get-Content -LiteralPath $file -TotalCount 1).ToCharArray()[0]) { + "$firstchar" { } + "<" { return "HTML error message" } + default { return "unknown file contents" } + } + + return "" +} + +function unexpand_svn_id($source, $dest) +{ + # For -NoNewLine: + #Requires -Version 5 + (Get-Content -Raw -Path $source) -replace ` + ('\$'+'Id: drivedb\.h [0-9][0-9]* 2[-0-9]* [012][:0-9]*Z [a-z][a-z0-9]* \$'),('$'+'Id'+'$') ` + | Set-Content -NoNewLine -Path $dest +} + +function selectkey($branch, [ref]$key) +{ + switch -RegEx ($branch) { + '^RELEASE_(5_4[0-3]|6_[0-6])_DRIVEDB$' { +# Smartmontools Signing Key (ext. to 2024) +# Smartmontools Signing Key (through 2018) +# Smartmontools Signing Key (through 2018) +# Key ID DFD22559 + $key.Value = ` +'-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFgOYoEBCAC93841SlFmpp6640hKUvZ8PbZR6OGnZnMXD6QRVzpibXGZXUDB +f6unujun5Ql4ObAWt6QuRqz5Gk2gF8tcOfN6edR/uK5gyX2rlWVLoZKOV91a3aDI +iIDh018tLWOpHg3VxgHL6f0iMcFogUYnD5zhC5Z2GVhFb/cVpj+ocZWcxQLQGPVv +uZPUQWrvdpFEzcnxPMtJJDqXEChzhrdFTXGm69ERxULOro7yDmG1Y5xWmhdGnPPM +cuCXVVlADz/Gh1w+ay7RqFnzPjqjQmHAuggns467TJEcS0yiX4LJnEoKLyPGen9L +FH6z38xHCNt4Da05/OeRgXwVLH9M95lu8d6TABEBAAG0U1NtYXJ0bW9udG9vbHMg +U2lnbmluZyBLZXkgKGV4dC4gdG8gMjAyNCkgPHNtYXJ0bW9udG9vbHMtZGF0YWJh +c2VAbGlzdGkuanBiZXJsaW4uZGU+iQFBBBMBAgArAhsDBQkPZe4NBgsJCAcDAgYV +CAIJCgsEFgIDAQIeAQIXgAUCXheK5gIZAQAKCRDzh2PO39IlWdUTCAC8v9Oa7umW ++/tXBiEtElDW/U2rEOC3OHWSzPvqE4iGjWc5fbvrAKS7bfccZM8Aq0a1t2pSbIlB +MvRrsNTGdQSPsOdhxPD8pEJW0uH9Z5VyPzoO9VIaoqi1irRdWnXCfhBJX9PLySAb +9BPQZXXQypmACieRDv31E4hiB+vYet/SpVuRyfL57XU3jmwFREip9OiFOp+61X2+ +oIlgvNU60JZy2vXpTo6PNbDGetEycfH6Y8vfCXniihMkSfeOnNqWI/hycBDprFB5 +CB5ShIH71vhCOPnVGwtYY30wlJ1+Ybg2ZAIi6JN8E38Dpx382IzeT2LydnZydiC6 +PcLCr7mbsX3hiQEcBBMBAgAGBQJeF4sWAAoJEC/N7AvTrxqr7ZAH/jB4xFtBTo1x +w8CGwslZCJ+/BeEZ5XpV+8zLdeRV2tXegUFjGZ9FI6UpzBeVyK2R1qGbcdSf2S45 +KutcM2gjKETW+ZwW76qHJD52mYihPPLXu2pRAG2WyH5GDnqNMj5iQ1inoPdZOTpi +evBMTv1YHJML6SiF6t/HoKorl5ffvHBE/1onBfUzLwQ/ct14sZ2UXHzyxdHo73vm +XWgcjQ1TQhCSdLqucQbwR78EyUa9tYxk/NWBqfc5YHt7t+KTVTLlp7Buk1wscLkj +NTlxl+IjAxRwsWc6PWnyRdAgXxtt2q6llYgFahWM21OyJVLVjbMGVF+oBtFumqq3 +lQy6H6tp/1uJAhwEEwECAAYFAl4XiyMACgkQvwsznGS8qosSiw//QjbWDldB2gHf +3Tfs+LaFdzkDbioWdnj96DiCynTSwZF8d5ISqwA+QTL/43Y0msU26WBMvIRBg2Xm ++r4TMMfWF4a1Yjq6cisKEaUsbjV9ztzH/XB2ydo8HgnxZuVKQoIuh1sSrE7p6mpQ +YUrV5eWRpqc79AI9ZzRBM5nhbBejqLVw2F8dyz6c3lfGM9IOenp+Y8N43SdNpBcp +DuHnzbQIMtkyoX7tTKDDv5gnoRNCsdBsCduTyNWYOIEdhRiCfo5Ce7kufIoo4ZqV +BM8dzwm1RrcYa0kMKPZAucJDRjwevEYDbOg7vmEYsuGPRbVmOFdx4uMx4gX8vF5+ +AG3rTSA805zkwD+WQXyYQohVZxNjeK7P/ukr6NCZx226gwAiw1ms7PYOo8snjK8e +nRlMTLKiGiMIH7xJu55JliVlcEvn3G7WO0n4qQOJj3Msh+xflBSfZmzBDAzPgxwC +m/RSmonGV0uZVJFDHCpqus35E6bzFF6yO3yXvpngAMTBrpX6Nzgea1SzlK2Iquls +te1GYAx/IXaY7cVYo4iEv/m346SINzLGHpXZkbbcenSgljBfHLCz7vF33IotfEWh +C7Kb4iKbEjERa+zzqR+vK+nDj6YG9Mvguj1EqnM47oDwgMaqWY6oPfefLCD8Tg51 +rlAAGFdcWb9g034vgtK8l+ooUtn63PKJAhwEEwECAAYFAl4XiywACgkQ6nSrJXIQ +QsUuTRAAsSMmQ7jsvmljExwrmIu6Oyh+1J5D/GPBRYhSyip/bnxCscCBnpjEk8+7 +VG9JtGTCa0zVY14Y3Cl4obND25QN9LhiE/y8olnIgJ2adtmpi6+zFpdGWVYUpDgZ +IMePUVKyZenTjezFwRlLsYsxbSb9wIR1iofP1l/dQF8DwhwFL9AGRmHTcWM1ZYoc +fv80A5SAposnspnkKKcuC3q2+pMsUtbHT9t/+iusVXBDERh+FPlvtYh+Khze3c8z +g4M9RsQLCanMp4jZhzgSakjeg9tCr33SIJIEKpn6MUftX9QC82S75UNwxXgC38EA +s2t+BjPLUaXENSdOe3l+KKY5ozbmRpRmQIHw7jlT3+9C0RUHGTPQYCidsx8OdYA0 +4wDRWcjCQcXWxTaUoeaoMJcE1iv5IIf/X0MXYMlCPG8OKAlDE2Kkrx0A8agPp7JH +0UAOaqpAA74kZnpuvJ6BqrX2hMbNbyVg1rWu1BQA3qESa41rKiWyEtjiLdQ/NtNu +6BsPhDGvaQqGbu4t0GfJ1PhbFnHrVkLW8v1NzYZRpLXAFJGZdD6Ue/L6bHFOJ6SJ +JwAHjH26nxSMuDV779AUrnOcmoXIkj6sdAwDZ5Z2ri7b2MgkrJzeapKd0SItnWUQ +TMe7YUl8B+kUATj01YWMLtHsX9yciFP0iDagW14/rFJHtchOBcu0U1NtYXJ0bW9u +dG9vbHMgU2lnbmluZyBLZXkgKHRocm91Z2ggMjAxOCkgPHNtYXJ0bW9udG9vbHMt +ZGF0YWJhc2VAbGlzdGkuanBiZXJsaW4uZGU+iQE+BBMBAgAoAhsDBgsJCAcDAgYV +CAIJCgsEFgIDAQIeAQIXgAUJD2XuDQUCXheK5gAKCRDzh2PO39IlWTDxCACtkOGn +vUs/m/uE7IHoSM6wj/6OXXo+TEM1rgnl40oySVoMgyonx7PSwi9rSoDC8AfRhN2q +bFLEQcrGI8V7PxLpjsz5Z0m/ZnZJAP7TB5WhLRJdu3w2cssjekhIRc+I2B00gcRl +H//okXyvGte3kr1JdgaownbslwcZRxyNdvWigQH/Vnz91lKAujGULJyl7hv6Kl02 +HYynYmxGmES3pd5VEOpA/DR7n54T2J+Vubh99RT+RH2v46e7LnPhZhN2uxvIiJKE +8Lp67l1aeMXfgZv6dQ7Dl+pu5lUUyyMQ+nUMBGKZBWftyqhekZrvYcVnTJYU93kU +41QULaRVIwg888kUiQEcBBMBAgAGBQJZ7kylAAoJEC/N7AvTrxqroQQH/jrZAGT5 +t8uyzRTzJCf3Bco8FqwKcfw8hhpF1Uaypa+quxkpYz9PtP+3e9lGxl0XSEzOwHjf +gGWXISUOM1ufVxo2hSLG87yO7naFAtylL8l0Zny8Fb6kmT9f3vMktbHdXHUTDNrC +UkoElEwwDK3qaur8IPUaIKeSTC3C8E/DVnasLs9cpOs2LPIKr3ishbqbHNeWOgGy +HbA4KCtvQzBhun9drmtQJW6OyCC9FcIoqPSFM/bs2KHf7qATNu9kSMg/YWw7WLAD +4GPqH9us1GigQ0h6Y4KG5EgmkFvuQFPLHvT4rtqv51zzs1iwFh4+GIagFp+HJ2jn +lp+GcZcySlwfnemJAT4EEwECACgFAlnuSe4CGwMFCQQcDQAGCwkIBwMCBhUIAgkK +CwQWAgMBAh4BAheAAAoJEPOHY87f0iVZVMQIAK5wPezq0ROsxiCYPLcR9dF/Qdp2 +1pLfodi6wsC9FAlTVJ3fk2vkNQDb5rMkNvZ/MHf2EWoVIFHvPZcJ6paBjZlapvGF +qDNrU6hDbakO0PIej5yy+qVeIYcSQpNZeHchAhOOJcnN0o8H6SzZik38b4Hb8H5X +do78LsZJwU0jsKG6LH3gjiWJtrC+WCXCMYzEGjAJXev2npU2DMVVwxsfYLfdZWq7 +FJJINv8R9EUjtSQQIynJAwb2lFvZB+jC6u8Vv9N1Wid6wh5lF5ejMt6KXqWOvNn+ +YreopmQfbn2XJZxpyn9d7Ev91epYW11E5qG4xNI3m3AmtEGjMTGjfMUstNK0V1Nt +YXJ0bW9udG9vbHMgU2lnbmluZyBLZXkgKHRocm91Z2ggMjAxOCkgPHNtYXJ0bW9u +dG9vbHMtZGF0YWJhc2VAbGlzdHMuc291cmNlZm9yZ2UubmV0PokBPgQTAQIAKAIb +AwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAl4XiZMFCQ9l7g0ACgkQ84djzt/S +JVnl5Qf+PVRoLmEpDIqQ+58DMIwz98+yajCJ1vQvEOKjMcgeePOn475eV5Phkvsp +KtW6TedWhN9l/NcDZzEPCpkhrz24WJDLFV+o16B4MZwSkGTl4/3qijERKsd8M+MS +tiLr3+eUCFi4dAp0uhPytETvUmtj3ByA0R2luoOK+kEutq6i2x9BPr8Qc55Lqdwt +SK8pPU05WSaCu1m2oThJhkELVklOQ2cj+D8MrQdJGd3plEb9j5oUbhj7LW/y0i4M +lqk1rQCQKnY3vTFQBpj1o7T6kLiGqQCOLTX0B6RQ8vt+PEzXPHi0lIdwOrQk5l7h +utnjwXmWaWEpRjlsuQ5PBrFDsD9N+IkBHAQTAQIABgUCWA5kYwAKCRDfDxpJxKSQ +Op+/CADTlsgisoXI6b+0oohRaD4ZVl5eBtkvTrxNQf6EF7Z1uPkVOqi1OLWFGyAm +beLcRmN6c4/DVcaa6GAG7GA+KQwVPRCyC+9Ibsn/+uG6ZFXAez+0eG9NxOfkCnYH +8ZP8o2VH+9uKJlGGujh9o5r1SNGVifoLGTc8NkWCW+MAKj8dw8WW+wDc80YrdCRr +SyLrRU9NLTSE4pIJWKcHLwG63xkXHQPPR1lsJgzdAalfEv1TQdIF3sM+GXp4lZ6b +uahFDiILBh1vj+5C9TdpWZAlqHDYFICa7Rv/MvQa4O9UUl3SlN3sed8zwAmL3Heo +XE5tBu8iatMaS9e3BmSsVYlhd/q+iQEcBBMBAgAGBQJYDmSWAAoJEC/N7AvTrxqr +8HsH+QGQuhHYt9Syccd8AF36psyT03mqgbGLMZL8H9ngoa9ZqVMq7O8Aqz23SGTt +uNuw6EyrcHo7Dy1311GftshI6arsFNJxE2ZNGIfGocRxu9m3Ez+AysWT9sxz/haH +E+d58NTg+/7R8YWS1q+Tk6m8dA0Xyf3tMBsIJfj0zJvuGMbCLmd93Yw4nk76qtSn +9UHbnf76UJN5SctAd8+gK3uO6O4XDcZqC06xkWKl193lzcC8sZJBdI15NszC3y/e +pnILDDMBUNQMBm/XlCYQUetyrJnAVzFGXurtjEXQ/DDnbfy2Z8efoG8rtq7v3fxS +1TC5jSVOIEqOE4TwzRz1Y/dfqSU= +=3Lcg +-----END PGP PUBLIC KEY BLOCK----- +' + } + + '^RELEASE_7_[023]_DRIVEDB$' { +# Smartmontools Signing Key (through 2025) +# Smartmontools Signing Key (through 2020) +# Key ID 721042C5 + $key.Value = ` +'-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFwmhpUBEADRoOZaXq13MrqyAmbGe6FlHi6P9ujsT/SJGhTiAoN3W1X56Dbm +KP21nO9ZAjdXnvA2OmzppfCUX7v5Q3/TG3vN3WwfyQIO/dgSaTrGa1E8odbHEGc7 +rhzYA8ekAn3TmxhOrEUTcRIogumW0zlQewHOlTe0OYsxat6/N8l3Cqn28HwZUpRH +MrJW3RgefFihQGEhXlnfzo+Tltl14IriURbwBZIDeZOk2AWLGweI0+zqTgYSbF5A +tI5rXO1QDeoyBYZhSX3MtnncwPdCnxoRasizU5w3KoZWYyKAc5bxJBJgUUp9HDOu +ATgNqekc8j28x/cUAWerXe183SBYQp0QkzMPbmE9TCGW3GjtW+Kk/NDbNe8ufj6O +hk0r7EbGyBO0qvgzHLzSsQiSsgaMCkLc5Xt4NzB4g2DvnReFU2WwgRh031lHOVLm +mvFqRtHzJb20dKufyjOmSMzNKRzURVmobECKARaBlGNP0wHYhq97n4OxM1o0eq7a +4ugaSp2q+6BSaAQhbZN8ULCF/oGA/376Sz7RNuoOmQwl9aFqnfl3YgopBIqKvnSP +h4j0QynN45rUFOe/VywTmpWKj+DonGCupxe9VvyZ87NKRgKiHprXGDrhdB0GcNXM +wV66WbjKBV7qlpSh/GH3oiHwlcYT8LNyZbxTJXcVF5ODtlZfc9zqRtUBWQARAQAB +tFNTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjUpIDxzbWFy +dG1vbnRvb2xzLWRhdGFiYXNlQGxpc3RpLmpwYmVybGluLmRlPokCQQQTAQIAKwIb +AwUJDS6amwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAl/gnzECGQEACgkQ6nSr +JXIQQsW11g//UmnWOtIgozoqs6beK12NpZyubn/lecEd0yJPzed9cygKpObySBbT +5jz7e5IDGwFLDsTm9fE/2GoyvuVW/riyTsowxrYYleoKm4Pmv30crNruVM7mC7c8 ++rbwmx5ZlmHC1tMsM/BdIxK0gqHyAXxWmzyB/YDGElkWnq2/+wjEoARbROUoKQYL +qG6q6bv/DQvv4tq/Yw+fsaLZsR4Cou87hB3wAwR3rv3p3GC7N+if86fbkS8rQh5b +j3qwTHnf3ugyYz9iEy2pjrHqgnDMV227tP2UiC2ECy3u1Z7eQvMeN2r0x8EIB79D +G7ny7ML3QXsJG9Pamg4VHlMh+Sb23GE6rRQuv9m265PeS4/6CsbuHdGer+UaG78V +N4bfFhMWpE4sjDZlQZBcm6VLbExhuS89GI7+9zYMtLoXE6Z5Mz0XFjSKlzEK94UT +RPcDdcQUHW59NvhG77SvTKN5PHGbcs+0uQkUkvaOxoovio2vWcYANG4eIPC/YvPZ +9q7f/bhMDbKid7eIvtCgvijSiYKQLjt1FtJJZRYF/EESdWWNJTs2OgSFMgSDBE3K +Da5alJyx3+IlYFwvF/khtQnGeTB1XRIGL8G7UMaNzpvJQOAEbqEiznyqoo5cNpz+ +03wTOw9IGVJ2fcvg2g+j7ffKQfs+GDYWAqicSKHDYpW2csBAW/1QE62JARwEEwEC +AAYFAl/gnzoACgkQL83sC9OvGqvE0Af/XXZ4GWMf4rEB0G3lXr9L9bvX4a/tVWz0 +hag57D6By9R6cWNDpRtKx5R0Y1Fv+O+sPHptM3P6LUsWI0d7dEf307n34FxkI/vh +4W1g8ITvhYfJWmJTzA1kNAief45uNPx0QWhGlVf4nQzhe41XnuBdFhYfOkHGf6k8 +9SJ9qWRitzE657h6mVO0EKqvjTld8w6lR2rA+oHPQnc9iDmXcZLfSTHP/NapQXPl +qtXiR1z0BkswBBaKCnJxVPpzjQA0W8jSyhQ4qPheMjOmVaFoQxZ4CbEaFI67EmVl +kwgwf+c6BlKr3DoOca/KmHYT/9dqUv1gfoYYTCm+ATN76vYCG794EokCHAQTAQIA +BgUCX+CfRQAKCRC/CzOcZLyqiwQWD/9eNQNnKWxkYL3qjSRt0DwUUaCcFDoj40rb +fRxWdU+LZKL7KjAWoRhdfaH7T30wZ9NFenrQXaU/QzuYioz1sHRwIIRYyUp2s0Jc +VHAIuOPjk6Q3TDVnbEm0AO0Er32gdxC0DYk4RfGp95n1Aw1kd2BSvKPJuZSRJrIV +f8iU3Im1KT4Avl7Fw7FEojQMMvn/qZzeo2pk/QdrrK3KnHkQwy2edx/szY82o2a5 +g5WarFFRcxVS2H/xrvNMGUL4TsWcGd3Z2oHoZ0u5A20/PpT2xG1LGXGEwBAqtMS2 +6iRAzbQFkkLhcdETTvOSqkDWkzr7NqJ6adhLOEVXsHXNLx23p1Tn+Li/ezpQ6/eQ +QDPclU19BjARmfInDq0w5V1q0RNET1J2Xu+Adxtq+Dl8TyhCmJMzO8e4htYnIRZu +90iSgZdt5cZgoH04weXCMwDugn/+Q3rzKvRUTrEfSOivJYg65D/mhbz6HoUTs4JD +SstTYa9qNCwKQGRSeis4PAgu0hCpnDAhZuN3Ja5AFC2Wi2szQ7R+Zx/JucIBm5S4 +U30W66MtsyUHeulSJ3AV3HrbFfnqu6zfQM4XLw7MpAtQUNJceS/lWfGIquAp3tY/ +IjZIHwgZqKB3czWDhM83wBzCWgAmxyzIrpb4MBYJ5PGuCyC7R/YTdtPJXxsPQl2l +znsX/9ssa4kBHAQTAQIABgUCX+CfSAAKCRDzh2PO39IlWVcuB/9UkLaPtGY4sDDV +/A7qjSvSy93mv8gkaIj9dhqoZw+r7cLiEtX04Cz9PqocOFgCYJXKrufHNNkHke2A +jE9EJfRKiPU/bkeWmrACvtrOd/DZbdmXfxTOekOr516D2ip/U8GBPw6zxfCQVot6 +htpBpB6zzMDtzMOeLnkOxoxR4EMu5K6eJ48bHvG/lbGBByyfRzhtqPh6AAA9G1CC +IdhNkaA5W1qums3N1mCXrTBnWyjaFhdnttGQfrMdHvTQ77HeL0c2axT2y5PYfrXY +2ZfZowYLEtFXRSTpDaJfgG+qem3N+pMv6SMOG/4CvlH4/3Hq0aCNvKcY5KUXfIgT +xmc3/n/wtFNTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjAp +IDxzbWFydG1vbnRvb2xzLWRhdGFiYXNlQGxpc3RpLmpwYmVybGluLmRlPokCPgQT +AQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAl/gnzAFCQ0umpsACgkQ +6nSrJXIQQsVK7RAAqbZfT3wZEfJkw8MK2JlvgGWH76fHKn5ZoH5i0mA4AvN4QLbU +5Q20HmqHnO9mfAZQ6u4Tn/aFcYT7nlSsEsEmFX+s5QU2y6m2Tx9ThDbZ03ezREOS +0wNf0FOQunV9ZVPT/7cKIgWJa5mZy+LClor9OHllyGUfs9tKNzwxaHh1zBrCNJow +Fi/1bkWy3iMc7vZhWHASwPSp64KHjB4UdMz2hV4pROiUhWi7BY0exIHyZrkcANMP +Hhl9lP32ZvNbOy8osBdPUgXyK3HePD+ftcwJMkoc4mFQXYi9UY7NQpk7STRO10cx +Kq/CgDDvYxbnViRjQoJ0sfwKCaOfsnY/gea7I0aCx8uNISYpHO9iMidd/tJ7+lgx +NiKZTI0EppHYvkyMY15/NGb0gTJbYjuVYdbqDS9mnLuLQAjAX43+n9ND2NjX1o0q +Z9bBqV2VFioNmnxKqGphhRFX9jEzTklieOjhpRrd8v9ljprT6vLFNpYpeLkel8om +VFXrHxrfzKtVFcto5wqHVOcyZyE2zm1QmsS8qvWOTrNfY6p2q9MA2rysqdfgfvN7 +pNDaXutK6ooQi6YlyyTA2ANnHFKa0ncRH+dg+5OF9rhNvM7RyaBXgxF7+5gnU5Gb +VQRKbJ+LOtSKkj0pApR5AKSwyGslZ2bNVlKsADWhk5xj8QlHVlNWiht+i/6JARwE +EwECAAYFAlwmhpwACgkQL83sC9OvGqsVOggAqLB5eQrUv8E9ikD6kJCito827bzD +WF29yD7PvfhjXaz5in54jOVpwg3o9CsqIjjRW0/1bBVswC8ZL0sAdZ+GDSDMw5F2 +IpkD77gjnFY79M/e6C9xYyxYzHC7emDPSz9IroOvdkkEgrB+OABKkaOCcS18P4Lk +3WNHaPw5c7aI0z1iJP52EmSfvB8r86mtUFJB+f15eD/4vaRfkZLFjF9FQ3kgEK1U ++rV4s1O2bCFfP3WPDcc83NgwRUvtXmcSOSOIoXnemJzyJr+JnqCWVET4XWF6i20m +RFXVEpWtf5AkJYgR3z/jW0djELbBWA/35bAnpXy5pDHv9NbZsTkBZxK/kokBHAQT +AQIABgUCXCaGnQAKCRAY7NpGy/a6xn4lB/90tXTnZsgmoftol9uivfQrPdR88WmO +ZLYmUeQAd1rqSFMxe+KzO/qLuU8s6OF4nznwL2cPfbGZxezM4PiYmAmbbEU/3gTO +NwjVBBA0Gfimy/fITEezFtCigo1thkaJ195g/dqY+zE3Vt4rzC03j1vx8mUHRPU6 +kkvKj8cP0j+XHX2xQDsTXTstfnom29wBmGnvSZ9HgcdL71e1VXJXwikmnO3P4J/1 +C2LeCOlWrGqWZ2c0WBLKdJnsYUx7Dm/OvkkB4lF+zWp98zS8jS/5h+1apVgEzrdT +MvT8ydTkUr7ObKGkIhK+L+Xo5BD+V9Qf6xKGYPwhhdj/E5/kyjULrm10iQEcBBMB +AgAGBQJcJoadAAoJEPOHY87f0iVZfiUH/3yKS5wGvTeRInse8+W1WzKuto3XzqXL +ngb9QXWw7nCwqmNS7PbzDnufQi2ThKrMfcK14WgNYABNZPU75I+6bcb0oCB5tloo +IUEV/2Ut/5Hl/83zFFoNA/kQKVz8kIDqgRcxC+zY2VJ4eTKHyQDvXygVk8wnKTBa +e3gX+CIZqJHPXiiygHlbl31Mi3G1Iaxu57dP6ocV0vX1dytKSwd4Rbviwwb4L76o +/tVT9t3GwFM15uK1SqtnAaiaktEdMi3XI4d01H3VUVz/iR0XQbf13RZoEM6CJWms +Q/qvYlwkbKOdlahjoHrFlkhADSBaO9N1OZp3OYDjziIujMdt2IPKnmM= +=7MQk +-----END PGP PUBLIC KEY BLOCK----- +' + } + + default { + error "No known public key for branches/${branch}" + } + } +} + +function run_join_out_err($cmd) # $arg1, $arg2, ... +{ + $cmdobj = Get-Command -CommandType Application -Name $cmd + # Don't prepend $input with BOM + $enc = [Console]::InputEncoding + [Console]::InputEncoding = [System.Text.UTF8Encoding]::new() + $ErrorActionPreference = "Continue" # Don't abort command on first stderr output + $LASTEXITCODE = 42 + # Run command and convert ErrorRecords from stderr to plain Strings + $($input | & $cmdobj @args 2>&1) | %{ $_.ToString() } + $ErrorActionPreference = "Stop" + [Console]::InputEncoding = $enc +} + +function gpg_verify($ascfile, $file, [ref]$ok) +{ + # Create temp home dir + if (!$env:TEMP) { error "Environment variable TEMP is not set" } + $gnupgtmp = Join-Path $env:TEMP "gnupg.$(New-Guid)" + rm_rf $gnupgtmp + New-Item -Type Directory -Path $gnupgtmp | Out-Null + + # Import public key + $env:LC_MESSAGES = "C" + $out = ($public_key | run_join_out_err $gpg "--batch" "--no-tty" "--homedir=$gnupgtmp" "--import") + if ($LASTEXITCODE -ne 0) { + echo $out + exit 1 + } + vecho $out + + # Verify + $out = run_join_out_err $gpg "--batch" "--no-tty" "--homedir=$gnupgtmp" "--verify" $ascfile $file + if ($LASTEXITCODE -eq 0) { + vecho $out + $ok.Value = $true + } + else { + # print gpg error always + echo $out + $ok.Value = $false + } + + # Stop the gpg-agent possibly started by gpg + if ($gpgconf) { + $out = run_join_out_err $gpgconf "--homedir=$gnupgtmp" "--kill" "gpg-agent" + if ($LASTEXITCODE -ne 0) { + echo $out + } + } + + # Remove temp home dir + try { + rm_rf "$gnupgtmp" + } catch { + warning "$_" + } +} + +function get_db_version($file) +{ + $x = (Select-String -CaseSensitive -Pattern '^[ {]*"VERSION: *[^"]*"' -Path $file).Line ` + -replace '^[ {]*"VERSION: ([1-9][./0-9]* [^"]*)".*$','$1' + $v = $x -replace ' .*$','' + if ($v -match '^[1-9][.0-9]*$') { # trunk: get rev from expanded SVN-Id + $r = $x -replace '^[^$]*\$Id: drivedb\.h ([1-9][0-9]*) .*$','$1' + if (!($r -match '^[1-9][0-9]*$')) { + $r = "?" + } + $v = "$v/$r" + } elseif (!($v -match '^[1-9][./0-9]*$')) { + return "" + } + return $v +} + +function mv_all($prefix, $old, $new) +{ + mv_f "${prefix}${old}" "${prefix}${new}" + mv_f "${prefix}${old}.raw" "${prefix}${new}.raw" + if (test_f "${prefix}${old}.raw.asc") { + mv_f "${prefix}${old}.raw.asc" "${prefix}${new}.raw.asc" + } else { + rm_f "${prefix}${new}.raw.asc" + } +} + +# Set defaults +if (!$Smartctl) { + $Smartctl = $default_smartctl +} + +if ($Branch) { + $brname = $Branch -replace '^([567])\.([0-9][0-9]*)$','RELEASE_$1_$2_DRIVEDB' + if ($brname -eq $Branch) { + error "invalid branch version '${Branch}'" + } +} else { + $brname = $default_branch +} + +if (!$Drivedb) { + $Drivedb = $default_drivedb +} + +if ($ExportKey) { + $key = "" + selectkey $brname ([ref]$key) + echo $key + exit 0 +} + +# Check selected source +if (!$Url -and !$File) { + if (!$UrlOf) { + $UrlOf = "svn" + } + $Url = "" + selecturl $UrlOf ([ref]$Url) + if (!$Trunk) { + $Url = $Url -replace "/trunk/","/branches/$brname/" + $Url = $Url -replace "/master/","/origin/$brname/" + } elseif (!$NoVerify) { + error "'-Trunk' requires '-NoVerify'" + } +} elseif (!$UrlOf -and $Url -and !$File) { + if (!($Url -match '^[a-z][a-z0-9]*:[^ ][^ ]*$')) { + error "${Url}: Invalid URL" + } +} elseif (!$UrlOf -and !$Url -and $File) { +} else { + error "only one of '-UrlOf', '-Url', '-File' is allowed" +} + +# Determine path of signature file +$FileAsc = "" +$UrlAsc = "" +if (!$NoVerify) { + if (!$Url) { + $FileAsc = "${File}.raw.asc" + } elseif ($Url -match '\?') { + $UrlAsc = $Url -replace '\?','.raw.asc?' + } else { + $UrlAsc = "${Url}.raw.asc" + } +} + +# Check option compatibility +if ($UrlOf -eq "svni") { + if ($Insecure) { + $Insecure = $false + } + else { + error "'-UrlOf svni' requires '-Insecure'" + } +} + +# Check for smartctl +if ($Smartctl -ne "-") { + if (!(Get-Command -Type Application -Name $Smartctl -ErrorAction Ignore)) { + error "${Smartctl}: not found ('-Smartctl -' to ignore)" + } +} + +# Check for GnuPG +$gpgconf = "" +if (!$NoVerify) { + $gpgobj = $null + if ($gpg) { + $gpgobj = Get-Command -Type Application -Name $gpg -ErrorAction Ignore + } + if (!$gpgobj) { + error "GnuPG is not available ('-NoVerify' to ignore)" + } + $public_key = "" + selectkey $brname ([ref]$public_key) + # Check for gpgconf in same directory + $gpgconf = "gpgconf" + $gpgconfobj = Get-Command -Type Application -Name $gpgconf -ErrorAction Ignore; + if (!($gpgconfobj -and ((Split-Path $gpgobj.Source) -eq (Split-Path $gpgconfobj.Source)))) { + $gpgconf = "" + } +} + +# Remove possible garbage from last download +if (!$DryRun) { + rm_f "${Drivedb}.new" "${Drivedb}.new.raw" "${Drivedb}.new.raw.asc" +} + +if ($Url) { + # Download + vecho "Download drivedb.h" + $errmsg = "" + download $Url "${Drivedb}.new" ([ref]$errmsg) + if ($errmsg) { + rm_f "${Drivedb}.new" + error "drivedb.h: download failed: $errmsg" + } + + if ($UrlAsc) { + vecho "Download drivedb.h.raw.asc" + download $UrlAsc "${Drivedb}.new.raw.asc" ([ref]$errmsg) + if ($errmsg) { + rm_f "${Drivedb}.new" "${Drivedb}.new.raw.asc" + error "drivedb.h.raw.asc: download failed: $errmsg ('-NoVerify' to ignore)" + } + } +} else { + # Copy from local file + if (!(test_f $File)) { + error "${File}: file not found" + } + if ($FileAsc -and !(test_f $FileAsc)) { + error "${FileAsc}: file not found ('-NoVerify' to ignore)" + } + + vcopy $File "${Drivedb}.new" + if ($FileAsc) { + vcopy $FileAsc "${Drivedb}.new.raw.asc" + } +} + +if ($DryRun) { + exit 0 +} + +# Check files and adjust timestamps +$errmsg = check_file "${Drivedb}.new" '/' 10000 1000000 +if ($errmsg) { + rm_f "${Drivedb}.new.raw.asc" + mv_f "${Drivedb}.new" "${Drivedb}.error" + error "${Drivedb}.error: $errmsg" +} +touch "${Drivedb}.new" + +if (test_f "${Drivedb}.new.raw.asc") { + $errmsg = check_file "${Drivedb}.new.raw.asc" '-' 200 2000 + if ($errmsg) { + rm_f "${Drivedb}.new" + mv_f "${Drivedb}.new.raw.asc" "${Drivedb}.error.raw.asc" + error "${Drivedb}.error.raw.asc: $errmsg" + } + touch "${Drivedb}.new.raw.asc" +} + +# Create raw file with unexpanded SVN Id +# (This assumes newlines are LF and not CR/LF) +unexpand_svn_id "${Drivedb}.new" "${Drivedb}.new.raw" + +# Check whether installed file is identical +$equal = $false +if (test_f $Drivedb) { + if (!(test_f "${Drivedb}.raw")) { + # Create missing raw file + unexpand_svn_id "${Drivedb}" "${Drivedb}.raw" + } + # Ignore missing Id keyword expansion in new file + if ( (cmp "${Drivedb}.raw" "${Drivedb}.new.raw") ` + -and ( (cmp "${Drivedb}" "${Drivedb}.new") ` + -or (cmp "${Drivedb}.raw" "${Drivedb}.new"))) { + $equal = $true + } +} + +if (!$NoVerify) { + # Verify raw file + $ok = $false + gpg_verify "${Drivedb}.new.raw.asc" "${Drivedb}.new.raw" ([ref]$ok) + if (!$ok) { + mv_all $Drivedb ".new" ".error" + if ($equal) { + warning "${Drivedb}: *** installed file is identical to broken new file ***" + } + error "${Drivedb}.error.raw: *** BAD signature or outdated key ***" + } +} + +# Get version +$newver = get_db_version "${Drivedb}.new" +if (!$newver) { + if (!$Force) { + mv_all $Drivedb ".new" ".error" + error "${Drivedb}.error: no VERSION information found ('-Force' to ignore)" + } + $newver = "?/?" +} elseif ($newver -match '/\?$') { + if (!$Trunk) { + mv_all $Drivedb ".new" ".error" + error "${Drivedb}.error: VERSION information is incomplete ('-Trunk' to ignore)" + } +} + +if ($Smartctl -ne "-") { + # Check syntax + run_join_out_err $Smartctl -B "${Drivedb}.new" -P showall | Out-Null + if (!$?) { + mv_all $Drivedb ".new" ".error" + error "${Drivedb}.error: rejected by $Smartctl, probably no longer compatible" + } + vecho "${Smartctl}: syntax OK" +} + +# Always install if missing +rm_f "${Drivedb}.lastcheck" +if (!(Test-Path -PathType Leaf -Path $Drivedb)) { + mv_all $Drivedb ".new" "" + iecho "$Drivedb $newver newly installed$(if ($NoVerify) {" (NOT VERIFIED)"})" + exit 0 +} + +# Keep old file if identical +if ($equal) { + if (test_f "${Drivedb}.new.raw.asc") { + if (!(cmp "${Drivedb}.new.raw.asc" "${Drivedb}.raw.asc")) { + mv_f "${Drivedb}.new.raw.asc" "${Drivedb}.raw.asc" + iecho "${Drivedb}.raw.asc $newver updated" + } + } + rm_f "${Drivedb}.new" "${Drivedb}.new.raw" "${Drivedb}.new.raw.asc" + touch "${Drivedb}.lastcheck" + iecho "$Drivedb $newver is already up to date$(if ($NoVerify) {" (NOT VERIFIED)"})" + exit 0 +} + +# Check branch and file version +$oldver = $(get_db_version "${Drivedb}") +if (!$oldver) { + $oldver = "?/?" +} + +if ( ($newver -match '/\?$') ` + -or ($oldver -match '/\?$') ` + -or (($newver -replace '/.*$','') -ne ($oldver -replace '/.*$',''))) { + # Always install from trunk or other branch + $updmsg = "replaced with" +} elseif ((($newver -replace '^.*/','') - ($oldver -replace '^.*/','')) -lt 0) { + # Install older file only if '-Force' is used + if (!$Force) { + rm_f "${Drivedb}.new" "${Drivedb}.new.raw" "${Drivedb}.new.raw.asc" + iecho "$Drivedb $oldver not downgraded to $newver ('-Force' to override)" + exit 0 + } + $updmsg = "downgraded to" +} else { + $updmsg = "updated to" +} + +mv_all $Drivedb "" ".old" +mv_all $Drivedb ".new" "" +iecho "$Drivedb $oldver $updmsg $newver$(if ($NoVerify) {" (NOT VERIFIED)"})" +exit 0 diff -Nru smartmontools-7.1/os_win32.cpp smartmontools-7.3/os_win32.cpp --- smartmontools-7.1/os_win32.cpp 2019-12-29 15:28:32.000000000 +0000 +++ smartmontools-7.3/os_win32.cpp 2021-10-31 18:34:22.000000000 +0000 @@ -3,7 +3,7 @@ * * Home page of code is: https://www.smartmontools.org * - * Copyright (C) 2004-19 Christian Franke + * Copyright (C) 2004-21 Christian Franke * * Original AACRaid code: * Copyright (C) 2015 Nidhi Malhotra @@ -43,31 +43,9 @@ #endif #include // offsetof() -#include // access() -// WIN32_LEAN_AND_MEAN may be required to prevent inclusion of -#define WIN32_LEAN_AND_MEAN #include - -#if HAVE_NTDDDISK_H -// i686-pc-cygwin, i686-w64-mingw32, x86_64-w64-mingw32 -// (Missing: FILE_DEVICE_SCSI) -#include -#include -#include -#include -#elif HAVE_DDK_NTDDDISK_H -// older i686-pc-cygwin, i686-pc-mingw32, i586-mingw32msvc -// (Missing: IOCTL_IDE_PASS_THROUGH, IOCTL_ATA_PASS_THROUGH, FILE_DEVICE_SCSI) -#include -#include -#include -#else -// MSVC10, older MinGW -// (Missing: IOCTL_SCSI_MINIPORT_*) -#include -#include -#endif +#include // IOCTL_ATA_PASS_THROUGH, IOCTL_SCSI_PASS_THROUGH, ... #ifndef _WIN32 // csmisas.h and aacraid.h require _WIN32 but w32api-headers no longer define it on Cygwin @@ -94,7 +72,7 @@ #define strnicmp strncasecmp #endif -const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 5021 2019-12-29 15:28:32Z chrfranke $"; +const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 5239 2021-10-31 18:34:22Z chrfranke $"; ///////////////////////////////////////////////////////////////////////////// // Windows I/O-controls, some declarations are missing in the include files @@ -136,35 +114,6 @@ // ATA PASS THROUGH (Win2003, XP SP2) -#ifndef IOCTL_ATA_PASS_THROUGH - -#define IOCTL_ATA_PASS_THROUGH \ - CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -typedef struct _ATA_PASS_THROUGH_EX { - USHORT Length; - USHORT AtaFlags; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR ReservedAsUchar; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG ReservedAsUlong; - ULONG_PTR DataBufferOffset; - UCHAR PreviousTaskFile[8]; - UCHAR CurrentTaskFile[8]; -} ATA_PASS_THROUGH_EX; - -#define ATA_FLAGS_DRDY_REQUIRED 0x01 -#define ATA_FLAGS_DATA_IN 0x02 -#define ATA_FLAGS_DATA_OUT 0x04 -#define ATA_FLAGS_48BIT_COMMAND 0x08 -#define ATA_FLAGS_USE_DMA 0x10 -#define ATA_FLAGS_NO_MULTIPLE 0x20 // Vista - -#endif // IOCTL_ATA_PASS_THROUGH - STATIC_ASSERT(IOCTL_ATA_PASS_THROUGH == 0x04d02c); STATIC_ASSERT(sizeof(ATA_PASS_THROUGH_EX) == SELECT_WIN_32_64(40, 48)); @@ -202,57 +151,12 @@ #endif // IOCTL_SCSI_MINIPORT_SMART_VERSION STATIC_ASSERT(IOCTL_SCSI_MINIPORT == 0x04d008); +STATIC_ASSERT(IOCTL_SCSI_MINIPORT_SMART_VERSION == 0x1b0500); STATIC_ASSERT(sizeof(SRB_IO_CONTROL) == 28); // IOCTL_STORAGE_QUERY_PROPERTY -#ifndef IOCTL_STORAGE_QUERY_PROPERTY - -#define IOCTL_STORAGE_QUERY_PROPERTY \ - CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) - -typedef struct _STORAGE_DEVICE_DESCRIPTOR { - ULONG Version; - ULONG Size; - UCHAR DeviceType; - UCHAR DeviceTypeModifier; - BOOLEAN RemovableMedia; - BOOLEAN CommandQueueing; - ULONG VendorIdOffset; - ULONG ProductIdOffset; - ULONG ProductRevisionOffset; - ULONG SerialNumberOffset; - STORAGE_BUS_TYPE BusType; - ULONG RawPropertiesLength; - UCHAR RawDeviceProperties[1]; -} STORAGE_DEVICE_DESCRIPTOR; - -typedef enum _STORAGE_QUERY_TYPE { - PropertyStandardQuery = 0, - PropertyExistsQuery, - PropertyMaskQuery, - PropertyQueryMaxDefined -} STORAGE_QUERY_TYPE; - -typedef enum _STORAGE_PROPERTY_ID { - StorageDeviceProperty = 0, - StorageAdapterProperty, - StorageDeviceIdProperty, - StorageDeviceUniqueIdProperty, - StorageDeviceWriteCacheProperty, - StorageMiniportProperty, - StorageAccessAlignmentProperty -} STORAGE_PROPERTY_ID; - -typedef struct _STORAGE_PROPERTY_QUERY { - STORAGE_PROPERTY_ID PropertyId; - STORAGE_QUERY_TYPE QueryType; - UCHAR AdditionalParameters[1]; -} STORAGE_PROPERTY_QUERY; - -#endif // IOCTL_STORAGE_QUERY_PROPERTY - STATIC_ASSERT(IOCTL_STORAGE_QUERY_PROPERTY == 0x002d1400); STATIC_ASSERT(sizeof(STORAGE_DEVICE_DESCRIPTOR) == 36+1+3); STATIC_ASSERT(sizeof(STORAGE_PROPERTY_QUERY) == 8+1+3); @@ -452,7 +356,7 @@ m_fh(INVALID_HANDLE_VALUE) { } - virtual ~win_smart_device() throw(); + virtual ~win_smart_device(); virtual bool is_open() const; @@ -474,7 +378,7 @@ // Common routines for devices with HANDLEs -win_smart_device::~win_smart_device() throw() +win_smart_device::~win_smart_device() { if (m_fh != INVALID_HANDLE_VALUE) ::CloseHandle(m_fh); @@ -1177,10 +1081,11 @@ } if (data.desc.ProductIdOffset) { - while (i > 1 && model[i-2] == ' ') // Keep last blank from VendorId + // Keep only first trailing blank after VendorId + while (i > 0 && model[i-1] == ' ' && (i < 2 || model[i-2] == ' ')) i--; // Ignore VendorId "ATA" - if (i <= 4 && !strncmp(model, "ATA", 3) && (i == 3 || model[3] == ' ')) + if (i <= 4 && !memcmp(model, "ATA", 3) && (i == 3 || model[3] == ' ')) i = 0; for (unsigned j = 0; i < sizeof(model)-1 && data.raw[data.desc.ProductIdOffset+j]; i++, j++) model[i] = data.raw[data.desc.ProductIdOffset+j]; @@ -1415,15 +1320,15 @@ public: win_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual ~win_ata_device() throw(); + virtual ~win_ata_device(); - virtual bool open(); + virtual bool open() override; - virtual bool is_powered_down(); + virtual bool is_powered_down() override; - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; - virtual bool ata_identify_is_cached() const; + virtual bool ata_identify_is_cached() const override; private: bool open(bool query_device); @@ -1453,7 +1358,7 @@ { } -win_ata_device::~win_ata_device() throw() +win_ata_device::~win_ata_device() { } @@ -1583,7 +1488,7 @@ m_is_3ware = (vers_ex.wIdentifier == SMART_VENDOR_3WARE); unsigned portmap = 0; - if (port >= 0 && devmap >= 0) { + if (devmap >= 0) { // 3ware RAID: check vendor id if (!m_is_3ware) { pout("SMART_GET_VERSION returns unknown Identifier = 0x%04x\n" @@ -2273,7 +2178,7 @@ virtual public /*implements*/ ata_device { public: - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; protected: csmi_ata_device() @@ -2392,19 +2297,19 @@ win_csmi_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual ~win_csmi_device() throw(); + virtual ~win_csmi_device(); - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; - virtual bool is_open() const; + virtual bool is_open() const override; bool open_scsi(); protected: virtual bool csmi_ioctl(unsigned code, IOCTL_HEADER * csmi_buffer, - unsigned csmi_bufsiz); + unsigned csmi_bufsiz) override; private: HANDLE m_fh; ///< Controller device handle @@ -2421,7 +2326,7 @@ { } -win_csmi_device::~win_csmi_device() throw() +win_csmi_device::~win_csmi_device() { if (m_fh != INVALID_HANDLE_VALUE) CloseHandle(m_fh); @@ -2563,11 +2468,11 @@ public: win_tw_cli_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual bool is_open() const; + virtual bool is_open() const override; - virtual bool open(); + virtual bool open() override; - virtual bool close(); + virtual bool close() override; protected: virtual int ata_command_interface(smart_command_set command, int select, char * data); @@ -2777,9 +2682,9 @@ public: win_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type); - virtual bool open(); + virtual bool open() override; - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; private: bool open(int pd_num, int ld_num, int tape_num, int sub_addr); @@ -3180,11 +3085,11 @@ { public: win_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - virtual bool open(); - virtual smart_device * autodetect_open(); - virtual bool arcmsr_lock(); - virtual bool arcmsr_unlock(); - virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); + virtual bool open() override; + virtual smart_device * autodetect_open() override; + virtual bool arcmsr_lock() override; + virtual bool arcmsr_unlock() override; + virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override; private: HANDLE m_mutex; @@ -3294,11 +3199,11 @@ { public: win_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); - virtual bool open(); - virtual smart_device * autodetect_open(); - virtual bool arcmsr_lock(); - virtual bool arcmsr_unlock(); - virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); + virtual bool open() override; + virtual smart_device * autodetect_open() override; + virtual bool arcmsr_lock() override; + virtual bool arcmsr_unlock() override; + virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override; private: HANDLE m_mutex; @@ -3429,11 +3334,11 @@ public: win_aacraid_device(smart_interface *intf, const char *dev_name,unsigned int ctrnum, unsigned int target, unsigned int lun); - virtual ~win_aacraid_device() throw(); + virtual ~win_aacraid_device(); - virtual bool open(); + virtual bool open() override; - virtual bool scsi_pass_through(struct scsi_cmnd_io *iop); + virtual bool scsi_pass_through(struct scsi_cmnd_io *iop) override; private: //Device Host number @@ -3458,7 +3363,7 @@ set_info().dev_type = strprintf("aacraid,%d,%d,%d", m_ctrnum, m_lun, m_target); } -win_aacraid_device::~win_aacraid_device() throw() +win_aacraid_device::~win_aacraid_device() { } @@ -3509,12 +3414,15 @@ pout("buff %s\n",buff); } - char ioBuffer[1000]; + // Create buffer with appropriate size + constexpr unsigned scsiRequestBlockSize = sizeof(SCSI_REQUEST_BLOCK); + constexpr unsigned dataOffset = (sizeof(SRB_IO_CONTROL) + scsiRequestBlockSize + 7) & 0xfffffff8; + raw_buffer pthru_raw_buf(dataOffset + iop->dxfer_len + 8); // 32|64-bit: 96|120 + ... + + char * ioBuffer = reinterpret_cast(pthru_raw_buf.data()); SRB_IO_CONTROL * pSrbIO = (SRB_IO_CONTROL *) ioBuffer; SCSI_REQUEST_BLOCK * pScsiIO = (SCSI_REQUEST_BLOCK *) (ioBuffer + sizeof(SRB_IO_CONTROL)); - DWORD scsiRequestBlockSize = sizeof(SCSI_REQUEST_BLOCK); char *pRequestSenseIO = (char *) (ioBuffer + sizeof(SRB_IO_CONTROL) + scsiRequestBlockSize); - DWORD dataOffset = (sizeof(SRB_IO_CONTROL) + scsiRequestBlockSize + 7) & 0xfffffff8; char *pDataIO = (char *) (ioBuffer + dataOffset); memset(pScsiIO, 0, scsiRequestBlockSize); pScsiIO->Length = (USHORT) scsiRequestBlockSize; @@ -3624,9 +3532,9 @@ win_nvme_device(smart_interface * intf, const char * dev_name, const char * req_type, unsigned nsid); - virtual bool open(); + virtual bool open() override; - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; bool open_scsi(int n); @@ -3821,9 +3729,9 @@ win10_nvme_device(smart_interface * intf, const char * dev_name, const char * req_type, unsigned nsid); - virtual bool open(); + virtual bool open() override; - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; private: bool open(int phydrive, int logdrive); @@ -3995,31 +3903,27 @@ : public /*implements*/ smart_interface { public: - virtual std::string get_os_version_str(); + virtual std::string get_os_version_str() override; - virtual std::string get_app_examples(const char * appname); - -#ifndef __CYGWIN__ - virtual int64_t get_timer_usec(); -#endif + virtual std::string get_app_examples(const char * appname) override; - virtual bool disable_system_auto_standby(bool disable); + virtual bool disable_system_auto_standby(bool disable) override; virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, - const char * pattern = 0); + const char * pattern = 0) override; protected: - virtual ata_device * get_ata_device(const char * name, const char * type); + virtual ata_device * get_ata_device(const char * name, const char * type) override; - virtual scsi_device * get_scsi_device(const char * name, const char * type); + virtual scsi_device * get_scsi_device(const char * name, const char * type) override; - virtual nvme_device * get_nvme_device(const char * name, const char * type, unsigned nsid); + virtual nvme_device * get_nvme_device(const char * name, const char * type, unsigned nsid) override; - virtual smart_device * autodetect_smart_device(const char * name); + virtual smart_device * autodetect_smart_device(const char * name) override; - virtual smart_device * get_custom_smart_device(const char * name, const char * type); + virtual smart_device * get_custom_smart_device(const char * name, const char * type) override; - virtual std::string get_valid_custom_dev_types_str(); + virtual std::string get_valid_custom_dev_types_str() override; private: smart_device * get_usb_device(const char * name, int phydrive, int logdrive = -1); @@ -4033,7 +3937,7 @@ static bool is_wow64() { BOOL (WINAPI * IsWow64Process_p)(HANDLE, PBOOL) = - (BOOL (WINAPI *)(HANDLE, PBOOL)) + (BOOL (WINAPI *)(HANDLE, PBOOL))(void *) GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process"); if (!IsWow64Process_p) return false; @@ -4058,7 +3962,7 @@ // Starting with Windows 8.1, GetVersionEx() does no longer report the // actual OS version. RtlGetVersion() is not affected. LONG /*NTSTATUS*/ (WINAPI /*NTAPI*/ * RtlGetVersion_p)(LPOSVERSIONINFOEXW) = - (LONG (WINAPI *)(LPOSVERSIONINFOEXW)) + (LONG (WINAPI *)(LPOSVERSIONINFOEXW))(void *) GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); OSVERSIONINFOEXW vi; memset(&vi, 0, sizeof(vi)); @@ -4100,20 +4004,32 @@ case 17763: w = "w10-1809"; break; case 18362: w = "w10-1903"; break; case 18363: w = "w10-1909"; break; - default: w = "w10"; + case 19041: w = "w10-2004"; break; + case 19042: w = "w10-20H2"; break; + case 19043: w = "w10-21H1"; break; + case 19044: w = "w10-21H2"; break; + case 22000: w = "w11-21H2"; break; + default: w = (vi.dwBuildNumber < 22000 + ? "w10" + : "w11"); build = vi.dwBuildNumber; break; } break; case 0xa0<<1 | 1: switch (vi.dwBuildNumber) { - case 14393: w = "2016"; break; + case 14393: w = "2016-1607"; break; case 16299: w = "2016-1709"; break; case 17134: w = "2016-1803"; break; - case 17763: w = "2019"; break; + case 17763: w = "2019-1809"; break; case 18362: w = "2019-1903"; break; case 18363: w = "2019-1909"; break; + case 19041: w = "2019-2004"; break; + case 19042: w = "2019-20H2"; break; + case 20348: w = "2022-21H2"; break; default: w = (vi.dwBuildNumber < 17763 ? "2016" - : "2019"); + : vi.dwBuildNumber < 20348 + ? "2019" + : "2022"); build = vi.dwBuildNumber; break; } break; } @@ -4140,30 +4056,6 @@ return vstr; } -#ifndef __CYGWIN__ -// MSVCRT only provides ftime() which uses GetSystemTime() -// This provides only ~15ms resolution by default. -// Use QueryPerformanceCounter instead (~300ns). -// (Cygwin provides CLOCK_MONOTONIC which has the same effect) -int64_t win_smart_interface::get_timer_usec() -{ - static int64_t freq = 0; - - LARGE_INTEGER t; - if (freq == 0) - freq = (QueryPerformanceFrequency(&t) ? t.QuadPart : -1); - if (freq <= 0) - return smart_interface::get_timer_usec(); - - if (!QueryPerformanceCounter(&t)) - return -1; - if (!(0 <= t.QuadPart && t.QuadPart <= (int64_t)(~(uint64_t)0 >> 1)/1000000)) - return -1; - - return (t.QuadPart * 1000000LL) / freq; -} -#endif // __CYGWIN__ - ata_device * win_smart_interface::get_ata_device(const char * name, const char * type) { @@ -4235,10 +4127,21 @@ // aacraid? unsigned ctrnum, lun, target; - n1 = -1; + n1 = -1; n2 = -1; + + if ( sscanf(type, "aacraid,%u,%u,%u%n,force%n", &ctrnum, &lun, &target, &n1, &n2) >= 3 + && (n1 == (int)strlen(type) || n2 == (int)strlen(type))) { + + if (n2 < 0) { + set_err(ENOSYS, + "smartmontools AACRAID support is reportedly broken on Windows.\n" + "See https://www.smartmontools.org/ticket/1515 for details.\n" + "Use '-d aacraid,H,L,ID,force' to try anyway at your own risk.\n" + "If you could provide help to fix the problem, please inform\n" + PACKAGE_BUGREPORT "\n"); + return 0; + } - if ( sscanf(type, "aacraid,%u,%u,%u%n", &ctrnum, &lun, &target, &n1) >= 3 - && n1 == (int)strlen(type)) { #define aacraid_MAX_CTLR_NUM 16 if (ctrnum >= aacraid_MAX_CTLR_NUM) { set_err(EINVAL, "aacraid: invalid host number %u", ctrnum); @@ -4761,7 +4664,8 @@ { // Remove "." from DLL search path if supported // to prevent DLL preloading attacks - BOOL (WINAPI * SetDllDirectoryA_p)(LPCSTR) = (BOOL (WINAPI *)(LPCSTR)) + BOOL (WINAPI * SetDllDirectoryA_p)(LPCSTR) = + (BOOL (WINAPI *)(LPCSTR))(void *) GetProcAddress(GetModuleHandleA("kernel32.dll"), "SetDllDirectoryA"); if (SetDllDirectoryA_p) SetDllDirectoryA_p(""); diff -Nru smartmontools-7.1/popen_as_ugid.cpp smartmontools-7.3/popen_as_ugid.cpp --- smartmontools-7.1/popen_as_ugid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ smartmontools-7.3/popen_as_ugid.cpp 2021-12-13 19:22:38.000000000 +0000 @@ -0,0 +1,271 @@ +/* + * popen_as_ugid.cpp + * + * Home page of code is: https://www.smartmontools.org + * + * Copyright (C) 2021 Christian Franke + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "popen_as_ugid.h" + +const char * popen_as_ugid_cvsid = "$Id: popen_as_ugid.cpp 5269 2021-12-13 19:22:38Z chrfranke $" + POPEN_AS_UGID_H_CVSID; + +#include +#include +#include +#include +#include +#include +#include +#include + +static FILE * s_popen_file /* = 0 */; +static pid_t s_popen_pid /* = 0 */; + +FILE * popen_as_ugid(const char * cmd, const char * mode, uid_t uid, gid_t gid) +{ + // Only "r" supported + if (*mode != 'r') { + errno = EINVAL; + return (FILE *)0; + } + + // Only one stream supported + if (s_popen_file) { + errno = EMFILE; + return (FILE *)0; + } + + int pd[2] = {-1, -1}; + int sd[2] = {-1, -1}; + FILE * fp = 0; + pid_t pid; + errno = 0; + if (!(// Create stdout and status pipe ... + !pipe(pd) && !pipe(sd) && + // ... connect stdout pipe to FILE ... + !!(fp = fdopen(pd[0], "r")) && + // ... and then fork() + (pid = fork()) != (pid_t)-1) ) { + int err = (errno ? errno : ENOSYS); + if (fp) { + fclose(fp); close(pd[1]); + } + else if (pd[0] >= 0) { + close(pd[0]); close(pd[1]); + } + if (sd[0] >= 0) { + close(sd[0]); close(sd[1]); + } + errno = err; + return (FILE *)0; + } + + if (!pid) { // Child + // Do not inherit any unneeded file descriptors + fclose(fp); + for (int i = 0; i < getdtablesize(); i++) { + if (i == pd[1] || i == sd[1]) + continue; + close(i); + } + + FILE * fc = 0; + int err = errno = 0; + if (!(// Connect stdio to /dev/null ... + open("/dev/null", O_RDWR) == 0 && + dup(0) == 1 && dup(0) == 2 && + // ... don't inherit pipes ... + !fcntl(pd[1], F_SETFD, FD_CLOEXEC) && + !fcntl(sd[1], F_SETFD, FD_CLOEXEC) && + // ... set group and user (assumes we are root) ... + (!gid || (!setgid(gid) && !setgroups(1, &gid))) && + (!uid || !setuid(uid)) && + // ... and then call popen() from std library + !!(fc = popen(cmd, mode)) )) { + err = (errno ? errno : ENOSYS); + } + + // Send setup result to parent + if (write(sd[1], &err, sizeof(err)) != (int)sizeof(err)) + err = EIO; + close(sd[1]); + if (!fc) + _exit(127); + + // Send popen's FILE stream to parent's FILE + int c; + while (!err && (c = getc(fc)) != EOF) { + char cb = (char)c; + if (write(pd[1], &cb, 1) != 1) + err = EIO; + } + + // Return status or re-throw signal + int status = pclose(fc); + if (WIFSIGNALED(status)) + kill(getpid(), WTERMSIG(status)); + _exit(WIFEXITED(status) ? WEXITSTATUS(status) : 127); + } + + // Parent + close(pd[1]); close(sd[1]); + + // Get setup result from child + int err = 0; + if (read(sd[0], &err, sizeof(err)) != (int)sizeof(err)) + err = EIO; + close(sd[0]); + if (err) { + fclose(fp); + errno = err; + return (FILE *)0; + } + + // Save for pclose_as_ugid() + s_popen_file = fp; + s_popen_pid = pid; + return fp; +} + +int pclose_as_ugid(FILE * f) +{ + if (f != s_popen_file) { + errno = EBADF; + return -1; + } + + fclose(f); + s_popen_file = 0; + + pid_t pid; int status; + do + pid = waitpid(s_popen_pid, &status, 0); + while (pid == (pid_t)-1 && errno == EINTR); + s_popen_pid = 0; + + if (pid == (pid_t)-1) + return -1; + return status; +} + +const char * parse_ugid(const char * s, uid_t & uid, gid_t & gid, + std::string & uname, std::string & gname ) +{ + // Split USER:GROUP + int len = strlen(s), n1 = -1, n2 = -1; + char un[64+1] = "", gn[64+1] = ""; + if (!( sscanf(s, "%64[^ :]%n:%64[^ :]%n", un, &n1, gn, &n2) >= 1 + && (n1 == len || n2 == len) )) { + return "Syntax error"; + } + + // Lookup user + const struct passwd * pwd; + unsigned u = 0; + if (sscanf(un, "%u%n", &u, (n1 = -1, &n1)) == 1 && n1 == (int)strlen(un)) { + uid = (uid_t)u; + pwd = getpwuid(uid); + } + else { + pwd = getpwnam(un); + if (!pwd) + return "Unknown user name"; + uid = pwd->pw_uid; + } + if (pwd) + uname = pwd->pw_name; + + const struct group * grp; + if (gn[0]) { + // Lookup group + unsigned g = 0; + if (sscanf(gn, "%u%n", &g, (n1 = -1, &n1)) == 1 && n1 == (int)strlen(gn)) { + gid = (gid_t)g; + grp = getgrgid(gid); + } + else { + grp = getgrnam(gn); + if (!grp) + return "Unknown group name"; + gid = grp->gr_gid; + } + } + else { + // Use default group + if (!pwd) + return "Unknown default group"; + gid = pwd->pw_gid; + grp = getgrgid(gid); + } + if (grp) + gname = grp->gr_name; + + return (const char *)0; +} + +// Test program +#ifdef TEST + +int main(int argc, char **argv) +{ + const char * user_group, * cmd; + switch (argc) { + case 2: user_group = 0; cmd = argv[1]; break; + case 3: user_group = argv[1]; cmd = argv[2]; break; + default: + printf("Usage: %s [USER[:GROUP]] \"COMMAND ARG...\"\n", argv[0]); + return 1; + } + + int leak = open("/dev/null", O_RDONLY); + + FILE * f; + if (user_group) { + uid_t uid; gid_t gid; + std::string uname = "unknown", gname = "unknown"; + const char * err = parse_ugid(user_group, uid, gid, uname, gname); + if (err) { + fprintf(stderr, "Error: %s\n", err); + return 1; + } + printf("popen_as_ugid(\"%s\", \"r\", %u(%s), %u(%s)):\n", cmd, + (unsigned)uid, uname.c_str(), (unsigned)gid, gname.c_str()); + f = popen_as_ugid(cmd, "r", uid, gid); + } + else { + printf("popen(\"%s\", \"r\"):\n", cmd); + f = popen(cmd, "r"); + } + fflush(stdout); + close(leak); + + if (!f) { + perror("popen"); + return 1; + } + + int cnt, c; + for (cnt = 0; (c = getc(f)) != EOF; cnt++) + putchar(c); + printf("[EOF]\nread %d bytes\n", cnt); + + int status; + if (user_group) + status = pclose_as_ugid(f); + else + status = pclose(f); + + if (status == -1) { + perror("pclose"); + return 1; + } + printf("pclose() = 0x%04x (exit = %d, sig = %d)\n", + status, WEXITSTATUS(status), WTERMSIG(status)); + return 0; +} + +#endif diff -Nru smartmontools-7.1/popen_as_ugid.h smartmontools-7.3/popen_as_ugid.h --- smartmontools-7.1/popen_as_ugid.h 1970-01-01 00:00:00.000000000 +0000 +++ smartmontools-7.3/popen_as_ugid.h 2021-12-13 18:55:13.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * popen_as_ugid.h + * + * Home page of code is: https://www.smartmontools.org + * + * Copyright (C) 2021 Christian Franke + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef POPEN_AS_UGID_H_CVSID +#define POPEN_AS_UGID_H_CVSID "$Id: popen_as_ugid.h 5268 2021-12-13 18:55:13Z chrfranke $" + +#include +#include +#include +#include + +// Wrapper for popen(3) which prevents that unneeded file descriptors +// are inherited to the command run by popen() and optionally drops +// privileges of root user: +// If uid != 0, popen() is run as this user. +// If gid != 0, popen() is run as this group and no supplemental groups. +// Only mode "r" is supported. Only one open stream at a time is supported. +FILE * popen_as_ugid(const char * cmd, const char * mode, uid_t uid, gid_t gid); + +// Call corresponding pclose(3) and return its result. +int pclose_as_ugid(FILE * f); + +// Parse "USER[:GROUP]" string and set uid, gid, uname and gname accordingly. +// USER and GROUP may be specified as numeric ids or names. +// If a numeric id is used and the corresponding user (or group) does not +// exist, the function succeeds but leaves uname (or gname) unchanged. +// If no GROUP is specified, the default group of USER is used instead. +// Returns nullptr on success or a message string on error. +const char * parse_ugid(const char * s, uid_t & uid, gid_t & gid, + std::string & uname, std::string & gname ); + +#endif // POPEN_AS_UGID_H_CVSID diff -Nru smartmontools-7.1/scsiata.cpp smartmontools-7.3/scsiata.cpp --- smartmontools-7.1/scsiata.cpp 2018-12-05 18:30:46.000000000 +0000 +++ smartmontools-7.3/scsiata.cpp 2022-02-27 07:53:55.000000000 +0000 @@ -1,10 +1,10 @@ /* * scsiata.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2006-15 Douglas Gilbert - * Copyright (C) 2009-18 Christian Franke + * Copyright (C) 2009-21 Christian Franke * * SPDX-License-Identifier: GPL-2.0-or-later * The code in this file is based on the SCSI to ATA Translation (SAT) @@ -55,7 +55,7 @@ #include "dev_tunnelled.h" // tunnelled_device<> #include "sg_unaligned.h" -const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 4848 2018-12-05 18:30:46Z chrfranke $"; +const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 5337 2022-02-27 07:53:55Z dpgilbert $"; /* This is a slightly stretched SCSI sense "descriptor" format header. The addition is to allow the 0x70 and 0x71 response codes. The idea @@ -114,13 +114,13 @@ sat_device(smart_interface * intf, scsi_device * scsidev, const char * req_type, sat_scsi_mode mode = sat_always, int passthrulen = 0); - virtual ~sat_device() throw(); + virtual ~sat_device(); - virtual smart_device * autodetect_open(); + virtual smart_device * autodetect_open() override; - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; - virtual bool scsi_pass_through(scsi_cmnd_io * iop); + virtual bool scsi_pass_through(scsi_cmnd_io * iop) override; private: int m_passthrulen; @@ -148,7 +148,7 @@ (mode == sat_always ? "SAT" : mode == sat_auto ? "SCSI/SAT" : "SCSI")); } -sat_device::~sat_device() throw() +sat_device::~sat_device() { } @@ -256,11 +256,11 @@ ) return false; - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; struct sg_scsi_sense_hdr ssh; - unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN]; - unsigned char sense[32]; + unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN] = {}; + unsigned char sense[32] = {}; const unsigned char * ardp; int ard_len, have_sense; int extend = 0; @@ -272,9 +272,6 @@ int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE; bool sense_descriptor = true; - memset(cdb, 0, sizeof(cdb)); - memset(sense, 0, sizeof(sense)); - // Set data direction // TODO: This works only for commands where sector_count holds count! switch (in.direction) { @@ -346,7 +343,6 @@ cdb[14] = lo.command; } - memset(&io_hdr, 0, sizeof(io_hdr)); if (0 == t_length) { io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; @@ -612,10 +608,10 @@ usbcypress_device(smart_interface * intf, scsi_device * scsidev, const char * req_type, unsigned char signature); - virtual ~usbcypress_device() throw(); + virtual ~usbcypress_device(); protected: - virtual int ata_command_interface(smart_command_set command, int select, char * data); + virtual int ata_command_interface(smart_command_set command, int select, char * data) override; unsigned char m_signature; }; @@ -630,7 +626,7 @@ set_info().info_name = strprintf("%s [USB Cypress]", scsidev->get_info_name()); } -usbcypress_device::~usbcypress_device() throw() +usbcypress_device::~usbcypress_device() { } @@ -639,9 +635,9 @@ #define USBCYPRESS_PASSTHROUGH_LEN 16 int usbcypress_device::ata_command_interface(smart_command_set command, int select, char *data) { - struct scsi_cmnd_io io_hdr; - unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN]; - unsigned char sense[32]; + struct scsi_cmnd_io io_hdr = {}; + unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN] = {}; + unsigned char sense[32] = {}; int copydata = 0; int outlen = 0; int ck_cond = 0; /* set to 1 to read register(s) back */ @@ -656,9 +652,6 @@ int lba_high = 0; int passthru_size = USBCYPRESS_PASSTHROUGH_LEN; - memset(cdb, 0, sizeof(cdb)); - memset(sense, 0, sizeof(sense)); - ata_command = ATA_SMART_CMD; switch (command) { case CHECK_POWER_MODE: @@ -766,7 +759,6 @@ cdb[10] = lba_high; cdb[12] = ata_command; - memset(&io_hdr, 0, sizeof(io_hdr)); if (0 == t_length) { io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; @@ -870,51 +862,6 @@ return 0; } -#if 0 // Not used, see autodetect_sat_device() below. -static int isprint_string(const char *s) -{ - while (*s) { - if (isprint(*s) == 0) - return 0; - s++; - } - return 1; -} - -/* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command - If successful return 1, else 0 */ -// TODO: Combine with has_sat_pass_through above -static int has_usbcypress_pass_through(ata_device * atadev, const char *manufacturer, const char *product) -{ - struct ata_identify_device drive; - char model[40], serial[20], firm[8]; - - /* issue the command and do a checksum if possible */ - if (ataReadHDIdentity(atadev, &drive) < 0) - return 0; - - /* check if model string match, revision doesn't work for me */ - format_ata_string(model, drive.model, 40); - if (*model == 0 || isprint_string(model) == 0) - return 0; - - if (manufacturer && strncmp(manufacturer, model, 8)) - pout("manufacturer doesn't match in pass_through test\n"); - if (product && - strlen(model) > 8 && strncmp(product, model+8, strlen(model)-8)) - pout("product doesn't match in pass_through test\n"); - - /* check serial */ - format_ata_string(serial, drive.serial_no, 20); - if (isprint_string(serial) == 0) - return 0; - format_ata_string(firm, drive.fw_rev, 8); - if (isprint_string(firm) == 0) - return 0; - return 1; -} -#endif - ///////////////////////////////////////////////////////////////////////////// /// JMicron USB Bridge support. @@ -930,11 +877,11 @@ const char * req_type, bool prolific, bool ata_48bit_support, int port); - virtual ~usbjmicron_device() throw(); + virtual ~usbjmicron_device(); - virtual bool open(); + virtual bool open() override; - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; private: bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size); @@ -956,7 +903,7 @@ set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name()); } -usbjmicron_device::~usbjmicron_device() throw() +usbjmicron_device::~usbjmicron_device() { } @@ -1006,8 +953,7 @@ if (m_port < 0) return set_err(EIO, "Unknown JMicron port"); - scsi_cmnd_io io_hdr; - memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; bool rwbit = true; unsigned char smart_status = 0xff; @@ -1127,8 +1073,7 @@ cdb[12] = 0x06; cdb[13] = 0x7b; - scsi_cmnd_io io_hdr; - memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = size; io_hdr.dxferp = buf; @@ -1158,9 +1103,9 @@ usbprolific_device(smart_interface * intf, scsi_device * scsidev, const char * req_type); - virtual ~usbprolific_device() throw(); + virtual ~usbprolific_device(); - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; }; @@ -1172,7 +1117,7 @@ set_info().info_name = strprintf("%s [USB Prolific]", scsidev->get_info_name()); } -usbprolific_device::~usbprolific_device() throw() +usbprolific_device::~usbprolific_device() { } @@ -1187,8 +1132,7 @@ ) return false; - scsi_cmnd_io io_hdr; - memset(&io_hdr, 0, sizeof(io_hdr)); + scsi_cmnd_io io_hdr = {}; unsigned char cmd_rw = 0x10; // Read switch (in.direction) { @@ -1297,9 +1241,9 @@ usbsunplus_device(smart_interface * intf, scsi_device * scsidev, const char * req_type); - virtual ~usbsunplus_device() throw(); + virtual ~usbsunplus_device(); - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override; }; @@ -1311,7 +1255,7 @@ set_info().info_name = strprintf("%s [USB Sunplus]", scsidev->get_info_name()); } -usbsunplus_device::~usbsunplus_device() throw() +usbsunplus_device::~usbsunplus_device() { } @@ -1325,12 +1269,11 @@ ) return false; - scsi_cmnd_io io_hdr; + scsi_cmnd_io io_hdr = {}; unsigned char cdb[12]; if (in.in_regs.is_48bit_cmd()) { // Set "previous" registers - memset(&io_hdr, 0, sizeof(io_hdr)); io_hdr.dxfer_dir = DXFER_NONE; cdb[ 0] = 0xf8; diff -Nru smartmontools-7.1/scsicmds.cpp smartmontools-7.3/scsicmds.cpp --- smartmontools-7.1/scsicmds.cpp 2019-12-29 13:13:06.000000000 +0000 +++ smartmontools-7.3/scsicmds.cpp 2022-02-27 07:53:55.000000000 +0000 @@ -36,7 +36,7 @@ #include "utility.h" #include "sg_unaligned.h" -const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 5013 2019-12-29 13:13:06Z chrfranke $" +const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 5337 2022-02-27 07:53:55Z dpgilbert $" SCSICMDS_H_CVSID; static const char * logSenStr = "Log Sense"; @@ -49,8 +49,8 @@ supported_vpd_pages::supported_vpd_pages(scsi_device * device) : num_valid(0) { - unsigned char b[0xfc]; /* pre SPC-3 INQUIRY max response size */ - memset(b, 0, sizeof(b)); + unsigned char b[0xfc] = {}; /* pre SPC-3 INQUIRY max response size */ + if (device && (0 == scsiInquiryVpd(device, SCSI_VPD_SUPPORTED_VPD_PAGES, b, sizeof(b)))) { num_valid = sg_get_unaligned_be16(b + 2); @@ -150,15 +150,12 @@ bool is_scsi_cdb(const uint8_t * cdbp, int clen) { - int ilen, sa; - uint8_t opcode; - uint8_t top3bits; - if (clen < 6) return false; - opcode = cdbp[0]; - top3bits = opcode >> 5; + uint8_t opcode = cdbp[0]; + uint8_t top3bits = opcode >> 5; if (0x3 == top3bits) { /* Opcodes 0x60 to 0x7f */ + int ilen, sa; if ((clen < 12) || (clen % 4)) return false; /* must be modulo 4 and 12 or more bytes */ switch (opcode) { @@ -235,7 +232,8 @@ const char * scsi_get_opcode_name(uint8_t opcode) { - int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]); + static const int len = sizeof(opcode_name_arr) / + sizeof(opcode_name_arr[0]); if (opcode >= 0xc0) return vendor_specific; @@ -277,6 +275,7 @@ switch (sinfo->sense_key) { case SCSI_SK_NO_SENSE: case SCSI_SK_RECOVERED_ERR: + case SCSI_SK_COMPLETED: return SIMPLE_NO_ERROR; case SCSI_SK_NOT_READY: if (SCSI_ASC_NO_MEDIUM == sinfo->asc) @@ -304,6 +303,10 @@ return SIMPLE_ERR_TRY_AGAIN; case SCSI_SK_ABORTED_COMMAND: return SIMPLE_ERR_ABORTED_COMMAND; + case SCSI_SK_DATA_PROTECT: + return SIMPLE_ERR_PROTECTION; + case SCSI_SK_MISCOMPARE: + return SIMPLE_ERR_MISCOMPARE; default: return SIMPLE_ERR_UNKNOWN; } @@ -339,11 +342,55 @@ return "unknown error (unexpected sense key)"; case SIMPLE_ERR_ABORTED_COMMAND: return "aborted command"; + case SIMPLE_ERR_PROTECTION: + return "data protection error"; + case SIMPLE_ERR_MISCOMPARE: + return "miscompare"; default: return "unknown error"; } } +static const char * sense_key_desc[] = { + "No Sense", /* Filemark, ILI and/or EOM; progress + indication (during FORMAT); power + condition sensing (REQUEST SENSE) */ + "Recovered Error", /* The last command completed successfully + but used error correction */ + "Not Ready", /* The addressed target is not ready */ + "Medium Error", /* Data error detected on the medium */ + "Hardware Error", /* Controller or device failure */ + "Illegal Request", + "Unit Attention", /* Removable medium was changed, or + the target has been reset */ + "Data Protect", /* Access to the data is blocked */ + "Blank Check", /* Reached unexpected written or unwritten + region of the medium */ + "Vendor specific(9)", /* Vendor specific */ + "Copy Aborted", /* COPY or COMPARE was aborted */ + "Aborted Command", /* The target aborted the command */ + "Equal", /* SEARCH DATA found data equal (obsolete) */ + "Volume Overflow", /* Medium full with data to be written */ + "Miscompare", /* Source data and data on the medium + do not agree */ + "Completed" /* may occur for successful cmd (spc4r23) */ +}; + +/* Yield string associated with sense_key value. Returns 'buff'. */ +char * +scsi_get_sense_key_str(int sense_key, int buff_len, char * buff) +{ + if (1 == buff_len) { + buff[0] = '\0'; + return buff; + } + if ((sense_key >= 0) && (sense_key < 16)) + snprintf(buff, buff_len, "%s", sense_key_desc[sense_key]); + else + snprintf(buff, buff_len, "invalid value: 0x%x", sense_key); + return buff; +} + /* Iterates to next designation descriptor in the device identification * VPD page. The 'initial_desig_desc' should point to start of first * descriptor with 'page_len' being the number of valid bytes in that @@ -513,9 +560,9 @@ int bufLen, int known_resp_len) { int pageLen; - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; if (known_resp_len > bufLen) @@ -532,8 +579,6 @@ else memset(pBuf, 0, pageLen); - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = pageLen; io_hdr.dxferp = pBuf; @@ -547,9 +592,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int res; if ((res = scsiSimpleSenseFilter(&sinfo))) return res; @@ -560,8 +604,6 @@ if (0 == u) return SIMPLE_ERR_BAD_RESP; pageLen = u + 4; - if (4 == pageLen) /* why define a lpage with no payload? */ - pageLen = 252; /* some IBM tape drives don't like double fetch */ /* some SCSI HBA don't like "odd" length transfers */ if (pageLen % 2) pageLen += 1; @@ -584,9 +626,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int status = scsiSimpleSenseFilter(&sinfo); if (0 != status) return status; @@ -607,13 +648,11 @@ scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -628,9 +667,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -642,15 +680,13 @@ scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; if ((bufLen < 0) || (bufLen > 255)) return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -664,16 +700,9 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int status = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN == status) { - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); - status = scsiSimpleSenseFilter(&sinfo); - } if ((0 == status) && (ALL_MODE_PAGES != pagenum)) { int offset; @@ -696,9 +725,9 @@ int scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; int pg_offset, pg_len, hdr_plus_1_pg; @@ -711,8 +740,6 @@ return -EINVAL; pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */ pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = hdr_plus_1_pg; io_hdr.dxferp = pBuf; @@ -725,9 +752,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -739,13 +765,11 @@ scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -759,16 +783,9 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); int status = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN == status) { - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); - status = scsiSimpleSenseFilter(&sinfo); - } if ((0 == status) && (ALL_MODE_PAGES != pagenum)) { int offset; @@ -791,9 +808,9 @@ int scsiModeSelect10(scsi_device * device, int sp, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; int pg_offset, pg_len, hdr_plus_1_pg; @@ -807,8 +824,6 @@ pBuf[0] = 0; pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */ pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = hdr_plus_1_pg; io_hdr.dxferp = pBuf; @@ -822,9 +837,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -835,14 +849,12 @@ scsiStdInquiry(scsi_device * device, uint8_t *pBuf, int bufLen) { struct scsi_sense_disect sinfo; - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + uint8_t cdb[6] = {}; uint8_t sense[32]; if ((bufLen < 0) || (bufLen > 1023)) return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -854,9 +866,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -867,9 +878,9 @@ int scsiInquiryVpd(scsi_device * device, int vpd_page, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; int res; @@ -882,8 +893,6 @@ if ((bufLen < 0) || (bufLen > 1023)) return -EINVAL; try_again: - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); if (bufLen > 1) pBuf[1] = 0x0; io_hdr.dxfer_dir = DXFER_FROM_DEVICE; @@ -899,9 +908,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); if ((SCSI_STATUS_CHECK_CONDITION == io_hdr.scsi_status) && (SCSI_SK_ILLEGAL_REQUEST == sinfo.sense_key) && (SCSI_ASC_INVALID_FIELD == sinfo.asc) && @@ -928,14 +936,13 @@ int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info) { - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + uint8_t cdb[6] = {}; uint8_t sense[32]; - uint8_t buff[18]; - int sz_buff = sizeof(buff); + uint8_t buff[18] = {}; + bool ok; + static const int sz_buff = sizeof(buff); - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = sz_buff; io_hdr.dxferp = buff; @@ -947,7 +954,13 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (sense_info) + ok = scsi_pass_through_yield_sense(device, &io_hdr, *sense_info); + else { + scsi_sense_disect dummy_sense; + ok = scsi_pass_through_yield_sense(device, &io_hdr, dummy_sense); + } + if (! ok) return -device->get_errno(); if (sense_info) { uint8_t resp_code = buff[0] & 0x7f; @@ -1001,6 +1014,46 @@ return 0; } +/* Send Start Stop Unit command with power_condition setting and + * Power condition command. Returns 0 if ok, anything else major problem. + * If power_cond is 0, treat as SSU(START) as that is better than + * SSU(STOP) which would be the case if byte 4 of the cdb was zero. + * Ref: SBC-4 revision 22, section 4.20 SSU and power conditions. + * + * SCSI_POW_COND_ACTIVE 0x1 + * SCSI_POW_COND_IDLE 0x2 + * SCSI_POW_COND_STANDBY 0x3 + * + */ + +int +scsiSetPowerCondition(scsi_device * device, int power_cond, int pcond_modifier) +{ + struct scsi_cmnd_io io_hdr = {}; + struct scsi_sense_disect sinfo; + uint8_t cdb[6] = {}; + uint8_t sense[32]; + + io_hdr.dxfer_dir = DXFER_NONE; + cdb[0] = START_STOP_UNIT; + /* IMMED bit (cdb[1] = 0x1) not set, therefore will wait */ + if (power_cond > 0) { + cdb[3] = pcond_modifier & 0xf; + cdb[4] = power_cond << 4; + } else + cdb[4] = 0x1; /* START */ + io_hdr.cmnd = cdb; + io_hdr.cmnd_len = sizeof(cdb); + io_hdr.sensep = sense; + io_hdr.max_sense_len = sizeof(sense); + io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; + + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) + return -device->get_errno(); + + return scsiSimpleSenseFilter(&sinfo); +} + /* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command * not supported, 3 if field in command not supported or returns negated * errno. SPC-3 section 6.28 (rev 22a) */ @@ -1008,13 +1061,11 @@ scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[6]; + uint8_t cdb[6] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1033,22 +1084,20 @@ /* worst case is an extended foreground self test on a big disk */ io_hdr.timeout = SCSI_TIMEOUT_SELF_TEST; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */ static int -_testunitready(scsi_device * device, struct scsi_sense_disect * sinfo) +_testunitready(scsi_device * device, struct scsi_sense_disect * sinfop) { - struct scsi_cmnd_io io_hdr; - uint8_t cdb[6]; + struct scsi_cmnd_io io_hdr = {}; + bool ok; + uint8_t cdb[6] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; io_hdr.dxferp = NULL; @@ -1059,9 +1108,14 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, sinfo); + if (sinfop) + ok = scsi_pass_through_yield_sense(device, &io_hdr, *sinfop); + else { + struct scsi_sense_disect dummy_si; + ok = scsi_pass_through_yield_sense(device, &io_hdr, dummy_si); + } + if (! ok) + return -device->get_errno(); return 0; } @@ -1076,15 +1130,7 @@ status = _testunitready(device, &sinfo); if (0 != status) return status; - status = scsiSimpleSenseFilter(&sinfo); - if (SIMPLE_ERR_TRY_AGAIN == status) { - /* power on reset, media changed, ok ... try again */ - status = _testunitready(device, &sinfo); - if (0 != status) - return status; - status = scsiSimpleSenseFilter(&sinfo); - } - return status; + return scsiSimpleSenseFilter(&sinfo); } /* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if @@ -1095,13 +1141,11 @@ scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1115,9 +1159,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) - return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) + return -device->get_errno(); /* Look for "(Primary|Grown) defect list not found" */ if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc)) return 101; @@ -1132,13 +1175,11 @@ scsiReadDefect12(scsi_device * device, int req_plist, int req_glist, int dl_format, int addrDescIndex, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[12]; + uint8_t cdb[12] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1153,15 +1194,56 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); /* Look for "(Primary|Grown) defect list not found" */ if ((sinfo.resp_code >= 0x70) && (0x1c == sinfo.asc)) return 101; return scsiSimpleSenseFilter(&sinfo); } +/* Call scsi_pass_through, and retry only if a UNIT_ATTENTION (UA) is raised. + * When false returned, the caller should invoke device->get_error(). + * When true returned, the caller should check sinfo. + * All SCSI commands can receive pending Unit Attentions, apart from: + * INQUIRY, REPORT LUNS, REQUEST SENSE and NOTIFY DATA TRANSFER DEVICE + * (ADC-3 spec). The first three are the important ones. */ +bool +scsi_pass_through_yield_sense(scsi_device * device, scsi_cmnd_io * iop, + /* OUT param */ scsi_sense_disect & sinfo) +{ + int k; + uint32_t opcode = (iop->cmnd_len > 0) ? iop->cmnd[0] : 0xffff; + + if (scsi_debugmode > 2) + pout("%s: opcode: 0x%x\n", __func__, opcode); + + if (! device->scsi_pass_through(iop)) + return false; // this will be missing device, timeout, etc + + scsi_do_sense_disect(iop, &sinfo); + + switch (opcode) { + case INQUIRY: + case REPORT_LUNS: + case REQUEST_SENSE: + return true; /* in these cases, it shouldn't be a UA */ + default: + break; /* continue on for all other SCSI commands to check for UA */ + } + + /* There can be multiple UAs pending, allow for three */ + for (k = 0; (k < 3) && (SCSI_SK_UNIT_ATTENTION == sinfo.sense_key); ++k) { + if (scsi_debugmode > 0) + pout("%s Unit Attention %d: asc/ascq=0x%x,0x%x, retrying\n", + __func__, k + 1, sinfo.asc, sinfo.ascq); + if (! device->scsi_pass_through(iop)) + return false; + scsi_do_sense_disect(iop, &sinfo); + } + return true; +} + /* READ CAPACITY (10) command. Returns 0 if ok, 1 if NOT READY, 2 if * command not supported, 3 if field in command not supported or returns * negated errno. SBC-3 section 5.15 (rev 26) */ @@ -1170,15 +1252,12 @@ unsigned int * lb_sizep) { int res; - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[10]; + uint8_t cdb[10] = {}; uint8_t sense[32]; - uint8_t resp[8]; + uint8_t resp[8] = {}; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - memset(resp, 0, sizeof(resp)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = sizeof(resp); io_hdr.dxferp = resp; @@ -1189,9 +1268,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (! scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); res = scsiSimpleSenseFilter(&sinfo); if (res) return res; @@ -1208,13 +1286,11 @@ int scsiReadCapacity16(scsi_device * device, uint8_t *pBuf, int bufLen) { - struct scsi_cmnd_io io_hdr; + struct scsi_cmnd_io io_hdr = {}; struct scsi_sense_disect sinfo; - uint8_t cdb[16]; + uint8_t cdb[16] = {}; uint8_t sense[32]; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; @@ -1227,9 +1303,8 @@ io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; - if (!device->scsi_pass_through(&io_hdr)) + if (!scsi_pass_through_yield_sense(device, &io_hdr, sinfo)) return -device->get_errno(); - scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo); } @@ -1279,16 +1354,13 @@ return 0; try_12 = true; } else { /* rcap16 succeeded */ - bool prot_en; - uint8_t p_type; - ret_val = sg_get_unaligned_be64(rc16resp + 0) + 1; lb_size = sg_get_unaligned_be32(rc16resp + 8); if (srrp) { /* writes to all fields */ srrp->num_lblocks = ret_val; srrp->lb_size = lb_size; - prot_en = !!(0x1 & rc16resp[12]); - p_type = ((rc16resp[12] >> 1) & 0x7); + bool prot_en = !!(0x1 & rc16resp[12]); + uint8_t p_type = ((rc16resp[12] >> 1) & 0x7); srrp->prot_type = prot_en ? (1 + p_type) : 0; srrp->p_i_exp = ((rc16resp[13] >> 4) & 0xf); srrp->lb_p_pb_exp = (rc16resp[13] & 0xf); @@ -1525,10 +1597,9 @@ int scsiGetTemp(scsi_device * device, uint8_t *currenttemp, uint8_t *triptemp) { - uint8_t tBuf[252]; + uint8_t tBuf[252] = {}; int err; - memset(tBuf, 0, sizeof(tBuf)); if ((err = scsiLogSense(device, TEMPERATURE_LPAGE, 0, tBuf, sizeof(tBuf), 0))) { *currenttemp = 0; @@ -1551,17 +1622,16 @@ uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp, uint8_t *triptemp) { - uint8_t tBuf[252]; + uint8_t tBuf[252] = {}; struct scsi_sense_disect sense_info; int err; uint8_t currTemp, trTemp; + memset(&sense_info, 0, sizeof(sense_info)); *asc = 0; *ascq = 0; *currenttemp = 0; *triptemp = 0; - memset(tBuf,0,sizeof(tBuf)); // need to clear stack space of junk - memset(&sense_info, 0, sizeof(sense_info)); if (hasIELogPage) { if ((err = scsiLogSense(device, IE_LPAGE, 0, tBuf, sizeof(tBuf), 0))) { @@ -1851,8 +1921,8 @@ const char * scsiTapeAlertsTapeDevice(unsigned short code) { - const int num = sizeof(TapeAlertsMessageTable) / - sizeof(TapeAlertsMessageTable[0]); + static const int num = sizeof(TapeAlertsMessageTable) / + sizeof(TapeAlertsMessageTable[0]); return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert"; } @@ -1999,8 +2069,8 @@ const char * scsiTapeAlertsChangerDevice(unsigned short code) { - const int num = sizeof(ChangerTapeAlertsMessageTable) / - sizeof(ChangerTapeAlertsMessageTable[0]); + static const int num = sizeof(ChangerTapeAlertsMessageTable) / + sizeof(ChangerTapeAlertsMessageTable[0]); return (code < num) ? ChangerTapeAlertsMessageTable[code] : "Unknown Alert"; @@ -2237,9 +2307,8 @@ int modese_len) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] = {}; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, MPAGE_CONTROL_CURRENT, @@ -2263,10 +2332,25 @@ return -EINVAL; if (buff[offset + 1] >= 0xa) { int res = sg_get_unaligned_be16(buff + offset + 10); - *durationSec = res; - return 0; - } - else + + if (res < 0xffff) { + *durationSec = res; + return 0; + } + /* The value 0xffff (all bits set in 16 bit field) indicates that + * the Extended Inquiry VPD page should be consulted, it has a + * similarly named 16 bit field, but the unit is minutes. */ + uint8_t b[64]; + + if ((0 == scsiInquiryVpd(device, SCSI_VPD_EXTENDED_INQUIRY_DATA, + b, sizeof(b))) && + ((sg_get_unaligned_be16(b + 2)) > 11)) { + res = sg_get_unaligned_be16(b + 10); + *durationSec = res * 60; /* VPD field is in minutes */ + return 0; + } else + return -EINVAL; + } else return -EINVAL; } @@ -2315,7 +2399,7 @@ memset(nmep, 0, sizeof(*nmep)); int num = sg_get_unaligned_be16(resp + 2); unsigned char * ucp = &resp[0] + 4; - int szof = sizeof(nmep->counterPC0); + static int szof = sizeof(nmep->counterPC0); while (num > 3) { int pc = sg_get_unaligned_be16(ucp + 0); int pl = ucp[3] + 4; @@ -2452,10 +2536,9 @@ scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] = {}; int pc = current ? MPAGE_CONTROL_CURRENT : MPAGE_CONTROL_DEFAULT; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, pc, buff, sizeof(buff)))) { @@ -2481,17 +2564,19 @@ /* Returns a negative value on error, 0 if unknown and 1 if SSD, * otherwise the positive returned value is the speed in rpm. First checks * the Block Device Characteristics VPD page and if that fails it tries the - * RIGID_DISK_DRIVE_GEOMETRY_PAGE mode page. */ + * RIGID_DISK_DRIVE_GEOMETRY_PAGE mode page. + * In SBC-4 the 2 bit ZONED field in this VPD page is written to *haw_zbcp + * if haw_zbcp is non-NULL. In SBC-5 the ZONED field is now obsolete, + * the Zoned block device characteristics VPD page should be used instead. */ int scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp, int * haw_zbcp) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] = {}; int pc = MPAGE_CONTROL_DEFAULT; - memset(buff, 0, sizeof(buff)); if ((0 == scsiInquiryVpd(device, SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS, buff, sizeof(buff))) && ((sg_get_unaligned_be16(buff + 2)) > 2)) { @@ -2499,7 +2584,7 @@ if (form_factorp) *form_factorp = buff[7] & 0xf; if (haw_zbcp) - *haw_zbcp = !!(0x10 & buff[8]); + *haw_zbcp = (buff[8] >> 4) & 0x3; return speed; } if (form_factorp) @@ -2534,11 +2619,11 @@ short int * rcdp) { int err, offset, resp_len, sp; - uint8_t buff[64], ch_buff[64]; + uint8_t buff[64] = {}; + uint8_t ch_buff[64]; short set_wce = *wcep; short set_rcd = *rcdp; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { err = scsiModeSense(device, CACHING_PAGE, 0, MPAGE_CONTROL_CURRENT, buff, sizeof(buff)); @@ -2637,10 +2722,9 @@ scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len) { int err, offset, resp_len, sp; - uint8_t buff[64]; + uint8_t buff[64] = {}; uint8_t ch_buff[64]; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, 0, MPAGE_CONTROL_CURRENT, @@ -2708,9 +2792,8 @@ scsiFetchTransportProtocol(scsi_device * device, int modese_len) { int err, offset; - uint8_t buff[64]; + uint8_t buff[64] {}; - memset(buff, 0, sizeof(buff)); if (modese_len <= 6) { if ((err = scsiModeSense(device, PROTOCOL_SPECIFIC_PORT_PAGE, 0, MPAGE_CONTROL_CURRENT, diff -Nru smartmontools-7.1/scsicmds.h smartmontools-7.3/scsicmds.h --- smartmontools-7.1/scsicmds.h 2018-12-02 16:07:26.000000000 +0000 +++ smartmontools-7.3/scsicmds.h 2022-02-27 07:53:55.000000000 +0000 @@ -1,7 +1,7 @@ /* * scsicmds.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-8 Bruce Allen * Copyright (C) 2000 Michael Cornwell @@ -19,7 +19,7 @@ #ifndef SCSICMDS_H_ #define SCSICMDS_H_ -#define SCSICMDS_H_CVSID "$Id: scsicmds.h 4842 2018-12-02 16:07:26Z chrfranke $\n" +#define SCSICMDS_H_CVSID "$Id: scsicmds.h 5337 2022-02-27 07:53:55Z dpgilbert $\n" #include #include @@ -69,7 +69,7 @@ #ifndef READ_DEFECT_12 #define READ_DEFECT_12 0xb7 #endif -#ifndef START_STOP_UNIT +#ifndef START_STOP_UNIT /* SSU */ #define START_STOP_UNIT 0x1b #endif #ifndef REPORT_LUNS @@ -167,13 +167,18 @@ uint16_t l_a_lba; /* Lowest Aligned Logical Block Address */ }; +struct scsi_supp_log_pages { + uint8_t page_code; + uint8_t subpage_code; +}; + /* SCSI Peripheral types (of interest) */ #define SCSI_PT_DIRECT_ACCESS 0x0 #define SCSI_PT_SEQUENTIAL_ACCESS 0x1 #define SCSI_PT_CDROM 0x5 #define SCSI_PT_MEDIUM_CHANGER 0x8 #define SCSI_PT_ENCLOSURE 0xd -#define SCSI_PT_HOST_MANAGED 0x14 +#define SCSI_PT_HOST_MANAGED 0x14 /* Zoned disk */ /* Transport protocol identifiers or just Protocol identifiers */ #define SCSI_TPROTO_FCP 0 @@ -208,6 +213,7 @@ #define APPLICATION_CLIENT_LPAGE 0x0f #define SELFTEST_RESULTS_LPAGE 0x10 #define SS_MEDIA_LPAGE 0x11 /* SBC-3 */ +#define DEVICE_STATS_LPAGE 0x14 /* SSC-5 */ #define BACKGROUND_RESULTS_LPAGE 0x15 /* SBC-3 */ #define ATA_PT_RESULTS_LPAGE 0x16 /* SAT */ #define NONVOL_CACHE_LPAGE 0x17 /* SBC-3 */ @@ -286,6 +292,7 @@ #define SCSI_VPD_BLOCK_LIMITS 0xb0 #define SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS 0xb1 #define SCSI_VPD_LOGICAL_BLOCK_PROVISIONING 0xb2 +#define SCSI_VPD_ZONED_BLOCK_DEV_CHAR 0xb6 /* defines for useful SCSI Status codes */ #define SCSI_STATUS_CHECK_CONDITION 0x2 @@ -298,7 +305,10 @@ #define SCSI_SK_HARDWARE_ERROR 0x4 #define SCSI_SK_ILLEGAL_REQUEST 0x5 #define SCSI_SK_UNIT_ATTENTION 0x6 +#define SCSI_SK_DATA_PROTECT 0x7 #define SCSI_SK_ABORTED_COMMAND 0xb +#define SCSI_SK_MISCOMPARE 0xe +#define SCSI_SK_COMPLETED 0xf /* defines for useful Additional Sense Codes (ASCs) */ #define SCSI_ASC_NOT_READY 0x4 /* more info in ASCQ code */ @@ -324,6 +334,8 @@ #define SIMPLE_ERR_MEDIUM_HARDWARE 9 /* medium or hardware error */ #define SIMPLE_ERR_UNKNOWN 10 /* unknown sense value */ #define SIMPLE_ERR_ABORTED_COMMAND 11 /* probably transport error */ +#define SIMPLE_ERR_PROTECTION 12 /* data protect sense key */ +#define SIMPLE_ERR_MISCOMPARE 13 /* from VERIFY commands */ /* defines for functioncode parameter in SENDDIAGNOSTIC function */ @@ -335,6 +347,11 @@ #define SCSI_DIAG_FG_EXTENDED_SELF_TEST 0x06 #define SCSI_DIAG_ABORT_SELF_TEST 0x04 +/* Defines for power_cond in scsiSetPowerCondition() (SSU command) */ +#define SCSI_POW_COND_ACTIVE 0x1 +#define SCSI_POW_COND_IDLE 0x2 +#define SCSI_POW_COND_STANDBY 0x3 + /* SCSI command timeout values (units are seconds) */ #define SCSI_TIMEOUT_DEFAULT 60 // should be longer than the spin up time @@ -355,13 +372,9 @@ { public: explicit supported_vpd_pages(scsi_device * device); - ~supported_vpd_pages() { num_valid = 0; } bool is_supported(int vpd_page_num) const; - /* Returns 0 or less for VPD pages not supported or error */ - int num_pages() const { return num_valid; } - private: int num_valid; /* 0 or less for invalid */ unsigned char pages[256]; @@ -396,6 +409,9 @@ const char * scsiErrString(int scsiErr); +/* Yield string associated with sense_key value. Returns 'buff'. */ +char * scsi_get_sense_key_str(int sense_key, int buff_len, char * buff); + int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len, int * off, int m_assoc, int m_desig_type, int m_code_set); @@ -433,9 +449,15 @@ int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info); +int scsiSetPowerCondition(scsi_device * device, int power_cond, + int pcond_modifier = 0); + int scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf, int bufLen); +bool scsi_pass_through_yield_sense(scsi_device * device, scsi_cmnd_io * iop, + struct scsi_sense_disect & sinfo); + int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format, uint8_t *pBuf, int bufLen); diff -Nru smartmontools-7.1/scsinvme.cpp smartmontools-7.3/scsinvme.cpp --- smartmontools-7.1/scsinvme.cpp 2018-12-11 20:20:40.000000000 +0000 +++ smartmontools-7.3/scsinvme.cpp 2022-02-27 07:53:55.000000000 +0000 @@ -1,27 +1,119 @@ /* * scsinvme.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * + * Copyright (C) 2020-21 Christian Franke * Copyright (C) 2018 Harry Mallon * * SPDX-License-Identifier: GPL-2.0-or-later - * */ #include "config.h" #include "dev_interface.h" #include "dev_tunnelled.h" +#include "nvmecmds.h" #include "scsicmds.h" #include "sg_unaligned.h" #include "utility.h" #include +const char * scsinvme_cpp_svnid = "$Id: scsinvme.cpp 5337 2022-02-27 07:53:55Z dpgilbert $"; + // SNT (SCSI NVMe Translation) namespace and prefix namespace snt { +///////////////////////////////////////////////////////////////////////////// +// sntasmedia_device + +class sntasmedia_device +: public tunnelled_device< + /*implements*/ nvme_device, + /*by tunnelling through a*/ scsi_device + > +{ +public: + sntasmedia_device(smart_interface * intf, scsi_device * scsidev, + const char * req_type, unsigned nsid); + + virtual ~sntasmedia_device(); + + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; +}; + +sntasmedia_device::sntasmedia_device(smart_interface * intf, scsi_device * scsidev, + const char * req_type, unsigned nsid) +: smart_device(intf, scsidev->get_dev_name(), "sntasmedia", req_type), + tunnelled_device(scsidev, nsid) +{ + set_info().info_name = strprintf("%s [USB NVMe ASMedia]", scsidev->get_info_name()); +} + +sntasmedia_device::~sntasmedia_device() +{ +} + +bool sntasmedia_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & /* out */) +{ + unsigned size = in.size; + unsigned cdw10_hi = in.cdw10 >> 16; + switch (in.opcode) { + case smartmontools::nvme_admin_identify: + if (in.cdw10 == 0x0000001) // Identify controller + break; + if (in.cdw10 == 0x0000000) { // Identify namespace + if (in.nsid == 1) + break; + return set_err(ENOSYS, "NVMe Identify Namespace 0x%x not supported", in.nsid); + } + return set_err(ENOSYS, "NVMe Identify with CDW10=0x%08x not supported", in.cdw10); + case smartmontools::nvme_admin_get_log_page: + if (!(in.nsid == 0xffffffff || !in.nsid)) + return set_err(ENOSYS, "NVMe Get Log Page with NSID=0x%x not supported", in.nsid); + if (size > 0x200) { // Reading more results in command timeout + // TODO: Add ability to return short reads to caller + size = 0x200; + cdw10_hi = (size / 4) - 1; + pout("Warning: NVMe Get Log truncated to 0x%03x bytes, 0x%03x bytes zero filled\n", size, in.size - size); + } + break; + default: + return set_err(ENOSYS, "NVMe admin command 0x%02x not supported", in.opcode); + break; + } + if (in.cdw11 || in.cdw12 || in.cdw13 || in.cdw14 || in.cdw15) + return set_err(ENOSYS, "Nonzero NVMe command dwords 11-15 not supported"); + + uint8_t cdb[16] = {0, }; + cdb[0] = 0xe6; + cdb[1] = in.opcode; + //cdb[2] = ? + cdb[3] = (uint8_t)in.cdw10; + //cdb[4..6] = ? + cdb[7] = (uint8_t)cdw10_hi; + //cdb[8..15] = ? + + scsi_cmnd_io io_hdr = {}; + io_hdr.cmnd = cdb; + io_hdr.cmnd_len = sizeof(cdb); + io_hdr.dxfer_dir = DXFER_FROM_DEVICE; + io_hdr.dxferp = (uint8_t *)in.buffer; + io_hdr.dxfer_len = size; + memset(in.buffer, 0, in.size); + + scsi_device * scsidev = get_tunnel_dev(); + if (!scsidev->scsi_pass_through_and_check(&io_hdr, "sntasmedia_device::nvme_pass_through: ")) + return set_err(scsidev->get_err()); + + //out.result = ?; + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// sntjmicron_device + #define SNT_JMICRON_NVME_SIGNATURE 0x454d564eu // 'NVME' reversed (little endian) #define SNT_JMICRON_CDB_LEN 12 #define SNT_JMICRON_NVM_CMD_LEN 512 @@ -36,11 +128,11 @@ sntjmicron_device(smart_interface * intf, scsi_device * scsidev, const char * req_type, unsigned nsid); - virtual ~sntjmicron_device() throw(); + virtual ~sntjmicron_device(); - virtual bool open(); + virtual bool open() override; - virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out); + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; private: enum { @@ -57,7 +149,7 @@ set_info().info_name = strprintf("%s [USB NVMe JMicron]", scsidev->get_info_name()); } -sntjmicron_device::~sntjmicron_device() throw() +sntjmicron_device::~sntjmicron_device() { } @@ -92,7 +184,7 @@ bool sntjmicron_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) { /* Only admin commands used */ - bool admin = true; + constexpr bool admin = true; // 1: "NVM Command Set Payload" { @@ -121,8 +213,7 @@ for (unsigned i = 0; i < (SNT_JMICRON_NVM_CMD_LEN / sizeof(uint32_t)); i++) swapx(&nvm_cmd[i]); - scsi_cmnd_io io_nvm; - memset(&io_nvm, 0, sizeof(io_nvm)); + scsi_cmnd_io io_nvm = {}; io_nvm.cmnd = cdb; io_nvm.cmnd_len = SNT_JMICRON_CDB_LEN; @@ -141,8 +232,7 @@ unsigned char cdb[SNT_JMICRON_CDB_LEN] = { 0 }; cdb[0] = SAT_ATA_PASSTHROUGH_12; - scsi_cmnd_io io_data; - memset(&io_data, 0, sizeof(io_data)); + scsi_cmnd_io io_data = {}; io_data.cmnd = cdb; io_data.cmnd_len = SNT_JMICRON_CDB_LEN; @@ -186,8 +276,7 @@ unsigned nvm_reply[SNT_JMICRON_NVM_CMD_LEN / sizeof(unsigned)] = { 0 }; - scsi_cmnd_io io_reply; - memset(&io_reply, 0, sizeof(io_reply)); + scsi_cmnd_io io_reply = {}; io_reply.cmnd = cdb; io_reply.cmnd_len = SNT_JMICRON_CDB_LEN; @@ -218,6 +307,88 @@ return true; } +///////////////////////////////////////////////////////////////////////////// +// sntrealtek_device + +class sntrealtek_device +: public tunnelled_device< + /*implements*/ nvme_device, + /*by tunnelling through a*/ scsi_device + > +{ +public: + sntrealtek_device(smart_interface * intf, scsi_device * scsidev, + const char * req_type, unsigned nsid); + + virtual ~sntrealtek_device(); + + virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override; +}; + +sntrealtek_device::sntrealtek_device(smart_interface * intf, scsi_device * scsidev, + const char * req_type, unsigned nsid) +: smart_device(intf, scsidev->get_dev_name(), "sntrealtek", req_type), + tunnelled_device(scsidev, nsid) +{ + set_info().info_name = strprintf("%s [USB NVMe Realtek]", scsidev->get_info_name()); +} + +sntrealtek_device::~sntrealtek_device() +{ +} + +bool sntrealtek_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & /* out */) +{ + unsigned size = in.size; + switch (in.opcode) { + case smartmontools::nvme_admin_identify: + if (in.cdw10 == 0x0000001) // Identify controller + break; + if (in.cdw10 == 0x0000000) { // Identify namespace + if (in.nsid == 1) + break; + return set_err(ENOSYS, "NVMe Identify Namespace 0x%x not supported", in.nsid); + } + return set_err(ENOSYS, "NVMe Identify with CDW10=0x%08x not supported", in.cdw10); + case smartmontools::nvme_admin_get_log_page: + if (!(in.nsid == 0xffffffff || !in.nsid)) + return set_err(ENOSYS, "NVMe Get Log Page with NSID=0x%x not supported", in.nsid); + if (size > 0x200) { // Reading more apparently returns old data from previous command + // TODO: Add ability to return short reads to caller + size = 0x200; + pout("Warning: NVMe Get Log truncated to 0x%03x bytes, 0x%03x bytes zero filled\n", size, in.size - size); + } + break; + default: + return set_err(ENOSYS, "NVMe admin command 0x%02x not supported", in.opcode); + break; + } + if (in.cdw11 || in.cdw12 || in.cdw13 || in.cdw14 || in.cdw15) + return set_err(ENOSYS, "Nonzero NVMe command dwords 11-15 not supported"); + + uint8_t cdb[16] = {0, }; + cdb[0] = 0xe4; + sg_put_unaligned_le16(size, cdb+1); + cdb[3] = in.opcode; + cdb[4] = (uint8_t)in.cdw10; + + scsi_cmnd_io io_hdr = {}; + io_hdr.cmnd = cdb; + io_hdr.cmnd_len = sizeof(cdb); + io_hdr.dxfer_dir = DXFER_FROM_DEVICE; + io_hdr.dxferp = (uint8_t *)in.buffer; + io_hdr.dxfer_len = size; + memset(in.buffer, 0, in.size); + + scsi_device * scsidev = get_tunnel_dev(); + if (!scsidev->scsi_pass_through_and_check(&io_hdr, "sntrealtek_device::nvme_pass_through: ")) + return set_err(scsidev->get_err()); + + //out.result = ?; // TODO + return true; +} + + } // namespace snt using namespace snt; @@ -238,7 +409,12 @@ return 0; } - if (!strncmp(type, "sntjmicron", 10)) { + if (!strcmp(type, "sntasmedia")) { + // No namespace supported + sntdev = new sntasmedia_device(this, scsidev, type, 0xffffffff); + } + + else if (!strncmp(type, "sntjmicron", 10)) { int n1 = -1, n2 = -1, len = strlen(type); unsigned nsid = 0; // invalid namespace id -> use default sscanf(type, "sntjmicron%n,0x%x%n", &n1, &nsid, &n2); @@ -248,6 +424,12 @@ } sntdev = new sntjmicron_device(this, scsidev, type, nsid); } + + else if (!strcmp(type, "sntrealtek")) { + // No namespace supported + sntdev = new sntrealtek_device(this, scsidev, type, 0xffffffff); + } + else { set_err(EINVAL, "Unknown SNT device type '%s'", type); return 0; diff -Nru smartmontools-7.1/scsiprint.cpp smartmontools-7.3/scsiprint.cpp --- smartmontools-7.1/scsiprint.cpp 2019-12-29 13:14:34.000000000 +0000 +++ smartmontools-7.3/scsiprint.cpp 2022-02-27 07:53:55.000000000 +0000 @@ -5,7 +5,7 @@ * * Copyright (C) 2002-11 Bruce Allen * Copyright (C) 2000 Michael Cornwell - * Copyright (C) 2003-19 Douglas Gilbert + * Copyright (C) 2003-20 Douglas Gilbert * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -30,15 +30,19 @@ #define GBUF_SIZE 65532 -const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 5014 2019-12-29 13:14:34Z chrfranke $" +const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 5337 2022-02-27 07:53:55Z dpgilbert $" SCSIPRINT_H_CVSID; +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) uint8_t gBuf[GBUF_SIZE]; #define LOG_RESP_LEN 252 #define LOG_RESP_LONG_LEN ((62 * 256) + 252) #define LOG_RESP_TAPE_ALERT_LEN 0x144 +/* Supported log pages + Supported log pages and subpages maximum count */ +#define SCSI_SUPP_LOG_PAGES_MAX_COUNT (252 + (62 * 128) + 126) + /* Log pages supported */ static bool gSmartLPage = false; /* Informational Exceptions log page */ static bool gTempLPage = false; @@ -60,6 +64,8 @@ static bool gPendDefectsLPage = false; static bool gBackgroundOpLPage = false; static bool gLPSMisalignLPage = false; +static bool gTapeDeviceStatsLPage = false; +static bool gZBDeviceStatsLPage = false; /* Vendor specific log pages */ static bool gSeagateCacheLPage = false; @@ -114,16 +120,30 @@ return true; } +// trim from right. By default trims whitespace. +static std::string rtrim(const std::string& s, const char* t = " \t\n\r\f\v") +{ + std::string r(s); + + r.erase(r.find_last_not_of(t) + 1); + return r; +} + static void scsiGetSupportedLogPages(scsi_device * device) { bool got_subpages = false; - int k, bump, err, payload_len, num_unreported, num_unreported_spg; - int payload_len_pg0_0 = 0; + int k, err, resp_len, num_unreported, num_unreported_spg; + int supp_lpg_and_spg_count = 0; + const uint8_t * up; uint8_t sup_lpgs[LOG_RESP_LEN]; + struct scsi_supp_log_pages supp_lpg_and_spg[SCSI_SUPP_LOG_PAGES_MAX_COUNT]; memset(gBuf, 0, LOG_RESP_LEN); + memset(supp_lpg_and_spg, 0, sizeof(supp_lpg_and_spg)); + + /* Get supported log pages */ if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf, LOG_RESP_LEN, 0 /* do double fetch */))) { if (scsi_debugmode > 0) @@ -138,12 +158,23 @@ logSenStr, scsiErrString(err)); if (err) return; - memcpy(sup_lpgs, gBuf, LOG_RESP_LEN); - } else if ((scsi_version >= SCSI_VERSION_SPC_4) && - (scsi_version <= SCSI_VERSION_HIGHEST)) { + } + + memcpy(sup_lpgs, gBuf, LOG_RESP_LEN); + resp_len = gBuf[3]; + up = gBuf + LOGPAGEHDRSIZE; + + for (k = 0; k < resp_len; k += 1) { + uint8_t page_code = 0x3f & up[k]; + supp_lpg_and_spg[supp_lpg_and_spg_count++] = {page_code, 0}; + } + + /* Get supported log pages and subpages. Most drives seems to include the + supported log pages here as well, but some drives such as the Samsung + PM1643a will only report the additional log pages with subpages here */ + if ((scsi_version >= SCSI_VERSION_SPC_4) && + (scsi_version <= SCSI_VERSION_HIGHEST)) { /* unclear what code T10 will choose for SPC-6 */ - memcpy(sup_lpgs, gBuf, LOG_RESP_LEN); - payload_len_pg0_0 = sup_lpgs[3]; if ((err = scsiLogSense(device, SUPPORTED_LPAGES, SUPP_SPAGE_L_SPAGE, gBuf, LOG_RESP_LONG_LEN, -1 /* just single not double fetch */))) { @@ -151,6 +182,7 @@ pout("%s for supported pages and subpages failed [%s]\n", logSenStr, scsiErrString(err)); } else { + /* Ensure we didn't get the same answer than without the subpages */ if (0 == memcmp(gBuf, sup_lpgs, LOG_RESP_LEN)) { if (scsi_debugmode > 0) pout("%s: %s ignored subpage field, bad\n", @@ -160,44 +192,35 @@ if (scsi_debugmode > 0) pout("%s supported subpages is bad SPF=%u SUBPG=%u\n", logSenRspStr, !! (0x40 & gBuf[0]), gBuf[2]); - } else + } else { got_subpages = true; + } } - } else - memcpy(sup_lpgs, gBuf, LOG_RESP_LEN); + } if (got_subpages) { - payload_len = sg_get_unaligned_be16(gBuf + 2); - if (payload_len <= payload_len_pg0_0) { - /* something is rotten ....., ignore SUPP_SPAGE_L_SPAGE */ - payload_len = payload_len_pg0_0; - bump = 1; - up = sup_lpgs + LOGPAGEHDRSIZE; - got_subpages = false; - (void)got_subpages; // not yet used below, suppress warning - } else { - bump = 2; - up = gBuf + LOGPAGEHDRSIZE; + resp_len = sg_get_unaligned_be16(gBuf + 2); + up = gBuf + LOGPAGEHDRSIZE; + for (k = 0; k < resp_len; k += 2) { + uint8_t page_code = 0x3f & up[k]; + uint8_t subpage_code = up[k+1]; + supp_lpg_and_spg[supp_lpg_and_spg_count++] = {page_code, subpage_code}; } - } else { - payload_len = payload_len_pg0_0; - bump = 1; - up = sup_lpgs + LOGPAGEHDRSIZE; } + num_unreported = 0; num_unreported_spg = 0; - for (num_unreported = 0, k = 0; k < payload_len; k += bump, up += bump) { - uint8_t pg_num = 0x3f & up[0]; - uint8_t sub_pg_num = (0x40 & up[0]) ? up[1] : 0; + for (k = 0; k < supp_lpg_and_spg_count; k += 1) { + struct scsi_supp_log_pages supp_lpg = supp_lpg_and_spg[k]; - switch (pg_num) + switch (supp_lpg.page_code) { case SUPPORTED_LPAGES: - if (! ((NO_SUBPAGE_L_SPAGE == sub_pg_num) || - (SUPP_SPAGE_L_SPAGE == sub_pg_num))) { + if (! ((NO_SUBPAGE_L_SPAGE == supp_lpg.subpage_code) || + (SUPP_SPAGE_L_SPAGE == supp_lpg.subpage_code))) { if (scsi_debugmode > 1) pout("%s: Strange Log page number: 0x0,0x%x\n", - __func__, sub_pg_num); + __func__, supp_lpg.subpage_code); } break; case READ_ERROR_COUNTER_LPAGE: @@ -216,13 +239,13 @@ gNonMediumELPage = true; break; case TEMPERATURE_LPAGE: - if (NO_SUBPAGE_L_SPAGE == sub_pg_num) + if (NO_SUBPAGE_L_SPAGE == supp_lpg.subpage_code) gTempLPage = true; - else if (ENVIRO_REP_L_SPAGE == sub_pg_num) + else if (ENVIRO_REP_L_SPAGE == supp_lpg.subpage_code) gEnviroReportingLPage = true; - else if (ENVIRO_LIMITS_L_SPAGE == sub_pg_num) + else if (ENVIRO_LIMITS_L_SPAGE == supp_lpg.subpage_code) gEnviroLimitsLPage = true; - else if (SUPP_SPAGE_L_SPAGE != sub_pg_num) { + else if (SUPP_SPAGE_L_SPAGE != supp_lpg.subpage_code) { ++num_unreported; ++num_unreported_spg; } @@ -231,11 +254,11 @@ reporting of ,0xff so it is not an error. */ break; case STARTSTOP_CYCLE_COUNTER_LPAGE: - if (NO_SUBPAGE_L_SPAGE == sub_pg_num) + if (NO_SUBPAGE_L_SPAGE == supp_lpg.subpage_code) gStartStopLPage = true; - else if (UTILIZATION_L_SPAGE == sub_pg_num) + else if (UTILIZATION_L_SPAGE == supp_lpg.subpage_code) gUtilizationLPage = true; - else if (SUPP_SPAGE_L_SPAGE != sub_pg_num) { + else if (SUPP_SPAGE_L_SPAGE != supp_lpg.subpage_code) { ++num_unreported; ++num_unreported_spg; } @@ -246,16 +269,22 @@ case IE_LPAGE: gSmartLPage = true; break; + case DEVICE_STATS_LPAGE: + if (NO_SUBPAGE_L_SPAGE == supp_lpg.subpage_code) + gTapeDeviceStatsLPage = true; + else if (ZB_DEV_STATS_L_SPAGE == supp_lpg.subpage_code) + gZBDeviceStatsLPage = true; + break; case BACKGROUND_RESULTS_LPAGE: - if (NO_SUBPAGE_L_SPAGE == sub_pg_num) + if (NO_SUBPAGE_L_SPAGE == supp_lpg.subpage_code) gBackgroundResultsLPage = true; - else if (PEND_DEFECTS_L_SPAGE == sub_pg_num) + else if (PEND_DEFECTS_L_SPAGE == supp_lpg.subpage_code) gPendDefectsLPage = true; - else if (BACKGROUND_OP_L_SPAGE == sub_pg_num) + else if (BACKGROUND_OP_L_SPAGE == supp_lpg.subpage_code) gBackgroundOpLPage = true; - else if (LPS_MISALIGN_L_SPAGE == sub_pg_num) + else if (LPS_MISALIGN_L_SPAGE == supp_lpg.subpage_code) gLPSMisalignLPage = true; - else if (SUPP_SPAGE_L_SPAGE != sub_pg_num) { + else if (SUPP_SPAGE_L_SPAGE != supp_lpg.subpage_code) { ++num_unreported; ++num_unreported_spg; } @@ -289,9 +318,10 @@ gSeagateFactoryLPage = true; break; default: - if (pg_num < 0x30) { /* don't count VS pages */ + if (supp_lpg.page_code < 0x30) { /* don't count VS pages */ ++num_unreported; - if ((sub_pg_num > 0) && (SUPP_SPAGE_L_SPAGE != sub_pg_num)) + if ((supp_lpg.subpage_code > 0) && + (SUPP_SPAGE_L_SPAGE != supp_lpg.subpage_code)) ++num_unreported_spg; } break; @@ -348,8 +378,8 @@ pout("Drive Trip Temperature: \n"); else { jout("Drive Trip Temperature: %d C\n", triptemp); - jglb["temperature"]["drive_trip"] = triptemp; - } + jglb["scsi_temperature"]["drive_trip"] = triptemp; + } } pout("\n"); return err; @@ -361,14 +391,17 @@ static const char * const severities = "CWI"; static int -scsiGetTapeAlertsData(scsi_device * device, int peripheral_type) +scsiPrintActiveTapeAlerts(scsi_device * device, int peripheral_type, + bool from_health) { unsigned short pagelength; unsigned short parametercode; - int i, err; + int i, k, j, m, err; const char *s; const char *ts; int failures = 0; + const char * pad = from_health ? "" : " "; + static const char * const tapealert_s = "scsi_tapealert"; print_on(); if ((err = scsiLogSense(device, TAPE_ALERTS_LPAGE, 0, gBuf, @@ -378,14 +411,15 @@ return -1; } if (gBuf[0] != 0x2e) { - pout("TapeAlerts %s Failed\n", logSenStr); + pout("%sTapeAlerts %s Failed\n", pad, logSenStr); print_off(); return -1; } pagelength = sg_get_unaligned_be16(gBuf + 2); - for (s=severities; *s; s++) { - for (i = 4; i < pagelength; i += 5) { + json::ref jref = jglb[tapealert_s]["status"]; + for (s=severities, k = 0, j = 0; *s; s++, ++k) { + for (i = 4, m = 0; i < pagelength; i += 5, ++k, ++m) { parametercode = sg_get_unaligned_be16(gBuf + i); if (gBuf[i + 4]) { @@ -394,9 +428,13 @@ scsiTapeAlertsTapeDevice(parametercode); if (*ts == *s) { if (!failures) - pout("TapeAlert Errors (C=Critical, W=Warning, " - "I=Informational):\n"); - pout("[0x%02x] %s\n", parametercode, ts); + jout("%sTapeAlert Errors (C=Critical, W=Warning, " + "I=Informational):\n", pad); + jout("%s[0x%02x] %s\n", pad, parametercode, ts); + jref[j]["descriptor_idx"] = m + 1; + jref[j]["parameter_code"] = parametercode; + jref[j]["string"] = ts; + ++j; failures += 1; } } @@ -404,8 +442,10 @@ } print_off(); - if (! failures) - pout("TapeAlert: OK\n"); + if (! failures) { + jout("%sTapeAlert: OK\n", pad); + jglb[tapealert_s]["status"] = "Good"; + } return failures; } @@ -415,6 +455,9 @@ { int err, len, k, extra; unsigned char * ucp; + char b[32]; + const char * q; + static const char * jname = "scsi_start_stop_cycle_counter"; if ((err = scsiLogSense(device, STARTSTOP_CYCLE_COUNTER_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) { @@ -444,29 +487,45 @@ bool is_all_ffs = (extra > 7) ? all_ffs(ucp + 4, 4) : false; switch (pc) { case 1: - if (10 == extra) - pout("Manufactured in week %.2s of year %.4s\n", ucp + 8, + if (10 == extra) { + jout("Manufactured in week %.2s of year %.4s\n", ucp + 8, ucp + 4); + snprintf(b, sizeof(b), "%.4s", ucp + 4); + jglb[jname]["year_of_manufacture"] = b; + snprintf(b, sizeof(b), "%.2s", ucp + 8); + jglb[jname]["week_of_manufacture"] = b; + } break; case 2: /* ignore Accounting date */ break; case 3: - if ((extra > 7) && (! is_all_ffs)) - pout("Specified cycle count over device lifetime: %u\n", u); + if ((extra > 7) && (! is_all_ffs)) { + q = "Specified cycle count over device lifetime"; + jout("%s: %u\n", q, u); + jglb[jname][q] = u; + } break; case 4: - if ((extra > 7) && (! is_all_ffs)) - pout("Accumulated start-stop cycles: %u\n", u); + if ((extra > 7) && (! is_all_ffs)) { + q = "Accumulated start-stop cycles"; + jout("%s: %u\n", q, u); + jglb[jname][q] = u; + } break; case 5: - if ((extra > 7) && (! is_all_ffs)) - pout("Specified load-unload count over device lifetime: " - "%u\n", u); + if ((extra > 7) && (! is_all_ffs)) { + q = "Specified load-unload count over device lifetime"; + jout("%s: %u\n", q, u); + jglb[jname][q] = u; + } break; case 6: - if ((extra > 7) && (! is_all_ffs)) - pout("Accumulated load-unload cycles: %u\n", u); + if ((extra > 7) && (! is_all_ffs)) { + q = "Accumulated load-unload cycles"; + jout("%s: %u\n", q, u); + jglb[jname][q] = u; + } break; default: /* ignore */ @@ -478,12 +537,10 @@ static void scsiPrintPendingDefectsLPage(scsi_device * device) { - int num, pl, pc, err; - uint32_t count; - const uint8_t * bp; static const char * pDefStr = "Pending Defects"; - static const char * jname = "pending_defects"; + static const char * jname = "scsi_pending_defects"; + int err; if ((err = scsiLogSense(device, BACKGROUND_RESULTS_LPAGE, PEND_DEFECTS_L_SPAGE, gBuf, LOG_RESP_LONG_LEN, 0))) { @@ -499,20 +556,21 @@ print_off(); return; } - num = sg_get_unaligned_be16(gBuf + 2); + int num = sg_get_unaligned_be16(gBuf + 2); if (num > LOG_RESP_LONG_LEN) { print_on(); pout("%s %s too long\n", pDefStr, logSenRspStr); print_off(); return; } - bp = gBuf + 4; + const uint8_t * bp = gBuf + 4; while (num > 3) { - pc = sg_get_unaligned_be16(bp + 0); - pl = bp[3] + 4; + int pc = sg_get_unaligned_be16(bp + 0); + int pl = bp[3] + 4; + uint32_t count; switch (pc) { case 0x0: - printf(" Pending defect count:"); + jout(" Pending defect count:"); if ((pl < 8) || (num < 8)) { print_on(); pout("%s truncated descriptor\n", pDefStr); @@ -637,17 +695,30 @@ "number of elements]\n\n", dl_len); else { jout("Elements in grown defect list: %u\n\n", dl_len / div); - jglb["scsi_grown_defect_list"] = dl_len; + jglb["scsi_grown_defect_list"] = dl_len / div; } } } +static uint64_t +variableLengthIntegerParam(const unsigned char * ucp) +{ + static const size_t sz_u64 = (int)sizeof(uint64_t); + unsigned int u = ucp[3]; + const unsigned char * xp = ucp + 4; + + if (u > sz_u64) { + xp += (u - sz_u64); + u = sz_u64; + } + return sg_get_unaligned_be(u, xp + 0); +} + static void scsiPrintSeagateCacheLPage(scsi_device * device) { int num, pl, pc, err, len; unsigned char * ucp; - uint64_t ull; static const char * seaCacStr = "Seagate Cache"; if ((err = scsiLogSense(device, SEAGATE_CACHE_LPAGE, 0, gBuf, @@ -705,15 +776,7 @@ "> segment size"); break; default: pout(" Unknown Seagate parameter code [0x%x]", pc); break; } - int k = pl - 4; - const int sz_ull = (int)sizeof(ull); - unsigned char * xp = ucp + 4; - if (k > sz_ull) { - xp += (k - sz_ull); - k = sz_ull; - } - ull = sg_get_unaligned_be(k, xp + 0); - pout(" = %" PRIu64 "\n", ull); + pout(" = %" PRIu64 "\n", variableLengthIntegerParam(ucp)); num -= pl; ucp += pl; } @@ -780,7 +843,7 @@ pl = ucp[3] + 4; good = 0; switch (pc) { - case 0: pout(" number of hours powered up"); + case 0: jout(" number of hours powered up"); good = 1; break; case 8: pout(" number of minutes until next internal SMART test"); @@ -796,15 +859,9 @@ break; } if (good) { - int k = pl - 4; - unsigned char * xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - (int)sizeof(ull)); - k = (int)sizeof(ull); - } - ull = sg_get_unaligned_be(k, xp + 0); + ull = variableLengthIntegerParam(ucp); if (0 == pc) { - pout(" = %.2f\n", ull / 60.0 ); + jout(" = %.2f\n", ull / 60.0 ); jglb["power_on_time"]["hours"] = ull / 60; jglb["power_on_time"]["minutes"] = ull % 60; } @@ -959,7 +1016,7 @@ "Completed, segment failed", "Failed in first segment ", "Failed in second segment ", - "Failed in segment --> ", + "Failed in segment", /* special handling for result 7 */ "Reserved(8) ", "Reserved(9) ", "Reserved(10) ", @@ -977,13 +1034,13 @@ static int scsiPrintSelfTest(scsi_device * device) { + bool noheader = true; int num, k, err, durationSec; - int noheader = 1; int retval = 0; uint8_t * ucp; - uint64_t ull; struct scsi_sense_disect sense_info; static const char * hname = "Self-test"; + static const char * fixup_stres7 = " --> "; /* only for non-json */ // check if test is running if (!scsiRequestSense(device, &sense_info) && @@ -1018,31 +1075,36 @@ // loop through the twenty possible entries for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) { // timestamp in power-on hours (or zero if test in progress) - int n = sg_get_unaligned_be16(ucp + 6); + unsigned int poh = sg_get_unaligned_be16(ucp + 6); + unsigned int u, tr; + char st[32]; + snprintf(st, sizeof(st), "scsi_self_test_%d", k); // The spec says "all 20 bytes will be zero if no test" but // DG has found otherwise. So this is a heuristic. - if ((0 == n) && (0 == ucp[4])) + if ((0 == poh) && (0 == ucp[4])) break; // only print header if needed if (noheader) { - pout("SMART %s log\n", hname); - pout("Num Test Status segment " + jout("SMART %s log\n", hname); + jout("Num Test Status segment " "LifeTime LBA_first_err [SK ASC ASQ]\n"); - pout(" Description number " + jout(" Description number " "(hours)\n"); - noheader=0; + noheader = false; } // print parameter code (test number) & self-test code text - pout("#%2d %s", sg_get_unaligned_be16(ucp + 0), - self_test_code[(ucp[4] >> 5) & 0x7]); + u = (ucp[4] >> 5) & 0x7; + jout("#%2d %s", sg_get_unaligned_be16(ucp + 0), self_test_code[u]); + jglb[st]["code"]["value"] = u; + jglb[st]["code"]["string"] = rtrim(self_test_code[u]); // check the self-test result nibble, using the self-test results // field table from T10/1416-D (SPC-3) Rev. 23, section 7.2.10: - int res; - switch ((res = ucp[4] & 0xf)) { + tr = ucp[4] & 0xf; + switch (tr) { case 0x3: // an unknown error occurred while the device server // was processing the self-test and the device server @@ -1072,7 +1134,9 @@ default: break; } - pout(" %s", self_test_result[res]); + jout(" %s%s", self_test_result[tr], (tr == 7 ? fixup_stres7 : "")); + jglb[st]["result"]["value"] = tr; + jglb[st]["result"]["string"] = rtrim(self_test_result[tr]); // self-test number identifies test that failed and consists // of either the number of the segment that failed during @@ -1080,50 +1144,72 @@ // number of the segment in which the test was run, using a // vendor-specific method of putting both numbers into a // single byte. - if (ucp[5]) - pout(" %3d", (int)ucp[5]); - else - pout(" -"); + u = ucp[5]; + if (u > 0) { + jout(" %3u", u); + jglb[st]["failed_segment"]["value"] = u; + jglb[st]["failed_segment"]["aka"] = "self_test_number"; + } else + jout(" -"); // print time that the self-test was completed - if (n==0 && res==0xf) + if (poh==0 && tr==0xf) { // self-test in progress - pout(" NOW"); - else - pout(" %5d", n); + jout(" NOW"); + jglb[st]["self_test_in_progress"] = true; + } else { + jout(" %5d", poh); + jglb[st]["power_on_time"]["hours"] = poh; + jglb[st]["power_on_time"]["aka"] = "accumulated_power_on_hours"; + } // construct 8-byte integer address of first failure - ull = sg_get_unaligned_be64(ucp + 8); + uint64_t ull = sg_get_unaligned_be64(ucp + 8); bool is_all_ffs = all_ffs(ucp + 8, 8); // print Address of First Failure, if sensible - if ((! is_all_ffs) && (res > 0) && (res < 0xf)) { + if ((! is_all_ffs) && (tr > 0) && (tr < 0xf)) { char buff[32]; // was hex but change to decimal to conform with ATA snprintf(buff, sizeof(buff), "%" PRIu64, ull); // snprintf(buff, sizeof(buff), "0x%" PRIx64, ull); - pout("%18s", buff); + jout("%18s", buff); + jglb[st]["lba_first_failure"]["value"] = ull; + jglb[st]["lba_first_failure"]["aka"] = "address_of_first_failure"; } else - pout(" -"); + jout(" -"); // if sense key nonzero, then print it, along with // additional sense code and additional sense code qualifier - if (ucp[16] & 0xf) - pout(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); - else + if (ucp[16] & 0xf) { + char b[48]; + + jout(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); + u = ucp[16] & 0xf; + jglb[st]["sense_key"]["value"] = u; + jglb[st]["sense_key"]["string"] = + scsi_get_sense_key_str(u, sizeof(b), b); + jglb[st]["asc"] = ucp[17]; + jglb[st]["ascq"] = ucp[18]; + jglb[st]["vendor_specific"] = ucp[19]; + } else pout(" [- - -]\n"); } // if header never printed, then there was no output if (noheader) - pout("No %ss have been logged\n", hname); - else - if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec, + jout("No %ss have been logged\n", hname); + else if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec, modese_len)) && (durationSec > 0)) { - pout("\nLong (extended) %s duration: %d seconds " - "[%.1f minutes]\n", hname, durationSec, durationSec / 60.0); + if (durationSec > 14400) + jout("\nLong (extended) %s duration: %d seconds " + "[%.1f hours]\n", hname, durationSec, durationSec / 3600.0); + else + jout("\nLong (extended) %s duration: %d seconds " + "[%.1f minutes]\n", hname, durationSec, durationSec / 60.0); + jglb["scsi_extended_self_test_seconds"] = durationSec; } - pout("\n"); + jout("\n"); return retval; } @@ -1155,15 +1241,22 @@ // Returns 0 if ok else FAIL* bitmask. Note can have a status entry // and up to 2048 events (although would hope to have less). May set // FAILLOG if serious errors detected (in the future). +// When only_pow_time is true only print "Accumulated power on time" +// data, if available. static int -scsiPrintBackgroundResults(scsi_device * device) +scsiPrintBackgroundResults(scsi_device * device, bool only_pow_time) { + bool noheader = true; + bool firstresult = true; int num, j, m, err, truncated; - int noheader = 1; - int firstresult = 1; int retval = 0; + unsigned int u; + uint64_t lba; uint8_t * ucp; + char b[48]; + char res_s[32]; static const char * hname = "Background scan results"; + static const char * jname = "scsi_background_scan"; if ((err = scsiLogSense(device, BACKGROUND_RESULTS_LPAGE, 0, gBuf, LOG_RESP_LONG_LEN, 0))) { @@ -1181,9 +1274,12 @@ // compute page length num = sg_get_unaligned_be16(gBuf + 2) + 4; if (num < 20) { - print_on(); - pout("%s %s length is %d, no scan status\n", hname, logSenStr, num); - print_off(); + if (! only_pow_time) { + print_on(); + pout("%s %s length is %d, no scan status\n", hname, logSenStr, + num); + print_off(); + } return FAILSMART; } truncated = (num > LOG_RESP_LONG_LEN) ? num : 0; @@ -1198,67 +1294,105 @@ switch (pc) { case 0: if (noheader) { - noheader = 0; - pout("%s log\n", hname); + noheader = false; + if (! only_pow_time) + jout("%s log\n", hname); } - pout(" Status: "); + if (! only_pow_time) + jout(" Status: "); if ((pl < 16) || (num < 16)) { - pout("\n"); + if (! only_pow_time) + jout("\n"); break; } j = ucp[9]; - if (j < (int)(sizeof(bms_status) / sizeof(bms_status[0]))) - pout("%s\n", bms_status[j]); - else - pout("unknown [0x%x] background scan status value\n", j); + if (! only_pow_time) { + if (j < (int)ARRAY_SIZE(bms_status)) { + jout("%s\n", bms_status[j]); + jglb[jname]["status"]["value"] = j; + jglb[jname]["status"]["string"] = bms_status[j]; + } else { + jout("unknown [0x%x] background scan status value\n", j); + jglb[jname]["status"]["value"] = j; + } + } j = sg_get_unaligned_be32(ucp + 4); - pout(" Accumulated power on time, hours:minutes %d:%02d " - "[%d minutes]\n", (j / 60), (j % 60), j); + jout("%sAccumulated power on time, hours:minutes %d:%02d", + (only_pow_time ? "" : " "), (j / 60), (j % 60)); + if (only_pow_time) + jout("\n"); + else + jout(" [%d minutes]\n", j); jglb["power_on_time"]["hours"] = j / 60; jglb["power_on_time"]["minutes"] = j % 60; - pout(" Number of background scans performed: %d, ", - sg_get_unaligned_be16(ucp + 10)); - pout("scan progress: %.2f%%\n", - (double)sg_get_unaligned_be16(ucp + 12) * 100.0 / 65536.0); - pout(" Number of background medium scans performed: %d\n", - sg_get_unaligned_be16(ucp + 14)); + if (only_pow_time) + break; + u = sg_get_unaligned_be16(ucp + 10); + jout(" Number of background scans performed: %u, ", u); + jglb[jname]["status"]["number_scans_performed"] = u; + u = sg_get_unaligned_be16(ucp + 12); + snprintf(b, sizeof(b), "%.2f%%", (double)u * 100.0 / 65536.0); + jout("scan progress: %s\n", b); + jglb[jname]["status"]["scan_progress"] = b; + u = sg_get_unaligned_be16(ucp + 14); + jout(" Number of background medium scans performed: %d\n", u); + jglb[jname]["status"]["number_medium_scans_performed"] = u; break; default: if (noheader) { - noheader = 0; - pout("\n%s log\n", hname); + noheader = false; + if (! only_pow_time) + jout("\n%s log\n", hname); } + if (only_pow_time) + break; if (firstresult) { firstresult = 0; - pout("\n # when lba(hex) [sk,asc,ascq] " + jout("\n # when lba(hex) [sk,asc,ascq] " "reassign_status\n"); } - pout(" %3d ", pc); + snprintf(res_s, sizeof(res_s), "result_%d", pc); + jout(" %3d ", pc); + jglb[jname][res_s]["parameter_code"] = pc; if ((pl < 24) || (num < 24)) { if (pl < 24) - pout("parameter length >= 24 expected, got %d\n", pl); + jout("parameter length >= 24 expected, got %d\n", pl); break; } - j = sg_get_unaligned_be32(ucp + 4); - pout("%4d:%02d ", (j / 60), (j % 60)); + u = sg_get_unaligned_be32(ucp + 4); + jout("%4u:%02u ", (u / 60), (u % 60)); + jglb[jname][res_s]["accumulated_power_on"]["minutes"] = u; for (m = 0; m < 8; ++m) - pout("%02x", ucp[16 + m]); - pout(" [%x,%x,%x] ", ucp[8] & 0xf, ucp[9], ucp[10]); - j = (ucp[8] >> 4) & 0xf; - if (j < - (int)(sizeof(reassign_status) / sizeof(reassign_status[0]))) - pout("%s\n", reassign_status[j]); - else - pout("Reassign status: reserved [0x%x]\n", j); + jout("%02x", ucp[16 + m]); + lba = sg_get_unaligned_be64(ucp + 16); + jglb[jname][res_s]["lba"] = lba; + u = ucp[8] & 0xf; + jout(" [%x,%x,%x] ", u, ucp[9], ucp[10]); + jglb[jname][res_s]["sense_key"]["value"] = u; + jglb[jname][res_s]["sense_key"]["string"] = + scsi_get_sense_key_str(u, sizeof(b), b); + jglb[jname][res_s]["asc"] = ucp[9]; + jglb[jname][res_s]["ascq"] = ucp[10]; + u = (ucp[8] >> 4) & 0xf; + if (u < ARRAY_SIZE(reassign_status)) { + jout("%s\n", reassign_status[u]); + jglb[jname][res_s]["reassign_status"]["value"] = u; + jglb[jname][res_s]["reassign_status"]["string"] = + reassign_status[u]; + } else { + jout("Reassign status: reserved [0x%x]\n", u); + jglb[jname][res_s]["reassign_status"]["value"] = u; + } break; } num -= pl; ucp += pl; } - if (truncated) - pout(" >>>> log truncated, fetched %d of %d available " + if (truncated && (! only_pow_time)) + jout(" >>>> log truncated, fetched %d of %d available " "bytes\n", LOG_RESP_LONG_LEN, truncated); - pout("\n"); + if (! only_pow_time) + jout("\n"); return retval; } @@ -1272,6 +1406,7 @@ int num, err, truncated; int retval = 0; uint8_t * ucp; + const char * q; static const char * hname = "Solid state media"; if ((err = scsiLogSense(device, SS_MEDIA_LPAGE, 0, gBuf, @@ -1313,8 +1448,409 @@ print_off(); return FAILSMART; } - jout("Percentage used endurance indicator: %d%%\n", ucp[7]); - jglb["scsi_percentage_used_endurance_indicator"] = ucp[7]; + q = "Percentage used endurance indicator"; + jout("%s: %d%%\n", q, ucp[7]); + jglb[std::string("scsi_") + q] = ucp[7]; + default: /* ignore other parameter codes */ + break; + } + num -= pl; + ucp += pl; + } + return retval; +} + +static int +scsiPrintZBDeviceStats(scsi_device * device) +{ + int num, err, truncated; + int retval = 0; + uint32_t u; + uint8_t * ucp; + const char * q; + static const char * hname = "Zoned block device statistics"; + static const char * jname = "scsi_zoned_block_device_statistics"; + + jout("%s:\n", hname); + if ((err = scsiLogSense(device, DEVICE_STATS_LPAGE, ZB_DEV_STATS_L_SPAGE, + gBuf, LOG_RESP_LONG_LEN, 0))) { + print_on(); + pout("%s: Failed [%s]\n", __func__, scsiErrString(err)); + print_off(); + return FAILSMART; + } + if (((gBuf[0] & 0x3f) != DEVICE_STATS_LPAGE) && + (gBuf[1] == ZB_DEV_STATS_L_SPAGE)) { + print_on(); + pout("%s %s, page mismatch\n", hname, logSenStr); + print_off(); + return FAILSMART; + } + // compute page length + num = sg_get_unaligned_be16(gBuf + 2) + 4; + if (num < 12) { + print_on(); + pout("%s %s length is %d, too short\n", hname, logSenStr, num); + print_off(); + return FAILSMART; + } + truncated = (num > LOG_RESP_LONG_LEN) ? num : 0; + if (truncated) + num = LOG_RESP_LONG_LEN; + ucp = gBuf + 4; + num -= 4; + while (num > 3) { + int pc = sg_get_unaligned_be16(ucp + 0); + // pcb = ucp[2]; + int pl = ucp[3] + 4; + + if (pl < 12) + goto skip; /* DC HC650 has non-compliant 4 byte parameters */ + switch (pc) { + case 0: + q = "Maximum open zones"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 1: + q = "Maximum explicitly open zones"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 2: + q = "Maximum implicitly open zones"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 3: + q = "Minimum empty zones"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 4: + q = "Maximum nonseq zones"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 5: + q = "Zones emptied"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 6: + q = "Suboptimal write commands"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 7: + q = "Commands exceeding optinmal limit"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 8: + q = "Failed explicit opens"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 9: + q = "Read rule violations"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 0xa: + q = "Write rule violations"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + case 0xb: + q = "Maximum implicitly open sequential or before required zones"; + u = sg_get_unaligned_be32(ucp + 8); + jout(" %s: %u\n", q, u); + jglb[jname][q] = u; + break; + default: /* ignore other parameter codes */ + break; + } +skip: + num -= pl; + ucp += pl; + } + return retval; +} + +static int +scsiPrintTapeDeviceStats(scsi_device * device) +{ + int num, err, truncated; + int retval = 0; + uint32_t k, n, u; + uint64_t ull; + uint8_t * ucp; + const char * q; + static const char * hname = "Device statistics (SSC, tape)"; + static const char * jname = "scsi_device_statistics"; + + if ((err = scsiLogSense(device, DEVICE_STATS_LPAGE, 0, + gBuf, LOG_RESP_LONG_LEN, 0))) { + print_on(); + pout("%s: Failed [%s]\n", __func__, scsiErrString(err)); + print_off(); + return FAILSMART; + } + if (((gBuf[0] & 0x3f) != DEVICE_STATS_LPAGE) && + (gBuf[1] != 0)) { + print_on(); + pout("%s %s, page mismatch\n", hname, logSenStr); + print_off(); + return FAILSMART; + } + // compute page length + num = sg_get_unaligned_be16(gBuf + 2) + 4; + if (num < 12) { + print_on(); + pout("%s %s length is %d, too short\n", hname, logSenStr, num); + print_off(); + return FAILSMART; + } + truncated = (num > LOG_RESP_LONG_LEN) ? num : 0; + if (truncated) + num = LOG_RESP_LONG_LEN; + ucp = gBuf + 4; + num -= 4; + while (num > 3) { + int pc = sg_get_unaligned_be16(ucp + 0); + // pcb = ucp[2]; + int pl = ucp[3] + 4; + switch (pc) { + case 0: + q = "Lifetime volume loads"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 1: + q = "Lifetime cleaning operations"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 2: + q = "Lifetime power on hours"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 3: + q = "Lifetime medium motion hours"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 4: + q = "Lifetime meters of tape processed"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 5: + q = "Lifetime medium motion hours at last incompatible volume " + "load"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 6: + q = "Lifetime power on hours at last temperature condition " + "occurrence"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 7: + q = "Lifetime power on hours at last power consumption condition " + "occurrence"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 8: + q = "Medium motion hours since last successful cleaning " + "operation"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 9: + q = "Medium motion hours since second to last successful " + "cleaning operation"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0xa: + q = "Medium motion hours since third to last successful " + "cleaning operation"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0xb: + q = "Lifetime power on hours at last operator initiated forced " + "reset and/or emergency eject occurrence"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0xc: + q = "Lifetime power cycles"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0xd: + q = "Volume loads since last parameter reset"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0xe: + q = "Hard write errors"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0xf: + q = "Hard read errors"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x10: + q = "Duty cycle sample time"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x11: + q = "Read duty cycle"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x12: + q = "Write duty cycle"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x13: + q = "Activity duty cycle"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x14: + q = "Volume not present duty cycle"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x15: + q = "Ready duty cycle"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x16: + q = "Megabytes transferred from application client in duty cycle" + "sample time"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x17: + q = "Megabytes transferred to application client in duty cycle" + "sample time"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x40: + { + std::string s((const char *)(ucp + 4), ucp[3]); + q = "Drive manufacturer's serial number"; + jout(" %s: %s\n", q, s.c_str()); + jglb[jname][q] = s; + } + break; + case 0x41: + { + std::string s((const char *)(ucp + 4), ucp[3]); + q = "Drive serial number"; + jout(" %s: %s\n", q, s.c_str()); + jglb[jname][q] = s; + } + break; + case 0x42: + { + std::string s((const char *)(ucp + 4), ucp[3]); + q = "Manufacturing date year,month,day"; + jout(" %s: %s\n", q, s.c_str()); + jglb[jname][q] = s; + } + break; + case 0x43: + { + std::string s((const char *)(ucp + 4), ucp[3]); + q = "Manufacturing date year,week"; + jout(" %s: %s\n", q, s.c_str()); + jglb[jname][q] = s; + } + break; + case 0x44: + { + std::string s((const char *)(ucp + 4), ucp[3]); + q = "Manufacturing date year,week"; + jout(" %s: %s\n", q, s.c_str()); + jglb[jname][q] = s; + } + break; + case 0x80: + q = "Medium removal prevented"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x81: + q = "Maximum recommended mechanism temperature exceeded"; + ull = variableLengthIntegerParam(ucp); + jout(" %s: %" PRIu64 "\n", q, ull); + jglb[jname][q] = ull; + break; + case 0x1000: + q = "Medium motion hours for each medium type"; + n = ucp[3] / 8; + jout(" %s, number of element: %u\n", q, n); + for (k = 0; k < n; ++k, ucp += 8) { + u = sg_get_unaligned_be32(ucp + 8); + jout(" [%d] density code: %u, density code: %u, hours: " + "%u\n", k + 1, ucp[6], ucp[7], u); + jglb[jname][q][k]["density code"] = ucp[6]; + jglb[jname][q][k]["medium type"] = ucp[7]; + jglb[jname][q][k]["medium motion hours"] = u; + } + break; default: /* ignore other parameter codes */ break; } @@ -1327,16 +1863,12 @@ static int scsiPrintFormatStatus(scsi_device * device) { - bool is_count; - int k, num, err, truncated; + int num, err, truncated; int retval = 0; uint64_t ull; uint8_t * ucp; - uint8_t * xp; - const char * jout_str; - const char * jglb_str; static const char * hname = "Format Status"; - static const char * jname = "format_status"; + static const char * jname = "scsi_format_status"; if ((err = scsiLogSense(device, FORMAT_STATUS_LPAGE, 0, gBuf, LOG_RESP_LONG_LEN, 0))) { @@ -1369,9 +1901,9 @@ // pcb = ucp[2]; int pl = ucp[3] + 4; - is_count = true; - jout_str = ""; - jglb_str = "x"; + bool is_count = true; + const char * jout_str = ""; + const char * jglb_str = "x"; switch (pc) { case 0: if (scsi_debugmode > 1) { @@ -1413,16 +1945,10 @@ break; } if (is_count) { - k = pl - 4; - xp = ucp + 4; - if (all_ffs(xp, k)) { + if (all_ffs(ucp + 4, ucp[3])) { pout("%s \n", jout_str); } else { - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = sg_get_unaligned_be(k, xp); + ull = variableLengthIntegerParam(ucp); jout("%s = %" PRIu64 "\n", jout_str, ull); jglb[jname][jglb_str] = ull; } @@ -1435,130 +1961,202 @@ } static void -show_sas_phy_event_info(int peis, unsigned int val, unsigned thresh_val) +show_sas_phy_event_info(const json::ref & jref, int peis, unsigned int val, + unsigned thresh_val) { unsigned int u; + const char * q; + static const char * pvd_th = "Peak value detector threshold"; + static const char * pvd_th_j = "pvd_threshold"; switch (peis) { case 0: - pout(" No event\n"); + jout(" No event\n"); break; - case 0x1: - pout(" Invalid word count: %u\n", val); + case 0x1: /* 0x1 to 0x4 will be duplicates so append "_2" to name */ + q = "Invalid dword count"; + jout(" %s: %u\n", q, val); + jref[std::string(q) + "_2"] = val; break; case 0x2: - pout(" Running disparity error count: %u\n", val); + q = "Running disparity error count"; + jout(" %s: %u\n", q, val); + jref[std::string(q) + "_2"] = val; break; case 0x3: - pout(" Loss of dword synchronization count: %u\n", val); + q = "Loss of dword synchronization count"; + jout(" %s: %u\n", q, val); + jref[std::string(q) + "_2"] = val; break; case 0x4: - pout(" Phy reset problem count: %u\n", val); + q = "Phy reset problem count"; + jout(" %s: %u\n", q, val); + jref[std::string(q) + "_2"] = val; break; case 0x5: - pout(" Elasticity buffer overflow count: %u\n", val); + q = "Elasticity buffer overflow count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x6: - pout(" Received ERROR count: %u\n", val); + q = "Received ERROR count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x20: - pout(" Received address frame error count: %u\n", val); + q = "Received address frame error count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x21: - pout(" Transmitted abandon-class OPEN_REJECT count: %u\n", val); + q = "Transmitted abandon-class OPEN_REJECT count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x22: - pout(" Received abandon-class OPEN_REJECT count: %u\n", val); + q = "Received abandon-class OPEN_REJECT count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x23: - pout(" Transmitted retry-class OPEN_REJECT count: %u\n", val); + q = "Transmitted retry-class OPEN_REJECT count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x24: - pout(" Received retry-class OPEN_REJECT count: %u\n", val); + q = "Received retry-class OPEN_REJECT count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x25: - pout(" Received AIP (WAITING ON PARTIAL) count: %u\n", val); + q = "Received AIP (WAITING ON PARTIAL) count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x26: - pout(" Received AIP (WAITING ON CONNECTION) count: %u\n", val); + q = "Received AIP (WAITING ON CONNECTION) count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x27: - pout(" Transmitted BREAK count: %u\n", val); + q = "Transmitted BREAK count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x28: - pout(" Received BREAK count: %u\n", val); + q = "Received BREAK count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x29: - pout(" Break timeout count: %u\n", val); + q = "Break timeout count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x2a: - pout(" Connection count: %u\n", val); + q = "Connection count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x2b: - pout(" Peak transmitted pathway blocked count: %u\n", - val & 0xff); - pout(" Peak value detector threshold: %u\n", - thresh_val & 0xff); + q = "Peak transmitted pathway blocked"; + jout(" %s count: %u\n", q, val & 0xff); + jout(" %s: %u\n", pvd_th, thresh_val & 0xff); + jref[q]["count"] = val & 0xff; + jref[q][pvd_th_j] = thresh_val & 0xff; break; case 0x2c: + q = "Peak transmitted arbitration wait time"; u = val & 0xffff; - if (u < 0x8000) - pout(" Peak transmitted arbitration wait time (us): " - "%u\n", u); - else - pout(" Peak transmitted arbitration wait time (ms): " - "%u\n", 33 + (u - 0x8000)); + if (u < 0x8000) { + jout(" %s (us): %u\n", q, u); + jref[std::string(q) + "_us"]["event"] = u; + } else { + jout(" %s (ms): %u\n", q, 33 + (u - 0x8000)); + jref[std::string(q) + "_ms"]["event"] = 33 + (u - 0x8000); + } u = thresh_val & 0xffff; - if (u < 0x8000) - pout(" Peak value detector threshold (us): %u\n", - u); - else - pout(" Peak value detector threshold (ms): %u\n", - 33 + (u - 0x8000)); + if (u < 0x8000) { + jout(" %s (us): %u\n", pvd_th, u); + jref[std::string(q) + "_us"][pvd_th_j] = u; + } else { + jout(" %s (ms): %u\n", pvd_th, 33 + (u - 0x8000)); + jref[std::string(q) + "_ms"][pvd_th_j] = 33 + (u - 0x8000); + } break; case 0x2d: - pout(" Peak arbitration time (us): %u\n", val); - pout(" Peak value detector threshold: %u\n", thresh_val); + q = "Peak arbitration time"; + jout(" %s (us): %u\n", q, val); + jref[std::string(q) + "_us"]["event"] = val; + jout(" %s: %u\n", pvd_th, thresh_val); + jref[std::string(q) + "_us"][pvd_th_j] = thresh_val; break; case 0x2e: - pout(" Peak connection time (us): %u\n", val); - pout(" Peak value detector threshold: %u\n", thresh_val); + q = "Peak connection time"; + jout(" %s (us): %u\n", q, val); + jref[std::string(q) + "_us"]["event"] = val; + jout(" %s: %u\n", pvd_th, thresh_val); + jref[std::string(q) + "_us"][pvd_th_j] = thresh_val; break; case 0x40: - pout(" Transmitted SSP frame count: %u\n", val); + q = "Transmitted SSP frame count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x41: - pout(" Received SSP frame count: %u\n", val); + q = "Received SSP frame count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x42: - pout(" Transmitted SSP frame error count: %u\n", val); + q = "Transmitted SSP frame error count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x43: - pout(" Received SSP frame error count: %u\n", val); + q = "Received SSP frame error count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x44: - pout(" Transmitted CREDIT_BLOCKED count: %u\n", val); + q = "Transmitted CREDIT_BLOCKED count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x45: - pout(" Received CREDIT_BLOCKED count: %u\n", val); + q = "Received CREDIT_BLOCKED count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x50: - pout(" Transmitted SATA frame count: %u\n", val); + q = "Transmitted SATA frame count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x51: - pout(" Received SATA frame count: %u\n", val); + q = "Received SATA frame count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x52: - pout(" SATA flow control buffer overflow count: %u\n", val); + q = "SATA flow control buffer overflow count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x60: - pout(" Transmitted SMP frame count: %u\n", val); + q = "Transmitted SMP frame count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x61: - pout(" Received SMP frame count: %u\n", val); + q = "Received SMP frame count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; case 0x63: - pout(" Received SMP frame error count: %u\n", val); + q = "Received SMP frame error count"; + jout(" %s: %u\n", q, val); + jref[q] = val; break; default: break; @@ -1566,23 +2164,34 @@ } static void -show_sas_port_param(unsigned char * ucp, int param_len) +show_sas_port_param(int port_num, unsigned char * ucp, int param_len) { - int j, m, nphys, t, sz, spld_len; + int k, j, m, nphys, t, sz, spld_len; + char pn[32]; unsigned char * vcp; char s[64]; + const char * q; + snprintf(pn, sizeof(pn), "scsi_sas_port_%d", port_num); sz = sizeof(s); // pcb = ucp[2]; t = sg_get_unaligned_be16(ucp + 0); - pout("relative target port id = %d\n", t); - pout(" generation code = %d\n", ucp[6]); + jout("relative target port id = %d\n", t); + jglb[pn]["relative_target_port_id"] = t; + jout(" generation code = %d\n", ucp[6]); + jglb[pn]["generation_code"] = ucp[6]; nphys = ucp[7]; - pout(" number of phys = %d\n", nphys); + jout(" number of phys = %d\n", nphys); + jglb[pn]["number_of_phys"] = nphys; - for (j = 0, vcp = ucp + 8; j < (param_len - 8); - vcp += spld_len, j += spld_len) { - pout(" phy identifier = %d\n", vcp[1]); + for (j = 0, k = 0, vcp = ucp + 8; j < (param_len - 8); + vcp += spld_len, j += spld_len, ++k) { + char yn[32]; + + snprintf(yn, sizeof(yn), "phy_%d", k); + json::ref jref = jglb[pn][yn]; + jout(" phy identifier = %d\n", vcp[1]); + jref["identifier"] = vcp[1]; spld_len = vcp[3]; if (spld_len < 44) spld_len = 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */ @@ -1596,7 +2205,9 @@ case 3: snprintf(s, sz, "expander device (fanout)"); break; default: snprintf(s, sz, "reserved [%d]", t); break; } - pout(" attached device type: %s\n", s); + q = "attached device type"; + jout(" %s: %s\n", q, s); + jref[q] = s; t = 0xf & vcp[4]; switch (t) { case 0: snprintf(s, sz, "unknown"); break; @@ -1613,7 +2224,9 @@ break; default: snprintf(s, sz, "reserved [0x%x]", t); break; } - pout(" attached reason: %s\n", s); + q = "attached reason"; + jout(" %s: %s\n", q, s); + jref[q] = s; t = (vcp[5] & 0xf0) >> 4; switch (t) { case 0: snprintf(s, sz, "unknown"); break; @@ -1630,7 +2243,9 @@ break; default: snprintf(s, sz, "reserved [0x%x]", t); break; } - pout(" reason: %s\n", s); + q = "reason"; + jout(" %s: %s\n", q, s); + jref[q] = s; t = (0xf & vcp[5]); switch (t) { case 0: snprintf(s, sz, "phy enabled; unknown"); @@ -1652,43 +2267,77 @@ case 0xb: snprintf(s, sz, "phy enabled; 12 Gbps"); break; default: snprintf(s, sz, "reserved [%d]", t); break; } - pout(" negotiated logical link rate: %s\n", s); - pout(" attached initiator port: ssp=%d stp=%d smp=%d\n", + q = "negotiated logical link rate"; + jout(" %s: %s\n", q, s); + jref[q] = s; + q = "attached initiator port"; + jout(" %s: ssp=%d stp=%d smp=%d\n", q, !! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2)); - pout(" attached target port: ssp=%d stp=%d smp=%d\n", + snprintf(s, sz, "%03d", ((vcp[6] & 8) ? 100 : 0) + + ((vcp[6] & 4) ? 10 : 0) + ((vcp[6] & 2) ? 1 : 0)); + jref[q]["ssp_stp_smp"] = s; + q = "attached target port"; + jout(" %s: ssp=%d stp=%d smp=%d\n", q, !! (vcp[7] & 8), !! (vcp[7] & 4), !! (vcp[7] & 2)); + snprintf(s, sz, "%03d", ((vcp[7] & 8) ? 100 : 0) + + ((vcp[7] & 4) ? 10 : 0) + ((vcp[7] & 2) ? 1 : 0)); + jref[q]["ssp_stp_smp"] = s; if (!dont_print_serial_number) { uint64_t ull = sg_get_unaligned_be64(vcp + 8); + char b[32]; - pout(" SAS address = 0x%" PRIx64 "\n", ull); + snprintf(b, sizeof(b), "0x%" PRIx64, ull); + q = "SAS address"; + jout(" %s = %s\n", q, b); + jref[q] = b; ull = sg_get_unaligned_be64(vcp + 16); - pout(" attached SAS address = 0x%" PRIx64 "\n", ull); - } - pout(" attached phy identifier = %d\n", vcp[24]); + snprintf(b, sizeof(b), "0x%" PRIx64, ull); + q = "attached SAS address"; + jout(" %s = %s\n", q, b); + jref[q] = b; + } + q = "attached phy identifier"; + jout(" %s = %d\n", q, vcp[24]); + jref[q] = vcp[24]; unsigned int ui = sg_get_unaligned_be32(vcp + 32); - pout(" Invalid DWORD count = %u\n", ui); + q = "Invalid DWORD count"; + jout(" %s = %u\n", q, ui); + jref[q] = ui; ui = sg_get_unaligned_be32(vcp + 36); - pout(" Running disparity error count = %u\n", ui); + q = "Running disparity error count"; + jout(" %s = %u\n", q, ui); + jref[q] = ui; ui = sg_get_unaligned_be32(vcp + 40); - pout(" Loss of DWORD synchronization = %u\n", ui); + q = "Loss of DWORD synchronization count"; + jout(" %s = %u\n", q, ui); + jref[q] = ui; ui = sg_get_unaligned_be32(vcp + 44); - pout(" Phy reset problem = %u\n", ui); + q = "Phy reset problem count"; + jout(" %s = %u\n", q, ui); + jref[q] = ui; if (spld_len > 51) { + bool header_given = false; + bool allow_dupl = (scsi_debugmode > 0); int num_ped; unsigned char * xcp; num_ped = vcp[51]; - if (num_ped > 0) - pout(" Phy event descriptors:\n"); xcp = vcp + 52; for (m = 0; m < (num_ped * 12); m += 12, xcp += 12) { int peis; unsigned int pvdt; + peis = xcp[3]; ui = sg_get_unaligned_be32(xcp + 4); pvdt = sg_get_unaligned_be32(xcp + 8); - show_sas_phy_event_info(peis, ui, pvdt); + if (allow_dupl || (peis > 0x4)) { + if (! header_given) { + header_given = true; + jout(" Phy event descriptors:\n"); + } + show_sas_phy_event_info(jref, peis, ui, pvdt); + } } } } @@ -1696,19 +2345,19 @@ // Returns 1 if okay, 0 if non SAS descriptors static int -show_protocol_specific_page(unsigned char * resp, int len) +show_protocol_specific_port_page(unsigned char * resp, int len) { - int k, num; + int k, j, num; unsigned char * ucp; num = len - 4; - for (k = 0, ucp = resp + 4; k < num; ) { + for (k = 0, j = 0, ucp = resp + 4; k < num; ++j) { int param_len = ucp[3] + 4; if (SCSI_TPROTO_SAS != (0xf & ucp[4])) return 0; /* only decode SAS log page */ if (0 == k) - pout("Protocol Specific port log page for SAS SSP\n"); - show_sas_port_param(ucp, param_len); + jout("\nProtocol Specific port log page for SAS SSP\n"); + show_sas_port_param(j, ucp, param_len); k += param_len; ucp += param_len; } @@ -1741,7 +2390,7 @@ } // compute page length num = sg_get_unaligned_be16(gBuf + 2); - if (1 != show_protocol_specific_page(gBuf, num + 4)) { + if (1 != show_protocol_specific_port_page(gBuf, num + 4)) { print_on(); pout("Only support %s log page on SAS devices\n\n", hname); print_off(); @@ -1798,13 +2447,13 @@ /* Symbolic indexes to this array SCSI_TPROTO_* in scscmds.h */ static const char * transport_proto_arr[] = { - "Fibre channel (FCP-2)", - "Parallel SCSI (SPI-4)", + "Fibre channel (FCP-4)", + "Parallel SCSI (SPI-4)", /* obsolete */ "SSA", - "IEEE 1394 (SBP-2)", + "IEEE 1394 (SBP-3)", "RDMA (SRP)", "iSCSI", - "SAS (SPL-3)", + "SAS (SPL-4)", "ADT", "ATA (ACS-2)", "UAS", @@ -1818,18 +2467,22 @@ /* Returns 0 on success, 1 on general error and 2 for early, clean exit */ static int -scsiGetDriveInfo(scsi_device * device, uint8_t * peripheral_type, bool all) +scsiGetDriveInfo(scsi_device * device, uint8_t * peripheral_type, + bool & have_zbc, bool all) { struct scsi_iec_mode_page iec; int err, iec_err, len, req_len, avail_len; + bool ok; bool is_tape = false; int peri_dt = 0; int transport = -1; int form_factor = 0; int haw_zbc = 0; int protect = 0; + const char * q; memset(gBuf, 0, 96); + have_zbc = false; req_len = 36; if ((err = scsiStdInquiry(device, gBuf, req_len))) { print_on(); @@ -1850,6 +2503,8 @@ len = (avail_len < req_len) ? avail_len : req_len; peri_dt = gBuf[0] & 0x1f; *peripheral_type = peri_dt; + if (SCSI_PT_HOST_MANAGED == peri_dt) + have_zbc = true; if ((SCSI_PT_SEQUENTIAL_ACCESS == peri_dt) || (SCSI_PT_MEDIUM_CHANGER == peri_dt)) is_tape = true; @@ -1872,15 +2527,15 @@ pout("=== START OF INFORMATION SECTION ===\n"); jout("Vendor: %.8s\n", scsi_vendor); - jglb["vendor"] = scsi_vendor; + jglb["scsi_vendor"] = scsi_vendor; jout("Product: %.16s\n", product); - jglb["product"] = product; - jglb["model_name"] = strprintf("%s%s%s", + jglb["scsi_product"] = product; + jglb["scsi_model_name"] = strprintf("%s%s%s", scsi_vendor, (*scsi_vendor && *product ? " " : ""), product); if (gBuf[32] >= ' ') { jout("Revision: %.4s\n", revision); // jglb["firmware_version"] = revision; - jglb["revision"] = revision; /* could be a hardware rev */ + jglb["scsi_revision"] = revision; } if ((scsi_version > 0x3) && (scsi_version < 0x8)) { char sv_arr[8]; @@ -1909,6 +2564,7 @@ unsigned char lb_prov_resp[8]; uint64_t capacity = scsiGetSize(device, false /*avoid_rcap16 */, &srr); + static const char * lb_prov_j = "scsi_lb_provisioning"; if (capacity) { char cap_str[64], si_str[64]; @@ -1945,15 +2601,20 @@ srr.prot_type); break; } + jglb["scsi_protection_type"] = srr.prot_type; unsigned p_i_per_lb = (1 << srr.p_i_exp); const unsigned pi_sz = 8; /* ref-tag(4 bytes), app-tag(2), tag-mask(2) */ - if (p_i_per_lb > 1) - pout("%d protection information intervals per " + if (p_i_per_lb > 1) { + jout("%d protection information intervals per " "logical block\n", p_i_per_lb); - pout("%d bytes of protection information per logical " + jglb["scsi_protection_intervals_per_lb"] = srr.prot_type; + } + jout("%d bytes of protection information per logical " "block\n", pi_sz * p_i_per_lb); + jglb["scsi_protection_interval_bytes_per_lb"] = + pi_sz * p_i_per_lb; } /* Pick up some LB provisioning info since its available */ lbpme = (int)srr.lbpme; @@ -1977,30 +2638,41 @@ switch (prov_type) { case 0: if (lbpme <= 0) { - pout("LU is fully provisioned"); + jout("LU is fully provisioned"); + jglb[lb_prov_j]["name"] = "fully provisioned"; if (lbprz) - pout(" [LBPRZ=%d]\n", lbprz); + jout(" [LBPRZ=%d]\n", lbprz); else - pout("\n"); - } else - pout("LB provisioning type: not reported [LBPME=1, " - "LBPRZ=%d]\n", lbprz); + jout("\n"); + } else { + jout("LB provisioning type: not reported [LBPME=1, " + "LBPRZ=%d]\n", lbprz); + jglb[lb_prov_j]["name"] = "not reported"; + } break; case 1: - pout("LU is resource provisioned, LBPRZ=%d\n", lbprz); + jout("LU is resource provisioned, LBPRZ=%d\n", lbprz); + jglb[lb_prov_j]["name"] = "resource provisioned"; break; case 2: - pout("LU is thin provisioned, LBPRZ=%d\n", lbprz); + jout("LU is thin provisioned, LBPRZ=%d\n", lbprz); + jglb[lb_prov_j]["name"] = "thin provisioned"; break; default: - pout("LU provisioning type reserved [%d], LBPRZ=%d\n", + jout("LU provisioning type reserved [%d], LBPRZ=%d\n", prov_type, lbprz); + jglb[lb_prov_j]["name"] = "reserved"; break; } + jglb[lb_prov_j]["value"] = prov_type; + jglb[lb_prov_j]["management_enabled"]["name"] = "LBPME"; + jglb[lb_prov_j]["management_enabled"]["value"] = lbpme; + jglb[lb_prov_j]["read_zeros"]["name"] = "LBPRZ"; + jglb[lb_prov_j]["read_zeros"]["value"] = lbprz; } else if (1 == lbpme) { if (scsi_debugmode > 0) - pout("rcap_16 sets LBPME but no LB provisioning VPD page\n"); - pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz); + jout("rcap_16 sets LBPME but no LB provisioning VPD page\n"); + jout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz); } int rpm = scsiGetRPM(device, modese_len, &form_factor, &haw_zbc); @@ -2041,8 +2713,26 @@ jglb["form_factor"]["name"] = strprintf("%s inches", cp); } } - if (haw_zbc > 0) - pout("Host aware zoned block capable\n"); + if (haw_zbc == 1) { + have_zbc = true; + q = "Host aware zoned block capable"; + jout("%s\n", q); + jglb[std::string("scsi_") + q] = true; + } else if (haw_zbc == 2) { + have_zbc = true; + q = "Device managed zoned block capable"; + jout("%s\n", q); + jglb[std::string("scsi_") + q] = true; + } else { + supported_vpd_pages * s_vpd_pp = supported_vpd_pages_p; + + if (s_vpd_pp && + s_vpd_pp->is_supported(SCSI_VPD_ZONED_BLOCK_DEV_CHAR)) { + // TODO: need to read that VPD page and look at the + // 'Zoned block device extension' field + + } + } } /* Do this here to try and detect badly conforming devices (some USB @@ -2065,8 +2755,10 @@ len = gBuf[3]; scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport); - if (strlen(s) > 0) - pout("Logical Unit id: %s\n", s); + if (strlen(s) > 0) { + jout("Logical Unit id: %s\n", s); + jglb["logical_unit_id"] = s; + } } else if (scsi_debugmode > 0) { print_on(); if (SIMPLE_ERR_BAD_RESP == err) @@ -2095,9 +2787,9 @@ } // print SCSI peripheral device type + jglb["device_type"]["scsi_terminology"] = "Peripheral Device Type [PDT]"; jglb["device_type"]["scsi_value"] = peri_dt; - if (peri_dt < (int)(sizeof(peripheral_dt_arr) / - sizeof(peripheral_dt_arr[0]))) { + if (peri_dt < (int)(ARRAY_SIZE(peripheral_dt_arr))) { jout("Device type: %s\n", peripheral_dt_arr[peri_dt]); jglb["device_type"]["name"] = peripheral_dt_arr[peri_dt]; } @@ -2107,15 +2799,13 @@ // See if transport protocol is known if (transport < 0) transport = scsiFetchTransportProtocol(device, modese_len); - if ((transport >= 0) && (transport <= 0xf)) - pout("Transport protocol: %s\n", transport_proto_arr[transport]); + if ((transport >= 0) && (transport <= 0xf)) { + jout("Transport protocol: %s\n", transport_proto_arr[transport]); + jglb["scsi_transport_protocol"]["name"] = transport_proto_arr[transport]; + jglb["scsi_transport_protocol"]["value"] = transport; + } - // print current time and date and timezone - time_t now = time(0); - char timedatetz[DATEANDEPOCHLEN]; dateandtimezoneepoch(timedatetz, now); - jout("Local Time is: %s\n", timedatetz); - jglb["local_time"]["time_t"] = now; - jglb["local_time"]["asctime"] = timedatetz; + jout_startup_datetime("Local Time is: "); // See if unit accepts SCSI commands from us if ((err = scsiTestUnitReady(device))) { @@ -2152,8 +2842,9 @@ if (iec_err) { if (!is_tape) { print_on(); - pout("SMART support is: Unavailable - device lacks SMART " + jout("SMART support is: Unavailable - device lacks SMART " "capability.\n"); + jglb["smart_support"]["available"] = false; if (scsi_debugmode > 0) pout(" [%s]\n", scsiErrString(iec_err)); print_off(); @@ -2162,13 +2853,17 @@ return 0; } - if (!is_tape) - pout("SMART support is: Available - device has SMART capability.\n" - "SMART support is: %s\n", - (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled"); - pout("%s\n", (scsi_IsWarningEnabled(&iec)) ? - "Temperature Warning: Enabled" : - "Temperature Warning: Disabled or Not Supported"); + if (!is_tape) { + ok = scsi_IsExceptionControlEnabled(&iec); + jout("SMART support is: Available - device has SMART capability.\n" + "SMART support is: %s\n", ok ? "Enabled" : "Disabled"); + jglb["smart_support"]["available"] = true; + jglb["smart_support"]["enabled"] = ok; + } + ok = scsi_IsWarningEnabled(&iec); + jout("Temperature Warning: %s\n", + ok ? "Enabled" : "Disabled or Not Supported"); + jglb["temperature_warning"]["enabled"] = ok; return 0; } @@ -2270,27 +2965,256 @@ pout("\n"); } +static void +scsiPrintEnviroReporting(scsi_device * device) +{ + int len, num, err; + int temp_num = 0; + int humid_num = 0; + unsigned char * ucp; + const char * q; + static const char * hname = "Environmental Reports"; + static const char * jname = "scsi_environmental_reports"; + static const char * rh_n = "relative humidity"; + static const char * temp_n = "temperature"; + static const char * sop_n = "since power on"; + static const char * unkn_n = "unknown"; + + if ((err = scsiLogSense(device, TEMPERATURE_LPAGE, ENVIRO_REP_L_SPAGE, + gBuf, LOG_RESP_LEN, -1 /* single fetch */))) { + print_on(); + pout("%s Failed [%s]\n", __func__, scsiErrString(err)); + print_off(); + return; + } + if (((gBuf[0] & 0x3f) != TEMPERATURE_LPAGE) || + (gBuf[1] != ENVIRO_REP_L_SPAGE)) { + print_on(); + pout("%s %s Failed, page mismatch\n", hname, logSenStr); + print_off(); + return; + } + if (! (gBuf[0] & 0x40)) { + if (scsi_debugmode > 0) { + print_on(); + pout("Another flaky device that doesn't set the SPF bit\n"); + print_off(); + } + } + len = sg_get_unaligned_be16(gBuf + 2); + num = len - 4; + ucp = &gBuf[0] + 4; + + while (num > 3) { + int pc = sg_get_unaligned_be16(ucp + 0); + int pl = ucp[3] + 4; + char pc_s[32]; + + if ((pc < 0x100) && (pl == 12)) { + snprintf(pc_s, sizeof(pc_s), "temperature_%d", ++temp_num); + /* temperature is two's complement 8 bit in centigrade */ + int temp = (int)(int8_t)ucp[5]; + + jglb[jname][pc_s]["parameter_code"] = pc; + q = "Current"; + if (ucp[5] == 0x80) { + jout("%s %s = %s\n", q, temp_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("%s %s = %d\n", q, temp_n, temp); + jglb[jname][pc_s][q] = temp; + } + temp = (int)(int8_t)ucp[6]; + q = "Lifetime maximum"; + if (ucp[6] == 0x80) { + jout("%s %s = %s\n", q, temp_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("%s %s = %d\n", q, temp_n, temp); + jglb[jname][pc_s][q] = temp; + } + temp = (int)(int8_t)ucp[7]; + q = "Lifetime minimum"; + if (ucp[7] == 0x80) { + jout("%s %s = %s\n", q, temp_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("%s %s = %d\n", q, temp_n, temp); + jglb[jname][pc_s][q] = temp; + } + temp = (int)(int8_t)ucp[8]; + q = "Maximum since power on"; + if (ucp[8] == 0x80) { + jout("Maximum %s %s = %s\n", temp_n, sop_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("Maximum %s %s = %d\n", temp_n, sop_n, temp); + jglb[jname][pc_s][q] = temp; + } + temp = (int)(int8_t)ucp[9]; + q = "Minimum since power on"; + if (ucp[9] == 0x80) { + jout("Minimum %s %s = %s\n", temp_n, sop_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("Minimum %s %s = %d\n", temp_n, sop_n, temp); + jglb[jname][pc_s][q] = temp; + } + if ((ucp[4] & 0x3) == 1) { /* OTV field set to 1 */ + temp = (int)(int8_t)ucp[10]; + q = "Maximum other"; + if (ucp[10] == 0x80) { + jout("%s %s = %s\n", q, temp_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("%s %s = %d\n", q, temp_n, temp); + jglb[jname][pc_s][q] = temp; + } + temp = (int)(int8_t)ucp[11]; + q = "Minimum other"; + if (ucp[11] == 0x80) { + jout("%s %s = %s\n", q, temp_n, unkn_n); + jglb[jname][pc_s][q] = unkn_n; + } else { + jout("%s %s = %d\n", q, temp_n, temp); + jglb[jname][pc_s][q] = temp; + } + } + } else if ((pc < 0x200) && (pl == 12)) { + snprintf(pc_s, sizeof(pc_s), "relative_humidity_%d", ++humid_num); + jglb[jname][pc_s]["parameter_code"] = pc; + jout("Relative humidity = %u\n", ucp[5]); + jglb[jname][pc_s]["current"] = ucp[5]; + q = "Lifetime maximum"; + jout("%s %s = %d\n", q, rh_n, ucp[6]); + jglb[jname][pc_s][q] = ucp[6]; + q = "Lifetime minimum"; + jout("%s %s = %d\n", q, rh_n, ucp[7]); + jglb[jname][pc_s][q] = ucp[7]; + jout("Maximum %s %s = %d\n", rh_n, sop_n, ucp[8]); + jglb[jname][pc_s]["maximum_since_power_on"] = ucp[8]; + jout("Minimum %s %s = %d\n", rh_n, sop_n, ucp[9]); + jglb[jname][pc_s]["minimum_since_power_on"] = ucp[9]; + if ((ucp[4] & 0x3) == 1) { /* ORHV field set to 1 */ + q = "Maximum other"; + jout("%s %s = %d\n", q, rh_n, ucp[10]); + jglb[jname][pc_s][q] = ucp[10]; + q = "Minimum other"; + jout("%s %s = %d\n", q, rh_n, ucp[11]); + jglb[jname][pc_s][q] = ucp[11]; + } + } else { + if (scsi_debugmode > 0) { + print_on(); + if ((pc < 0x200) && (pl != 12)) + pout("%s sub-lpage unexpected parameter length [%d], skip\n", + hname, pl); + else + pout("%s sub-lpage has unexpected parameter [0x%x], skip\n", + hname, pc); + print_off(); + } + return; + } + num -= pl; + ucp += pl; + } +} + /* Main entry point used by smartctl command. Return 0 for success */ int scsiPrintMain(scsi_device * device, const scsi_print_options & options) { - int checkedSupportedLogPages = 0; + bool checkedSupportedLogPages = false; + bool envRepDone = false; uint8_t peripheral_type = 0; int returnval = 0; int res, durationSec; struct scsi_sense_disect sense_info; bool is_disk; + bool is_zbc; bool is_tape; - bool any_output = options.drive_info; - if (supported_vpd_pages_p) { - delete supported_vpd_pages_p; - supported_vpd_pages_p = NULL; +// Enable -n option for SCSI Drives + const char * powername = NULL; + bool powerchg = false; + + if (options.powermode) { + scsiRequestSense(device, &sense_info) ; + if (sense_info.asc == 0x5E) { + unsigned char powerlimit = 0xff; + int powermode = sense_info.ascq ; + + // 5Eh/00h DZTPRO A K LOW POWER CONDITION ON + // 5Eh/01h DZTPRO A K IDLE CONDITION ACTIVATED BY TIMER + // 5Eh/02h DZTPRO A K STANDBY CONDITION ACTIVATED BY TIMER + // 5Eh/03h DZTPRO A K IDLE CONDITION ACTIVATED BY COMMAND + // 5Eh/04h DZTPRO A K STANDBY CONDITION ACTIVATED BY COMMAND + // 5Eh/05h DZTPRO A K IDLE_B CONDITION ACTIVATED BY TIMER + // 5Eh/06h DZTPRO A K IDLE_B CONDITION ACTIVATED BY COMMAND + // 5Eh/07h DZTPRO A K IDLE_C CONDITION ACTIVATED BY TIMER + // 5Eh/08h DZTPRO A K IDLE_C CONDITION ACTIVATED BY COMMAND + // 5Eh/09h DZTPRO A K STANDBY_Y CONDITION ACTIVATED BY TIMER + // 5Eh/0Ah DZTPRO A K STANDBY_Y CONDITION ACTIVATED BY COMMAND + // 5Eh/41h B POWER STATE CHANGE TO ACTIVE + // 5Eh/42h B POWER STATE CHANGE TO IDLE + // 5Eh/43h B POWER STATE CHANGE TO STANDBY + // 5Eh/45h B POWER STATE CHANGE TO SLEEP + // 5Eh/47h BK POWER STATE CHANGE TO DEVICE CONTROL + + switch (powermode) { + case -1: + if (device->is_syscall_unsup()) { + pout("CHECK POWER MODE not implemented, ignoring -n option\n"); break; + } + powername = "SLEEP"; powerlimit = 2; + break; + + case 0x00: // LOW POWER CONDITION ON + powername = "LOW POWER"; powerlimit = 2; break; + case 0x01: // IDLE CONDITION ACTIVATED BY TIMER + powername = "IDLE BY TIMER"; powerlimit = 4; break; + case 0x02: // STANDBY CONDITION ACTIVATED BY TIMER + powername = "STANDBY BY TIMER"; powerlimit = 2; break; + case 0x03: // IDLE CONDITION ACTIVATED BY COMMAND + powername = "IDLE BY COMMAND"; powerlimit = 4; break; + case 0x04: // STANDBY CONDITION ACTIVATED BY COMMAND + powername = "STANDBY BY COMMAND"; powerlimit = 2; break; + case 0x05: // IDLE_B CONDITION ACTIVATED BY TIMER + powername = "IDLE BY TIMER"; powerlimit = 4; break; + case 0x06: // IDLE_B CONDITION ACTIVATED BY COMMAND + powername = "IDLE_ BY COMMAND"; powerlimit = 4; break; + case 0x07: // IDLE_C CONDITION ACTIVATED BY TIMER + powername = "IDLE_C BY TIMER"; powerlimit = 4; break; + case 0x08: // IDLE_C CONDITION ACTIVATED BY COMMAND + powername = "IDLE_C BY COMMAND"; powerlimit = 4; break; + case 0x09: // STANDBY_Y CONDITION ACTIVATED BY TIMER + powername = "STANDBY_Y BY TIMER"; powerlimit = 2; break; + case 0x0A: // STANDBY_Y CONDITION ACTIVATED BY COMMAND + powername = "STANDBY_Y BY COMMAND"; powerlimit = 2; break; + + default: + pout("CHECK POWER MODE returned unknown value 0x%02x, " + "ignoring -n option\n", powermode); + break; + } + if (powername) { + if (options.powermode >= powerlimit) { + jinf("Device is in %s mode, exit(%d)\n", powername, options.powerexit); + return options.powerexit; + } + powerchg = (powermode != 0xff); + } + } else + powername = "ACTIVE"; } + + delete supported_vpd_pages_p; supported_vpd_pages_p = new supported_vpd_pages(device); - res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info); + res = scsiGetDriveInfo(device, &peripheral_type, is_zbc, + options.drive_info); if (res) { if (2 == res) return 0; @@ -2317,11 +3241,14 @@ res ? "Unavailable" : // error !wce ? "Disabled" : "Enabled"); } - } else any_output = true; + } - if (options.drive_info) + if (options.drive_info) { + if (powername) // Print power condition if requested -n (nocheck) + pout("Power mode %s %s\n", (powerchg?"was:":"is: "), powername); pout("\n"); + } // START OF THE ENABLE/DISABLE SECTION OF THE CODE if (options.smart_disable || options.smart_enable || @@ -2399,16 +3326,21 @@ if (options.smart_check_status) { scsiGetSupportedLogPages(device); - checkedSupportedLogPages = 1; + checkedSupportedLogPages = true; if (is_tape) { if (gTapeAlertsLPage) { - if (options.drive_info) - pout("TapeAlert Supported\n"); - if (-1 == scsiGetTapeAlertsData(device, peripheral_type)) - failuretest(OPTIONAL_CMD, returnval |= FAILSMART); + if (options.drive_info) { + jout("TapeAlert Supported\n"); + jglb["tapealert"]["supported"] = true; + } + if (options.health_opt_count > 1) { + if (-1 == scsiPrintActiveTapeAlerts(device, peripheral_type, true)) + failuretest(OPTIONAL_CMD, returnval |= FAILSMART); + } + } else { + jout("TapeAlert Not Supported\n"); + jglb["tapealert"]["supported"] = false; } - else - pout("TapeAlert Not Supported\n"); } else { /* disk, cd/dvd, enclosure, etc */ if ((res = scsiGetSmartData(device, options.smart_vendor_attrib))) { @@ -2422,8 +3354,10 @@ } if (is_disk && options.smart_ss_media_log) { - if (! checkedSupportedLogPages) + if (! checkedSupportedLogPages) { scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } res = 0; if (gSSMediaLPage) res = scsiPrintSSMedia(device); @@ -2436,10 +3370,22 @@ any_output = true; } if (options.smart_vendor_attrib) { - if (! checkedSupportedLogPages) + if (! checkedSupportedLogPages) { scsiGetSupportedLogPages(device); - if (gTempLPage) + checkedSupportedLogPages = true; + } + if (gEnviroReportingLPage && options.smart_env_rep) { + scsiPrintEnviroReporting(device); + envRepDone = true; + } else if (gTempLPage) scsiPrintTemp(device); + // in the 'smartctl -A' case only want: "Accumulated power on time" + if ((! options.smart_background_log) && is_disk) { + res = 0; + if (gBackgroundResultsLPage) + res = scsiPrintBackgroundResults(device, true); + (void)res; // not yet used below, suppress warning + } if (gStartStopLPage) scsiGetStartStopData(device); if (is_disk) { @@ -2451,20 +3397,32 @@ } any_output = true; } - if (options.smart_error_log) { - if (! checkedSupportedLogPages) + if (options.smart_error_log || options.scsi_pending_defects) { + if (! checkedSupportedLogPages) { scsiGetSupportedLogPages(device); - scsiPrintErrorCounterLog(device); - if (gPendDefectsLPage) + checkedSupportedLogPages = true; + } + if (options.smart_error_log) { + scsiPrintErrorCounterLog(device); + any_output = true; + } + if (gPendDefectsLPage) { scsiPrintPendingDefectsLPage(device); - if (1 == scsiFetchControlGLTSD(device, modese_len, 1)) - pout("\n[GLTSD (Global Logging Target Save Disable) set. " - "Enable Save with '-S on']\n"); - any_output = true; + any_output = true; + } + if (options.smart_error_log) { + if (1 == scsiFetchControlGLTSD(device, modese_len, 1)) { + pout("\n[GLTSD (Global Logging Target Save Disable) set. " + "Enable Save with '-S on']\n"); + any_output = true; + } + } } if (options.smart_selftest_log) { - if (! checkedSupportedLogPages) + if (! checkedSupportedLogPages) { scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } res = 0; if (gSelfTestLPage) res = scsiPrintSelfTest(device); @@ -2477,11 +3435,13 @@ any_output = true; } if (options.smart_background_log && is_disk) { - if (! checkedSupportedLogPages) + if (! checkedSupportedLogPages) { scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } res = 0; if (gBackgroundResultsLPage) - res = scsiPrintBackgroundResults(device); + res = scsiPrintBackgroundResults(device, false); else { pout("Device does not support Background scan results logging\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -2490,6 +3450,63 @@ failuretest(OPTIONAL_CMD, returnval|=res); any_output = true; } + if (options.zoned_device_stats && is_zbc) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + res = 0; + if (gZBDeviceStatsLPage) + res = scsiPrintZBDeviceStats(device); + else { + pout("Device does not support Zoned block device " + "statistics logging\n"); + failuretest(OPTIONAL_CMD, returnval|=FAILSMART); + } + if (0 != res) + failuretest(OPTIONAL_CMD, returnval|=res); + any_output = true; + + } + if (is_tape) { + if (options.tape_device_stats) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + res = 0; + if (gTapeDeviceStatsLPage) { + jout("\nDevice Statistics (SSC, tape) log page:\n"); + res = scsiPrintTapeDeviceStats(device); + } else { + pout("Device does not support (tape) device characteristics " + "(SSC) logging\n"); + failuretest(OPTIONAL_CMD, returnval|=FAILSMART); + } + if (0 != res) + failuretest(OPTIONAL_CMD, returnval|=res); + any_output = true; + } + if (options.tape_alert) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + res = 0; + if (gTapeAlertsLPage) { + jout("\nTape Alert log page:\n"); + res = scsiPrintActiveTapeAlerts(device, peripheral_type, false); + } else { + pout("Device does not support TapeAlert logging\n"); + failuretest(OPTIONAL_CMD, returnval|=FAILSMART); + } + if (res < 0) + failuretest(OPTIONAL_CMD, returnval|=res); + if ((scsi_debugmode > 0) && (res == 0)) + pout("TapeAlerts only printed if active, so none printed is good\n"); + any_output = true; + } + } if (options.smart_default_selftest) { if (scsiSmartDefaultSelfTest(device)) return returnval | FAILSMART; @@ -2554,11 +3571,48 @@ pout("Self Test returned without error\n"); any_output = true; } - if (options.sasphy && gProtocolSpecificLPage) { - if (scsiPrintSasPhy(device, options.sasphy_reset)) - return returnval | FAILSMART; - any_output = true; + if (options.sasphy) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + if (gProtocolSpecificLPage) { + if (scsiPrintSasPhy(device, options.sasphy_reset)) + return returnval | FAILSMART; + any_output = true; + } } + if (options.smart_env_rep && ! envRepDone) { + if (! checkedSupportedLogPages) { + scsiGetSupportedLogPages(device); + checkedSupportedLogPages = true; + } + if (gEnviroReportingLPage) { + scsiPrintEnviroReporting(device); + any_output = true; + } + } + + if (options.set_standby == 1) { + if (scsiSetPowerCondition(device, SCSI_POW_COND_ACTIVE)) { + pout("SCSI SSU(ACTIVE) command failed: %s\n", + device->get_errmsg()); + returnval |= FAILSMART; + } else + pout("Device placed in ACTIVE mode\n"); + } else if (options.set_standby > 1) { + pout("SCSI SSU(STANDBY) with timeout not supported yet\n"); + returnval |= FAILSMART; + } else if (options.set_standby_now) { + if (scsiSetPowerCondition(device, SCSI_POW_COND_STANDBY)) { + pout("SCSI STANDBY command failed: %s\n", device->get_errmsg()); + returnval |= FAILSMART; + } else + pout("Device placed in STANDBY mode\n"); + } + + if (!any_output && powername) // Output power mode if -n (nocheck) + pout("Device is in %s mode\n", powername); if (!any_output) pout("SCSI device successfully opened\n\nUse 'smartctl -a' (or '-x') " diff -Nru smartmontools-7.1/scsiprint.h smartmontools-7.3/scsiprint.h --- smartmontools-7.1/scsiprint.h 2018-08-19 18:45:53.000000000 +0000 +++ smartmontools-7.3/scsiprint.h 2022-02-26 01:02:56.000000000 +0000 @@ -1,7 +1,7 @@ /* * scsiprint.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-9 Bruce Allen * Copyright (C) 2000 Michael Cornwell @@ -16,52 +16,49 @@ #ifndef SCSI_PRINT_H_ #define SCSI_PRINT_H_ -#define SCSIPRINT_H_CVSID "$Id: scsiprint.h 4760 2018-08-19 18:45:53Z chrfranke $\n" +#define SCSIPRINT_H_CVSID "$Id: scsiprint.h 5334 2022-02-26 01:02:56Z dpgilbert $\n" // Options for scsiPrintMain struct scsi_print_options { - bool drive_info; - bool smart_check_status; - bool smart_vendor_attrib; - bool smart_error_log; - bool smart_selftest_log; - bool smart_background_log; - bool smart_ss_media_log; - - bool smart_disable, smart_enable; - bool smart_auto_save_disable, smart_auto_save_enable; - - bool smart_default_selftest; - bool smart_short_selftest, smart_short_cap_selftest; - bool smart_extend_selftest, smart_extend_cap_selftest; - bool smart_selftest_abort; - bool smart_selftest_force; // Ignore already running test + bool drive_info = false; + bool smart_check_status = false; + bool smart_vendor_attrib = false; + bool smart_error_log = false; + bool smart_selftest_log = false; + bool smart_background_log = false; + bool smart_ss_media_log = false; + + bool smart_disable = false, smart_enable = false; + bool smart_auto_save_disable = false, smart_auto_save_enable = false; + + bool smart_default_selftest = false; + bool smart_short_selftest = false, smart_short_cap_selftest = false; + bool smart_extend_selftest = false, smart_extend_cap_selftest = false; + bool smart_selftest_abort = false; + bool smart_selftest_force = false; // Ignore already running test + bool scsi_pending_defects = false; - bool sasphy, sasphy_reset; + bool smart_env_rep = false; + + bool sasphy = false, sasphy_reset = false; + + bool tape_device_stats = false; + bool tape_alert = false; + + bool zoned_device_stats = false; - bool get_wce, get_rcd; - short int set_wce, set_rcd; // disable(-1), enable(1) cache + bool get_wce = false, get_rcd = false; + short int set_wce = 0, set_rcd = 0; // disable(-1), enable(1) cache + + unsigned char powermode = 0; // Enhancement Skip check, if disk in idle or standby mode + unsigned char powerexit = 0; // exit() code for low power mode + + int set_standby = 0; // set(1..255->0..254) standby timer + bool set_standby_now = false; // set drive to standby + bool set_active = false; // set drive to active - scsi_print_options() - : drive_info(false), - smart_check_status(false), - smart_vendor_attrib(false), - smart_error_log(false), - smart_selftest_log(false), - smart_background_log(false), - smart_ss_media_log(false), - smart_disable(false), smart_enable(false), - smart_auto_save_disable(false), smart_auto_save_enable(false), - smart_default_selftest(false), - smart_short_selftest(false), smart_short_cap_selftest(false), - smart_extend_selftest(false), smart_extend_cap_selftest(false), - smart_selftest_abort(false), - smart_selftest_force(false), - sasphy(false), sasphy_reset(false), - get_wce(false), get_rcd(false), - set_wce(0), set_rcd(0) - { } + int health_opt_count = 0; // TapeAlert log page only read if this value > 1 }; int scsiPrintMain(scsi_device * device, const scsi_print_options & options); diff -Nru smartmontools-7.1/smartctl.8.in smartmontools-7.3/smartctl.8.in --- smartmontools-7.1/smartctl.8.in 2019-12-29 13:37:25.000000000 +0000 +++ smartmontools-7.3/smartctl.8.in 2022-02-26 00:15:22.000000000 +0000 @@ -1,10 +1,10 @@ .ig Copyright (C) 2002-10 Bruce Allen -Copyright (C) 2004-19 Christian Franke +Copyright (C) 2004-22 Christian Franke SPDX-License-Identifier: GPL-2.0-or-later -$Id: smartctl.8.in 5018 2019-12-29 13:37:25Z chrfranke $ +$Id: smartctl.8.in 5333 2022-02-26 00:15:22Z dpgilbert $ .. .\" Macros borrowed from pages generated with Pod::Man @@ -48,8 +48,8 @@ ACS-3, ACS-2, ATA8-ACS, ATA/ATAPI-7 and earlier standards (see \fBREFERENCES\fP below). .PP -\fBsmartctl\fP also provides support for polling TapeAlert messages -from SCSI tape drives and changers. +\fBsmartctl\fP also provides support for SCSI tape drives and +changers (see \fBTAPE DRIVES\fP below). .PP The user must specify the device to be controlled or interrogated as the final argument to \fBsmartctl\fP. The command set used by the device @@ -60,7 +60,7 @@ .\" %IF OS Linux .IP \fBLINUX\fP: 9 Use the forms \fB"/dev/sd[a\-z]"\fP for ATA/SATA and SCSI/SAS devices. -For SCSI Tape Drives and Changers with TapeAlert support use the +For SCSI Tape Drives and Changers use the devices \fB"/dev/nst*"\fP and \fB"/dev/sg*"\fP. For disks behind 3ware controllers you may need \fB"/dev/sd[a\-z]"\fP or \fB"/dev/twe[0\-9]"\fP, \fB"/dev/twa[0\-9]"\fP or \fB"/dev/twl[0\-9]"\fP: @@ -89,8 +89,7 @@ equivalently \fB/dev/rdisk[0\-9]\fP. Long forms are also available: please use \*(Aq\-h\*(Aq to see some examples. .Sp -There is NVMe support based on the undocumented SMART API in OSX. Currently only -SMART and Controller information pages are supported. +There is NVMe support based on the NVMeSMARTLib API in OSX. .Sp Note that Darwin SCSI support is not yet implemented. .Sp @@ -150,7 +149,6 @@ with AMD RAID driver, use \fB"/dev/csmi[0\-9],N"\fP where N specifies the port behind the logical scsi controller "\\\\.\\Scsi[0\-9]:". .br -[NEW EXPERIMENTAL SMARTCTL FEATURE] The AMD RAID driver may return incomplete information about port assignment. To allow access to ports not reported, device scan returns all ports. Device open fails then if the port is unused. @@ -250,8 +248,8 @@ the longest output. .TP .B \-a, \-\-all -Prints all SMART information about the disk, or TapeAlert information -about the tape drive or changer. For ATA devices this is equivalent +Prints all SMART information about the disk. +For ATA devices this is equivalent to .br \*(Aq\-H \-i \-c \-A \-l error \-l selftest \-l selective\*(Aq @@ -277,9 +275,14 @@ \-l xselftest,selftest \-l selective \-l directory \-l scttemp \-l scterc \-l devstat \-l defects \-l sataphy\*(Aq. .br -and for SCSI, this is equivalent to +and for SCSI disks, this is equivalent to +.br +\*(Aq\-H \-i \-g all \-A \-l error \-l selftest \-l background \-l sasphy +\-l defects \-l env_rep\*(Aq. .br -\*(Aq\-H \-i \-g all \-A \-l error \-l selftest \-l background \-l sasphy\*(Aq. +and for SCSI zoned disks, add \-l zdevstat +.br +and for SCSI tape drivers and changers, add \-l tapedevstat .br .\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin For NVMe, this is equivalent to @@ -316,15 +319,15 @@ .TP .B RUN-TIME BEHAVIOR OPTIONS: .TP -.B \-j, \-\-json[=cgiosuv] -[NEW EXPERIMENTAL SMARTCTL FEATURE] -Enables JSON output mode. +.B \-j, \-\-json[=cgiosuvy] +Enables JSON or YAML output mode. .Sp The output could be modified or enhanced by the optional argument which -consists of one or more characters from the set \*(Aqcgiosuv\*(Aq: +consists of one or more characters from the set \*(Aqcgiosuvy\*(Aq: .br \*(Aqc\*(Aq: Outputs \fBc\fPompact format without extra spaces and newlines. By default, output is pretty-printed. +If used with YAML format, the indentation of arrays is reduced. .br \*(Aqg\*(Aq: Outputs JSON structure as single assignments to allow the usage of \fBg\fPrep. @@ -347,16 +350,18 @@ byte array (\*(AqKEY_le\*(Aq). By default, the additional elements are only output if the value actually exceeds the range. +.br +\*(Aqy\*(Aq: [NEW EXPERIMENTAL SMARTCTL FEATURE] Outputs in YAML format. .Sp The following two arguments are primarily indented for development: .br \*(Aqi\*(Aq: Includes lines from the plaintext output which print info already \fBi\fPmplemented for JSON output. -The lines appear as objects with key \*(Aqsmartctl_NNNN_i\*(Aq. +The lines appear as strings with key \*(Aqsmartctl_NNNN_i\*(Aq. .br \*(Aqu\*(Aq: Includes lines from the plaintext output which print info still \fBu\fPnimplemented for JSON output. -The lines appear as objects with key \*(Aqsmartctl_NNNN_u\*(Aq. +The lines appear as strings with key \*(Aqsmartctl_NNNN_u\*(Aq. .TP .B \-q TYPE, \-\-quietmode=TYPE Specifies that \fBsmartctl\fP should run in one of the quiet modes @@ -464,25 +469,52 @@ \- this device type is for SATA disks that are behind a SunplusIT USB to SATA bridge. .Sp -.I sntjmicron[,NSID] +.I sntasmedia \- [NEW EXPERIMENTAL SMARTCTL FEATURE] -this device type is for NVMe disks that are behind a JMicron USB to NVMe +this device type is for NVMe disks that are behind an ASMedia USB to NVMe +bridge. +.Sp +.I sntjmicron[,NSID] +\- this device type is for NVMe disks that are behind a JMicron USB to NVMe bridge. The optional parameter NSID specifies the namespace id (in hex) passed to the driver. The default namespace id is the broadcast namespace id (0xffffffff). .Sp +.I sntrealtek +\- [NEW EXPERIMENTAL SMARTCTL FEATURE] +this device type is for NVMe disks that are behind a Realtek USB to NVMe +bridge. +.Sp .\" %ENDIF NOT OS Darwin -.\" %IF OS Linux +.\" %IF OS Linux FreeBSD .I marvell \- [Linux only] interact with SATA disks behind Marvell chip-set controllers (using the Marvell rather than libata driver). .Sp .I megaraid,N -\- [Linux only] the device consists of one or more SCSI/SAS disks connected +\- [FreeBSD and Linux only] the device consists of one or more SCSI/SAS disks connected to a MegaRAID controller. The non-negative integer N (in the range of 0 to -127 inclusive) denotes which disk on the controller is monitored. +127 inclusive) denotes which disk on the controller is monitored. This interface +will also work for Dell PERC controllers. Use syntax such as: +.\" %ENDIF OS Linux FreeBSD +.\" %IF OS ALL +.br +FreeBSD: +.\" %ENDIF OS ALL +.\" %IF OS FreeBSD +.br +\fBsmartctl \-a \-d megaraid,2 /dev/mfi0\fP +.br +\fBsmartctl \-a \-d megaraid,0 /dev/mrsas0\fP +.br +.Sp +.\" %ENDIF OS FreeBSD +.\" %IF OS ALL +Linux: +.\" %ENDIF OS ALL +.\" %IF OS Linux .br \fBsmartctl \-a \-d megaraid,2 /dev/sda\fP .br @@ -490,7 +522,6 @@ .br \fBsmartctl \-a \-d megaraid,0 /dev/bus/0\fP .br -This interface will also work for Dell PERC controllers. It is possible to set RAID device name as /dev/bus/N, where N is a SCSI bus number. .Sp @@ -691,10 +722,12 @@ Vendor Specific Log at address 0xc0. Using this option with other devices may have undesirable side effects.\fP .Sp -.I jmb39x,N[,sLBA][,force][+TYPE] +.I jmb39x[\-q],N[,sLBA][,force][+TYPE] \- [NEW EXPERIMENTAL SMARTCTL FEATURE] the device consists of multiple SATA disks connected to a JMicron JMB39x RAID port multiplier. +The suffix \*(Aq\-q\*(Aq selects a slightly different command variant used by +some QNAP NAS devices. The integer N is the port number from 0 to 4. .br \fBWARNING: The ATA pass-through commands are issued via READ/WRITE commands @@ -708,8 +741,14 @@ zero filled. The \*(Aqforce\*(Aq flag disables this check. .br -\fBWARNING: Orignal sector data is not written back if smartctl is aborted +\fBWARNING: Original sector data is not written back if smartctl is aborted with a signal.\fP +.Sp +.I jms56x,N[,sLBA][,force][+TYPE] +\- [NEW EXPERIMENTAL SMARTCTL FEATURE] +the device consists of multiple SATA disks connected to a JMicron JMS56x +USB to SATA RAID bridge. +See \*(Aqjmb39x...\*(Aq above for valid arguments. .TP .B \-T TYPE, \-\-tolerance=TYPE [ATA only] Specifies how tolerant \fBsmartctl\fP should be of ATA and SMART @@ -811,8 +850,10 @@ behaviour. This is does not work for SCSI devices yet. .TP -.B \-n POWERMODE[,STATUS], \-\-nocheck=POWERMODE[,STATUS] -[ATA only] Specifies if \fBsmartctl\fP should exit before performing any +.B \-n POWERMODE[,STATUS[,STATUS2]], \-\-nocheck=POWERMODE[,STATUS[,STATUS2]] +[ATA] +[SCSI: NEW EXPERIMENTAL SMARTCTL FEATURE] +Specifies if \fBsmartctl\fP should exit before performing any checks when the device is in a low-power mode. It may be used to prevent a disk from being spun-up by \fBsmartctl\fP. The power mode is ignored by default. @@ -825,7 +866,7 @@ specified low-power modes. This status is also returned if the device open or identification failed (see EXIT STATUS below). -The optional STATUS parameter allows to override this default. +The optional STATUS parameter allows one to override this default. STATUS is an integer in the range from 0 to 255 inclusive. For example use \*(Aq\-n standby,0\*(Aq to return success if a device is in SLEEP or STANDBY mode. @@ -837,19 +878,27 @@ \- check the device always, but print the power mode if \*(Aq\-i\*(Aq is specified. .Sp -.I sleep[,STATUS] +.I sleep[,STATUS[,STATUS2]] \- check the device unless it is in SLEEP mode. .Sp -.I standby[,STATUS] +.I standby[,STATUS[,STATUS2]] \- check the device unless it is in SLEEP or STANDBY mode. In these modes most disks are not spinning, so if you want to prevent a disk from spinning up, this is probably what you want. .Sp -.I idle[,STATUS] +.I idle[,STATUS[,STATUS2]] \- check the device unless it is in SLEEP, STANDBY or IDLE mode. In the IDLE state, most disks are still spinning, so this is probably not what you want. .Sp +The \*(Aq\-n\*(Aq option is ignored if the power mode check is not supported +or returns an unknown value. +.br +[ATA only][NEW EXPERIMENTAL SMARTCTL FEATURE] +If the optional STATUS2 parameter is specified, \fBsmartctl\fP exits +immediately with STATUS2 in this case. +For example use \*(Aq\-n standby,3,5\*(Aq to return unique exit statuses in +the STANDBY and UNSUPPORTED cases. .TP .B SMART FEATURE ENABLE/DISABLE COMMANDS: .IP @@ -1010,8 +1059,8 @@ frozen mode may already be set by BIOS or OS. .Sp .I standby,[N|off] -\- [ATA only] Sets the standby (spindown) timer and places the drive in the -IDLE mode. A value of 0 or \*(Aqoff\*(Aq disables the standby timer. +\- [ATA] Sets the standby (spindown) timer and places the drive in +the IDLE mode. A value of 0 or \*(Aqoff\*(Aq disables the standby timer. Values from 1 to 240 specify timeouts from 5 seconds to 20 minutes in 5 second increments. Values from 241 to 251 specify timeouts from 30 minutes to 330 minutes in 30 minute increments. Value 252 specifies 21 minutes. @@ -1023,12 +1072,21 @@ placed in the STANDBY mode without temporarily placing it in the IDLE mode. Note that ATA standards do not specify a command to set the standby timer without affecting the power mode. +.br +[SCSI: NEW EXPERIMENTAL SMARTCTL FEATURE] +Only the set option with \*(Aqstandby,off\*(Aq or +\*(Aqstandby,0\*(Aq is accepted and will place the SCSI disk +into "ACTIVE" power condition. .Sp .I standby,now -\- [ATA only] Places the drive in the STANDBY mode. +\- [ATA] Places the drive in the STANDBY mode. This usually spins down the drive. The setting of the standby timer is not affected unless \*(Aq\-s standby,[N|off]\*(Aq is also specified. +.br +[SCSI: NEW EXPERIMENTAL SMARTCTL FEATURE] +Only the set option is accepted and will place the SCSI +disk into "STANDBY_Z" power condition. .Sp .I wcache[,on|off] \- [ATA] Gets/sets the volatile write cache feature (if supported). @@ -1074,7 +1132,11 @@ .B SMART READ AND DISPLAY DATA OPTIONS: .TP .B \-H, \-\-health -Prints the health status of the device or pending TapeAlert messages. +Prints the health status of the device. +.Sp +[SCSI tape drive or changer] For SCSI tape drives the TapeAlert log page is +not checked for pending alerts unless this option is given twice (see +\fBTAPE DRIVES\fP for the rationale). .Sp If the device reports failing health status, this means .B either @@ -1098,11 +1160,7 @@ (IE) log page (if supported) and/or from SCSI sense data. .Sp [SCSI tape drive or changer] TapeAlert status is obtained by reading the -TapeAlert log page. -Please note that the TapeAlert log page flags are cleared for the initiator -when the page is read. -This means that each alert condition is reported only once by \fBsmartctl\fP -for each initiator for each activation of the condition. +TapeAlert log page only when this option is given twice. .\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin .Sp [NVMe] NVMe status is obtained by reading the "Critical Warning" byte from @@ -1465,7 +1523,7 @@ non-volatile setting by the next hard reset. The default interval is vendor specific, typical values are 1, 2, or 5 minutes. .Sp -.I scterc[,READTIME,WRITETIME] +.I scterc[,READTIME,WRITETIME][,p|reset] \- [ATA only] prints values and descriptions of the SCT Error Recovery Control settings. These are equivalent to TLER (as used by Western Digital), CCTL (as used @@ -1474,6 +1532,16 @@ Values of 0 disable the feature, other values less than 65 are probably not supported. For RAID configurations, this is typically set to 70,70 deciseconds. +.br +[NEW EXPERIMENTAL SMARTCTL FEATURE] +If \*(Aqscterc,READTIME,WRITETIME,p\*(Aq is specified, these time values +will be persistent over a power-on reset. +If \*(Aqscterc,p\*(Aq is specified, the persistent over power-on values +are printed. +If \*(Aqscterc,reset\*(Aq is specified, all SCT timer settings are restored +to the manufacturer's default value. +The \*(Aq,p\*(Aq and \*(Aq,reset\*(Aq options require the device to support +ATA ACS-4 or higher. .Sp .I devstat[,PAGE] \- [ATA only] prints values and descriptions of the ATA Device Statistics @@ -1483,13 +1551,26 @@ introduced in ACS-2 and is only supported by some recent devices. .Sp .I defects[,NUM] -\- [ATA only] prints LBA and hours values from the ATA Pending Defects log +\- [ATA] prints LBA and hours values from the ATA Pending Defects log (General Purpose Log address 0x0c). Only the 31 entries from first log page are printed by default. This number can be changed by the optional parameter NUM. The size of the log and the order of the entries are vendor specific. The Pending Defects log was introduced in ACS-4 Revision 01 (Mar 2014). .Sp +.I defects +\- [SCSI: NEW EXPERIMENTAL SMARTCTL FEATURE] prints LBAs that the background +scan was unable to read (i.e. a defect). Entries, if any, show the defective +LBA and the value of the power\-on hours (since manufacture) when the background +scan found the defect. Note these pending defects may appear in advance of any +application trying to read a defective LBA. +.Sp +.I envrep +\- [SCSI only: NEW EXPERIMENTAL SMARTCTL FEATURE] +prints values and descriptions of the SCSI Environmental reporting log +page. This includes one or more temperatures and may include relative +humidities. Lifetime maximums and minimums are also reported. +.Sp .I sataphy[,reset] \- [SATA only] prints values and descriptions of the SATA Phy Event Counters (General Purpose Log address 0x11). If \*(Aq\-l sataphy,reset\*(Aq @@ -1502,6 +1583,20 @@ Protocol Specific log page (log page 0x18). If \*(Aq\-l sasphy,reset\*(Aq is specified, all counters are reset after reading the values. .Sp +.I tapealert +\- [SCSI tape drives and changers: NEW EXPERIMENTAL SMARTCTL FEATURE] +prints values and descriptions of the (SSC) Tape Alert log page. See +\fBTAPE DRIVES\fP below for issue associated with printing this log page. +.Sp +.I tapedevstat +\- [SCSI tape drives and changers: NEW EXPERIMENTAL SMARTCTL FEATURE] +prints values and descriptions of the (SSC) Device Statistics log page. +.Sp +.I zdevstat +\- [SCSI zoned disks: NEW EXPERIMENTAL SMARTCTL FEATURE] +prints values and descriptions of the Zoned Block Device Statistics log +page (ZBC\-2). +.Sp .I gplog,ADDR[,FIRST[\-LAST|+SIZE]] \- [ATA only] prints a hex dump of any log accessible via General Purpose Logging (GPL) feature. The log address ADDR is the hex address @@ -1868,7 +1963,7 @@ .Sp If .\" %IF NOT OS Windows -\fB/usr/local/share/smartmontools/drivedb.h\fP +\fB/usr/local/var/lib/smartmontools/drivedb.h\fP .\" %ENDIF NOT OS Windows .\" %IF OS ALL (Windows: \fBEXEDIR/drivedb.h\fP) @@ -2214,6 +2309,37 @@ a Network Attached Storage (NAS) box) and fetching the logs via a browser. .Sp +.SH TAPE DRIVES +Commands for SCSI Tape drives as defined in the SSC\-4 standard (ANSI +INCITS 516\-2013). SSC stands for "SCSI Streaming Commands". Draft +standards can be found at <\fBhttps://www.t10.org/\fP> . +.PP +Many SMART related features of SCSI disks are shared by SCSI tape drives. +One important tape\-specific log page is called "TapeAlert" which is used +to report abnormal conditions. Unlike most other log pages the TapeAlert +log page +.B clears +pending alerts after that page is fetched (i.e. read from +the tape drive). To be more precise, the TapeAlert log page is cleared +for the I_T nexus (initiator-target pair) that sent the (SCSI LOG SENSE) +command; so another initiator (e.g. a HBA on another machine) will still +have pending alerts reported. [This clearing action can be controlled by +the TAPLSD bit is the [SSC] Device Configuration Extension mode page but +the original and default action remains: clear any pending TapeAlerts. +The sdparm utility can be used to access and change TAPLSD.] +.PP +Previous versions of smartctl have supported polling the TapeAlert log +page when the \-\-health option is given. This clearing of pending alerts +has created problems for other tape\-specific tools. This version of +smartctl will only fetch the TapeAlert log page if the \-\-health option +is given +.B twice +in the command line invocation (or the \-\-log=tapealert option is given). +.PP +There are other tape\-specific log pages such as \-\-log=tapedevstat +that behave normally (i.e. they don't change any state information in +the tape drive). +.Sp .SH EXAMPLES .B smartctl \-a /dev/sda .br @@ -2366,7 +2492,7 @@ full path of this executable. .\" %IF ENABLE_DRIVEDB .TP -.B /usr/local/share/smartmontools/drivedb.h +.B /usr/local/var/lib/smartmontools/drivedb.h drive database (see \*(Aq\-B\*(Aq option). .\" %ENDIF ENABLE_DRIVEDB .TP @@ -2434,4 +2560,4 @@ .SH PACKAGE VERSION CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV .br -$Id: smartctl.8.in 5018 2019-12-29 13:37:25Z chrfranke $ +$Id: smartctl.8.in 5333 2022-02-26 00:15:22Z dpgilbert $ diff -Nru smartmontools-7.1/smartctl.cpp smartmontools-7.3/smartctl.cpp --- smartmontools-7.1/smartctl.cpp 2018-12-27 20:03:12.000000000 +0000 +++ smartmontools-7.3/smartctl.cpp 2022-02-26 00:15:22.000000000 +0000 @@ -1,10 +1,10 @@ /* * smartctl.cpp * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-18 Christian Franke + * Copyright (C) 2008-21 Christian Franke * Copyright (C) 2000 Michael Cornwell * * SPDX-License-Identifier: GPL-2.0-or-later @@ -42,7 +42,7 @@ #include "utility.h" #include "svnversion.h" -const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 4871 2018-12-27 20:03:12Z chrfranke $" +const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 5333 2022-02-26 00:15:22Z dpgilbert $" CONFIG_H_CVSID SMARTCTL_H_CVSID; // Globals to control printing @@ -132,8 +132,8 @@ ); pout( "================================== SMARTCTL RUN-TIME BEHAVIOR OPTIONS =====\n\n" -" -j, --json[=[cgiosuv]]\n" -" Print output in JSON format\n\n" +" -j, --json[=cgiosuvy]\n" +" Print output in JSON or YAML format\n\n" " -q TYPE, --quietmode=TYPE (ATA)\n" " Set smartctl quiet mode to one of: errorsonly, silent, noserial\n\n" " -d TYPE, --device=TYPE\n" @@ -145,7 +145,7 @@ " Set action on bad checksum to one of: warn, exit, ignore\n\n" " -r TYPE, --report=TYPE\n" " Report transactions (see man page)\n\n" -" -n MODE[,STATUS], --nocheck=MODE[,STATUS] (ATA)\n" +" -n MODE[,STATUS[,STATUS2]], --nocheck=MODE[,STATUS[,STATUS2]] (ATA, SCSI)\n" " No check if: never, sleep, standby, idle (see man page)\n\n", getvalidarglist('d').c_str()); // TODO: Use this function also for other options ? pout( @@ -176,8 +176,9 @@ " Show device log. TYPE: error, selftest, selective, directory[,g|s],\n" " xerror[,N][,error], xselftest[,N][,selftest], background,\n" " sasphy[,reset], sataphy[,reset], scttemp[sts,hist],\n" -" scttempint,N[,p], scterc[,N,M], devstat[,N], defects[,N], ssd,\n" -" gplog,N[,RANGE], smartlog,N[,RANGE], nvmelog,N,SIZE\n\n" +" scttempint,N[,p], scterc[,N,M][,p|reset], devstat[,N], defects[,N],\n" +" ssd, gplog,N[,RANGE], smartlog,N[,RANGE], nvmelog,N,SIZE\n" +" tapedevstat, zdevstat, envrep\n\n" " -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" " Set display OPTION for vendor Attribute N (see man page)\n\n" " -F TYPE, --firmwarebug=TYPE (ATA)\n" @@ -243,9 +244,9 @@ "xerror[,N][,error], xselftest[,N][,selftest], " "background, sasphy[,reset], sataphy[,reset], " "scttemp[sts,hist], scttempint,N[,p], " - "scterc[,N,M], devstat[,N], defects[,N], ssd, " - "gplog,N[,RANGE], smartlog,N[,RANGE], " - "nvmelog,N,SIZE"; + "scterc[,N,M][,p|reset], devstat[,N], defects[,N], " + "ssd, gplog,N[,RANGE], smartlog,N[,RANGE], " + "nvmelog,N,SIZE, tapedevstat, zdevstat, envrep"; case 'P': return "use, ignore, show, showall"; case 't': @@ -254,7 +255,8 @@ case 'F': return std::string(get_valid_firmwarebug_args()) + ", swapid"; case 'n': - return "never, sleep[,STATUS], standby[,STATUS], idle[,STATUS]"; + return "never, sleep[,STATUS[,STATUS2]], standby[,STATUS[,STATUS2]], " + "idle[,STATUS[,STATUS2]]"; case 'f': return "old, brief, hex[,id|val]"; case 'g': @@ -266,7 +268,7 @@ case 's': return getvalidarglist(opt_smart)+", "+getvalidarglist(opt_set); case 'j': - return "c, g, i, o, s, u, v"; + return "c, g, i, o, s, u, v, y"; case opt_identify: return "n, wn, w, v, wv, wb"; case 'v': @@ -491,6 +493,7 @@ case 'H': ataopts.smart_check_status = scsiopts.smart_check_status = nvmeopts.smart_check_status = true; scsiopts.smart_ss_media_log = true; + ++scsiopts.health_opt_count; break; case 'F': if (!strcmp(optarg, "swapid")) @@ -540,14 +543,21 @@ ataopts.devstat_ssd_page = true; scsiopts.smart_ss_media_log = true; } else if (!strcmp(optarg,"scterc")) { - ataopts.sct_erc_get = true; + ataopts.sct_erc_get = 1; } else if (!strcmp(optarg,"scttemp")) { ataopts.sct_temp_sts = ataopts.sct_temp_hist = true; + } else if (!strcmp(optarg,"envrep")) { + scsiopts.smart_env_rep = true; } else if (!strcmp(optarg,"scttempsts")) { ataopts.sct_temp_sts = true; } else if (!strcmp(optarg,"scttemphist")) { ataopts.sct_temp_hist = true; - + } else if (!strcmp(optarg,"tapealert")) { + scsiopts.tape_alert = true; + } else if (!strcmp(optarg,"tapedevstat")) { + scsiopts.tape_device_stats = true; + } else if (!strcmp(optarg,"zdevstat")) { + scsiopts.zoned_device_stats = true; } else if (!strncmp(optarg, "scttempint,", sizeof("scstempint,")-1)) { unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg); if (!( sscanf(optarg,"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1 @@ -577,6 +587,7 @@ int n1 = -1, n2 = -1, len = strlen(optarg); unsigned val = ~0; sscanf(optarg, "defects%n,%u%n", &n1, &val, &n2); + scsiopts.scsi_pending_defects = true; if (n1 == len) ataopts.pending_defects_log = 31; // Entries of first page else if (n2 == len && val <= 0xffff * 32 - 1) @@ -615,15 +626,20 @@ badarg = true; } else if (!strncmp(optarg, "scterc,", sizeof("scterc,")-1)) { - unsigned rt = ~0, wt = ~0; int n = -1; - sscanf(optarg,"scterc,%u,%u%n", &rt, &wt, &n); - if (n == (int)strlen(optarg) && rt <= 999 && wt <= 999) { - ataopts.sct_erc_set = true; + int n1 = -1, n2 = -1, len = strlen(optarg); + unsigned rt = ~0, wt = ~0; + sscanf(optarg, "scterc,%u,%u%n,p%n", &rt, &wt, &n1, &n2); + if ((n1 == len || n2 == len) && rt <= 999 && wt <= 999) { + ataopts.sct_erc_set = (n2 == len ? 2 : 1); ataopts.sct_erc_readtime = rt; ataopts.sct_erc_writetime = wt; - } - else { - snprintf(extraerror, sizeof(extraerror), "Option -l scterc,[READTIME,WRITETIME] syntax error\n"); + } else if (!strcmp(optarg, "scterc,p")) { + ataopts.sct_erc_get = 2; + } else if (!strcmp(optarg, "scterc,reset")) { + ataopts.sct_erc_set = 3; + ataopts.sct_erc_readtime = ataopts.sct_erc_writetime = 0; + } else { + snprintf(extraerror, sizeof(extraerror), "Option -l scterc[,READTIME,WRITETIME][,p|reset] syntax error\n"); badarg = true; } } else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) @@ -717,7 +733,7 @@ ataopts.smart_selective_selftest_log = true; ataopts.smart_logdir = ataopts.gp_logdir = true; ataopts.sct_temp_sts = ataopts.sct_temp_hist = true; - ataopts.sct_erc_get = true; + ataopts.sct_erc_get = 1; ataopts.sct_wcache_reorder_get = true; ataopts.devstat_all_pages = true; ataopts.pending_defects_log = 31; @@ -731,6 +747,10 @@ scsiopts.smart_background_log = true; scsiopts.smart_ss_media_log = true; scsiopts.sasphy = true; + scsiopts.smart_env_rep = true; + scsiopts.scsi_pending_defects = true; + scsiopts.tape_device_stats = true; + scsiopts.zoned_device_stats = true; if (!output_format_set) ataopts.output_format |= ata_print_options::FMT_BRIEF; break; @@ -860,22 +880,29 @@ // skip disk check if in low-power mode if (!strcmp(optarg, "never")) { ataopts.powermode = 1; // do not skip, but print mode + scsiopts.powermode = 1; } else { - int n1 = -1, n2 = -1, len = strlen(optarg); - char s[7+1]; unsigned i = FAILPOWER; - sscanf(optarg, "%9[a-z]%n,%u%n", s, &n1, &i, &n2); - if (!((n1 == len || n2 == len) && i <= 255)) + int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg); + char s[7+1]; unsigned i = FAILPOWER, j = 0; + sscanf(optarg, "%7[a-z]%n,%u%n,%u%n", s, &n1, &i, &n2, &j, &n3); + if (!((n1 == len || n2 == len || n3 == len) && i <= 255 && j <= 255)) badarg = true; - else if (!strcmp(s, "sleep")) + else if (!strcmp(s, "sleep")) { ataopts.powermode = 2; - else if (!strcmp(s, "standby")) + scsiopts.powermode = 2; + } else if (!strcmp(s, "standby")) { ataopts.powermode = 3; - else if (!strcmp(s, "idle")) + scsiopts.powermode = 3; + } else if (!strcmp(s, "idle")) { ataopts.powermode = 4; - else + scsiopts.powermode = 4; + } else badarg = true; + ataopts.powerexit = i; + ataopts.powerexit_unsup = (n3 == len ? j : -1); + scsiopts.powerexit = i; } break; case 'f': @@ -1035,13 +1062,16 @@ } else if (!get && !strcmp(optarg, "standby,now")) { ataopts.set_standby_now = true; + scsiopts.set_standby_now = true; } else if (!get && !strcmp(name, "standby")) { - if (off) + if (off) { ataopts.set_standby = 0 + 1; - else if (val <= 255) + scsiopts.set_standby = 0 + 1; + } else if (val <= 255) { ataopts.set_standby = val + 1; - else { + scsiopts.set_standby = val + 1; + } else { snprintf(extraerror, sizeof(extraerror), "Option -s standby,N must have 0 <= N <= 255\n"); badarg = true; } @@ -1093,7 +1123,7 @@ print_as_json = true; print_as_json_options.pretty = true; print_as_json_options.sorted = false; - print_as_json_options.flat = false; + print_as_json_options.format = 0; print_as_json_output = false; print_as_json_impl = print_as_json_unimpl = false; bool json_verbose = false; @@ -1101,12 +1131,13 @@ for (int i = 0; optarg[i]; i++) { switch (optarg[i]) { case 'c': print_as_json_options.pretty = false; break; - case 'g': print_as_json_options.flat = true; break; + case 'g': print_as_json_options.format = 'g'; break; case 'i': print_as_json_impl = true; break; case 'o': print_as_json_output = true; break; case 's': print_as_json_options.sorted = true; break; case 'u': print_as_json_unimpl = true; break; case 'v': json_verbose = true; break; + case 'y': print_as_json_options.format = 'y'; break; default: badarg = true; } } @@ -1124,7 +1155,7 @@ // Check whether the option is a long option that doesn't map to -h. if (arg[1] == '-' && optchar != 'h') { // Iff optopt holds a valid option then argument must be missing. - if (optopt && (optopt >= opt_scan || strchr(shortopts, optopt))) { + if (optopt && (optopt > '~' || strchr(shortopts, optopt))) { jerr("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2); printvalidarglistmessage(optopt); } else @@ -1395,6 +1426,14 @@ va_end(ap); } +static char startup_datetime_buf[DATEANDEPOCHLEN]; + +// Print smartctl start-up date and time and timezone +void jout_startup_datetime(const char *prefix) +{ + jout("%s%s\n", prefix, startup_datetime_buf); +} + // Globals to set failuretest() policy bool failuretest_conservative = false; unsigned char failuretest_permissive = 0; @@ -1539,6 +1578,14 @@ return status; } + // Store formatted current time for jout_startup_datetime() + // Output as JSON regardless of '-i' option + { + time_t now = time(nullptr); + dateandtimezoneepoch(startup_datetime_buf, now); + jglb["local_time"] += { {"time_t", now}, {"asctime", startup_datetime_buf} }; + } + const char * name = argv[argc-1]; smart_device_auto_ptr dev; diff -Nru smartmontools-7.1/smartctl.h smartmontools-7.3/smartctl.h --- smartmontools-7.1/smartctl.h 2018-12-02 16:07:26.000000000 +0000 +++ smartmontools-7.3/smartctl.h 2021-02-07 14:19:40.000000000 +0000 @@ -1,10 +1,10 @@ /* * smartctl.h * - * Home page of code is: http://www.smartmontools.org + * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-10 Bruce Allen - * Copyright (C) 2008-17 Christian Franke + * Copyright (C) 2008-21 Christian Franke * Copyright (C) 2000 Michael Cornwell * * SPDX-License-Identifier: GPL-2.0-or-later @@ -13,7 +13,7 @@ #ifndef SMARTCTL_H_ #define SMARTCTL_H_ -#define SMARTCTL_H_CVSID "$Id: smartctl.h 4842 2018-12-02 16:07:26Z chrfranke $\n" +#define SMARTCTL_H_CVSID "$Id: smartctl.h 5200 2021-02-07 14:19:40Z chrfranke $\n" // Return codes (bitmask) @@ -100,4 +100,7 @@ void jerr(const char *fmt, ...) __attribute_format_printf(1, 2); +// Print smartctl start-up date and time and timezone +void jout_startup_datetime(const char *prefix); + #endif diff -Nru smartmontools-7.1/smartd.8.in smartmontools-7.3/smartd.8.in --- smartmontools-7.1/smartd.8.in 2018-12-16 18:24:57.000000000 +0000 +++ smartmontools-7.3/smartd.8.in 2022-02-26 00:15:22.000000000 +0000 @@ -1,10 +1,10 @@ .ig Copyright (C) 2002-10 Bruce Allen -Copyright (C) 2004-18 Christian Franke +Copyright (C) 2004-22 Christian Franke SPDX-License-Identifier: GPL-2.0-or-later -$Id: smartd.8.in 4861 2018-12-16 18:24:57Z chrfranke $ +$Id: smartd.8.in 5333 2022-02-26 00:15:22Z dpgilbert $ .. .\" Macros borrowed from pages generated with Pod::Man @@ -99,9 +99,7 @@ .\" %ENDIF OS Windows .\" %IF ENABLE_SYSTEMD_NOTIFY .PP -[Linux only] -[NEW EXPERMIMENTAL SMARTD FEATURE] -If \fBsmartd\fP is started as a \fBsystemd\fP(1) service and +[Linux only] If \fBsmartd\fP is started as a \fBsystemd\fP(1) service and \*(AqType=Notify\*(Aq is specified in the service file, the service manager is notified after successful startup. Other state changes are reported via systemd notify STATUS messages. @@ -119,7 +117,7 @@ .\" %IF OS Linux .IP \fBLINUX:\fP 9 Examine all entries \fB"/dev/hd[a\-t]"\fP for IDE/ATA -devices, and \fB"/dev/sd[a\-z]"\fP, \fB"/dev/sd[a\-c][a\-z]"\fP +devices, and \fB"/dev/sd[a\-z]"\fP, \fB"/dev/sd[a\-z][a\-z]"\fP for ATA/SATA or SCSI/SAS devices. Disks behind RAID controllers are not included. .Sp @@ -194,8 +192,11 @@ .\" %IF ENABLE_ATTRIBUTELOG If this option is not specified, attribute information is written to files \*(Aq/usr/local/var/lib/smartmontools/attrlog.MODEL\-SERIAL.ata.csv\*(Aq. -To disable attribute log files, specify this option with an empty string -argument: \*(Aq\-A ""\*(Aq. +.br +[NEW EXPERIMENTAL SMARTD FEATURE] +If \*(Aq\-\*(Aq is specified as the argument, attribute log files are +disabled. +.Sp .\" %ENDIF ENABLE_ATTRIBUTELOG MODEL and SERIAL are build from drive identify information, invalid characters are replaced by underline. @@ -232,11 +233,25 @@ to perform quick and simple checks without a configuration file. .\" %IF ENABLE_CAPABILITIES .TP -.B \-C, \-\-capabilities +.B \-C, \-\-capabilities[=mail] [Linux only] Use libcap-ng to drop unneeded Linux process \fBcapabilities\fP(7). -The following capabilities are kept: CAP_SYS_ADMIN, CAP_SYS_RAWIO, CAP_MKNOD. -.Sp -Warning: Mail notification does not work when used. +The following capabilities are kept in the effective and permissive sets: +CAP_SYS_ADMIN, CAP_SYS_RAWIO, CAP_MKNOD. +If the \*(Aq\-u, \-\-warn_as_user\*(Aq option (see below) is used with a +non-privileged user or group, the following capabilities are also kept: +CAP_SETGID, CAP_SETUID. +The capability bounding set is cleared. +.Sp +[NEW EXPERIMENTAL SMARTD FEATURE] +Mail notification is no longer suppressed if capabilities are dropped. +It depends on the local MTA whether mail could be send from a root process +with all capabilities dropped. +It works with the \fBpostfix\fP MTA. +.Sp +If \*(Aq\-\-capabilities=mail\*(Aq is specified, the following +capabilities are added to the bounding set: +CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE. +This allows one to send mail with the \fBexim\fP MTA. .\" %ENDIF ENABLE_CAPABILITIES .TP .B \-d, \-\-debug @@ -270,6 +285,10 @@ \fIN\fP is a decimal integer. The minimum allowed value is ten and the maximum is the largest positive integer that can be represented on your system (often 2^31\-1). The default is 1800 seconds. +.br +[NEW EXPERIMENTAL SMARTD FEATURE] +The interval could be overridden with the \*(Aq\-c i=N\*(Aq directive, +see \fBsmartd.conf\fP(5) man page. .Sp Note that the superuser can make \fBsmartd\fP check the status of the disks at any time by sending it the \fBSIGUSR1\fP signal, for example @@ -350,7 +369,8 @@ .Sp .I nodev \- Exit if there are no devices to monitor, or if any errors are found -at startup in the configuration file. This is the default. +at startup in the configuration file. +This is the default. .Sp .I errors \- Exit if there are no devices to monitor, or if any errors are found @@ -364,10 +384,25 @@ .Sp .I never \- Only exit if a fatal error occurs (no remaining system memory, -invalid command line arguments). In this mode, even if there are no -devices to monitor, or if the configuration file -\fB/usr/local/etc/smartd.conf\fP has errors, \fBsmartd\fP will continue to run, -waiting to load a configuration file listing valid devices. +invalid command line arguments). +In this mode, even if there are no devices to monitor, or if the configuration +file \fB/usr/local/etc/smartd.conf\fP has errors, \fBsmartd\fP will continue +to run, waiting to load a configuration file listing valid devices. +.Sp +.I nodev0 +\- [NEW EXPERIMENTAL SMARTD FEATURE] +Same as \*(Aqnodev\*(Aq, except that the exit status is 0 if there are no +devices to monitor. +.Sp +.I nodev0startup +\- [NEW EXPERIMENTAL SMARTD FEATURE] +Same as \*(Aqnodevstartup\*(Aq, except that the exit status is 0 if there are no +devices to monitor. +.Sp +.I errors,nodev0 +\- [NEW EXPERIMENTAL SMARTD FEATURE] +Same as \*(Aqerrors\*(Aq, except that the exit status is 0 if there are no +devices to monitor. .Sp .I onecheck \- Start \fBsmartd\fP in debug mode, then register devices, then check @@ -447,8 +482,10 @@ for ATA devices and \*(Aq/usr/local/var/lib/smartmontools/smartd.VENDOR\-MODEL\-SERIAL.scsi.state\*(Aq for SCSI devices. -To disable state files, specify this option with an empty string -argument: \*(Aq\-s ""\*(Aq. +.br +[NEW EXPERIMENTAL SMARTD FEATURE] +If \*(Aq\-\*(Aq is specified as the argument, state files are disabled. +.Sp .\" %ENDIF ENABLE_SAVESTATES MODEL and SERIAL are build from drive identify information, invalid characters are replaced by underline. @@ -482,8 +519,47 @@ .\" %IF OS Windows .\"! \fBEXEDIR/smartd_warning.cmd\fP. .\" %ENDIF OS Windows +.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Solaris Cygwin +.TP +.B \-u USER[:GROUP], \-\-warn\-as\-user=USER[:GROUP] +[NEW EXPERIMENTAL SMARTD FEATURE] +Run the warning script as a non-privileged user instead of root. +The USER and optional GROUP may be specified as numeric ids or names. +If no GROUP is specified, the default group of USER is used instead. +.Sp +If a warning occurs, a child process is created with \fBfork\fP(2). +This process closes all inherited file descriptors, connects stdio to +/dev/null, changes the user and group ids, removes any supplementary +group ids and then calls the \fBpopen\fP(3) function from the standard +library. +.Sp +If \*(Aq0:0\*(Aq is specified, user and group are not changed, but the +remaining actions still apply. +.Sp +If \*(Aq-\*(Aq is specified, \fBpopen\fP(3) is called directly. +This is the default. +.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Solaris Cygwin .\" %IF OS Windows .TP +.B \-u MODE, \-\-warn\-as\-user=MODE +[Windows only] +[NEW EXPERIMENTAL SMARTD FEATURE] +Run the warning script with a modified access token. +The valid arguments to this option are: +.Sp +.I restricted +\- Run the warning script with a restricted access token. +The local \*(AqAdministrator\*(Aq group and most privileges +(all except \*(AqSeChangeNotifyPrivilege\*(Aq) are removed. +This is not effective if the current user is the local \*(AqSYSTEM\*(Aq +or \*(AqAdministrator\*(Aq account. +If this is the case, \fBsmartd\fP logs an error message during startup +and exits. +.Sp +.I unchanged +\- Run the warning script without changing the access token. +This is the default. +.TP .B \-\-service [Windows only] Enables \fBsmartd\fP to run as a Windows service. The option must be specified in the service command line as the first @@ -645,6 +721,11 @@ This also installs smartd.exe as a event message file for the Windows event viewer. .PP +This does not work if the option \*(Aq--warn-as-user=restricted\*(Aq is +specified because the local \*(AqSYSTEM\*(Aq account cannot be restricted. +The service must then be manually reconfigured to run as a another user +which is a member of the local \*(AqAdministrator\*(Aq group. +.PP \*(Aq\fBsmartd remove\fP\*(Aq can later be used to remove the service and event message entries from the registry. .PP @@ -731,6 +812,10 @@ .B 17: \fBsmartd\fP didn't find any devices to monitor. +.br +[NEW EXPERIMENTAL SMARTD FEATURE] +This could be changed to \fB0\fP (success) with one of the +\*(Aq-q *nodev0*\*(Aq options, see above. .TP .B 254: When in daemon mode, @@ -767,7 +852,7 @@ .\" %ENDIF ENABLE_SMARTDPLUGINDIR .\" %IF ENABLE_DRIVEDB .TP -.B /usr/local/share/smartmontools/drivedb.h +.B /usr/local/var/lib/smartmontools/drivedb.h drive database (see \*(Aq\-B\*(Aq option). .\" %ENDIF ENABLE_DRIVEDB .TP @@ -839,4 +924,4 @@ .SH PACKAGE VERSION CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV .br -$Id: smartd.8.in 4861 2018-12-16 18:24:57Z chrfranke $ +$Id: smartd.8.in 5333 2022-02-26 00:15:22Z dpgilbert $ diff -Nru smartmontools-7.1/smartd.conf.5.in smartmontools-7.3/smartd.conf.5.in --- smartmontools-7.1/smartd.conf.5.in 2019-12-13 20:20:45.000000000 +0000 +++ smartmontools-7.3/smartd.conf.5.in 2022-02-26 00:15:22.000000000 +0000 @@ -1,10 +1,10 @@ .ig Copyright (C) 2002-10 Bruce Allen -Copyright (C) 2004-19 Christian Franke +Copyright (C) 2004-21 Christian Franke SPDX-License-Identifier: GPL-2.0-or-later -$Id: smartd.conf.5.in 5004 2019-12-13 20:20:45Z chrfranke $ +$Id: smartd.conf.5.in 5333 2022-02-26 00:15:22Z dpgilbert $ .. .\" Macros borrowed from pages generated with Pod::Man @@ -116,15 +116,27 @@ # may become common with SATA disks in SAS and FC # environments. /dev/sda \-a \-d sat -.\" %IF OS Linux +.\" %IF OS FreeBSD Linux # -# Three disks connected to a MegaRAID controller +# Disks connected to a MegaRAID controller # Start short self\-tests daily between 1\-2, 2\-3, and # 3\-4 am. +.\" %ENDIF OS FreeBSD Linux +.\" %IF OS Linux +# Linux: /dev/sda \-d megaraid,0 \-a \-s S/../.././01 /dev/sda \-d megaraid,1 \-a \-s S/../.././02 /dev/sda \-d megaraid,2 \-a \-s S/../.././03 /dev/bus/0 \-d megaraid,2 \-a \-s S/../.././03 +.\" %ENDIF OS Linux +.\" %IF OS FreeBSD +# FreeBSD: +/dev/mfi0 \-d megaraid,0 \-a \-s S/../.././01 +/dev/mfi0 \-d megaraid,1 \-a \-s S/../.././02 +/dev/mfi0 \-d megaraid,2 \-a \-s S/../.././03 +/dev/mrsas0 \-d megaraid,2 \-a \-s S/../.././03 +.\" %ENDIF OS FreeBSD +.\" %IF OS Linux # # Three disks connected to an AacRaid controller # Start short self\-tests daily between 1\-2, 2\-3, and @@ -279,6 +291,12 @@ .PP A device is ignored by DEVICESCAN if a configuration line with the same device name exists. +.\" %IF NOT OS Windows OS2 +.br +[NEW EXPERIMENTAL SMARTD FEATURE] +Symbolic links are resolved before this check is done. +.PP +.\" %ENDIF NOT OS Windows OS2 A device name is also ignored if another device with same identify information (vendor, model, firmware version, serial number, WWN) already exists. @@ -439,32 +457,42 @@ \- this device type is for SATA disks that are behind a SunplusIT USB to SATA bridge. .Sp -.I sntjmicron[,NSID] +.I sntasmedia \- [NEW EXPERIMENTAL SMARTD FEATURE] -this device type is for NVMe disks that are behind a JMicron USB to NVMe +this device type is for NVMe disks that are behind an ASMedia USB to NVMe +bridge. +.Sp +.I sntjmicron[,NSID] +\- this device type is for NVMe disks that are behind a JMicron USB to NVMe bridge. The optional parameter NSID specifies the namespace id (in hex) passed to the driver. The default namespace id is the broadcast namespace id (0xffffffff). .Sp +.I sntrealtek +\- [NEW EXPERIMENTAL SMARTD FEATURE] +this device type is for NVMe disks that are behind a Realtek USB to NVMe +bridge. +.Sp .\" %ENDIF NOT OS Darwin .\" %IF OS Linux .I marvell \- [Linux only] interact with SATA disks behind Marvell chip-set controllers (using the Marvell rather than libata driver). .Sp +.\" %ENDIF OS FreeBSD Linux +.\" %IF OS FreeBSD Linux .I megaraid,N -\- [Linux only] the device consists of one or more SCSI/SAS disks connected +\- [Linux and FreeBSD only] the device consists of one or more SCSI/SAS disks connected to a MegaRAID controller. The non-negative integer N (in the range of 0 to 127 inclusive) denotes which disk on the controller is monitored. This interface will also work for Dell PERC controllers. In log files and email messages this disk will be identified as megaraid_disk_XXX with XXX in the range from 000 to 127 inclusive. -It is possible to set RAID device name as /dev/bus/N, where N is a SCSI bus -number. + Please see the \fBsmartctl\fP(8) man page for further details. .Sp -.\" %ENDIF OS Linux +.\" %ENDIF OS FreeBSD Linux .\" %IF OS Linux Windows Cygwin .I aacraid,H,L,ID \- [Linux, Windows and Cygwin only] the device consists of one or more @@ -540,16 +568,24 @@ The integer N is the port number from 0 to 3 of the ATA drive to be targeted. Please see the \fBsmartctl\fP(8) man page for further details. .Sp -.I jmb39x,N[,sLBA][,force][+TYPE] +.I jmb39x[\-q],N[,sLBA][,force][+TYPE] \- [NEW EXPERIMENTAL SMARTD FEATURE] the device consists of multiple SATA disks connected to a JMicron JMB39x RAID port multiplier. +The suffix \*(Aq\-q\*(Aq selects a slightly different command variant used by +some QNAP NAS devices. The integer N is the port number from 0 to 4. Please see the \fBsmartctl\fP(8) man page for further details. .Sp +.I jms56x,N[,sLBA][,force][+TYPE] +\- [NEW EXPERIMENTAL SMARTD FEATURE] +the device consists of multiple SATA disks connected to a JMicron JMS56x +USB to SATA RAID bridge. +See \*(Aqjmb39x...\*(Aq above for valid arguments. +.Sp .I ignore \- the device specified by this configuration entry should be ignored. -This allows to ignore specific devices which are detected by a following +This allows one to ignore specific devices which are detected by a following DEVICESCAN configuration line. It may also be used to temporary disable longer multi-line configuration entries. This Directive may be used in conjunction with the other \*(Aq\-d\*(Aq @@ -848,6 +884,25 @@ .\" This resets the margin to the level prior to the '.RS ... .RE' block. .TP .B \& +[NEW EXPERIMENTAL SMARTD FEATURE] +If the regular expression contains substrings of the form \fB:NNN\fP +or \fB:NNN-LLL\fP, where NNN and LLL are three decimal digits, staggered +tests are enabled. +Then a test will also be run if all 16 (or 20) characters of the string +\fBT/MM/DD/d/HH:NNN\fP (or \fBT/MM/DD/d/HH:NNN-LLL\fP) match the regular +expression. +This check is done for up to seven \fB:NNN\fP or \fB:NNN-LLL\fP found in +the regular expression. +The time used for the check is adjusted to the past such that tests of +the first drive are not delayed, tests of the second drive are delayed +by NNN hours, tests of the third drive are delayed by 2*NNN hours, and +so on. +.br +If LLL is also specified, delays are limited to LLL hours by calculating +each individual delay as: +.br +\*(Aq((DRIVE_INDEX * NNN) mod (LLL + 1))\*(Aq. +.Sp Some examples follow. In reading these, keep in mind that in extended regular expressions a dot \fB\*(Aq.\*(Aq\fP matches any single character, and a parenthetical expression such as \fB\*(Aq(A|B|C)\*(Aq\fP denotes any one @@ -861,6 +916,20 @@ .br \fB \-s L/../../7/04\fP .br +To enable staggered tests with delays in three hour steps, use: +.br +\fB \-s L/../../7/04:003\fP +.br +To enable staggered tests with delays 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, +0, ... hours, use: +.br +\fB \-s L/../../7/04:003-010\fP +.br +To enable staggered tests with delays 0, 1, 2, ..., 9, 10, 0, ... hours, +use: +.br +\fB \-s L/../../7/04:001-010\fP +.br To schedule a long Self-Test between 10\(en11 pm on the first and fifteenth day of each month, use: .br @@ -872,6 +941,11 @@ .br \fB \-s (O/../.././(00|06|12|18)|S/../.././01|L/../../6/03)\fP .br +To enable staggered Long Self-Tests with delays in three hour steps, +use: +.br +\fB \-s (O/../.././(00|06|12|18)|S/../.././01|L/../../6/03:003)\fP +.br If Long Self-Tests of a large disks take longer than the system uptime, a full disk test can be performed by several Selective Self-Tests. To setup a full test of a 1 TB disk within 20 days (one 50 GB span @@ -997,6 +1071,9 @@ are run instead. This is handled by the script /usr/local/etc/smartd_warning.sh (see also \*(Aq\-M exec\*(Aq below). +Plugin scripts without execute permission are silently ignored. +If any plugin script is missing or fails a with nonzero exit status, the warning +script exits immediately without sending mail. .\" %ENDIF NOT OS Windows .\" %ENDIF ENABLE_SMARTDPLUGINDIR .\" %IF OS Windows @@ -1151,6 +1228,15 @@ given, then this string will contain space characters and is NOT quoted, so to use it in a shell script you may want to enclose it in double quotes. +.\" %IF ENABLE_SMARTDPLUGINDIR +.\" %IF NOT OS Windows +.IP \fBSMARTD_ADDRESS_ORIG\fP 4 +is set to the original value of \fBSMARTD_ADDRESS\fP with \*(Aq@plugin\*(Aq +strings still present. +If there are no such strings in the \*(Aq\-m\*(Aq Directive, this variable is +NOT set. +.\" %ENDIF NOT OS Windows +.\" %ENDIF ENABLE_SMARTDPLUGINDIR .\" %IF OS Windows .IP \fBSMARTD_ADDRCSV\fP 4 [Windows only] is set to a comma-separated list of the addresses from @@ -1573,6 +1659,18 @@ Note that \-a is the default for ATA devices. If none of these other Directives is given, then \-a is assumed. .TP +.B \-c OPTION=VALUE +Allows one to override \fBsmartd\fP command line options for specific devices. +Only the following OPTION is currently supported: +.TP +.B \-c i=N, \-c interval=N +[NEW EXPERIMENTAL SMARTD FEATURE] +Sets the interval between disk checks to N seconds, where N is a decimal +integer. +The minimum allowed value is ten. +The default is the value from the \*(Aq\-i N, \-\-interval=N\*(Aq command +line option or its default of 1800 seconds. +.TP .B # Comment: ignore the remainder of the line. .TP @@ -1668,4 +1766,4 @@ .SH PACKAGE VERSION CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV .br -$Id: smartd.conf.5.in 5004 2019-12-13 20:20:45Z chrfranke $ +$Id: smartd.conf.5.in 5333 2022-02-26 00:15:22Z dpgilbert $ diff -Nru smartmontools-7.1/smartd.cpp smartmontools-7.3/smartd.cpp --- smartmontools-7.1/smartd.cpp 2019-12-29 13:10:18.000000000 +0000 +++ smartmontools-7.3/smartd.cpp 2022-02-22 18:00:47.000000000 +0000 @@ -2,7 +2,7 @@ * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-22 Christian Franke * Copyright (C) 2000 Michael Cornwell * Copyright (C) 2008 Oliver Bock * @@ -28,10 +28,11 @@ #include #include +#include // std::replace() +#include #include #include #include -#include // std::replace() // conditionally included files #ifndef _WIN32 @@ -42,7 +43,7 @@ #endif #ifdef _WIN32 -#include "os_win32/popen.h" // popen/pclose() +#include "os_win32/popen.h" // popen_as_rstr_user(), pclose() #ifdef _MSC_VER #pragma warning(disable:4761) // "conversion supplied" typedef unsigned short mode_t; @@ -72,6 +73,10 @@ #include "nvmecmds.h" #include "utility.h" +#ifdef HAVE_POSIX_API +#include "popen_as_ugid.h" +#endif + #ifdef _WIN32 // fork()/signal()/initd simulation for native Windows #include "os_win32/daemon_win32.h" // daemon_main/detach/signal() @@ -84,7 +89,7 @@ #define SIGQUIT_KEYNAME "CONTROL-\\" #endif // _WIN32 -const char * smartd_cpp_cvsid = "$Id: smartd.cpp 5012 2019-12-29 13:10:18Z chrfranke $" +const char * smartd_cpp_cvsid = "$Id: smartd.cpp 5324 2022-02-22 18:00:47Z chrfranke $" CONFIG_H_CVSID; extern "C" { @@ -147,8 +152,9 @@ static unsigned char debugmode = 0; // command-line: how long to sleep between checks -#define CHECKTIME 1800 -static int checktime=CHECKTIME; +static constexpr int default_checktime = 1800; +static int checktime = default_checktime; +static int checktime_min = 0; // Minimum individual check time, 0 if none // command-line: name of PID file (empty for no pid file) static std::string pid_file; @@ -177,12 +183,24 @@ // warning script file static std::string warning_script; +#ifdef HAVE_POSIX_API +// run warning script as non-privileged user +static bool warn_as_user; +static uid_t warn_uid; +static gid_t warn_gid; +static std::string warn_uname, warn_gname; +#elif defined(_WIN32) +// run warning script as restricted user +static bool warn_as_restr_user; +#endif + // command-line: when should we exit? enum quit_t { QUIT_NODEV, QUIT_NODEVSTARTUP, QUIT_NEVER, QUIT_ONECHECK, QUIT_SHOWTESTS, QUIT_ERRORS }; static quit_t quit = QUIT_NODEV; +static bool quit_nodev0 = false; // command-line; this is the default syslog(3) log facility to use. static int facility=LOG_DAEMON; @@ -326,9 +344,6 @@ class attribute_flags { public: - attribute_flags() - { memset(m_flags, 0, sizeof(m_flags)); } - bool is_set(int id, unsigned char flag) const { return (0 < id && id < (int)sizeof(m_flags) && (m_flags[id] & flag)); } @@ -339,7 +354,7 @@ } private: - unsigned char m_flags[256]; + unsigned char m_flags[256]{}; }; @@ -347,113 +362,72 @@ /// Supports copy & assignment and is compatible with STL containers. struct dev_config { - int lineno; // Line number of entry in file + int lineno{}; // Line number of entry in file std::string name; // Device name (with optional extra info) std::string dev_name; // Device name (plain, for SMARTD_DEVICE variable) std::string dev_type; // Device type argument from -d directive, empty if none std::string dev_idinfo; // Device identify info for warning emails std::string state_file; // Path of the persistent state file, empty if none std::string attrlog_file; // Path of the persistent attrlog file, empty if none - bool ignore; // Ignore this entry - bool id_is_unique; // True if dev_idinfo is unique (includes S/N or WWN) - bool smartcheck; // Check SMART status - bool usagefailed; // Check for failed Usage Attributes - bool prefail; // Track changes in Prefail Attributes - bool usage; // Track changes in Usage Attributes - bool selftest; // Monitor number of selftest errors - bool errorlog; // Monitor number of ATA errors - bool xerrorlog; // Monitor number of ATA errors (Extended Comprehensive error log) - bool offlinests; // Monitor changes in offline data collection status - bool offlinests_ns; // Disable auto standby if in progress - bool selfteststs; // Monitor changes in self-test execution status - bool selfteststs_ns; // Disable auto standby if in progress - bool permissive; // Ignore failed SMART commands - char autosave; // 1=disable, 2=enable Autosave Attributes - char autoofflinetest; // 1=disable, 2=enable Auto Offline Test + int checktime{}; // Individual check interval, 0 if none + bool ignore{}; // Ignore this entry + bool id_is_unique{}; // True if dev_idinfo is unique (includes S/N or WWN) + bool smartcheck{}; // Check SMART status + bool usagefailed{}; // Check for failed Usage Attributes + bool prefail{}; // Track changes in Prefail Attributes + bool usage{}; // Track changes in Usage Attributes + bool selftest{}; // Monitor number of selftest errors + bool errorlog{}; // Monitor number of ATA errors + bool xerrorlog{}; // Monitor number of ATA errors (Extended Comprehensive error log) + bool offlinests{}; // Monitor changes in offline data collection status + bool offlinests_ns{}; // Disable auto standby if in progress + bool selfteststs{}; // Monitor changes in self-test execution status + bool selfteststs_ns{}; // Disable auto standby if in progress + bool permissive{}; // Ignore failed SMART commands + char autosave{}; // 1=disable, 2=enable Autosave Attributes + char autoofflinetest{}; // 1=disable, 2=enable Auto Offline Test firmwarebug_defs firmwarebugs; // -F directives from drivedb or smartd.conf - bool ignorepresets; // Ignore database of -v options - bool showpresets; // Show database entry for this device - bool removable; // Device may disappear (not be present) - char powermode; // skip check, if disk in idle or standby mode - bool powerquiet; // skip powermode 'skipping checks' message - int powerskipmax; // how many times can be check skipped - unsigned char tempdiff; // Track Temperature changes >= this limit - unsigned char tempinfo, tempcrit; // Track Temperatures >= these limits as LOG_INFO, LOG_CRIT+mail + bool ignorepresets{}; // Ignore database of -v options + bool showpresets{}; // Show database entry for this device + bool removable{}; // Device may disappear (not be present) + char powermode{}; // skip check, if disk in idle or standby mode + bool powerquiet{}; // skip powermode 'skipping checks' message + int powerskipmax{}; // how many times can be check skipped + unsigned char tempdiff{}; // Track Temperature changes >= this limit + unsigned char tempinfo{}, tempcrit{}; // Track Temperatures >= these limits as LOG_INFO, LOG_CRIT+mail regular_expression test_regex; // Regex for scheduled testing + unsigned test_offset_factor{}; // Factor for staggering of scheduled tests // Configuration of email warning messages std::string emailcmdline; // script to execute, empty if no messages std::string emailaddress; // email address, or empty - unsigned char emailfreq; // Emails once (1) daily (2) diminishing (3) - bool emailtest; // Send test email? + unsigned char emailfreq{}; // Emails once (1) daily (2) diminishing (3) + bool emailtest{}; // Send test email? // ATA ONLY - int dev_rpm; // rotation rate, 0 = unknown, 1 = SSD, >1 = HDD - int set_aam; // disable(-1), enable(1..255->0..254) Automatic Acoustic Management - int set_apm; // disable(-1), enable(2..255->1..254) Advanced Power Management - int set_lookahead; // disable(-1), enable(1) read look-ahead - int set_standby; // set(1..255->0..254) standby timer - bool set_security_freeze; // Freeze ATA security - int set_wcache; // disable(-1), enable(1) write cache - int set_dsn; // disable(0x2), enable(0x1) DSN - - bool sct_erc_set; // set SCT ERC to: - unsigned short sct_erc_readtime; // ERC read time (deciseconds) - unsigned short sct_erc_writetime; // ERC write time (deciseconds) - - unsigned char curr_pending_id; // ID of current pending sector count, 0 if none - unsigned char offl_pending_id; // ID of offline uncorrectable sector count, 0 if none - bool curr_pending_incr, offl_pending_incr; // True if current/offline pending values increase - bool curr_pending_set, offl_pending_set; // True if '-C', '-U' set in smartd.conf + int dev_rpm{}; // rotation rate, 0 = unknown, 1 = SSD, >1 = HDD + int set_aam{}; // disable(-1), enable(1..255->0..254) Automatic Acoustic Management + int set_apm{}; // disable(-1), enable(2..255->1..254) Advanced Power Management + int set_lookahead{}; // disable(-1), enable(1) read look-ahead + int set_standby{}; // set(1..255->0..254) standby timer + bool set_security_freeze{}; // Freeze ATA security + int set_wcache{}; // disable(-1), enable(1) write cache + int set_dsn{}; // disable(0x2), enable(0x1) DSN + + bool sct_erc_set{}; // set SCT ERC to: + unsigned short sct_erc_readtime{}; // ERC read time (deciseconds) + unsigned short sct_erc_writetime{}; // ERC write time (deciseconds) + + unsigned char curr_pending_id{}; // ID of current pending sector count, 0 if none + unsigned char offl_pending_id{}; // ID of offline uncorrectable sector count, 0 if none + bool curr_pending_incr{}, offl_pending_incr{}; // True if current/offline pending values increase + bool curr_pending_set{}, offl_pending_set{}; // True if '-C', '-U' set in smartd.conf attribute_flags monitor_attr_flags; // MONITOR_* flags for each attribute ata_vendor_attr_defs attribute_defs; // -v options - - dev_config(); }; -dev_config::dev_config() -: lineno(0), - ignore(false), - id_is_unique(false), - smartcheck(false), - usagefailed(false), - prefail(false), - usage(false), - selftest(false), - errorlog(false), - xerrorlog(false), - offlinests(false), offlinests_ns(false), - selfteststs(false), selfteststs_ns(false), - permissive(false), - autosave(0), - autoofflinetest(0), - ignorepresets(false), - showpresets(false), - removable(false), - powermode(0), - powerquiet(false), - powerskipmax(0), - tempdiff(0), - tempinfo(0), tempcrit(0), - emailfreq(0), - emailtest(false), - dev_rpm(0), - set_aam(0), set_apm(0), - set_lookahead(0), - set_standby(0), - set_security_freeze(false), - set_wcache(0), set_dsn(0), - sct_erc_set(false), - sct_erc_readtime(0), sct_erc_writetime(0), - curr_pending_id(0), offl_pending_id(0), - curr_pending_incr(false), offl_pending_incr(false), - curr_pending_set(false), offl_pending_set(false) -{ -} - - // Number of allowed mail message types static const int SMARTD_NMAIL = 13; // Type for '-M test' mails (state not persistent) @@ -461,149 +435,102 @@ // TODO: Add const or enum for all mail types. struct mailinfo { - int logged;// number of times an email has been sent - time_t firstsent;// time first email was sent, as defined by time(2) - time_t lastsent; // time last email was sent, as defined by time(2) - - mailinfo() - : logged(0), firstsent(0), lastsent(0) { } + int logged{}; // number of times an email has been sent + time_t firstsent{}; // time first email was sent, as defined by time(2) + time_t lastsent{}; // time last email was sent, as defined by time(2) }; /// Persistent state data for a device. struct persistent_dev_state { - unsigned char tempmin, tempmax; // Min/Max Temperatures + unsigned char tempmin{}, tempmax{}; // Min/Max Temperatures - unsigned char selflogcount; // total number of self-test errors - unsigned short selfloghour; // lifetime hours of last self-test error + unsigned char selflogcount{}; // total number of self-test errors + unsigned short selfloghour{}; // lifetime hours of last self-test error - time_t scheduled_test_next_check; // Time of next check for scheduled self-tests + time_t scheduled_test_next_check{}; // Time of next check for scheduled self-tests - uint64_t selective_test_last_start; // Start LBA of last scheduled selective self-test - uint64_t selective_test_last_end; // End LBA of last scheduled selective self-test + uint64_t selective_test_last_start{}; // Start LBA of last scheduled selective self-test + uint64_t selective_test_last_end{}; // End LBA of last scheduled selective self-test mailinfo maillog[SMARTD_NMAIL]; // log info on when mail sent // ATA ONLY - int ataerrorcount; // Total number of ATA errors + int ataerrorcount{}; // Total number of ATA errors // Persistent part of ata_smart_values: struct ata_attribute { - unsigned char id; - unsigned char val; - unsigned char worst; // Byte needed for 'raw64' attribute only. - uint64_t raw; - unsigned char resvd; - - ata_attribute() : id(0), val(0), worst(0), raw(0), resvd(0) { } + unsigned char id{}; + unsigned char val{}; + unsigned char worst{}; // Byte needed for 'raw64' attribute only. + uint64_t raw{}; + unsigned char resvd{}; }; ata_attribute ata_attributes[NUMBER_ATA_SMART_ATTRIBUTES]; // SCSI ONLY struct scsi_error_counter_t { - struct scsiErrorCounter errCounter; - unsigned char found; - scsi_error_counter_t() : found(0) - { memset(&errCounter, 0, sizeof(errCounter)); } + struct scsiErrorCounter errCounter{}; + unsigned char found{}; }; scsi_error_counter_t scsi_error_counters[3]; struct scsi_nonmedium_error_t { - struct scsiNonMediumError nme; - unsigned char found; - scsi_nonmedium_error_t() : found(0) - { memset(&nme, 0, sizeof(nme)); } + struct scsiNonMediumError nme{}; + unsigned char found{}; }; scsi_nonmedium_error_t scsi_nonmedium_error; // NVMe only - uint64_t nvme_err_log_entries; - - persistent_dev_state(); + uint64_t nvme_err_log_entries{}; }; -persistent_dev_state::persistent_dev_state() -: tempmin(0), tempmax(0), - selflogcount(0), - selfloghour(0), - scheduled_test_next_check(0), - selective_test_last_start(0), - selective_test_last_end(0), - ataerrorcount(0), - nvme_err_log_entries(0) -{ -} - /// Non-persistent state data for a device. struct temp_dev_state { - bool must_write; // true if persistent part should be written + bool must_write{}; // true if persistent part should be written + + bool skip{}; // skip during next check cycle + time_t wakeuptime{}; // next wakeup time, 0 if unknown or global + + bool not_cap_offline{}; // true == not capable of offline testing + bool not_cap_conveyance{}; + bool not_cap_short{}; + bool not_cap_long{}; + bool not_cap_selective{}; + + unsigned char temperature{}; // last recorded Temperature (in Celsius) + time_t tempmin_delay{}; // time where Min Temperature tracking will start - bool not_cap_offline; // true == not capable of offline testing - bool not_cap_conveyance; - bool not_cap_short; - bool not_cap_long; - bool not_cap_selective; - - unsigned char temperature; // last recorded Temperature (in Celsius) - time_t tempmin_delay; // time where Min Temperature tracking will start - - bool removed; // true if open() failed for removable device - - bool powermodefail; // true if power mode check failed - int powerskipcnt; // Number of checks skipped due to idle or standby mode - int lastpowermodeskipped; // the last power mode that was skipped + bool removed{}; // true if open() failed for removable device + + bool powermodefail{}; // true if power mode check failed + int powerskipcnt{}; // Number of checks skipped due to idle or standby mode + int lastpowermodeskipped{}; // the last power mode that was skipped + + bool attrlog_dirty{}; // true if persistent part has new attr values that + // need to be written to attrlog // SCSI ONLY - unsigned char SmartPageSupported; // has log sense IE page (0x2f) - unsigned char TempPageSupported; // has log sense temperature page (0xd) - unsigned char ReadECounterPageSupported; - unsigned char WriteECounterPageSupported; - unsigned char VerifyECounterPageSupported; - unsigned char NonMediumErrorPageSupported; - unsigned char SuppressReport; // minimize nuisance reports - unsigned char modese_len; // mode sense/select cmd len: 0 (don't + // TODO: change to bool + unsigned char SmartPageSupported{}; // has log sense IE page (0x2f) + unsigned char TempPageSupported{}; // has log sense temperature page (0xd) + unsigned char ReadECounterPageSupported{}; + unsigned char WriteECounterPageSupported{}; + unsigned char VerifyECounterPageSupported{}; + unsigned char NonMediumErrorPageSupported{}; + unsigned char SuppressReport{}; // minimize nuisance reports + unsigned char modese_len{}; // mode sense/select cmd len: 0 (don't // know yet) 6 or 10 // ATA ONLY - uint64_t num_sectors; // Number of sectors - ata_smart_values smartval; // SMART data - ata_smart_thresholds_pvt smartthres; // SMART thresholds - bool offline_started; // true if offline data collection was started - bool selftest_started; // true if self-test was started - - temp_dev_state(); + uint64_t num_sectors{}; // Number of sectors + ata_smart_values smartval{}; // SMART data + ata_smart_thresholds_pvt smartthres{}; // SMART thresholds + bool offline_started{}; // true if offline data collection was started + bool selftest_started{}; // true if self-test was started }; -temp_dev_state::temp_dev_state() -: must_write(false), - not_cap_offline(false), - not_cap_conveyance(false), - not_cap_short(false), - not_cap_long(false), - not_cap_selective(false), - temperature(0), - tempmin_delay(0), - removed(false), - powermodefail(false), - powerskipcnt(0), - lastpowermodeskipped(0), - SmartPageSupported(false), - TempPageSupported(false), - ReadECounterPageSupported(false), - WriteECounterPageSupported(false), - VerifyECounterPageSupported(false), - NonMediumErrorPageSupported(false), - SuppressReport(false), - modese_len(0), - num_sectors(0), - offline_started(false), - selftest_started(false) -{ - memset(&smartval, 0, sizeof(smartval)); - memset(&smartthres, 0, sizeof(smartthres)); -} - /// Runtime state data for a device. struct dev_state : public persistent_dev_state, @@ -837,8 +764,7 @@ write_dev_state_line(f, "selective-test-last-start", state.selective_test_last_start); write_dev_state_line(f, "selective-test-last-end", state.selective_test_last_end); - int i; - for (i = 0; i < SMARTD_NMAIL; i++) { + for (int i = 0; i < SMARTD_NMAIL; i++) { if (i == MAILTYPE_TEST) // Don't suppress test mails continue; const mailinfo & mi = state.maillog[i]; @@ -852,8 +778,8 @@ // ATA ONLY write_dev_state_line(f, "ata-error-count", state.ataerrorcount); - for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { - const persistent_dev_state::ata_attribute & pa = state.ata_attributes[i]; + for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { + const auto & pa = state.ata_attributes[i]; if (!pa.id) continue; write_dev_state_line(f, "ata-smart-attribute", i, "id", pa.id); @@ -879,14 +805,13 @@ } - time_t now = time(0); + time_t now = time(nullptr); struct tm tmbuf, * tms = time_to_tm_local(&tmbuf, now); fprintf(f, "%d-%02d-%02d %02d:%02d:%02d;", 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec); // ATA ONLY - for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { - const persistent_dev_state::ata_attribute & pa = state.ata_attributes[i]; + for (const auto & pa : state.ata_attributes) { if (!pa.id) continue; fprintf(f, "\t%d;%d;%" PRIu64 ";", pa.id, pa.val, pa.raw); @@ -954,7 +879,10 @@ if (cfg.attrlog_file.empty()) continue; dev_state & state = states[i]; - write_dev_attrlog(cfg.attrlog_file.c_str(), state); + if (state.attrlog_dirty) { + write_dev_attrlog(cfg.attrlog_file.c_str(), state); + state.attrlog_dirty = false; + } } } @@ -1001,37 +929,42 @@ #ifdef HAVE_LIBCAP_NG // capabilities(7) support -static bool capabilities_enabled = false; +static int capabilities_mode /* = 0 */; // 1=enabled, 2=mail static void capabilities_drop_now() { - if (!capabilities_enabled) + if (!capabilities_mode) return; capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED), CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1); + if (warn_as_user && (warn_uid || warn_gid)) { + // For popen_as_ugid() + capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED), + CAP_SETGID, CAP_SETUID, -1); + } + if (capabilities_mode > 1) { + // For exim MTA + capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, + CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1); + } capng_apply(CAPNG_SELECT_BOTH); } -static void capabilities_check_config(dev_config_vector & configs) +static void capabilities_log_error_hint() { - if (!capabilities_enabled) + if (!capabilities_mode) return; - for (unsigned i = 0; i < configs.size(); i++) { - dev_config & cfg = configs[i]; - if (!cfg.emailaddress.empty() || !cfg.emailcmdline.empty()) { - PrintOut(LOG_INFO, "Device: %s, --capabilites is set, mail will be suppressed.\n", - cfg.name.c_str()); - cfg.emailaddress.clear(); cfg.emailcmdline.clear(); - } - } + PrintOut(LOG_INFO, "If mail notification does not work with '--capabilities%s\n", + (capabilities_mode == 1 ? "', try '--capabilities=mail'" + : "=mail', please inform " PACKAGE_BUGREPORT)); } #else // HAVE_LIBCAP_NG // No capabilities(7) support static inline void capabilities_drop_now() { } -static inline void capabilities_check_config(dev_config_vector &) { } +static inline void capabilities_log_error_hint() { } #endif // HAVE_LIBCAP_NG @@ -1048,16 +981,13 @@ class env_buffer { public: - env_buffer() - : m_buf((char *)0) { } + env_buffer() = default; + env_buffer(const env_buffer &) = delete; + void operator=(const env_buffer &) = delete; void set(const char * name, const char * value); - private: - char * m_buf; - - env_buffer(const env_buffer &); - void operator=(const env_buffer &); + char * m_buf = nullptr; }; void env_buffer::set(const char * name, const char * value) @@ -1129,7 +1059,7 @@ return; // To decide if to send mail, we need to know what time it is. - time_t epoch = time(0); + time_t epoch = time(nullptr); // Return if less than one day has gone by const int day = 24*3600; @@ -1207,19 +1137,45 @@ #endif // tell SYSLOG what we are about to do... - PrintOut(LOG_INFO,"%s %s to %s ...\n", - which?"Sending warning via":"Executing test of", executable, newadd); + PrintOut(LOG_INFO,"%s %s to %s%s ...\n", + (which ? "Sending warning via" : "Executing test of"), executable, newadd, + ( +#ifdef HAVE_POSIX_API + warn_as_user ? + strprintf(" (uid=%u(%s) gid=%u(%s))", + (unsigned)warn_uid, warn_uname.c_str(), + (unsigned)warn_gid, warn_gname.c_str() ).c_str() : +#elif defined(_WIN32) + warn_as_restr_user ? " (restricted user)" : +#endif + "" + ) + ); // issue the command to send mail or to run the user's executable errno=0; FILE * pfp; - if (!(pfp=popen(command, "r"))) + +#ifdef HAVE_POSIX_API + if (warn_as_user) { + pfp = popen_as_ugid(command, "r", warn_uid, warn_gid); + } else +#endif + { +#ifdef _WIN32 + pfp = popen_as_restr_user(command, "r", warn_as_restr_user); +#else + pfp = popen(command, "r"); +#endif + } + + if (!pfp) // failed to popen() mail process PrintOut(LOG_CRIT,"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n", newwarn, executable, newadd, errno?strerror(errno):""); else { // pipe succeeded! - int len, status; + int len; char buffer[EBUFLEN]; // if unexpected output on stdout/stderr, null terminate, print, and flush @@ -1245,7 +1201,18 @@ // if something went wrong with mail process, print warning errno=0; - if (-1==(status=pclose(pfp))) + int status; + +#ifdef HAVE_POSIX_API + if (warn_as_user) { + status = pclose_as_ugid(pfp); + } else +#endif + { + status = pclose(pfp); + } + + if (status == -1) PrintOut(LOG_CRIT,"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd, errno?strerror(errno):""); else { @@ -1256,9 +1223,11 @@ if (status8>128) PrintOut(LOG_CRIT,"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n", newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128)); - else if (status8) + else if (status8) { PrintOut(LOG_CRIT,"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n", newwarn, executable, newadd, status, status8); + capabilities_log_error_hint(); + } else PrintOut(LOG_INFO,"%s %s to %s: successful\n", newwarn, executable, newadd); } @@ -1429,7 +1398,7 @@ // flush all buffered streams. Else we might get two copies of open // streams since both parent and child get copies of the buffers. - fflush(NULL); + fflush(nullptr); if (do_fork) { pid_t pid; @@ -1482,7 +1451,7 @@ // No fork() on native Win32 // Detach this process from console - fflush(NULL); + fflush(nullptr); if (daemon_detach("smartd")) { PrintOut(LOG_CRIT,"smartd unable to detach from console!\n"); return EXIT_STARTUP; @@ -1561,6 +1530,7 @@ " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n" " -F TYPE Use firmware bug workaround:\n" " %s\n" + " -c i=N Set interval between disk checks to N seconds\n" " # Comment: text after a hash sign is ignored\n" " \\ Line continuation character\n" "Attribute ID is a decimal integer 1 <= ID <= 255\n" @@ -1572,13 +1542,13 @@ } /* Returns a pointer to a static string containing a formatted list of the valid - arguments to the option opt or NULL on failure. */ + arguments to the option opt or nullptr on failure. */ static const char *GetValidArgList(char opt) { switch (opt) { case 'A': case 's': - return ""; + return ", -"; case 'B': return "[+]"; case 'c': @@ -1586,7 +1556,7 @@ case 'l': return "daemon, local0, local1, local2, local3, local4, local5, local6, local7"; case 'q': - return "nodev, errors, nodevstartup, never, onecheck, showtests"; + return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests"; case 'r': return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]"; case 'p': @@ -1594,8 +1564,19 @@ return ""; case 'i': return ""; +#ifdef HAVE_POSIX_API + case 'u': + return "[:], -"; +#elif defined(_WIN32) + case 'u': + return "restricted, unchanged"; +#endif +#ifdef HAVE_LIBCAP_NG + case 'C': + return "mail, "; +#endif default: - return NULL; + return nullptr; } } @@ -1603,10 +1584,14 @@ static void Usage() { PrintOut(LOG_INFO,"Usage: smartd [options]\n\n"); +#ifdef SMARTMONTOOLS_ATTRIBUTELOG + PrintOut(LOG_INFO," -A PREFIX|-, --attributelog=PREFIX|-\n"); +#else PrintOut(LOG_INFO," -A PREFIX, --attributelog=PREFIX\n"); - PrintOut(LOG_INFO," Log ATA attribute information to {PREFIX}MODEL-SERIAL.ata.csv\n"); +#endif + PrintOut(LOG_INFO," Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n"); #ifdef SMARTMONTOOLS_ATTRIBUTELOG - PrintOut(LOG_INFO," [default is " SMARTMONTOOLS_ATTRIBUTELOG "MODEL-SERIAL.ata.csv]\n"); + PrintOut(LOG_INFO," [default is " SMARTMONTOOLS_ATTRIBUTELOG "MODEL-SERIAL.TYPE.csv]\n"); #endif PrintOut(LOG_INFO,"\n"); PrintOut(LOG_INFO," -B [+]FILE, --drivedb=[+]FILE\n"); @@ -1621,9 +1606,9 @@ PrintOut(LOG_INFO," Read configuration file NAME or stdin\n"); PrintOut(LOG_INFO," [default is %s]\n\n", configfile); #ifdef HAVE_LIBCAP_NG - PrintOut(LOG_INFO," -C, --capabilities\n"); + PrintOut(LOG_INFO," -C, --capabilities[=mail]\n"); PrintOut(LOG_INFO," Drop unneeded Linux process capabilities.\n" - " Warning: Mail notification does not work when used.\n\n"); + " Warning: Mail notification may not work when used.\n\n"); #endif PrintOut(LOG_INFO," -d, --debug\n"); PrintOut(LOG_INFO," Start smartd in debug mode\n\n"); @@ -1653,7 +1638,11 @@ PrintOut(LOG_INFO," Quit on one of: %s\n\n", GetValidArgList('q')); PrintOut(LOG_INFO," -r, --report=TYPE\n"); PrintOut(LOG_INFO," Report transactions for one of: %s\n\n", GetValidArgList('r')); +#ifdef SMARTMONTOOLS_SAVESTATES + PrintOut(LOG_INFO," -s PREFIX|-, --savestates=PREFIX|-\n"); +#else PrintOut(LOG_INFO," -s PREFIX, --savestates=PREFIX\n"); +#endif PrintOut(LOG_INFO," Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n"); #ifdef SMARTMONTOOLS_SAVESTATES PrintOut(LOG_INFO," [default is " SMARTMONTOOLS_SAVESTATES "MODEL-SERIAL.TYPE.state]\n"); @@ -1666,6 +1655,13 @@ #else PrintOut(LOG_INFO," [default is %s/smartd_warning.cmd]\n\n", get_exe_dir().c_str()); #endif +#ifdef HAVE_POSIX_API + PrintOut(LOG_INFO," -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n"); + PrintOut(LOG_INFO," Run warning script as non-privileged USER\n\n"); +#elif defined(_WIN32) + PrintOut(LOG_INFO," -u MODE, --warn-as-user=MODE\n"); + PrintOut(LOG_INFO," Run warning script with modified access token: %s\n\n", GetValidArgList('u')); +#endif #ifdef _WIN32 PrintOut(LOG_INFO," --service\n"); PrintOut(LOG_INFO," Running as windows service (see man page), install with:\n"); @@ -1687,6 +1683,22 @@ return 0; } +// Replace invalid characters in cfg.dev_idinfo +static bool sanitize_dev_idinfo(std::string & s) +{ + bool changed = false; + for (unsigned i = 0; i < s.size(); i++) { + char c = s[i]; + STATIC_ASSERT(' ' == 0x20 && '~' == 0x07e); // Assume ASCII + // Don't pass possible command escapes ('~! COMMAND') to the 'mail' command. + if ((' ' <= c && c <= '~') && !(i == 0 && c == '~')) + continue; + s[i] = '?'; + changed = true; + } + return changed; +} + // return true if a char is not allowed in a state file name static bool not_allowed_in_filename(char c) { @@ -1786,7 +1798,7 @@ case 0x04: msg = "was suspended by an interrupting command from host"; break; case 0x05: msg = "was aborted by an interrupting command from host"; break; case 0x06: msg = "was aborted by the device with a fatal error"; break; - default: msg = 0; + default: msg = nullptr; } if (msg) @@ -1812,7 +1824,7 @@ case 0x6: msg = "completed with error (servo/seek test element)"; break; case 0x7: msg = "completed with error (read test element)"; break; case 0x8: msg = "completed with error (handling damage?)"; break; - default: msg = 0; + default: msg = nullptr; } if (msg) @@ -1864,7 +1876,7 @@ // Start self-test regex check now if time was not read from state file if (!cfg.test_regex.empty() && !state.scheduled_test_next_check) - state.scheduled_test_next_check = time(0); + state.scheduled_test_next_check = time(nullptr); } // Common function to format result message for ATA setting @@ -1890,14 +1902,14 @@ if (!cfg.id_is_unique) return false; - for (unsigned i = 0; i < prev_cfgs.size(); i++) { - if (!prev_cfgs[i].id_is_unique) + for (const auto & prev_cfg : prev_cfgs) { + if (!prev_cfg.id_is_unique) continue; - if (cfg.dev_idinfo != prev_cfgs[i].dev_idinfo) + if (cfg.dev_idinfo != prev_cfg.dev_idinfo) continue; PrintOut(LOG_INFO, "Device: %s, same identity as %s, ignored\n", - cfg.dev_name.c_str(), prev_cfgs[i].dev_name.c_str()); + cfg.dev_name.c_str(), prev_cfg.dev_name.c_str()); return true; } @@ -1941,7 +1953,7 @@ state.num_sectors = sizes.sectors; cfg.dev_rpm = ata_get_rotation_rate(&drive); - char wwn[30]; wwn[0] = 0; + char wwn[64]; wwn[0] = 0; unsigned oui = 0; uint64_t unique_id = 0; int naa = ata_get_wwn(&drive, oui, unique_id); if (naa >= 0) @@ -1952,6 +1964,8 @@ cfg.dev_idinfo = strprintf("%s, S/N:%s, %sFW:%s, %s", model, serial, wwn, firmware, format_capacity(cap, sizeof(cap), sizes.capacity, ".")); cfg.id_is_unique = true; // TODO: Check serial? + if (sanitize_dev_idinfo(cfg.dev_idinfo)) + cfg.id_is_unique = false; PrintOut(LOG_INFO, "Device: %s, %s\n", name, cfg.dev_idinfo.c_str()); @@ -1967,13 +1981,16 @@ PrintOut(LOG_INFO, "Device: %s, smartd database not searched (Directive: -P ignore).\n", name); else { // Apply vendor specific presets, print warning if present + std::string dbversion; const drive_settings * dbentry = lookup_drive_apply_presets( - &drive, cfg.attribute_defs, cfg.firmwarebugs); + &drive, cfg.attribute_defs, cfg.firmwarebugs, dbversion); if (!dbentry) - PrintOut(LOG_INFO, "Device: %s, not found in smartd database.\n", name); + PrintOut(LOG_INFO, "Device: %s, not found in smartd database%s%s.\n", name, + (!dbversion.empty() ? " " : ""), (!dbversion.empty() ? dbversion.c_str() : "")); else { - PrintOut(LOG_INFO, "Device: %s, found in smartd database%s%s\n", - name, (*dbentry->modelfamily ? ": " : "."), (*dbentry->modelfamily ? dbentry->modelfamily : "")); + PrintOut(LOG_INFO, "Device: %s, found in smartd database%s%s%s%s\n", + name, (!dbversion.empty() ? " " : ""), (!dbversion.empty() ? dbversion.c_str() : ""), + (*dbentry->modelfamily ? ": " : "."), (*dbentry->modelfamily ? dbentry->modelfamily : "")); if (*dbentry->warningmsg) PrintOut(LOG_CRIT, "Device: %s, WARNING: %s\n", name, dbentry->warningmsg); } @@ -2303,8 +2320,8 @@ else if (locked) PrintOut(LOG_INFO, "Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n", name); - else if ( ataSetSCTErrorRecoveryControltime(atadev, 1, cfg.sct_erc_readtime ) - || ataSetSCTErrorRecoveryControltime(atadev, 2, cfg.sct_erc_writetime)) + else if ( ataSetSCTErrorRecoveryControltime(atadev, 1, cfg.sct_erc_readtime, false, false ) + || ataSetSCTErrorRecoveryControltime(atadev, 2, cfg.sct_erc_writetime, false, false)) PrintOut(LOG_INFO, "Device: %s, set of SCT Error Recovery Control failed\n", name); else PrintOut(LOG_INFO, "Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n", @@ -2395,7 +2412,7 @@ if (supported_vpd_pages_p) { delete supported_vpd_pages_p; - supported_vpd_pages_p = NULL; + supported_vpd_pages_p = nullptr; } supported_vpd_pages_p = new supported_vpd_pages(scsidev); @@ -2405,7 +2422,7 @@ if (0 == scsiInquiryVpd(scsidev, SCSI_VPD_DEVICE_IDENTIFICATION, vpdBuf, sizeof(vpdBuf))) { len = vpdBuf[3]; - scsi_decode_lu_dev_id(vpdBuf + 4, len, lu_id, sizeof(lu_id), NULL); + scsi_decode_lu_dev_id(vpdBuf + 4, len, lu_id, sizeof(lu_id), nullptr); } } serial[0] = '\0'; @@ -2432,6 +2449,8 @@ (serial[0] ? ", S/N: " : ""), (serial[0] ? serial : ""), (si_str[0] ? ", " : ""), (si_str[0] ? si_str : "")); cfg.id_is_unique = (lu_id[0] || serial[0]); + if (sanitize_dev_idinfo(cfg.dev_idinfo)) + cfg.id_is_unique = false; // format "model" string scsi_format_id_string(vendor, &inqBuf[8], 8); @@ -2621,9 +2640,9 @@ static int nvme_get_max_temp_kelvin(const nvme_smart_log & smart_log) { int k = (smart_log.temperature[1] << 8) | smart_log.temperature[0]; - for (int i = 0; i < 8; i++) { - if (smart_log.temp_sensor[i] > k) - k = smart_log.temp_sensor[i]; + for (auto s : smart_log.temp_sensor) { + if (s > k) + k = s; // cppcheck-suppress useStlAlgorithm } return k; } @@ -2660,6 +2679,8 @@ cfg.dev_idinfo = strprintf("%s, S/N:%s, FW:%s%s%s%s", model, serial, firmware, nsstr, (capstr[0] ? ", " : ""), capstr); cfg.id_is_unique = true; // TODO: Check serial? + if (sanitize_dev_idinfo(cfg.dev_idinfo)) + cfg.id_is_unique = false; PrintOut(LOG_INFO, "Device: %s, %s\n", name, cfg.dev_idinfo.c_str()); @@ -2869,7 +2890,7 @@ FixGlibcTimeZoneBug(); // Is it time for next check? - time_t now = (!usetime ? time(0) : usetime); + time_t now = (!usetime ? time(nullptr) : usetime); if (now < state.scheduled_test_next_check) { if (state.scheduled_test_next_check <= now + 3600) return 0; // Next check within one hour @@ -2881,39 +2902,72 @@ state.scheduled_test_next_check = now - (3600L*24*90); } + // Find ':NNN[-LLL]' in regex for possible offsets and limits + const unsigned max_offsets = 1 + num_test_types; + unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, }; + unsigned num_offsets = 1; // offsets/limits[0] == 0 always + for (const char * p = cfg.test_regex.get_pattern(); num_offsets < max_offsets; ) { + const char * q = strchr(p, ':'); + if (!q) + break; + p = q + 1; + unsigned offset = 0, limit = 0; int n1 = -1, n2 = -1, n3 = -1; + sscanf(p, "%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3); + if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0)))) + continue; + offsets[num_offsets] = offset; limits[num_offsets] = limit; + num_offsets++; + p += (n3 > 0 ? n3 : n1); + } + // Check interval [state.scheduled_test_next_check, now] for scheduled tests char testtype = 0; time_t testtime = 0; int testhour = 0; int maxtest = num_test_types-1; for (time_t t = state.scheduled_test_next_check; ; ) { - struct tm tmbuf, * tms = time_to_tm_local(&tmbuf, t); - // tm_wday is 0 (Sunday) to 6 (Saturday). We use 1 (Monday) to 7 (Sunday). - int weekday = (tms->tm_wday ? tms->tm_wday : 7); - for (int i = 0; i <= maxtest; i++) { - // Skip if drive not capable of this test - switch (test_type_chars[i]) { - case 'L': if (state.not_cap_long) continue; break; - case 'S': if (state.not_cap_short) continue; break; - case 'C': if (scsi || state.not_cap_conveyance) continue; break; - case 'O': if (scsi || state.not_cap_offline) continue; break; - case 'c': case 'n': - case 'r': if (scsi || state.not_cap_selective) continue; break; - default: continue; - } - // Try match of "T/MM/DD/d/HH" - char pattern[16]; - snprintf(pattern, sizeof(pattern), "%c/%02d/%02d/%1d/%02d", - test_type_chars[i], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour); - if (cfg.test_regex.full_match(pattern)) { - // Test found - testtype = pattern[0]; - testtime = t; testhour = tms->tm_hour; - // Limit further matches to higher priority self-tests - maxtest = i-1; - break; + // Check offset 0 and then all offsets for ':NNN' found above + for (unsigned i = 0; i < num_offsets; i++) { + unsigned offset = offsets[i], limit = limits[i]; + unsigned delay = cfg.test_offset_factor * offset; + if (0 < limit && limit < delay) + delay %= limit + 1; + struct tm tmbuf, * tms = time_to_tm_local(&tmbuf, t - (delay * 3600)); + + // tm_wday is 0 (Sunday) to 6 (Saturday). We use 1 (Monday) to 7 (Sunday). + int weekday = (tms->tm_wday ? tms->tm_wday : 7); + for (int j = 0; j <= maxtest; j++) { + // Skip if drive not capable of this test + switch (test_type_chars[j]) { + case 'L': if (state.not_cap_long) continue; break; + case 'S': if (state.not_cap_short) continue; break; + case 'C': if (scsi || state.not_cap_conveyance) continue; break; + case 'O': if (scsi || state.not_cap_offline) continue; break; + case 'c': case 'n': + case 'r': if (scsi || state.not_cap_selective) continue; break; + default: continue; + } + // Try match of "T/MM/DD/d/HH[:NNN]" + char pattern[64]; + snprintf(pattern, sizeof(pattern), "%c/%02d/%02d/%1d/%02d", + test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour); + if (i > 0) { + const unsigned len = sizeof("S/01/01/1/01") - 1; + snprintf(pattern + len, sizeof(pattern) - len, ":%03u", offset); + if (limit > 0) + snprintf(pattern + len + 4, sizeof(pattern) - len - 4, "-%03u", limit); + } + if (cfg.test_regex.full_match(pattern)) { + // Test found + testtype = pattern[0]; + testtime = t; testhour = tms->tm_hour; + // Limit further matches to higher priority self-tests + maxtest = j-1; + break; + } } } + // Exit if no tests left or current time reached if (maxtest < 0) break; @@ -2922,8 +2976,8 @@ // Check next hour if ((t += 3600) > now) t = now; - } - + } + // Do next check not before next hour. struct tm tmbuf, * tmnow = time_to_tm_local(&tmbuf, now); state.scheduled_test_next_check = now + (3600 - tmnow->tm_min*60 - tmnow->tm_sec); @@ -2952,7 +3006,7 @@ PrintOut(LOG_INFO, "\nNext scheduled self tests (at most 5 of each type per device):\n"); // FixGlibcTimeZoneBug(); // done in PrintOut() - time_t now = time(0); + time_t now = time(nullptr); char datenow[DATEANDEPOCHLEN], date[DATEANDEPOCHLEN]; dateandtimezoneepoch(datenow, now); @@ -2999,7 +3053,7 @@ static int DoSCSISelfTest(const dev_config & cfg, dev_state & state, scsi_device * device, char testtype) { int retval = 0; - const char *testname = 0; + const char *testname = nullptr; const char *name = cfg.name.c_str(); int inProgress; @@ -3026,7 +3080,7 @@ break; } // If we can't do the test, exit - if (NULL == testname) { + if (!testname) { PrintOut(LOG_CRIT, "Device: %s, not capable of %c Self-Test\n", name, testtype); return 1; @@ -3068,7 +3122,7 @@ // Check for capability to do the test int dotest = -1, mode = 0; - const char *testname = 0; + const char *testname = nullptr; switch (testtype) { case 'O': testname="Offline Immediate "; @@ -3155,7 +3209,7 @@ } // execute the test, and return status - int retval = smartcommandhandler(device, IMMEDIATE_OFFLINE, dotest, NULL); + int retval = smartcommandhandler(device, IMMEDIATE_OFFLINE, dotest, nullptr); if (retval) { PrintOut(LOG_CRIT, "Device: %s, execute %sTest failed.\n", name, testname); return retval; @@ -3236,7 +3290,7 @@ // First check if (!state.tempmin || currtemp < state.tempmin) // Delay Min Temperature update by ~ 30 minutes. - state.tempmin_delay = time(0) + CHECKTIME - 60; + state.tempmin_delay = time(nullptr) + default_checktime - 60; PrintOut(LOG_INFO, "Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n", cfg.name.c_str(), (int)currtemp, fmt_temp(state.tempmin, buf), state.tempmax, maxchg); if (triptemp) @@ -3247,7 +3301,7 @@ if (state.tempmin_delay) { // End Min Temperature update delay if ... if ( (state.tempmin && currtemp > state.tempmin) // current temp exceeds recorded min, - || (state.tempmin_delay <= time(0))) { // or delay time is over. + || (state.tempmin_delay <= time(nullptr))) { // or delay time is over. state.tempmin_delay = 0; if (!state.tempmin) state.tempmin = 255; @@ -3487,13 +3541,13 @@ name, mode, state.powerskipcnt, (state.powerskipcnt==1?"":"s")); } state.powerskipcnt = 0; - state.tempmin_delay = time(0) + CHECKTIME - 60; // Delay Min Temperature update + state.tempmin_delay = time(nullptr) + default_checktime - 60; // Delay Min Temperature update } else if (state.powerskipcnt) { PrintOut(LOG_INFO, "Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n", name, mode, state.powerskipcnt, (state.powerskipcnt==1?"":"s")); state.powerskipcnt = 0; - state.tempmin_delay = time(0) + CHECKTIME - 60; // Delay Min Temperature update + state.tempmin_delay = time(nullptr) + default_checktime - 60; // Delay Min Temperature update } } @@ -3626,6 +3680,7 @@ // Copy ATA attribute values to persistent state state.update_persistent_state(); + state.attrlog_dirty = true; return 0; } @@ -3701,6 +3756,7 @@ state.temperature = currenttemp; } CloseDevice(scsidev, name); + state.attrlog_dirty = true; return 0; } @@ -3714,6 +3770,7 @@ // Read SMART/Health log nvme_smart_log smart_log; if (!nvme_read_smart_log(nvmedev, smart_log)) { + CloseDevice(nvmedev, name); PrintOut(LOG_INFO, "Device: %s, failed to read NVMe SMART/Health Information\n", name); MailWarning(cfg, state, 6, "Device: %s, failed to read NVMe SMART/Health Information", name); state.must_write = true; @@ -3773,18 +3830,18 @@ } CloseDevice(nvmedev, name); + state.attrlog_dirty = true; return 0; } // 0=not used, 1=not disabled, 2=disable rejected by OS, 3=disabled static int standby_disable_state = 0; -static void init_disable_standby_check(dev_config_vector & configs) +static void init_disable_standby_check(const dev_config_vector & configs) { // Check for '-l offlinests,ns' or '-l selfteststs,ns' directives bool sts1 = false, sts2 = false; - for (unsigned i = 0; i < configs.size() && !(sts1 || sts2); i++) { - const dev_config & cfg = configs.at(i); + for (const auto & cfg : configs) { if (cfg.offlinests_ns) sts1 = true; if (cfg.selfteststs_ns) @@ -3861,6 +3918,13 @@ for (unsigned i = 0; i < configs.size(); i++) { const dev_config & cfg = configs.at(i); dev_state & state = states.at(i); + if (state.skip) { + if (debugmode) + PrintOut(LOG_INFO, "Device: %s, skipped (interval=%d)\n", cfg.name.c_str(), + (cfg.checktime ? cfg.checktime : checktime)); + continue; + } + smart_device * dev = devices.at(i); if (dev->is_ata()) ATACheckDevice(cfg, state, dev->to_ata(), firstpass, allow_selftests); @@ -3917,25 +3981,53 @@ } #endif -static time_t dosleep(time_t wakeuptime, bool & sigwakeup, int numdev) +time_t calc_next_wakeuptime(time_t wakeuptime, time_t timenow, int ct) +{ + if (timenow < wakeuptime) + return wakeuptime; + return timenow + ct - (timenow - wakeuptime) % ct; +} + +static time_t dosleep(time_t wakeuptime, const dev_config_vector & configs, + dev_state_vector & states, bool & sigwakeup) { // If past wake-up-time, compute next wake-up-time - time_t timenow=time(NULL); - while (wakeuptime<=timenow){ - time_t intervals = 1 + (timenow-wakeuptime)/checktime; - wakeuptime+=intervals*checktime; + time_t timenow = time(nullptr); + unsigned n = configs.size(); + int ct; + if (!checktime_min) { + // Same for all devices + wakeuptime = calc_next_wakeuptime(wakeuptime, timenow, checktime); + ct = checktime; + } + else { + // Determine wakeuptime of next device(s) + wakeuptime = 0; + for (unsigned i = 0; i < n; i++) { + const dev_config & cfg = configs.at(i); + dev_state & state = states.at(i); + if (!state.skip) + state.wakeuptime = calc_next_wakeuptime((state.wakeuptime ? state.wakeuptime : timenow), + timenow, (cfg.checktime ? cfg.checktime : checktime)); + if (!wakeuptime || state.wakeuptime < wakeuptime) + wakeuptime = state.wakeuptime; + } + ct = checktime_min; } - notify_wait(wakeuptime, numdev); + notify_wait(wakeuptime, n); - // sleep until we catch SIGUSR1 or have completed sleeping + // Sleep until we catch a signal or have completed sleeping + bool no_skip = false; int addtime = 0; while (timenow < wakeuptime+addtime && !caughtsigUSR1 && !caughtsigHUP && !caughtsigEXIT) { - - // protect user again system clock being adjusted backwards - if (wakeuptime>timenow+checktime){ + // Restart if system clock has been adjusted to the past + if (wakeuptime > timenow + ct) { PrintOut(LOG_INFO, "System clock time adjusted to the past. Resetting next wakeup time.\n"); - wakeuptime=timenow+checktime; + wakeuptime = timenow + ct; + for (auto & state : states) + state.wakeuptime = 0; + no_skip = true; } // Exit sleep when time interval has expired or a signal is received @@ -3949,7 +4041,7 @@ } #endif - timenow=time(NULL); + timenow = time(nullptr); // Actual sleep time too long? if (!addtime && timenow > wakeuptime+60) { @@ -3959,7 +4051,7 @@ // Wait another 20 seconds to avoid I/O errors during disk spin-up addtime = timenow-wakeuptime+20; // Use next wake-up-time if close - int nextcheck = checktime - addtime % checktime; + int nextcheck = ct - addtime % ct; if (nextcheck <= 20) addtime += nextcheck; } @@ -3970,7 +4062,13 @@ PrintOut(LOG_INFO,"Signal USR1 - checking devices now rather than in %d seconds.\n", wakeuptime-timenow>0?(int)(wakeuptime-timenow):0); caughtsigUSR1=0; - sigwakeup = true; + sigwakeup = no_skip = true; + } + + // Check which devices must be skipped in this cycle + if (checktime_min) { + for (auto & state : states) + state.skip = (!no_skip && timenow < state.wakeuptime); } // return adjusted wakeuptime @@ -4016,6 +4114,9 @@ PrintOut(priority, "aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] " "security-freeze, standby,[N|off], wcache,[on|off]"); break; + case 'c': + PrintOut(priority, "i=N, interval=N"); + break; } } @@ -4082,14 +4183,14 @@ // Concatenate strtok() results if quoted with "..." static const char * strtok_dequote(const char * delimiters) { - const char * t = strtok(0, delimiters); + const char * t = strtok(nullptr, delimiters); if (!t || t[0] != '"') return t; static std::string token; token = t+1; for (;;) { - t = strtok(0, delimiters); + t = strtok(nullptr, delimiters); if (!t || !*t) return "\""; token += ' '; @@ -4141,7 +4242,7 @@ switch (sym) { case 'C': // monitor current pending sector count (default 197) - if ((val = GetInteger(arg=strtok(NULL,delim), name, token, lineno, configfile, 0, 255, plus)) < 0) + if ((val = GetInteger((arg = strtok(nullptr, delim)), name, token, lineno, configfile, 0, 255, plus)) < 0) return -1; cfg.curr_pending_id = (unsigned char)val; cfg.curr_pending_incr = (*plus == '+'); @@ -4149,7 +4250,7 @@ break; case 'U': // monitor offline uncorrectable sectors (default 198) - if ((val = GetInteger(arg=strtok(NULL,delim), name, token, lineno, configfile, 0, 255, plus)) < 0) + if ((val = GetInteger((arg = strtok(nullptr, delim)), name, token, lineno, configfile, 0, 255, plus)) < 0) return -1; cfg.offl_pending_id = (unsigned char)val; cfg.offl_pending_incr = (*plus == '+'); @@ -4157,7 +4258,7 @@ break; case 'T': // Set tolerance level for SMART command failures - if ((arg = strtok(NULL, delim)) == NULL) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!strcmp(arg, "normal")) { // Normal mode: exit on failure of a mandatory S.M.A.R.T. command, but @@ -4173,7 +4274,7 @@ break; case 'd': // specify the device type - if ((arg = strtok(NULL, delim)) == NULL) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!strcmp(arg, "ignore")) { cfg.ignore = true; @@ -4189,7 +4290,7 @@ break; case 'F': // fix firmware bug - if (!(arg = strtok(0, delim))) + if (!(arg = strtok(nullptr, delim))) missingarg = 1; else if (!parse_firmwarebug_def(arg, cfg.firmwarebugs)) badarg = 1; @@ -4217,7 +4318,7 @@ break; case 'l': // track changes in SMART logs - if ((arg = strtok(NULL, delim)) == NULL) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!strcmp(arg, "selftest")) { // track changes in self-test log @@ -4267,7 +4368,7 @@ break; case 'o': // automatic offline testing enable/disable - if ((arg = strtok(NULL, delim)) == NULL) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!strcmp(arg, "on")) { cfg.autoofflinetest = 2; @@ -4279,16 +4380,17 @@ break; case 'n': // skip disk check if in idle or standby mode - if (!(arg = strtok(NULL, delim))) + if (!(arg = strtok(nullptr, delim))) missingarg = 1; else { - char *endptr = NULL; + char *endptr = nullptr; char *next = strchr(const_cast(arg), ','); cfg.powerquiet = false; cfg.powerskipmax = 0; - if (next!=NULL) *next='\0'; + if (next) + *next = '\0'; if (!strcmp(arg, "never")) cfg.powermode = 0; else if (!strcmp(arg, "sleep")) @@ -4301,7 +4403,7 @@ badarg = 1; // if optional arguments are present - if (!badarg && next!=NULL) { + if (!badarg && next) { next++; cfg.powerskipmax = strtol(next, &endptr, 10); if (endptr == next) @@ -4323,7 +4425,7 @@ break; case 'S': // automatic attribute autosave enable/disable - if ((arg = strtok(NULL, delim)) == NULL) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!strcmp(arg, "on")) { cfg.autosave = 2; @@ -4341,7 +4443,7 @@ cfg.test_regex = regular_expression(); } // check for missing argument - if (!(arg = strtok(NULL, delim))) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } // Compile regex @@ -4355,14 +4457,22 @@ // Do a bit of sanity checking and warn user if we think that // their regexp is "strange". User probably confused about shell // glob(3) syntax versus regular expression syntax regexp(7). - if (arg[(val = strspn(arg, "0123456789/.-+*|()?^$[]SLCOcnr"))]) - PrintOut(LOG_INFO, "File %s line %d (drive %s): warning, character %d (%c) looks odd in extended regular expression %s\n", - configfile, lineno, name, val+1, arg[val], arg); + // Check also for possible invalid number of digits in ':NNN[-LLL]' suffix. + static const regular_expression syntax_check( + "[^]$()*+./:?^[|0-9LSCOncr-]+|" + ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|" + ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})" + ); + regular_expression::match_range range; + if (syntax_check.execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo) + PrintOut(LOG_INFO, "File %s line %d (drive %s): warning, \"%.*s\" looks odd in " + "extended regular expression \"%s\"\n", + configfile, lineno, name, (int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg); } break; case 'm': // send email to address that follows - if (!(arg = strtok(NULL,delim))) + if (!(arg = strtok(nullptr, delim))) missingarg = 1; else { if (!cfg.emailaddress.empty()) @@ -4373,7 +4483,7 @@ break; case 'M': // email warning options - if (!(arg = strtok(NULL, delim))) + if (!(arg = strtok(nullptr, delim))) missingarg = 1; else if (!strcmp(arg, "once")) cfg.emailfreq = 1; @@ -4394,7 +4504,7 @@ return -1; } #else - arg = strtok(0, delim); + arg = strtok(nullptr, delim); #endif if (!arg) { PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n", @@ -4412,19 +4522,19 @@ break; case 'i': // ignore failure of usage attribute - if ((val=GetInteger(arg=strtok(NULL,delim), name, token, lineno, configfile, 1, 255))<0) + if ((val = GetInteger((arg = strtok(nullptr, delim)), name, token, lineno, configfile, 1, 255)) < 0) return -1; cfg.monitor_attr_flags.set(val, MONITOR_IGN_FAILUSE); break; case 'I': // ignore attribute for tracking purposes - if ((val=GetInteger(arg=strtok(NULL,delim), name, token, lineno, configfile, 1, 255))<0) + if ((val = GetInteger((arg = strtok(nullptr, delim)), name, token, lineno, configfile, 1, 255)) < 0) return -1; cfg.monitor_attr_flags.set(val, MONITOR_IGNORE); break; case 'r': // print raw value when tracking - if ((val = GetInteger(arg=strtok(NULL,delim), name, token, lineno, configfile, 1, 255, excl)) < 0) + if ((val = GetInteger((arg = strtok(nullptr, delim)), name, token, lineno, configfile, 1, 255, excl)) < 0) return -1; cfg.monitor_attr_flags.set(val, MONITOR_RAW_PRINT); if (*excl == '!') // attribute change is critical @@ -4432,7 +4542,7 @@ break; case 'R': // track changes in raw value (forces printing of raw value) - if ((val = GetInteger(arg=strtok(NULL,delim), name, token, lineno, configfile, 1, 255, excl)) < 0) + if ((val = GetInteger((arg = strtok(nullptr, delim)), name, token, lineno, configfile, 1, 255, excl)) < 0) return -1; cfg.monitor_attr_flags.set(val, MONITOR_RAW_PRINT|MONITOR_RAW); if (*excl == '!') // raw value change is critical @@ -4440,13 +4550,13 @@ break; case 'W': // track Temperature - if (Get3Integers(arg=strtok(NULL, delim), name, token, lineno, configfile, + if (Get3Integers((arg = strtok(nullptr, delim)), name, token, lineno, configfile, &cfg.tempdiff, &cfg.tempinfo, &cfg.tempcrit) < 0) return -1; break; case 'v': // non-default vendor-specific attribute meaning - if (!(arg=strtok(NULL,delim))) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!parse_attribute_def(arg, cfg.attribute_defs, PRIOR_USER)) { badarg = 1; @@ -4454,7 +4564,7 @@ break; case 'P': // Define use of drive-specific presets. - if (!(arg = strtok(NULL, delim))) { + if (!(arg = strtok(nullptr, delim))) { missingarg = 1; } else if (!strcmp(arg, "use")) { cfg.ignorepresets = false; @@ -4471,32 +4581,32 @@ case 'e': // Various ATA settings - if (!(arg = strtok(NULL, delim))) { + if (!(arg = strtok(nullptr, delim))) { missingarg = true; } else { - char arg2[16+1]; unsigned val; + char arg2[16+1]; unsigned uval; int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg); - if (sscanf(arg, "%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &val, &n3) >= 1 + if (sscanf(arg, "%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1 && (n1 == len || n2 > 0)) { bool on = (n2 > 0 && !strcmp(arg+n2, "on")); bool off = (n2 > 0 && !strcmp(arg+n2, "off")); if (n3 != len) - val = ~0U; + uval = ~0U; if (!strcmp(arg2, "aam")) { if (off) cfg.set_aam = -1; - else if (val <= 254) - cfg.set_aam = val + 1; + else if (uval <= 254) + cfg.set_aam = uval + 1; else badarg = true; } else if (!strcmp(arg2, "apm")) { if (off) cfg.set_apm = -1; - else if (1 <= val && val <= 254) - cfg.set_apm = val + 1; + else if (1 <= uval && uval <= 254) + cfg.set_apm = uval + 1; else badarg = true; } @@ -4514,8 +4624,8 @@ else if (!strcmp(arg2, "standby")) { if (off) cfg.set_standby = 0 + 1; - else if (val <= 255) - cfg.set_standby = val + 1; + else if (uval <= 255) + cfg.set_standby = uval + 1; else badarg = true; } @@ -4543,11 +4653,28 @@ } break; + case 'c': + // Override command line options + { + if (!(arg = strtok(nullptr, delim))) { + missingarg = true; + break; + } + int n = 0, nc = -1, len = strlen(arg); + if ( ( sscanf(arg, "i=%d%n", &n, &nc) == 1 + || sscanf(arg, "interval=%d%n", &n, &nc) == 1) + && nc == len && n >= 10) + cfg.checktime = n; + else + badarg = true; + } + break; + default: // Directive not recognized PrintOut(LOG_CRIT,"File %s line %d (drive %s): unknown Directive: %s\n", configfile, lineno, name, token); - Directives(); + PrintOut(LOG_CRIT, "Run smartd -D to print a list of valid Directives.\n"); return -1; } if (missingarg) { @@ -4609,7 +4736,7 @@ cfg.lineno = lineno; // parse tokens one at a time from the file. - while (char * token = strtok(0, delim)) { + while (char * token = strtok(nullptr, delim)) { int rc = ParseToken(token, cfg, scan_types); if (rc < 0) // error found on the line @@ -4864,6 +4991,9 @@ // Please update GetValidArgList() if you edit shortopts static const char shortopts[] = "c:l:q:dDni:p:r:s:A:B:w:Vh?" +#if defined(HAVE_POSIX_API) || defined(_WIN32) + "u:" +#endif #ifdef HAVE_LIBCAP_NG "C" #endif @@ -4892,19 +5022,23 @@ { "copyright", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { "usage", no_argument, 0, 'h' }, +#if defined(HAVE_POSIX_API) || defined(_WIN32) + { "warn-as-user", required_argument, 0, 'u' }, +#endif #ifdef HAVE_LIBCAP_NG - { "capabilities", no_argument, 0, 'C' }, + { "capabilities", optional_argument, 0, 'C' }, #endif { 0, 0, 0, 0 } }; opterr=optopt=0; bool badarg = false; + const char * badarg_msg = nullptr; bool use_default_db = true; // set false on '-B FILE' // Parse input options. int optchar; - while ((optchar = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { + while ((optchar = getopt_long(argc, argv, shortopts, longopts, nullptr)) != -1) { char *arg; char *tailptr; long lchecktime; @@ -4912,10 +5046,25 @@ switch(optchar) { case 'q': // when to quit + quit_nodev0 = false; if (!strcmp(optarg, "nodev")) quit = QUIT_NODEV; + else if (!strcmp(optarg, "nodev0")) { + quit = QUIT_NODEV; + quit_nodev0 = true; + } else if (!strcmp(optarg, "nodevstartup")) quit = QUIT_NODEVSTARTUP; + else if (!strcmp(optarg, "nodev0startup")) { + quit = QUIT_NODEVSTARTUP; + quit_nodev0 = true; + } + else if (!strcmp(optarg, "errors")) + quit = QUIT_ERRORS; + else if (!strcmp(optarg, "errors,nodev0")) { + quit = QUIT_ERRORS; + quit_nodev0 = true; + } else if (!strcmp(optarg, "never")) quit = QUIT_NEVER; else if (!strcmp(optarg, "onecheck")) { @@ -4926,8 +5075,6 @@ quit = QUIT_SHOWTESTS; debugmode = 1; } - else if (!strcmp(optarg, "errors")) - quit = QUIT_ERRORS; else badarg = true; break; @@ -5018,11 +5165,11 @@ break; case 's': // path prefix of persistent state file - state_path_prefix = optarg; + state_path_prefix = (strcmp(optarg, "-") ? optarg : ""); break; case 'A': // path prefix of attribute log file - attrlog_path_prefix = optarg; + attrlog_path_prefix = (strcmp(optarg, "-") ? optarg : ""); break; case 'B': { @@ -5040,6 +5187,28 @@ case 'w': warning_script = optarg; break; +#ifdef HAVE_POSIX_API + case 'u': + warn_as_user = false; + if (strcmp(optarg, "-")) { + warn_uname = warn_gname = "unknown"; + badarg_msg = parse_ugid(optarg, warn_uid, warn_gid, + warn_uname, warn_gname ); + if (badarg_msg) + break; + warn_as_user = true; + } + break; +#elif defined(_WIN32) + case 'u': + if (!strcmp(optarg, "restricted")) + warn_as_restr_user = true; + else if (!strcmp(optarg, "unchanged")) + warn_as_restr_user = false; + else + badarg = true; + break; +#endif // HAVE_POSIX_API ||_WIN32 case 'V': // print version and CVS info debugmode = 1; @@ -5048,7 +5217,12 @@ #ifdef HAVE_LIBCAP_NG case 'C': // enable capabilities - capabilities_enabled = true; + if (!optarg) + capabilities_mode = 1; + else if (!strcmp(optarg, "mail")) + capabilities_mode = 2; + else + badarg = true; break; #endif case 'h': @@ -5067,7 +5241,7 @@ // Check whether the option is a long option that doesn't map to -h. if (arg[1] == '-' && optchar != 'h') { // Iff optopt holds a valid option then argument must be missing. - if (optopt && (strchr(shortopts, optopt) != NULL)) { + if (optopt && strchr(shortopts, optopt)) { PrintOut(LOG_CRIT, "=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2); PrintValidArgs(optopt); } else { @@ -5078,7 +5252,7 @@ } if (optopt) { // Iff optopt holds a valid option then argument must be missing. - if (strchr(shortopts, optopt) != NULL){ + if (strchr(shortopts, optopt)){ PrintOut(LOG_CRIT, "=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt); PrintValidArgs(optopt); } else { @@ -5092,14 +5266,17 @@ } // Check to see if option had an unrecognized or incorrect argument. - if (badarg) { + if (badarg || badarg_msg) { debugmode=1; PrintHead(); // It would be nice to print the actual option name given by the user // here, but we just print the short form. Please fix this if you know // a clean way to do it. PrintOut(LOG_CRIT, "=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg); - PrintValidArgs(optchar); + if (badarg_msg) + PrintOut(LOG_CRIT, "%s\n", badarg_msg); + else + PrintValidArgs(optchar); PrintOut(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); return EXIT_BADCMD; } @@ -5133,6 +5310,16 @@ } #endif +#ifdef _WIN32 + if (warn_as_restr_user && !popen_as_restr_check()) { + // debugmode=1 // would suppress messages to eventlog or log file + PrintHead(); + PrintOut(LOG_CRIT, "Option '--warn-as-user=restricted' is not effective if the current user\n"); + PrintOut(LOG_CRIT, "is the local 'SYSTEM' or 'Administrator' account\n\n"); + return EXIT_BADCMD; + } +#endif + // Read or init drive database { unsigned char savedebug = debugmode; debugmode = 1; @@ -5142,6 +5329,7 @@ } // Check option compatibility of notify support + // cppcheck-suppress knownConditionTrueFalse if (!notify_post_init()) return EXIT_BADCMD; @@ -5167,7 +5355,7 @@ } // if no devices, return - if (devlist.size() <= 0) + if (devlist.size() == 0) return 0; // add empty device slots for existing config entries @@ -5180,12 +5368,18 @@ smart_device * dev = devlist.release(i); scanned_devs.push_back(dev); - // Copy configuration, update device and type name + // Append configuration and update names conf_entries.push_back(base_cfg); dev_config & cfg = conf_entries.back(); cfg.name = dev->get_info().info_name; cfg.dev_name = dev->get_info().dev_name; - cfg.dev_type = dev->get_info().dev_type; + + // Set type only if scanning is limited to specific types + // This is later used to set SMARTD_DEVICETYPE environment variable + if (!types.empty()) + cfg.dev_type = dev->get_info().dev_type; + else // SMARTD_DEVICETYPE=auto + cfg.dev_type.clear(); } return devlist.size(); @@ -5237,44 +5431,6 @@ return conf_entries.size(); } -// Return true if TYPE contains a RAID drive number -static bool is_raid_type(const char * type) -{ - if (str_starts_with(type, "sat,")) - return false; - int i; - if (sscanf(type, "%*[^,],%d", &i) != 1) - return false; - return true; -} - -// Return true if DEV is already in DEVICES[0..NUMDEVS) or IGNORED[*] -static bool is_duplicate_device(const smart_device * dev, - const smart_device_list & devices, unsigned numdevs, - const dev_config_vector & ignored) -{ - const smart_device::device_info & info1 = dev->get_info(); - bool is_raid1 = is_raid_type(info1.dev_type.c_str()); - - for (unsigned i = 0; i < numdevs; i++) { - const smart_device::device_info & info2 = devices.at(i)->get_info(); - // -d TYPE options must match if RAID drive number is specified - if ( info1.dev_name == info2.dev_name - && ( info1.dev_type == info2.dev_type - || !is_raid1 || !is_raid_type(info2.dev_type.c_str()))) - return true; - } - - for (unsigned i = 0; i < ignored.size(); i++) { - const dev_config & cfg2 = ignored.at(i); - if ( info1.dev_name == cfg2.dev_name - && ( info1.dev_type == cfg2.dev_type - || !is_raid1 || !is_raid_type(cfg2.dev_type.c_str()))) - return true; - } - return false; -} - // Register one device, return false on error static bool register_device(dev_config & cfg, dev_state & state, smart_device_auto_ptr & dev, const dev_config_vector * prev_cfgs) @@ -5369,20 +5525,28 @@ devices.clear(); states.clear(); - // Register entries - dev_config_vector ignored_entries; - unsigned numnoscan = 0; - for (unsigned i = 0; i < conf_entries.size(); i++){ + // Map of already seen non-DEVICESCAN devices (unique_name -> cfg.name) + typedef std::map prev_unique_names_map; + prev_unique_names_map prev_unique_names; + // Register entries + for (unsigned i = 0; i < conf_entries.size(); i++) { dev_config cfg = conf_entries[i]; + // Get unique device "name [type]" (with symlinks resolved) for duplicate detection + std::string unique_name = smi()->get_unique_dev_name(cfg.dev_name.c_str(), cfg.dev_type.c_str()); + if (debugmode && unique_name != cfg.dev_name) { + pout("Device: %s%s%s%s, unique name: %s\n", cfg.name.c_str(), + (!cfg.dev_type.empty() ? " [" : ""), cfg.dev_type.c_str(), + (!cfg.dev_type.empty() ? "]" : ""), unique_name.c_str()); + } + if (cfg.ignore) { - // Store for is_duplicate_device() check and ignore + // Store for duplicate detection and ignore PrintOut(LOG_INFO, "Device: %s%s%s%s, ignored\n", cfg.name.c_str(), - (!cfg.dev_type.empty() ? " [" : ""), - cfg.dev_type.c_str(), + (!cfg.dev_type.empty() ? " [" : ""), cfg.dev_type.c_str(), (!cfg.dev_type.empty() ? "]" : "")); - ignored_entries.push_back(cfg); + prev_unique_names[unique_name] = cfg.name; continue; } @@ -5394,9 +5558,11 @@ dev = scanned_devs.release(i); if (dev) { // Check for a preceding non-DEVICESCAN entry for the same device - if ( (numnoscan || !ignored_entries.empty()) - && is_duplicate_device(dev.get(), devices, numnoscan, ignored_entries)) { - PrintOut(LOG_INFO, "Device: %s, duplicate, ignored\n", dev->get_info_name()); + prev_unique_names_map::iterator ui = prev_unique_names.find(unique_name); + if (ui != prev_unique_names.end()) { + bool ne = (ui->second != cfg.name); + PrintOut(LOG_INFO, "Device: %s, %s%s, ignored\n", dev->get_info_name(), + (ne ? "same as " : "duplicate"), (ne ? ui->second.c_str() : "")); continue; } scanning = true; @@ -5411,12 +5577,13 @@ // exit unless the user has specified that the device is removable if (!scanning) { if (!(cfg.removable || quit == QUIT_NEVER)) { - PrintOut(LOG_CRIT, "Unable to register device %s (no Directive -d removable). Exiting.\n", cfg.name.c_str()); + PrintOut(LOG_CRIT, "Unable to register device %s (no Directive -d removable). Exiting.\n", + cfg.name.c_str()); return false; } PrintOut(LOG_INFO, "Device: %s, not available\n", cfg.name.c_str()); // Prevent retry of registration - ignored_entries.push_back(cfg); + prev_unique_names[unique_name] = cfg.name; } continue; } @@ -5426,9 +5593,22 @@ states.push_back(state); devices.push_back(dev); if (!scanning) - numnoscan = devices.size(); + // Store for duplicate detection + prev_unique_names[unique_name] = cfg.name; } + // Set minimum check time and factors for staggered tests + checktime_min = 0; + unsigned factor = 0; + for (auto & cfg : configs) { + if (cfg.checktime && (!checktime_min || checktime_min > cfg.checktime)) + checktime_min = cfg.checktime; + if (!cfg.test_regex.empty()) + cfg.test_offset_factor = factor++; + } + if (checktime_min && checktime_min > checktime) + checktime_min = checktime; + init_disable_standby_check(configs); return true; } @@ -5496,8 +5676,6 @@ } if (!(configs.size() == devices.size() && configs.size() == states.size())) throw std::logic_error("Invalid result from RegisterDevices"); - // Handle limitations if capabilities are dropped - capabilities_check_config(configs); } else if ( quit == QUIT_NEVER || ((quit == QUIT_NODEV || quit == QUIT_NODEVSTARTUP) && !firstpass)) { @@ -5516,7 +5694,7 @@ || (quit == QUIT_NODEVSTARTUP && !firstpass))) { PrintOut(LOG_INFO, "Unable to monitor any SMART enabled devices. %sExiting...\n", (!debugmode ? "Try debug (-d) option. " : "")); - status = EXIT_NODEV; + status = EXIT_NODEV; // later changed to 0 if quit_nodev0 is set break; } @@ -5585,13 +5763,13 @@ install_signal_handlers(); // Initialize wakeup time to CURRENT time - wakeuptime = time(0); + wakeuptime = time(nullptr); firstpass = false; } // sleep until next check time, or a signal arrives - wakeuptime = dosleep(wakeuptime, write_states_always, (int)devices.size()); + wakeuptime = dosleep(wakeuptime, configs, states, write_states_always); } while (!caughtsigEXIT); @@ -5627,7 +5805,7 @@ // and this should be the final output from smartd before it exits PrintOut((status ? LOG_CRIT : LOG_INFO), "smartd is exiting (exit status %d)\n", - status); + (!(status == EXIT_NODEV && quit_nodev0) ? status : 0)); } return status; @@ -5669,6 +5847,11 @@ PrintOut(LOG_CRIT, "Please inform " PACKAGE_BUGREPORT ", including output of smartd -V.\n"); notify_exit(status); + + // Return success if no devices to monitor and '-q *nodev0*' was specified + if (status == EXIT_NODEV && quit_nodev0) + status = 0; + #ifdef _WIN32 daemon_winsvc_exitcode = status; #endif diff -Nru smartmontools-7.1/smartd.service.in smartmontools-7.3/smartd.service.in --- smartmontools-7.1/smartd.service.in 2018-12-16 17:55:44.000000000 +0000 +++ smartmontools-7.3/smartd.service.in 2022-01-14 08:02:52.000000000 +0000 @@ -2,12 +2,15 @@ Description=Self Monitoring and Reporting Technology (SMART) Daemon Documentation=man:smartd(8) man:smartd.conf(5) +# Typically physical storage devices are managed by the host physical machine +# Override it if you are using PCI/USB passthrough +ConditionVirtualization=no + [Service] Type=notify EnvironmentFile=-/usr/local/etc/sysconfig/smartmontools ExecStart=/usr/local/sbin/smartd -n $smartd_opts ExecReload=/bin/kill -HUP $MAINPID -StandardOutput=syslog [Install] WantedBy=multi-user.target diff -Nru smartmontools-7.1/smartd_warning.sh.in smartmontools-7.3/smartd_warning.sh.in --- smartmontools-7.1/smartd_warning.sh.in 2018-11-27 18:26:08.000000000 +0000 +++ smartmontools-7.3/smartd_warning.sh.in 2021-10-23 10:22:01.000000000 +0000 @@ -2,13 +2,13 @@ # # smartd warning script # -# Home page of code is: http://www.smartmontools.org +# Home page of code is: https://www.smartmontools.org # -# Copyright (C) 2012-16 Christian Franke +# Copyright (C) 2012-21 Christian Franke # # SPDX-License-Identifier: GPL-2.0-or-later # -# $Id: smartd_warning.sh.in 4839 2018-11-27 18:26:08Z chrfranke $ +# $Id: smartd_warning.sh.in 5238 2021-10-23 10:22:01Z chrfranke $ # set -e @@ -120,64 +120,82 @@ fi ` +# Check whether a message line begins with the default 'mail' command escape char '~'. +# Heuristically detect dangerous command escapes for possible other escape characters. +esc=`echo "$fullmessage" | sed -n -e '/^~/p' -e '/^[^ 0-9A-Za-z][[:space:]]*[!:&2 + exit 1 +fi + # Export message with trailing newline export SMARTD_FULLMESSAGE="$fullmessage " # Run plugin scripts if requested -if test -n "$plugindir"; then - case " $SMARTD_ADDRESS" in +unset SMARTD_ADDRESS_ORIG +case " $SMARTD_ADDRESS" in *\ @*) - if [ -n "$dryrun" ]; then - echo "export SMARTD_SUBJECT='$SMARTD_SUBJECT'" - echo "export SMARTD_FULLMESSAGE='$SMARTD_FULLMESSAGE'" - fi - - # Run ALL scripts if requested - case " $SMARTD_ADDRESS " in - *\ @ALL\ *) - for cmd in "$plugindir"/*; do - if [ -f "$cmd" ] && [ -x "$cmd" ]; then - if [ -n "$dryrun" ]; then - echo "$cmd &2 + if [ -n "$plugindir" ]; then + plugins="${plugins}${plugins:+ }${ad#@}" fi ;; *) - SMARTD_ADDRESS="${SMARTD_ADDRESS:+ }$ad" + SMARTD_ADDRESS="${SMARTD_ADDRESS}${SMARTD_ADDRESS:+ }$ad" ;; esac done + # Run all scripts + if [ -n "$plugins" ]; then + if [ -n "$dryrun" ]; then + echo "export SMARTD_ADDRESS='$SMARTD_ADDRESS'" + echo "export SMARTD_ADDRESS_ORIG='$SMARTD_ADDRESS_ORIG'" + echo "export SMARTD_SUBJECT='$SMARTD_SUBJECT'" + echo "export SMARTD_FULLMESSAGE='$SMARTD_FULLMESSAGE'" + fi + for p in $plugins; do + cmd="$plugindir/$p" + if [ -f "$cmd" ]; then + if [ -x "$cmd" ]; then + if [ -n "$dryrun" ]; then + echo "$cmd &2 + exit $rc + fi + fi + fi + else + echo "$cmd: not found" >&2 + exit 1 + fi + done + fi + # Send email to remaining addresses test -n "$SMARTD_ADDRESS" || exit 0 ;; - esac -fi +esac # Send mail or run command if [ -n "$SMARTD_ADDRESS" ]; then diff -Nru smartmontools-7.1/update-smart-drivedb.8.in smartmontools-7.3/update-smart-drivedb.8.in --- smartmontools-7.1/update-smart-drivedb.8.in 2019-12-13 20:17:36.000000000 +0000 +++ smartmontools-7.3/update-smart-drivedb.8.in 2022-02-18 17:23:14.000000000 +0000 @@ -1,10 +1,10 @@ .ig Copyright (C) 2013 Hannes von Haugwitz -Copyright (C) 2014-19 Christian Franke +Copyright (C) 2014-22 Christian Franke SPDX-License-Identifier: GPL-2.0-or-later -$Id: update-smart-drivedb.8.in 5003 2019-12-13 20:17:36Z chrfranke $ +$Id: update-smart-drivedb.8.in 5318 2022-02-18 17:23:14Z chrfranke $ .. .\" Macros borrowed from pages generated with Pod::Man @@ -41,7 +41,7 @@ .\" %ENDIF NOT OS ALL .B update-smart-drivedb updates -.B /usr/local/share/smartmontools/drivedb.h +.B /usr/local/var/lib/smartmontools/drivedb.h or .I DESTFILE from branches/RELEASE_6_0_DRIVEDB of smartmontools SVN repository. @@ -67,10 +67,16 @@ The old file is kept if the downloaded file is identical (ignoring the differences in Id string) otherwise it is moved to .BR drivedb.h.old . +.PP +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +The old file is also kept if the downloaded file reports an older version +on the same branch. +This could be overridden with the \*(Aq\-\-force\*(Aq option. +If the branch version differs, the file is always updated. .Sp .SH "OPTIONS" .TP -.B \-s SMARTCTL +.B \-s SMARTCTL, \-\-smartctl SMARTCTL Use the .BR smartctl (8) executable at path SMARTCTL for drive database syntax check. @@ -78,7 +84,7 @@ The default is .BR /usr/local/sbin/smartctl . .TP -.B \-t TOOL +.B \-t [DIR/]TOOL, \-\-tool [DIR/]TOOL Use TOOL for download. TOOL is one of: .I curl wget lynx @@ -90,8 +96,12 @@ .\" %ENDIF OS OpenBSD .IR svn . The default is the first one found in PATH. +.br +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +A DIR could also be specified. +The plain TOOL name must then begin with any of the above names. .TP -.B \-u LOCATION +.B \-u LOCATION, \-\-url\-of LOCATION Use URL of LOCATION for download. LOCATION is one of: .br @@ -113,10 +123,37 @@ The default is .IR svn . .TP +.B \-\-url URL +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +Download from URL. +A valid OpenPGP/GPG signature with \*(Aq.raw.asc\*(Aq extension must also +exist unless \*(Aq\-\-no\-verify\*(Aq is also specified. +.TP +.B \-\-file FILE +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +Copy from local FILE. +A valid OpenPGP/GPG signature \*(AqFILE.raw.asc\*(Aq must also exist +unless \*(Aq\-\-no\-verify\*(Aq is also specified. +.\" %IF ENABLE_DB_INSTALL +.TP +.B \-\-install +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +Copy from originally installed drive database file. +This is the same as: +.br +\*(Aq\-\-no\-verify \-\-file /usr/local/share/smartmontools/drivedb.h\*(Aq +.\" %ENDIF ENABLE_DB_INSTALL +.TP .B \-\-trunk Download from SVN trunk. -This requires \*(Aq\-\-no\-verify\*(Aq unless the trunk version is still -identical to branches/RELEASE_6_0_DRIVEDB. +This requires \*(Aq\-\-no\-verify\*(Aq because the trunk versions are not +signed. +.TP +.B \-\-branch X.Y +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +Download from branches/RELEASE_\fBX\fP_\fBY\fP_DRIVEDB. +This also selects the OpenPGP/GPG key for older branches +(5.40 to 6.6: Key ID DFD22559). .TP .B \-\-cacert FILE Use CA certificates from FILE to verify the peer. @@ -132,25 +169,51 @@ .B \-\-no\-verify Don't verify signature with GnuPG. .TP +.B \-\-force +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +Allow downgrades. +By default, the database is not replaced with an older version of the +same branch. +.TP .B \-\-export\-key Print the OpenPGP/GPG public key block. .TP .B \-\-dryrun Print download commands only. .TP -.B \-v +.B \-q, \-\-quiet +[NEW EXPERIMENTAL UPDATE-SMART-DRIVEDB FEATURE] +Suppress info messages. +.TP +.B \-v, \-\-verbose Verbose output. +.TP +.B \-h, \-\-help +Print help text. .Sp .SH "EXAMPLES" +Regular update: .Vb 2 # update-smart-drivedb -/usr/local/share/smartmontools/drivedb.h updated from \e -branches/RELEASE_6_0_DRIVEDB +/usr/local/var/lib/smartmontools/drivedb.h 7.2/5225 updated to 7.2/5237 +.Ve +.PP +Revert to previous version: +.Vb 2 +# update-smart-drivedb --force \e + --file /usr/local/var/lib/smartmontools/drivedb.h.old +/usr/local/var/lib/smartmontools/drivedb.h 7.2/5237 downgraded to 7.2/5225 +.Ve +.PP +Download the database from SVN trunk to current directory: +.Vb 2 +$ update-smart-drivedb --trunk --no-verify -s - -u trac drivedb-trunk.h +drivedb-trunk.h 7.3/5254 newly installed (NOT VERIFIED) .Ve .Sp .SH "EXIT STATUS" -The exit status is 0 if the database has been successfully -updated. +The exit status is 0 if the database has been successfully updated or is +already up to date. If an error occurs the exit status is 1. .Sp .SH FILES @@ -160,23 +223,28 @@ .TP .B /usr/local/sbin/smartctl used to check syntax of new drive database. +.\" %IF ENABLE_DB_INSTALL .TP .B /usr/local/share/smartmontools/drivedb.h +originally installed drive database. +.\" %ENDIF ENABLE_DB_INSTALL +.TP +.B /usr/local/var/lib/smartmontools/drivedb.h current drive database. .TP -.B /usr/local/share/smartmontools/drivedb.h.raw +.B /usr/local/var/lib/smartmontools/drivedb.h.raw current drive database with unexpanded SVN Id string. .TP -.B /usr/local/share/smartmontools/drivedb.h.raw.asc +.B /usr/local/var/lib/smartmontools/drivedb.h.raw.asc signature file. .TP -.B /usr/local/share/smartmontools/drivedb.h.*old* +.B /usr/local/var/lib/smartmontools/drivedb.h.*old* previous files. .TP -.B /usr/local/share/smartmontools/drivedb.h.*error* +.B /usr/local/var/lib/smartmontools/drivedb.h.*error* new files if rejected due to errors. .TP -.B /usr/local/share/smartmontools/drivedb.h.lastcheck +.B /usr/local/var/lib/smartmontools/drivedb.h.lastcheck empty file created if downloaded file was identical. .Sp .SH AUTHORS @@ -200,4 +268,4 @@ .SH PACKAGE VERSION CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV .br -$Id: update-smart-drivedb.8.in 5003 2019-12-13 20:17:36Z chrfranke $ +$Id: update-smart-drivedb.8.in 5318 2022-02-18 17:23:14Z chrfranke $ diff -Nru smartmontools-7.1/update-smart-drivedb.in smartmontools-7.3/update-smart-drivedb.in --- smartmontools-7.1/update-smart-drivedb.in 2019-12-13 20:14:51.000000000 +0000 +++ smartmontools-7.3/update-smart-drivedb.in 2022-02-23 21:47:28.000000000 +0000 @@ -2,13 +2,13 @@ # # smartmontools drive database update script # -# Home page of code is: http://www.smartmontools.org +# Home page of code is: https://www.smartmontools.org # -# Copyright (C) 2010-19 Christian Franke +# Copyright (C) 2010-22 Christian Franke # # SPDX-License-Identifier: GPL-2.0-or-later # -# $Id: update-smart-drivedb.in 5002 2019-12-13 20:14:51Z chrfranke $ +# $Id: update-smart-drivedb.in 5332 2022-02-23 21:47:28Z chrfranke $ # set -e @@ -22,22 +22,24 @@ sbindir="@sbindir@" datarootdir="@datarootdir@" datadir="@datadir@" +localstatedir="@localstatedir@" +drivedbinstdir="@drivedbinstdir@" drivedbdir="@drivedbdir@" # Download tools os_dltools="@os_dltools@" -# drivedb.h update branch -BRANCH="@DRIVEDB_BRANCH@" +# Default drivedb.h update branch +default_branch="@DRIVEDB_BRANCH@" # Default drivedb location -DRIVEDB="$drivedbdir/drivedb.h" +default_drivedb="$drivedbdir/drivedb.h" # GnuPG used to verify signature (disabled if empty) -GPG="@gnupg@" +gpg="@gnupg@" -# Smartctl used for syntax check -SMARTCTL="$sbindir/smartctl" +# Default command used for syntax check +default_smartctl="$sbindir/smartctl" # PATH information for help and error messages @ENABLE_SCRIPTPATH_FALSE@pathinfo='$PATH' @@ -45,44 +47,60 @@ myname=$0 -usage() +print_help() { @ENABLE_SCRIPTPATH_TRUE@ pathinfo=" -@ENABLE_SCRIPTPATH_TRUE@ $pathinfo" +@ENABLE_SCRIPTPATH_TRUE@ $pathinfo" cat <&2 + test -z "$usageerr" || echo "Try '$myname -h' for help" >&2 exit 1 } @@ -94,15 +112,22 @@ esac } +# check_optarg "$@" +check_optarg() +{ + test $# -gt 1 || error "option '$1' requires an argument" +} + warning() { echo "$myname: (Warning) $*" >&2 } +# selecturl URL_OF selecturl() { case $1 in - github) # https://github.com/smartmontools/smartmontools/raw/origin/$BRANCH/smartmontools/drivedb.h + github) # https://github.com/smartmontools/smartmontools/raw/origin/$branch/smartmontools/drivedb.h # https://github.com/smartmontools/smartmontools/raw/master/smartmontools/drivedb.h # redirected to: url='https://raw.githubusercontent.com/smartmontools/smartmontools/master/smartmontools/drivedb.h' ;; @@ -110,7 +135,7 @@ svn) url='https://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools/drivedb.h' ;; svni) url='http://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools/drivedb.h' ;; trac) url='https://www.smartmontools.org/export/HEAD/trunk/smartmontools/drivedb.h' ;; - *) usage ;; + *) error "$1: is none of 'github sf svn svni trac'" esac } @@ -130,6 +155,11 @@ return $rc } +iecho() +{ + test -n "$quiet" || echo "$*" +} + vecho() { test -n "$q" || echo "$*" @@ -174,32 +204,35 @@ u=$1; f=$2 rc=0 - case $tool in - curl) - vrun curl ${q:+-s} -f --max-redirs 0 \ + case ${tool##*/} in + curl*) + # "Accept-Encoding" header avoids caching problems with svn URL + vrun "$tool" ${q:+-s} -f --max-redirs 0 \ + -H "Accept-Encoding: identity" \ ${cacert:+--cacert "$cacert"} \ ${capath:+--capath "$capath"} \ ${insecure:+--insecure} \ -o "$f" "$u" || rc=$? ;; - wget) - vrun wget $q --max-redirect=0 \ + wget*) + # wget >= 1.16.1 sets "Accept-Encoding: identity" header by default + vrun "$tool" $q --max-redirect=0 \ ${cacert:+--ca-certificate="$cacert"} \ ${capath:+--ca-directory="$capath"} \ ${insecure:+--no-check-certificate} \ -O "$f" "$u" || rc=$? ;; - lynx) + lynx*) test -z "$cacert" || vrun export SSL_CERT_FILE="$cacert" test -z "$capath" || vrun export SSL_CERT_DIR="$capath" # Check also stderr as lynx does not return != 0 on HTTP error - vrun2 "$f" lynx -stderr -noredir -source "$u" || rc=$? + vrun2 "$f" "$tool" -stderr -noredir -source "$u" || rc=$? ;; - svn) - vrun svn $q export \ + svn*) + vrun "$tool" $q export \ --non-interactive --no-auth-cache \ ${cacert:+--config-option "servers:global:ssl-trust-default-ca=no"} \ ${cacert:+--config-option "servers:global:ssl-authority-files=$cacert"} \ @@ -207,16 +240,16 @@ "$u" "$f" || rc=$? ;; - fetch) # FreeBSD - vrun fetch $q --no-redirect \ + fetch*) # FreeBSD + vrun "$tool" $q --no-redirect \ ${cacert:+--ca-cert "$cacert"} \ ${capath:+--ca-path "$capath"} \ ${insecure:+--no-verify-hostname} \ -o "$f" "$u" || rc=$? ;; - ftp) # OpenBSD - vrun ftp \ + ftp*) # OpenBSD + vrun "$tool" \ ${cacert:+-S cafile="$cacert"} \ ${capath:+-S capath="$capath"} \ ${insecure:+-S dont} \ @@ -232,7 +265,6 @@ check_file() { local firstchar f maxsize minsize size - test -z "$dryrun" || return 0 f=$1; firstchar=$2; minsize=$3; maxsize=$4 # Check first chars @@ -261,8 +293,111 @@ sed 's,\$''Id'': drivedb\.h [0-9][0-9]* 2[-0-9]* [012][:0-9]*Z [a-z][a-z0-9]* \$,$''Id''$,' } -# Smartmontools Signing Key (through 2020) -# +# selectkey BRANCH +selectkey() +{ + case $1 in + RELEASE_5_4[0-3]_DRIVEDB|RELEASE_6_[0-6]_DRIVEDB) +# Smartmontools Signing Key (ext. to 2024) +# Smartmontools Signing Key (through 2018) +# Smartmontools Signing Key (through 2018) +# Key ID DFD22559 +public_key="\ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFgOYoEBCAC93841SlFmpp6640hKUvZ8PbZR6OGnZnMXD6QRVzpibXGZXUDB +f6unujun5Ql4ObAWt6QuRqz5Gk2gF8tcOfN6edR/uK5gyX2rlWVLoZKOV91a3aDI +iIDh018tLWOpHg3VxgHL6f0iMcFogUYnD5zhC5Z2GVhFb/cVpj+ocZWcxQLQGPVv +uZPUQWrvdpFEzcnxPMtJJDqXEChzhrdFTXGm69ERxULOro7yDmG1Y5xWmhdGnPPM +cuCXVVlADz/Gh1w+ay7RqFnzPjqjQmHAuggns467TJEcS0yiX4LJnEoKLyPGen9L +FH6z38xHCNt4Da05/OeRgXwVLH9M95lu8d6TABEBAAG0U1NtYXJ0bW9udG9vbHMg +U2lnbmluZyBLZXkgKGV4dC4gdG8gMjAyNCkgPHNtYXJ0bW9udG9vbHMtZGF0YWJh +c2VAbGlzdGkuanBiZXJsaW4uZGU+iQFBBBMBAgArAhsDBQkPZe4NBgsJCAcDAgYV +CAIJCgsEFgIDAQIeAQIXgAUCXheK5gIZAQAKCRDzh2PO39IlWdUTCAC8v9Oa7umW ++/tXBiEtElDW/U2rEOC3OHWSzPvqE4iGjWc5fbvrAKS7bfccZM8Aq0a1t2pSbIlB +MvRrsNTGdQSPsOdhxPD8pEJW0uH9Z5VyPzoO9VIaoqi1irRdWnXCfhBJX9PLySAb +9BPQZXXQypmACieRDv31E4hiB+vYet/SpVuRyfL57XU3jmwFREip9OiFOp+61X2+ +oIlgvNU60JZy2vXpTo6PNbDGetEycfH6Y8vfCXniihMkSfeOnNqWI/hycBDprFB5 +CB5ShIH71vhCOPnVGwtYY30wlJ1+Ybg2ZAIi6JN8E38Dpx382IzeT2LydnZydiC6 +PcLCr7mbsX3hiQEcBBMBAgAGBQJeF4sWAAoJEC/N7AvTrxqr7ZAH/jB4xFtBTo1x +w8CGwslZCJ+/BeEZ5XpV+8zLdeRV2tXegUFjGZ9FI6UpzBeVyK2R1qGbcdSf2S45 +KutcM2gjKETW+ZwW76qHJD52mYihPPLXu2pRAG2WyH5GDnqNMj5iQ1inoPdZOTpi +evBMTv1YHJML6SiF6t/HoKorl5ffvHBE/1onBfUzLwQ/ct14sZ2UXHzyxdHo73vm +XWgcjQ1TQhCSdLqucQbwR78EyUa9tYxk/NWBqfc5YHt7t+KTVTLlp7Buk1wscLkj +NTlxl+IjAxRwsWc6PWnyRdAgXxtt2q6llYgFahWM21OyJVLVjbMGVF+oBtFumqq3 +lQy6H6tp/1uJAhwEEwECAAYFAl4XiyMACgkQvwsznGS8qosSiw//QjbWDldB2gHf +3Tfs+LaFdzkDbioWdnj96DiCynTSwZF8d5ISqwA+QTL/43Y0msU26WBMvIRBg2Xm ++r4TMMfWF4a1Yjq6cisKEaUsbjV9ztzH/XB2ydo8HgnxZuVKQoIuh1sSrE7p6mpQ +YUrV5eWRpqc79AI9ZzRBM5nhbBejqLVw2F8dyz6c3lfGM9IOenp+Y8N43SdNpBcp +DuHnzbQIMtkyoX7tTKDDv5gnoRNCsdBsCduTyNWYOIEdhRiCfo5Ce7kufIoo4ZqV +BM8dzwm1RrcYa0kMKPZAucJDRjwevEYDbOg7vmEYsuGPRbVmOFdx4uMx4gX8vF5+ +AG3rTSA805zkwD+WQXyYQohVZxNjeK7P/ukr6NCZx226gwAiw1ms7PYOo8snjK8e +nRlMTLKiGiMIH7xJu55JliVlcEvn3G7WO0n4qQOJj3Msh+xflBSfZmzBDAzPgxwC +m/RSmonGV0uZVJFDHCpqus35E6bzFF6yO3yXvpngAMTBrpX6Nzgea1SzlK2Iquls +te1GYAx/IXaY7cVYo4iEv/m346SINzLGHpXZkbbcenSgljBfHLCz7vF33IotfEWh +C7Kb4iKbEjERa+zzqR+vK+nDj6YG9Mvguj1EqnM47oDwgMaqWY6oPfefLCD8Tg51 +rlAAGFdcWb9g034vgtK8l+ooUtn63PKJAhwEEwECAAYFAl4XiywACgkQ6nSrJXIQ +QsUuTRAAsSMmQ7jsvmljExwrmIu6Oyh+1J5D/GPBRYhSyip/bnxCscCBnpjEk8+7 +VG9JtGTCa0zVY14Y3Cl4obND25QN9LhiE/y8olnIgJ2adtmpi6+zFpdGWVYUpDgZ +IMePUVKyZenTjezFwRlLsYsxbSb9wIR1iofP1l/dQF8DwhwFL9AGRmHTcWM1ZYoc +fv80A5SAposnspnkKKcuC3q2+pMsUtbHT9t/+iusVXBDERh+FPlvtYh+Khze3c8z +g4M9RsQLCanMp4jZhzgSakjeg9tCr33SIJIEKpn6MUftX9QC82S75UNwxXgC38EA +s2t+BjPLUaXENSdOe3l+KKY5ozbmRpRmQIHw7jlT3+9C0RUHGTPQYCidsx8OdYA0 +4wDRWcjCQcXWxTaUoeaoMJcE1iv5IIf/X0MXYMlCPG8OKAlDE2Kkrx0A8agPp7JH +0UAOaqpAA74kZnpuvJ6BqrX2hMbNbyVg1rWu1BQA3qESa41rKiWyEtjiLdQ/NtNu +6BsPhDGvaQqGbu4t0GfJ1PhbFnHrVkLW8v1NzYZRpLXAFJGZdD6Ue/L6bHFOJ6SJ +JwAHjH26nxSMuDV779AUrnOcmoXIkj6sdAwDZ5Z2ri7b2MgkrJzeapKd0SItnWUQ +TMe7YUl8B+kUATj01YWMLtHsX9yciFP0iDagW14/rFJHtchOBcu0U1NtYXJ0bW9u +dG9vbHMgU2lnbmluZyBLZXkgKHRocm91Z2ggMjAxOCkgPHNtYXJ0bW9udG9vbHMt +ZGF0YWJhc2VAbGlzdGkuanBiZXJsaW4uZGU+iQE+BBMBAgAoAhsDBgsJCAcDAgYV +CAIJCgsEFgIDAQIeAQIXgAUJD2XuDQUCXheK5gAKCRDzh2PO39IlWTDxCACtkOGn +vUs/m/uE7IHoSM6wj/6OXXo+TEM1rgnl40oySVoMgyonx7PSwi9rSoDC8AfRhN2q +bFLEQcrGI8V7PxLpjsz5Z0m/ZnZJAP7TB5WhLRJdu3w2cssjekhIRc+I2B00gcRl +H//okXyvGte3kr1JdgaownbslwcZRxyNdvWigQH/Vnz91lKAujGULJyl7hv6Kl02 +HYynYmxGmES3pd5VEOpA/DR7n54T2J+Vubh99RT+RH2v46e7LnPhZhN2uxvIiJKE +8Lp67l1aeMXfgZv6dQ7Dl+pu5lUUyyMQ+nUMBGKZBWftyqhekZrvYcVnTJYU93kU +41QULaRVIwg888kUiQEcBBMBAgAGBQJZ7kylAAoJEC/N7AvTrxqroQQH/jrZAGT5 +t8uyzRTzJCf3Bco8FqwKcfw8hhpF1Uaypa+quxkpYz9PtP+3e9lGxl0XSEzOwHjf +gGWXISUOM1ufVxo2hSLG87yO7naFAtylL8l0Zny8Fb6kmT9f3vMktbHdXHUTDNrC +UkoElEwwDK3qaur8IPUaIKeSTC3C8E/DVnasLs9cpOs2LPIKr3ishbqbHNeWOgGy +HbA4KCtvQzBhun9drmtQJW6OyCC9FcIoqPSFM/bs2KHf7qATNu9kSMg/YWw7WLAD +4GPqH9us1GigQ0h6Y4KG5EgmkFvuQFPLHvT4rtqv51zzs1iwFh4+GIagFp+HJ2jn +lp+GcZcySlwfnemJAT4EEwECACgFAlnuSe4CGwMFCQQcDQAGCwkIBwMCBhUIAgkK +CwQWAgMBAh4BAheAAAoJEPOHY87f0iVZVMQIAK5wPezq0ROsxiCYPLcR9dF/Qdp2 +1pLfodi6wsC9FAlTVJ3fk2vkNQDb5rMkNvZ/MHf2EWoVIFHvPZcJ6paBjZlapvGF +qDNrU6hDbakO0PIej5yy+qVeIYcSQpNZeHchAhOOJcnN0o8H6SzZik38b4Hb8H5X +do78LsZJwU0jsKG6LH3gjiWJtrC+WCXCMYzEGjAJXev2npU2DMVVwxsfYLfdZWq7 +FJJINv8R9EUjtSQQIynJAwb2lFvZB+jC6u8Vv9N1Wid6wh5lF5ejMt6KXqWOvNn+ +YreopmQfbn2XJZxpyn9d7Ev91epYW11E5qG4xNI3m3AmtEGjMTGjfMUstNK0V1Nt +YXJ0bW9udG9vbHMgU2lnbmluZyBLZXkgKHRocm91Z2ggMjAxOCkgPHNtYXJ0bW9u +dG9vbHMtZGF0YWJhc2VAbGlzdHMuc291cmNlZm9yZ2UubmV0PokBPgQTAQIAKAIb +AwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAl4XiZMFCQ9l7g0ACgkQ84djzt/S +JVnl5Qf+PVRoLmEpDIqQ+58DMIwz98+yajCJ1vQvEOKjMcgeePOn475eV5Phkvsp +KtW6TedWhN9l/NcDZzEPCpkhrz24WJDLFV+o16B4MZwSkGTl4/3qijERKsd8M+MS +tiLr3+eUCFi4dAp0uhPytETvUmtj3ByA0R2luoOK+kEutq6i2x9BPr8Qc55Lqdwt +SK8pPU05WSaCu1m2oThJhkELVklOQ2cj+D8MrQdJGd3plEb9j5oUbhj7LW/y0i4M +lqk1rQCQKnY3vTFQBpj1o7T6kLiGqQCOLTX0B6RQ8vt+PEzXPHi0lIdwOrQk5l7h +utnjwXmWaWEpRjlsuQ5PBrFDsD9N+IkBHAQTAQIABgUCWA5kYwAKCRDfDxpJxKSQ +Op+/CADTlsgisoXI6b+0oohRaD4ZVl5eBtkvTrxNQf6EF7Z1uPkVOqi1OLWFGyAm +beLcRmN6c4/DVcaa6GAG7GA+KQwVPRCyC+9Ibsn/+uG6ZFXAez+0eG9NxOfkCnYH +8ZP8o2VH+9uKJlGGujh9o5r1SNGVifoLGTc8NkWCW+MAKj8dw8WW+wDc80YrdCRr +SyLrRU9NLTSE4pIJWKcHLwG63xkXHQPPR1lsJgzdAalfEv1TQdIF3sM+GXp4lZ6b +uahFDiILBh1vj+5C9TdpWZAlqHDYFICa7Rv/MvQa4O9UUl3SlN3sed8zwAmL3Heo +XE5tBu8iatMaS9e3BmSsVYlhd/q+iQEcBBMBAgAGBQJYDmSWAAoJEC/N7AvTrxqr +8HsH+QGQuhHYt9Syccd8AF36psyT03mqgbGLMZL8H9ngoa9ZqVMq7O8Aqz23SGTt +uNuw6EyrcHo7Dy1311GftshI6arsFNJxE2ZNGIfGocRxu9m3Ez+AysWT9sxz/haH +E+d58NTg+/7R8YWS1q+Tk6m8dA0Xyf3tMBsIJfj0zJvuGMbCLmd93Yw4nk76qtSn +9UHbnf76UJN5SctAd8+gK3uO6O4XDcZqC06xkWKl193lzcC8sZJBdI15NszC3y/e +pnILDDMBUNQMBm/XlCYQUetyrJnAVzFGXurtjEXQ/DDnbfy2Z8efoG8rtq7v3fxS +1TC5jSVOIEqOE4TwzRz1Y/dfqSU= +=3Lcg +-----END PGP PUBLIC KEY BLOCK----- +" + ;; + + RELEASE_7_[023]_DRIVEDB) +# Smartmontools Signing Key (through 2025) +# Smartmontools Signing Key (through 2020) # Key ID 721042C5 public_key="\ -----BEGIN PGP PUBLIC KEY BLOCK----- @@ -278,47 +413,88 @@ 4ugaSp2q+6BSaAQhbZN8ULCF/oGA/376Sz7RNuoOmQwl9aFqnfl3YgopBIqKvnSP h4j0QynN45rUFOe/VywTmpWKj+DonGCupxe9VvyZ87NKRgKiHprXGDrhdB0GcNXM wV66WbjKBV7qlpSh/GH3oiHwlcYT8LNyZbxTJXcVF5ODtlZfc9zqRtUBWQARAQAB -tFNTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjApIDxzbWFy -dG1vbnRvb2xzLWRhdGFiYXNlQGxpc3RpLmpwYmVybGluLmRlPokCPgQTAQIAKAUC -XCaGlQIbAwUJA8etAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6nSrJXIQ -QsWXYQ/+IVHGQxDOg7lMX9iDbg/UDj/zrQfsJR2HQ2j0iI8TmsQLSK4pphwN0r9D -g0BuKhQBe3wPphLjwD40HueKatIacE91PgLse/KWmEe4OoQCDxshiIGad3YoIF3X -yrJg6pcMLOAnfT55Tg04EmWpT1LzWTJmH8RL2iftTM217Q2JnfQGKicTiD/GiYV1 -oyFUvn+H5/u5O7UYhvWKBcccJtal2uhc6h8U2HugMV0SpNM5p83oGDZkV0YYSJ0C -044im1+axbz06Aeq7Uh3JFScCcbjl+SQ7gK0NJF39uI8HbwC7fcfySCj5JDuVeaq -KjahWctKa/D6nauKA8+LIGOckkf2oN0sJBrES7Zn8ImHYN/1wLCff9oIDAlux6Jk -BZ6+MqIJKHit4SSYPd3QnkdI1ehn+2EdxK9VSBU0W2ZPlZmoUSamWboloumhwYyN -86ohFVJWnN4YWlZiJNJlxj/F6d4GTEJBFqoK9yStdz8Dsg16sAwuNYFVFtCKaesA -keuhcS3SfoFXwLsz+8cLfHVdsBHmm9/OCfNtOm3EPJqaD57lL5ocTWQeLaAqUCse -rOCDoIUZul5e6kRytjjNIHFNufWTbuw4YlYM3+FU1nkgckmhw4M9kI/xGtVj7bvs -tJKKN976kOoRZRIAL+9SlC+3Tqd9a4y4RRjYongvFzqpqRlQfS+JARwEEwECAAYF -AlwmhpwACgkQL83sC9OvGqsVOggAqLB5eQrUv8E9ikD6kJCito827bzDWF29yD7P -vfhjXaz5in54jOVpwg3o9CsqIjjRW0/1bBVswC8ZL0sAdZ+GDSDMw5F2IpkD77gj -nFY79M/e6C9xYyxYzHC7emDPSz9IroOvdkkEgrB+OABKkaOCcS18P4Lk3WNHaPw5 -c7aI0z1iJP52EmSfvB8r86mtUFJB+f15eD/4vaRfkZLFjF9FQ3kgEK1U+rV4s1O2 -bCFfP3WPDcc83NgwRUvtXmcSOSOIoXnemJzyJr+JnqCWVET4XWF6i20mRFXVEpWt -f5AkJYgR3z/jW0djELbBWA/35bAnpXy5pDHv9NbZsTkBZxK/kokBHAQTAQIABgUC -XCaGnQAKCRAY7NpGy/a6xn4lB/90tXTnZsgmoftol9uivfQrPdR88WmOZLYmUeQA -d1rqSFMxe+KzO/qLuU8s6OF4nznwL2cPfbGZxezM4PiYmAmbbEU/3gTONwjVBBA0 -Gfimy/fITEezFtCigo1thkaJ195g/dqY+zE3Vt4rzC03j1vx8mUHRPU6kkvKj8cP -0j+XHX2xQDsTXTstfnom29wBmGnvSZ9HgcdL71e1VXJXwikmnO3P4J/1C2LeCOlW -rGqWZ2c0WBLKdJnsYUx7Dm/OvkkB4lF+zWp98zS8jS/5h+1apVgEzrdTMvT8ydTk -Ur7ObKGkIhK+L+Xo5BD+V9Qf6xKGYPwhhdj/E5/kyjULrm10iQEcBBMBAgAGBQJc -JoadAAoJEPOHY87f0iVZfiUH/3yKS5wGvTeRInse8+W1WzKuto3XzqXLngb9QXWw -7nCwqmNS7PbzDnufQi2ThKrMfcK14WgNYABNZPU75I+6bcb0oCB5tlooIUEV/2Ut -/5Hl/83zFFoNA/kQKVz8kIDqgRcxC+zY2VJ4eTKHyQDvXygVk8wnKTBae3gX+CIZ -qJHPXiiygHlbl31Mi3G1Iaxu57dP6ocV0vX1dytKSwd4Rbviwwb4L76o/tVT9t3G -wFM15uK1SqtnAaiaktEdMi3XI4d01H3VUVz/iR0XQbf13RZoEM6CJWmsQ/qvYlwk -bKOdlahjoHrFlkhADSBaO9N1OZp3OYDjziIujMdt2IPKnmM= -=0uFV +tFNTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjUpIDxzbWFy +dG1vbnRvb2xzLWRhdGFiYXNlQGxpc3RpLmpwYmVybGluLmRlPokCQQQTAQIAKwIb +AwUJDS6amwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAl/gnzECGQEACgkQ6nSr +JXIQQsW11g//UmnWOtIgozoqs6beK12NpZyubn/lecEd0yJPzed9cygKpObySBbT +5jz7e5IDGwFLDsTm9fE/2GoyvuVW/riyTsowxrYYleoKm4Pmv30crNruVM7mC7c8 ++rbwmx5ZlmHC1tMsM/BdIxK0gqHyAXxWmzyB/YDGElkWnq2/+wjEoARbROUoKQYL +qG6q6bv/DQvv4tq/Yw+fsaLZsR4Cou87hB3wAwR3rv3p3GC7N+if86fbkS8rQh5b +j3qwTHnf3ugyYz9iEy2pjrHqgnDMV227tP2UiC2ECy3u1Z7eQvMeN2r0x8EIB79D +G7ny7ML3QXsJG9Pamg4VHlMh+Sb23GE6rRQuv9m265PeS4/6CsbuHdGer+UaG78V +N4bfFhMWpE4sjDZlQZBcm6VLbExhuS89GI7+9zYMtLoXE6Z5Mz0XFjSKlzEK94UT +RPcDdcQUHW59NvhG77SvTKN5PHGbcs+0uQkUkvaOxoovio2vWcYANG4eIPC/YvPZ +9q7f/bhMDbKid7eIvtCgvijSiYKQLjt1FtJJZRYF/EESdWWNJTs2OgSFMgSDBE3K +Da5alJyx3+IlYFwvF/khtQnGeTB1XRIGL8G7UMaNzpvJQOAEbqEiznyqoo5cNpz+ +03wTOw9IGVJ2fcvg2g+j7ffKQfs+GDYWAqicSKHDYpW2csBAW/1QE62JARwEEwEC +AAYFAl/gnzoACgkQL83sC9OvGqvE0Af/XXZ4GWMf4rEB0G3lXr9L9bvX4a/tVWz0 +hag57D6By9R6cWNDpRtKx5R0Y1Fv+O+sPHptM3P6LUsWI0d7dEf307n34FxkI/vh +4W1g8ITvhYfJWmJTzA1kNAief45uNPx0QWhGlVf4nQzhe41XnuBdFhYfOkHGf6k8 +9SJ9qWRitzE657h6mVO0EKqvjTld8w6lR2rA+oHPQnc9iDmXcZLfSTHP/NapQXPl +qtXiR1z0BkswBBaKCnJxVPpzjQA0W8jSyhQ4qPheMjOmVaFoQxZ4CbEaFI67EmVl +kwgwf+c6BlKr3DoOca/KmHYT/9dqUv1gfoYYTCm+ATN76vYCG794EokCHAQTAQIA +BgUCX+CfRQAKCRC/CzOcZLyqiwQWD/9eNQNnKWxkYL3qjSRt0DwUUaCcFDoj40rb +fRxWdU+LZKL7KjAWoRhdfaH7T30wZ9NFenrQXaU/QzuYioz1sHRwIIRYyUp2s0Jc +VHAIuOPjk6Q3TDVnbEm0AO0Er32gdxC0DYk4RfGp95n1Aw1kd2BSvKPJuZSRJrIV +f8iU3Im1KT4Avl7Fw7FEojQMMvn/qZzeo2pk/QdrrK3KnHkQwy2edx/szY82o2a5 +g5WarFFRcxVS2H/xrvNMGUL4TsWcGd3Z2oHoZ0u5A20/PpT2xG1LGXGEwBAqtMS2 +6iRAzbQFkkLhcdETTvOSqkDWkzr7NqJ6adhLOEVXsHXNLx23p1Tn+Li/ezpQ6/eQ +QDPclU19BjARmfInDq0w5V1q0RNET1J2Xu+Adxtq+Dl8TyhCmJMzO8e4htYnIRZu +90iSgZdt5cZgoH04weXCMwDugn/+Q3rzKvRUTrEfSOivJYg65D/mhbz6HoUTs4JD +SstTYa9qNCwKQGRSeis4PAgu0hCpnDAhZuN3Ja5AFC2Wi2szQ7R+Zx/JucIBm5S4 +U30W66MtsyUHeulSJ3AV3HrbFfnqu6zfQM4XLw7MpAtQUNJceS/lWfGIquAp3tY/ +IjZIHwgZqKB3czWDhM83wBzCWgAmxyzIrpb4MBYJ5PGuCyC7R/YTdtPJXxsPQl2l +znsX/9ssa4kBHAQTAQIABgUCX+CfSAAKCRDzh2PO39IlWVcuB/9UkLaPtGY4sDDV +/A7qjSvSy93mv8gkaIj9dhqoZw+r7cLiEtX04Cz9PqocOFgCYJXKrufHNNkHke2A +jE9EJfRKiPU/bkeWmrACvtrOd/DZbdmXfxTOekOr516D2ip/U8GBPw6zxfCQVot6 +htpBpB6zzMDtzMOeLnkOxoxR4EMu5K6eJ48bHvG/lbGBByyfRzhtqPh6AAA9G1CC +IdhNkaA5W1qums3N1mCXrTBnWyjaFhdnttGQfrMdHvTQ77HeL0c2axT2y5PYfrXY +2ZfZowYLEtFXRSTpDaJfgG+qem3N+pMv6SMOG/4CvlH4/3Hq0aCNvKcY5KUXfIgT +xmc3/n/wtFNTbWFydG1vbnRvb2xzIFNpZ25pbmcgS2V5ICh0aHJvdWdoIDIwMjAp +IDxzbWFydG1vbnRvb2xzLWRhdGFiYXNlQGxpc3RpLmpwYmVybGluLmRlPokCPgQT +AQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAl/gnzAFCQ0umpsACgkQ +6nSrJXIQQsVK7RAAqbZfT3wZEfJkw8MK2JlvgGWH76fHKn5ZoH5i0mA4AvN4QLbU +5Q20HmqHnO9mfAZQ6u4Tn/aFcYT7nlSsEsEmFX+s5QU2y6m2Tx9ThDbZ03ezREOS +0wNf0FOQunV9ZVPT/7cKIgWJa5mZy+LClor9OHllyGUfs9tKNzwxaHh1zBrCNJow +Fi/1bkWy3iMc7vZhWHASwPSp64KHjB4UdMz2hV4pROiUhWi7BY0exIHyZrkcANMP +Hhl9lP32ZvNbOy8osBdPUgXyK3HePD+ftcwJMkoc4mFQXYi9UY7NQpk7STRO10cx +Kq/CgDDvYxbnViRjQoJ0sfwKCaOfsnY/gea7I0aCx8uNISYpHO9iMidd/tJ7+lgx +NiKZTI0EppHYvkyMY15/NGb0gTJbYjuVYdbqDS9mnLuLQAjAX43+n9ND2NjX1o0q +Z9bBqV2VFioNmnxKqGphhRFX9jEzTklieOjhpRrd8v9ljprT6vLFNpYpeLkel8om +VFXrHxrfzKtVFcto5wqHVOcyZyE2zm1QmsS8qvWOTrNfY6p2q9MA2rysqdfgfvN7 +pNDaXutK6ooQi6YlyyTA2ANnHFKa0ncRH+dg+5OF9rhNvM7RyaBXgxF7+5gnU5Gb +VQRKbJ+LOtSKkj0pApR5AKSwyGslZ2bNVlKsADWhk5xj8QlHVlNWiht+i/6JARwE +EwECAAYFAlwmhpwACgkQL83sC9OvGqsVOggAqLB5eQrUv8E9ikD6kJCito827bzD +WF29yD7PvfhjXaz5in54jOVpwg3o9CsqIjjRW0/1bBVswC8ZL0sAdZ+GDSDMw5F2 +IpkD77gjnFY79M/e6C9xYyxYzHC7emDPSz9IroOvdkkEgrB+OABKkaOCcS18P4Lk +3WNHaPw5c7aI0z1iJP52EmSfvB8r86mtUFJB+f15eD/4vaRfkZLFjF9FQ3kgEK1U ++rV4s1O2bCFfP3WPDcc83NgwRUvtXmcSOSOIoXnemJzyJr+JnqCWVET4XWF6i20m +RFXVEpWtf5AkJYgR3z/jW0djELbBWA/35bAnpXy5pDHv9NbZsTkBZxK/kokBHAQT +AQIABgUCXCaGnQAKCRAY7NpGy/a6xn4lB/90tXTnZsgmoftol9uivfQrPdR88WmO +ZLYmUeQAd1rqSFMxe+KzO/qLuU8s6OF4nznwL2cPfbGZxezM4PiYmAmbbEU/3gTO +NwjVBBA0Gfimy/fITEezFtCigo1thkaJ195g/dqY+zE3Vt4rzC03j1vx8mUHRPU6 +kkvKj8cP0j+XHX2xQDsTXTstfnom29wBmGnvSZ9HgcdL71e1VXJXwikmnO3P4J/1 +C2LeCOlWrGqWZ2c0WBLKdJnsYUx7Dm/OvkkB4lF+zWp98zS8jS/5h+1apVgEzrdT +MvT8ydTkUr7ObKGkIhK+L+Xo5BD+V9Qf6xKGYPwhhdj/E5/kyjULrm10iQEcBBMB +AgAGBQJcJoadAAoJEPOHY87f0iVZfiUH/3yKS5wGvTeRInse8+W1WzKuto3XzqXL +ngb9QXWw7nCwqmNS7PbzDnufQi2ThKrMfcK14WgNYABNZPU75I+6bcb0oCB5tloo +IUEV/2Ut/5Hl/83zFFoNA/kQKVz8kIDqgRcxC+zY2VJ4eTKHyQDvXygVk8wnKTBa +e3gX+CIZqJHPXiiygHlbl31Mi3G1Iaxu57dP6ocV0vX1dytKSwd4Rbviwwb4L76o +/tVT9t3GwFM15uK1SqtnAaiaktEdMi3XI4d01H3VUVz/iR0XQbf13RZoEM6CJWms +Q/qvYlwkbKOdlahjoHrFlkhADSBaO9N1OZp3OYDjziIujMdt2IPKnmM= +=7MQk -----END PGP PUBLIC KEY BLOCK----- " + ;; + + *) error "No known public key for branches/$1" ;; + esac +} # gpg_verify FILE.asc FILE gpg_verify() { - local gnupgtmp opts out rc - opts="--quiet ${q:+--no-secmem-warnin} --batch --no-tty" + local gnupgtmp i out rc # Create temp home dir gnupgtmp="$tmpdir/.gnupg.$$.tmp" @@ -327,14 +503,15 @@ chmod 0700 "$gnupgtmp" # Import public key - "$GPG" $opts --homedir="$gnupgtmp" --import <&1`; then + echo "$out" >&2 + exit 1 + fi + vecho "$out" # Verify rc=0 - out=`"$GPG" $opts --homedir="$gnupgtmp" --verify "$1" "$2" &1` || rc=1 + out=`"$gpg" --batch --no-tty --homedir="$gnupgtmp" --verify "$1" "$2" &1` || rc=1 if [ $rc = 0 ]; then vecho "$out" else @@ -342,59 +519,122 @@ echo "$out" >&2 fi - rm -f -r "$gnupgtmp" + # Stop the gpg-agent possibly started by gpg + if [ -n "$gpgconf" ]; then + out=`"$gpgconf" --homedir="$gnupgtmp" --kill gpg-agent &1` || echo "$out" >&2 + fi + + # Remove temp home dir, retry on failure + i=0 + while ! out=`rm -f -r "$gnupgtmp" 2>&1`; do + let ++i + if [ $i -ge 10 ]; then + echo "$out" >&2; break + fi + vecho "$out" + sleep 1 + done + return $rc } +# get_db_version DRIVEDB > VERSION +get_db_version() +{ + local r v x + x=$(sed -n '/^[ {]*"VERSION: *[^"]*"/{s,^[ {]*"VERSION: \([1-9][./0-9]* [^"]*\)".*$,\1,p;q}' "$1") \ + || return 1 + v=${x%% *} + test -n "$v" || return 0 + if [ "${v%/*}" = "$v" ]; then # trunk: get rev from expanded SVN-Id + r=$(echo "$x" | sed -n 's,^[^$]*\$''Id: drivedb\.h \([1-9][0-9]*\) .*$,\1,p') + test -n "$r" || r="?" + v="$v/$r" + fi + echo "$v" +} + # mv_all PREFIX OLD NEW mv_all() { - mv "${1}${2}" "${1}${3}" - mv "${1}${2}.raw" "${1}${3}.raw" - mv "${1}${2}.raw.asc" "${1}${3}.raw.asc" + mv -f "${1}${2}" "${1}${3}" && \ + mv -f "${1}${2}.raw" "${1}${3}.raw" && \ + if [ -f "${1}${2}.raw.asc" ]; then + mv -f "${1}${2}.raw.asc" "${1}${3}.raw.asc" + else + rm -f "${1}${3}.raw.asc" + fi } # Parse options -smtctl=$SMARTCTL +smartctl=$default_smartctl tool= +url_of= url= +file= +quiet= q="-q" dryrun= trunk= +branch=$default_branch cacert= capath= insecure= no_verify= +force= +expkey= +usageerr=t while true; do case $1 in - -s) - shift; test -n "$1" || usage - smtctl=$1 ;; - - -t) - shift - case $1 in *\ *) usage ;; esac - case " $os_dltools " in *\ $1\ *) ;; *) usage ;; esac + -s|--smartctl) + check_optarg "$@"; shift + smartctl=$1 ;; + + -t|--tool) + check_optarg "$@"; shift tool=$1 ;; - -u) - shift; selecturl "$1" ;; + -u|--url-of) + check_optarg "$@"; shift + url_of=$1 ;; + + -q|--quiet) + quiet=t ;; - -v) + -v|--verbose) q= ;; + --url) + check_optarg "$@"; shift + url=$1 ;; + + --file) + check_optarg "$@"; shift + file=$1 ;; + + --install) + test "$drivedbinstdir" != "$drivedbdir" \ + || error "'$1' is not supported in this configuration" + file="$drivedbinstdir/drivedb.h" + no_verify=t ;; + --dryrun) dryrun=t ;; --trunk) - trunk=trunk ;; + trunk=t ;; + + --branch) + check_optarg "$@"; shift + branch=`echo "$1" | sed -n 's,^\([567]\)\.\([0-9][0-9]*\)$,RELEASE_\1_\2_DRIVEDB,p'` + test -n "$branch" || error "invalid branch version '$1'" ;; --cacert) - shift; test -n "$1" || usage + check_optarg "$@"; shift cacert=$1 ;; --capath) - shift; test -n "$1" || usage + check_optarg "$@"; shift capath=$1 ;; --insecure) @@ -403,154 +643,287 @@ --no-verify) no_verify=t ;; + --force) + force=t ;; + --export-key) - cat </dev/null 2>&1 \ - || err_notfound "$smtctl" "('-s -' to ignore)" +if [ "$smartctl" != "-" ]; then + "$smartctl" -V >/dev/null 2>&1 \ + || err_notfound "$smartctl" "('-s -' to ignore)" fi # Check for GnuPG +gpgconf= if [ -z "$no_verify" ]; then - test -n "$GPG" \ + test -n "$gpg" \ || error "GnuPG is not available ('--no-verify' to ignore)" - "$GPG" --version >/dev/null 2>&1 \ - || err_notfound "$GPG" "('--no-verify' to ignore)" + "$gpg" --version >/dev/null 2>&1 \ + || err_notfound "$gpg" "('--no-verify' to ignore)" + selectkey "$branch" + case $gpg in + */*) gpgconf="${gpg%/*}/gpgconf" ;; + *) gpgconf="gpgconf" ;; + esac + "$gpgconf" --version >/dev/null 2>&1 || gpgconf= fi +usageerr= # Use destination directory as temp directory for gpg -tmpdir=`dirname "$DEST"` +tmpdir=`dirname "$drivedb"` + +# Remove possible garbage from last download +test -n "$dryrun" || rm -f "$drivedb.new" "$drivedb.new.raw" "$drivedb.new.raw.asc" || exit 1 + +if [ -n "$url" ]; then + # Download + vecho "Download drivedb.h with $tool" + rc=0 + download "$url" "$drivedb.new" || rc=$? + if [ $rc != 0 ]; then + rm -f "$drivedb.new" + error "drivedb.h: download failed ($tool: exit $rc)" + fi + + if [ -n "$url_asc" ]; then + vecho "Download drivedb.h.raw.asc with $tool" + rc=0 + download "$url_asc" "$drivedb.new.raw.asc" || rc=$? + if [ $rc != 0 ]; then + rm -f "$drivedb.new" "$drivedb.new.raw.asc" + error "drivedb.h.raw.asc: download failed ($tool: exit $rc) ('--no-verify' to ignore)" + fi + fi +else + # Copy from local file + if [ ! -f "$file" ]; then + error "$file: file not found" + fi + if [ -n "$file_asc" ] && [ ! -f "$file_asc" ]; then + error "$file_asc: file not found ('--no-verify' to ignore)" + fi -# Adjust URLs -src=`echo "$url" | sed -e "s,/trunk/,/branches/$BRANCH/," \ - -e "s,/master/,/origin/$BRANCH/,"` -src_asc=`echo "$src" | sed "s,/drivedb\.h,/drivedb.h.raw.asc,"` -test -z "$trunk" || src=$url - -# Download -test -n "$dryrun" || rm -f "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc" - -vecho "Download ${trunk:-branches/$BRANCH}/drivedb.h with $tool" -rc=0 -download "$src" "$DEST.new" || rc=$? -if [ $rc != 0 ]; then - rm -f "$DEST.new" - error "${trunk:-$BRANCH}/drivedb.h: download failed ($tool: exit $rc)" -fi -if ! errmsg=`check_file "$DEST.new" '/' 10000 1000000`; then - mv "$DEST.new" "$DEST.error" - error "$DEST.error: $errmsg" -fi - -vecho "Download branches/$BRANCH/drivedb.h.raw.asc with $tool" -rc=0 -download "$src_asc" "$DEST.new.raw.asc" || rc=$? -if [ $rc != 0 ]; then - rm -f "$DEST.new" "$DEST.new.raw.asc" - error "$BRANCH/drivedb.h.raw.asc: download failed ($tool: exit $rc)" -fi -if ! errmsg=`check_file "$DEST.new.raw.asc" '-' 200 2000`; then - rm -f "$DEST.new" - mv "$DEST.new.raw.asc" "$DEST.error.raw.asc" - error "$DEST.error.raw.asc: $errmsg" + if ! vrun cp "$file" "$drivedb.new"; then + error "$file: copy failed" + fi + if [ -n "$file_asc" ]; then + if ! vrun cp "$file_asc" "$drivedb.new.raw.asc"; then + rm -f "$drivedb.new" + error "$file_asc: copy failed" + fi + fi fi test -z "$dryrun" || exit 0 +# Check files, adjust timestamps and permissions +if ! errmsg=`check_file "$drivedb.new" '/' 10000 1000000`; then + rm -f "$drivedb.new.raw.asc" + mv -f "$drivedb.new" "$drivedb.error" + error "$drivedb.error: $errmsg" +fi +touch "$drivedb.new" +chmod 0644 "$drivedb.new" + +if [ -f "$drivedb.new.raw.asc" ]; then + if ! errmsg=`check_file "$drivedb.new.raw.asc" '-' 200 2000`; then + rm -f "$drivedb.new" + mv -f "$drivedb.new.raw.asc" "$drivedb.error.raw.asc" + error "$drivedb.error.raw.asc: $errmsg" + fi + touch "$drivedb.new.raw.asc" + chmod 0644 "$drivedb.new.raw.asc" +fi + # Create raw file with unexpanded SVN Id # (This assumes newlines are LF and not CR/LF) -unexpand_svn_id < "$DEST.new" > "$DEST.new.raw" +unexpand_svn_id < "$drivedb.new" > "$drivedb.new.raw" +chmod 0644 "$drivedb.new.raw" -# Adjust timestamps and permissions -touch "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc" -chmod 0644 "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc" +# Check whether installed file is identical +equal= +if [ -f "$drivedb" ]; then + if [ ! -f "$drivedb.raw" ]; then + # Create missing raw file + unexpand_svn_id < "$drivedb" > "$drivedb.raw" + chmod 0644 "$drivedb.raw" + fi + # Ignore missing Id keyword expansion in new file + if cmp "$drivedb.raw" "$drivedb.new.raw" >/dev/null 2>&1 \ + && { cmp "$drivedb" "$drivedb.new" >/dev/null 2>&1 \ + || cmp "$drivedb.raw" "$drivedb.new" >/dev/null 2>&1; } + then + equal=t + fi +fi if [ -z "$no_verify" ]; then # Verify raw file - if ! gpg_verify "$DEST.new.raw.asc" "$DEST.new.raw"; then - mv_all "$DEST" ".new" ".error" - test -n "$trunk" || error "$DEST.error.raw: *** BAD signature or outdated key ***" - error "$DEST.error.raw: signature from branch no longer valid ('--no-verify' to ignore)" + if ! gpg_verify "$drivedb.new.raw.asc" "$drivedb.new.raw"; then + mv_all "$drivedb" ".new" ".error" + test -z "$equal" \ + || warning "$drivedb: *** installed file is identical to broken new file ***" + error "$drivedb.error.raw: *** BAD signature or outdated key ***" + fi +fi + +# Get version +newver=$(get_db_version "$drivedb.new") +if [ -z "$newver" ]; then + if [ -z "$force" ]; then + mv_all "$drivedb" ".new" ".error" + error "$drivedb.error: no VERSION information found ('--force' to ignore)" + fi + newver="?/?" +elif [ "${newver##*/}" = "?" ]; then + if [ -z "$trunk" ]; then + mv_all "$drivedb" ".new" ".error" + error "$drivedb.error: VERSION information is incomplete ('--trunk' to ignore)" fi fi -if [ "$smtctl" != "-" ]; then +if [ "$smartctl" != "-" ]; then # Check syntax - if ! "$smtctl" -B "$DEST.new" -P showall >/dev/null; then - mv_all "$DEST" ".new" ".error" - error "$DEST.error: rejected by $smtctl, probably no longer compatible" - fi - vecho "$smtctl: syntax OK" -fi - -# Keep old file if identical, ignore missing Id keyword expansion in new file -rm -f "$DEST.lastcheck" -if [ -f "$DEST" ]; then - if [ -f "$DEST.raw" ] && [ -f "$DEST.raw.asc" ]; then - if cmp "$DEST.raw" "$DEST.new.raw" >/dev/null 2>&1 \ - && cmp "$DEST.raw.asc" "$DEST.new.raw.asc" >/dev/null 2>&1 \ - && { cmp "$DEST" "$DEST.new" >/dev/null 2>&1 \ - || cmp "$DEST.raw" "$DEST.new" >/dev/null 2>&1; } - then - rm -f "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc" - touch "$DEST.lastcheck" - echo "$DEST is already up to date" - exit 0 - fi - mv_all "$DEST" "" ".old" - else - mv "$DEST" "$DEST.old" + if ! "$smartctl" -B "$drivedb.new" -P showall >/dev/null; then + mv_all "$drivedb" ".new" ".error" + error "$drivedb.error: rejected by $smartctl, probably no longer compatible" + fi + vecho "$smartctl: syntax OK" +fi + +# Always install if missing +rm -f "$drivedb.lastcheck" +if [ ! -f "$drivedb" ]; then + mv_all "$drivedb" ".new" "" + iecho "$drivedb $newver newly installed${no_verify:+ (NOT VERIFIED)}" + exit 0 +fi + +# Keep old file if identical +if [ -n "$equal" ]; then + if [ -f "$drivedb.new.raw.asc" ] \ + && ! cmp "$drivedb.new.raw.asc" "$drivedb.raw.asc" >/dev/null 2>&1; then + mv -f "$drivedb.new.raw.asc" "$drivedb.raw.asc" + iecho "$drivedb.raw.asc $newver updated" fi + rm -f "$drivedb.new" "$drivedb.new.raw" "$drivedb.new.raw.asc" + touch "$drivedb.lastcheck" + iecho "$drivedb $newver is already up to date${no_verify:+ (NOT VERIFIED)}" + exit 0 fi -mv_all "$DEST" ".new" "" +# Check branch and file version +oldver=$(get_db_version "$drivedb") +test -n "$oldver" || oldver="?/?" +if [ "${newver##*/}" = "?" ] \ + || [ "${oldver##*/}" = "?" ] \ + || [ "${newver%/*}" != "${oldver%/*}" ]; then + # Always install from trunk or other branch + updmsg="replaced with" +elif [ "${newver##*/}" -lt "${oldver##*/}" ]; then + # Install older file only if '--force' is used + if [ -z "$force" ]; then + rm -f "$drivedb.new" "$drivedb.new.raw" "$drivedb.new.raw.asc" + iecho "$drivedb $oldver not downgraded to $newver ('--force' to override)" + exit 0 + fi + updmsg="downgraded to" +else + updmsg="updated to" +fi -echo "$DEST updated from ${trunk:-branches/$BRANCH}${no_verify:+ (NOT VERIFIED)}" +mv_all "$drivedb" "" ".old" +mv_all "$drivedb" ".new" "" +iecho "$drivedb $oldver $updmsg $newver${no_verify:+ (NOT VERIFIED)}" diff -Nru smartmontools-7.1/utility.cpp smartmontools-7.3/utility.cpp --- smartmontools-7.1/utility.cpp 2019-10-19 15:34:34.000000000 +0000 +++ smartmontools-7.3/utility.cpp 2022-01-07 00:51:15.000000000 +0000 @@ -4,7 +4,7 @@ * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-12 Bruce Allen - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-22 Christian Franke * Copyright (C) 2000 Michael Cornwell * * SPDX-License-Identifier: GPL-2.0-or-later @@ -42,7 +42,20 @@ #include "dev_interface.h" #include "sg_unaligned.h" -const char * utility_cpp_cvsid = "$Id: utility.cpp 4974 2019-10-19 15:34:34Z chrfranke $" +#ifndef USE_CLOCK_MONOTONIC +#ifdef __MINGW32__ +// If MinGW-w64 < 9.0.0 or Windows < 8, GetSystemTimeAsFileTime() is used for +// std::chrono::high_resolution_clock. This provides only 1/64s (>15ms) resolution. +// CLOCK_MONOTONIC uses QueryPerformanceCounter() which provides <1us resolution. +#define USE_CLOCK_MONOTONIC 1 +#else +// Use std::chrono::high_resolution_clock. +#include +#define USE_CLOCK_MONOTONIC 0 +#endif +#endif // USE_CLOCK_MONOTONIC + +const char * utility_cpp_cvsid = "$Id: utility.cpp 5297 2022-01-07 00:51:15Z dpgilbert $" UTILITY_H_CVSID; const char * packet_types[] = { @@ -80,7 +93,7 @@ "(build date " __DATE__ ")" // checkout without expansion of Id keywords #endif " [%s] " BUILD_INFO "\n" - "Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org\n", + "Copyright (C) 2002-22, Bruce Allen, Christian Franke, www.smartmontools.org\n", prog_name, smi()->get_os_version_str().c_str() ); if (!full) @@ -92,7 +105,7 @@ "software, and you are welcome to redistribute it under\n" "the terms of the GNU General Public License; either\n" "version 2, or (at your option) any later version.\n" - "See http://www.gnu.org for further details.\n" + "See https://www.gnu.org for further details.\n" "\n" "smartmontools release " PACKAGE_VERSION " dated " SMARTMONTOOLS_RELEASE_DATE " at " SMARTMONTOOLS_RELEASE_TIME "\n" @@ -134,9 +147,19 @@ #endif "\n" "smartmontools configure arguments:" +#ifdef SOURCE_DATE_EPOCH + " [hidden in reproducible builds]\n" + "reproducible build SOURCE_DATE_EPOCH: " +#endif ; +#ifdef SOURCE_DATE_EPOCH + char ts[32]; struct tm tmbuf; + strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", time_to_tm_local(&tmbuf, SOURCE_DATE_EPOCH)); + info += strprintf("%u (%s)", (unsigned)SOURCE_DATE_EPOCH, ts); +#else info += (sizeof(SMARTMONTOOLS_CONFIGURE_ARGS) > 1 ? SMARTMONTOOLS_CONFIGURE_ARGS : " [no arguments given]"); +#endif info += '\n'; return info; @@ -811,6 +834,21 @@ #endif // HAVE___INT128 +// Get microseconds since some unspecified starting point. +long long get_timer_usec() +{ +#if USE_CLOCK_MONOTONIC + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + return -1; + return ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; +#else + return std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch() + ).count(); +#endif +} + // Runtime check of byte ordering, throws on error. static void check_endianness() { @@ -832,40 +870,7 @@ throw std::logic_error("CPU endianness does not match compile time test"); } -#ifndef HAVE_WORKING_SNPRINTF -// Some versions of (v)snprintf() don't append null char (MSVCRT.DLL), -// and/or return -1 on output truncation (glibc <= 2.0.6). -// Below are sane replacements substituted by #define in utility.h. - -#undef vsnprintf -#if defined(_WIN32) && defined(_MSC_VER) -#define vsnprintf _vsnprintf -#endif - -int safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap) -{ - int i; - if (size <= 0) - return 0; - i = vsnprintf(buf, size, fmt, ap); - if (0 <= i && i < size) - return i; - buf[size-1] = 0; - return strlen(buf); // Note: cannot detect for overflow, not necessary here. -} - -int safe_snprintf(char *buf, int size, const char *fmt, ...) -{ - int i; va_list ap; - va_start(ap, fmt); - i = safe_vsnprintf(buf, size, fmt, ap); - va_end(ap); - return i; -} - -static void check_snprintf() {} - -#elif defined(__GNUC__) && (__GNUC__ >= 7) +#if defined(__GNUC__) && (__GNUC__ >= 7) // G++ 7+: Assume sane implementation and avoid -Wformat-truncation warning static void check_snprintf() {} @@ -881,7 +886,7 @@ throw std::logic_error("Function snprintf() does not conform to C99"); } -#endif // HAVE_WORKING_SNPRINTF +#endif // Runtime check of ./configure result, throws on error. void check_config() diff -Nru smartmontools-7.1/utility.h smartmontools-7.3/utility.h --- smartmontools-7.1/utility.h 2019-10-19 15:34:34.000000000 +0000 +++ smartmontools-7.3/utility.h 2022-01-07 00:51:15.000000000 +0000 @@ -4,7 +4,7 @@ * Home page of code is: https://www.smartmontools.org * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-19 Christian Franke + * Copyright (C) 2008-21 Christian Franke * Copyright (C) 2000 Michael Cornwell * * SPDX-License-Identifier: GPL-2.0-or-later @@ -13,7 +13,7 @@ #ifndef UTILITY_H_ #define UTILITY_H_ -#define UTILITY_H_CVSID "$Id: utility.h 4974 2019-10-19 15:34:34Z chrfranke $" +#define UTILITY_H_CVSID "$Id: utility.h 5297 2022-01-07 00:51:15Z dpgilbert $" #include // *DBL_MANT_DIG #include @@ -35,7 +35,6 @@ #elif defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO // Check format of __mingw_*printf() instead of MSVCRT.DLL:*printf() #define __attribute_format_printf(x, y) __attribute__((format (gnu_printf, x, y))) -#define HAVE_WORKING_SNPRINTF 1 #else #define __attribute_format_printf(x, y) __attribute__((format (printf, x, y))) #endif @@ -55,15 +54,6 @@ inline bool str_starts_with(const std::string & str, const char * prefix) { return !strncmp(str.c_str(), prefix, strlen(prefix)); } -#ifndef HAVE_WORKING_SNPRINTF -// Substitute by safe replacement functions -int safe_snprintf(char *buf, int size, const char *fmt, ...) - __attribute_format_printf(3, 4); -int safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap); -#define snprintf safe_snprintf -#define vsnprintf safe_vsnprintf -#endif - // Convert time to broken-down local time, throw on error. struct tm * time_to_tm_local(struct tm * tp, time_t t); @@ -321,6 +311,11 @@ inline const char * uint128_hilo_to_str(char (& str)[SIZE], uint64_t value_hi, uint64_t value_lo) { return uint128_hilo_to_str(str, (int)SIZE, value_hi, value_lo); } +/// Get microseconds since some unspecified starting point. +/// Used only for command duration measurements in debug outputs. +/// Returns -1 if unsupported. +long long get_timer_usec(); + #ifdef _WIN32 // Get exe directory //(implemented in os_win32.cpp)