import smartmontools 7.0

Downloaded source from
https://sourceforge.net/projects/smartmontools/files/smartmontools/7.0/
and imported here to git.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2019-06-25 19:11:05 +02:00
parent a818ba584c
commit ff28b140e6
112 changed files with 15517 additions and 10616 deletions

View File

@ -1,4 +1,4 @@
$Id: AUTHORS 4403 2017-03-09 20:31:15Z chrfranke $
$Id: AUTHORS 4844 2018-12-02 16:56:12Z chrfranke $
Developers / Maintainers / Contributors:
@ -25,9 +25,11 @@ Song Liu <songliubraving@fb.com>
Dan Lukes <dan+smartmontools.changelog@obluda.cz>
Kai Mäkisara <kai.makisara@kolumbus.fi>
Nidhi Malhotra <nidhi.malhotra@pmcs.com>
Harry Mallon <hjmallon@gmail.com>
Eduard Martinescu <martines@rochester.rr.com>
Frédéric L. W. Meunier <...>
Kimihiro Nonaka <...>
Gabriele Pohl <contact@dipohl.de>
Alex Samorukov <samm@os2.kiev.ua>
Keiji Sawada <card_captor@users.sourceforge.net>
Manfred Schwarb <manfred99@gmx.ch>

893
ChangeLog
View File

@ -1,4 +1,895 @@
$Id: ChangeLog 4594 2017-11-05 15:21:35Z chrfranke $
$Id: ChangeLog 4883 2018-12-30 14:48:54Z chrfranke $
2018-12-30 Christian Franke <franke@computer.org>
smartmontools 7.0
2018-12-29 Christian Franke <franke@computer.org>
smartctl.8.in: Remove extra quote.
INSTALL: Update or remove various outdated info.
2018-12-28 Christian Franke <franke@computer.org>
configure.ac: Set drivedb.h branch to 7.0.
update-smart-drivedb.in: Update public key block.
update-smart-drivedb.8.in: Update key ID.
Create new branch RELEASE_7_0_DRIVEDB.
Sign drivedb.h using new key ID 721042C5.
2018-12-27 Christian Franke <franke@computer.org>
do_release: Add quotes to AC_INIT regex.
configure.ac: Update PACKAGE_HOMEPAGE.
configure.ac: Set release number to 7.0
smartctl.cpp: Set JSON format version to 1.0 (#766).
scsiprint.cpp: Omit JSON values for unavailable counters from
Format Status log page. This ensures that each JSON value always
has the same type.
drivedb.h:
- SandForce Driven SSDs: Kingston E50 (#756)
- WDC HGST Ultrastar He10 (#959, #997, #1093, #1111)
- Toshiba 2.5" HDD MQ04UBF... (USB 3.0) (#937)
- Seagate Barracuda 7200.10: HP OEM 160GB (#1037)
- Seagate Constellation ES.3: HP OEM 4TB
- Seagate Exos 5E8 (#1058)
- Seagate IronWolf Pro (#1076, GH issues/10, GH issues/14)
- WD Blue and Green SSDs: Rename, add Green (#980, #1073)
2018-12-20 Donald Pierce <...>
drivedb.h:
- Dell Certified Intel S3520 Series SSDs (#1147)
- Dell Certified Intel S4x00/D3-S4x10 Series SSDs (#1148)
2018-12-20 Christian Franke <franke@computer.org>
drivedb.h:
- SandForce Driven SSDs: Kingston HyperX Fury (#805)
- Phison Driven SSDs: PNY CS2211 (#992)
- JMicron based SSDs: ADATA SX390 (#818),
KingSpec KDM-SA.51-008GMJ (#741)
- SiliconMotion based SSDs: KingSpec KSD, KingSpec T60,
Team Group L5Lite 3D (#1144), Transcend ESD400
- USB: Transcend ESD400 (0x2174:0x2000)
smartd.cpp: Remove unneeded '.c_str()' call. Update a comment.
configure.ac: Use AS_HELP_STRING instead of AC_HELP_STRING
as suggested by autoupdate. Add missing check for 'enableval'.
2018-12-16 Christian Franke <franke@computer.org>
smartd.8.in: Don't use empty lines before '.SH' macros.
smartd.cpp: [_WIN32] Remove check for '-m [sys]msgbox'.
nvmeprint.cpp: Don't print NSID in SMART/Health Information title
line. This log is always read with broadcast NSID.
2018-12-16 Giuseppe Iuculano <iuculano@debian.org>
cciss.cpp: Fix kFreeBSD build (Debian kfreebsd.patch).
smartd.service.in: Declaring After=syslog.target is unnecessary by
now because syslog is socket-activated and will therefore be started
when needed (Debian removesyslogtarget.patch).
2018-12-11 Christian Franke <franke@computer.org>
smartd.conf.5.in: Update DEVICESCAN info and move it up to a
new section. Add section header for DEFAULT SETTINGS.
smartctl.8.in, smartd.8.in, smartd.conf.5.in: Remove EXPERIMENTAL
notes for features added before 6.5.
os_linux.cpp: Call realpath() with full /sys/* path instead of
device name (GH pull/23). This fixes detection of hpsa devices
(regression from r4603).
2018-12-11 Harry Mallon <hjmallon@gmail.com>
scsinvme.cpp: Fix debug message.
2018-12-05 Christian Franke <franke@computer.org>
smartctl.8.in, smartd.conf.5.in: Mark '-d sntjmicron' as
EXPERIMENTAL.
drivedb.h: Enable JMicron JMS583 entry, use an internal -d option.
scsinvme.cpp: Detect this internal -d option and ask user to test
'-d sntjmicron'.
scsinvme.cpp: Add missing include of config.h.
2018-12-05 Harry Mallon <hjmallon@gmail.com>
Add '-d sntjmicron[,NSID]' device type for NVMe drives behind
JMicron USB to NVMe bridges (JMS583).
2018-12-04 Christian Franke <franke@computer.org>
os_linux.cpp: Add '-d by-id' option to device scanning.
If specified, scan '/dev/disk/by-id/*' for symlinks to '/dev/sdX'
and remove duplicates.
2018-12-02 Christian Franke <franke@computer.org>
drivedb.h:
- Samsung based SSDs: CM851 (#1109), SM863a (#1140)
- SiliconMotion based SSDs: Transcend 420K (GH issues/20),
Transcend 630 (#1038)
- Western Digital Gold: Re-add 8TB *2 variant
- USB: Buffalo HD-PNTU3 (0x0411:0x01e7), HD-LC3 (0x0411:0x027e)
- USB: ADATA NH13 (0x125f:0xa13a), HD710P (0x125f:0xa75a)
- USB: Verbatim External Hard Drive (0x18a5:0x0408) (#1107)
AUTHORS: Add Harry Mallon.
2018-12-02 Harry Mallon <hjmallon@gmail.com>
drivedb.h: USB: LaCie Rugged Mini HDD (0x059f:0x106b)
Fix many typos.
ataprint.cpp: Fix Form Factor string with bits set in reserved area
- Happens with APPLE SSD SD0256F
2018-11-27 Christian Franke <franke@computer.org>
os_linux.cpp: Add USB ID detection for '/dev/sgN'.
smartd_warning.sh.in: Fix typo (#1138).
2018-11-27 Harry Mallon <hjmallon@gmail.com>
autogen.sh: allow automake 1.16 and 1.16.1.
2018-11-25 Christian Franke <franke@computer.org>
drivedb.h:
- Crucial/Micron BX/MX1/2/3/500, M5/600, 1100 SSDs: Micron 1100
alternative ID string (#1131)
- SandForce Driven SSDs: Comay BladeDrive E28 (#823),
MX-DS FUSION (#900), OCZ Deneva 2 *.C (#1119), OCZ-VERTEX3 LT
- Phison Driven SSDs: Kingston A400 with extra space in ID (#801)
- Samsung based SSDs: SM951 *HDGM variant (patch from #1113)
- SiliconMotion based SSDs: KingDian S400 (#1116)
- Western Digital Gold: 1TB, 2TB (#1035, #1047), 8TB (#1033),
12TB, attribute 22 "Helium_Level" (patch from #1115)
2018-11-25 Cameron Costa <cameron.costa@intel.com>
drivedb.h: Intel S4510 M.2 (#1121, #1122, #1123, #1133)
2018-11-13 Christian Franke <franke@computer.org>
os_linux.cpp: Drop device scan support for obsolete devfs.
Implement new version of scan_smart_devices(). This avoids
duplicates if multiple '-d TYPE' options are specified.
dev_interface.cpp, dev_interface.h: Add default implementation for
old version of scan_smart_devices().
2018-11-02 Oleksii Samorukov <samm@os2.kiev.ua>
os_darwin.cpp, os_freebsd.cpp: fix return value in error paths
patch provided by rikard.falkeborn (github)
2018-11-02 Christian Franke <franke@computer.org>
json.cpp: Allow UTF-8 characters in strings.
ataprint.cpp: Add JSON support for '-l defects'.
Add numeric values to JSON 'interface_speed' info.
Replace local 'le*_to_uint()' with 'sg_get_unaligned_le*()'.
ataprint.cpp, ataprint.h: Remove request to send '-l defects' output.
Remove 'pending_defects_info' flag.
smartctl.cpp, smartctl.8.in: Add '-l defects' to '-x' output.
2018-10-25 Christian Franke <franke@computer.org>
json.cpp, json.h: Add 'pretty' print option.
smartctl.cpp, smartctl.8.in: Add '--json=c' option to disable
pretty-printing.
ataprint.cpp, nvmeprint.cpp, smartctl.cpp: Use const references
for json::ref function parameters.
json.cpp, json.h: Clean up usage of 'int64_t' and 'long long'.
Use PRI?64 instead of "ll?" in printf() format strings.
This re-enables build on older versions of MinGW.
2018-10-23 Christian Franke <franke@computer.org>
json.cpp: Remove extra space after JSON key names.
json.cpp, json.h: Remove return of self reference from operator=().
json.cpp, json.h: Change handling of unsafe and 128-bit integers:
Output as string 'KEY_s' and LE byte array 'KEY_le' if range exceeded
or verbose mode enabled.
smartctl.cpp, smartctl.8.in: Add '--json=v' option.
2018-10-17 Christian Franke <franke@computer.org>
os_win32/popen_win32.cpp, os_win32/popen.h: New popen()/pclose()
for Windows. Unlike MSVCRT _popen(), it does not open a new console.
os_win32.cpp: Remove run_cmd(), use popen() instead.
os_win32/daemon_win32.cpp, os_win32/daemon_win32.h: Remove
daemon_spawn().
smartd.cpp: Remove _WIN32 specific usage of daemon_spawn(),
use generic code with popen() also on Windows.
Place quotes around warning script path on Windows.
Makefile.am, os_win32/vc14/smart*.vcxproj*: Add new files.
2018-10-17 Rick Chen <juihsiang.chen@gmail.com>
scsiprint.cpp: Add SCSI information to JSON output as below:
- Drive trip temperature (#1079)
- Error counter log read/write/verify (#1079)
- Grown defect list (#1082)
- Percentage used endurance indicator (#1083)
2018-10-14 Christian Franke <franke@computer.org>
drivedb.h:
- Crucial/Micron BX/MX1/2/3/500, M5/600, 1100 SSDs: MX500 M.2
- Samsung based SSDs: Samsung SM841 (#1043), PM841 (#1052),
Samsung 860 EVO (#1034, #1040, #1051, #1059),
Samsung 860 PRO (#1010, #1068, #1102, #1103, #1104),
Samsung Portable SSD T5 (#1050)
- USB: Samsung Portable SSD T5 (0x04e8:0x61f5) (#1050)
os_darwin.cpp: Add missing braces to SMART RETURN STATUS LBA register
setting. Detected by g++ 7.3 -Wmisleading-indentation.
2018-10-11 Christian Franke <franke@computer.org>
os_win32.cpp: Decode Windows 10 1809 and Server 2019 build number.
Move "(64)" to end of version info.
os_linux.cpp: Fix '-d megaraid' open crash on missing /proc/devices.
There is no /proc/devices on ESXi (see #800) and WSL.
2018-10-09 Christian Franke <franke@computer.org>
smartd.cpp: Move code for '--capabilities' to separate functions.
smartd.cpp: Rework main loop.
smartctl.cpp, smartd.cpp, os_linux.cpp, os_solaris.cpp:
Replace all uses of EXIT() macro. Use early return where possible,
use throw otherwise.
utility.h: Remove EXIT() macro.
utility.cpp: Detect more C++ language versions for -V option.
drivedb.h:
- Crucial/Micron BX/MX1/2/3/500, M5/600, 1100 SSDs: Rename,
BX500 (#1095)
- Seagate Samsung SpinPoint F4 EG (AF) (#1090)
- Seagate Momentus 5400.6: Add '-F xerrorlba' (#1094)
- USB: JMicron JM562 (0x152d:0x0562) (IDENTIFY only, see #966)
- USB: VIA VL715 (0x2109:0x0715) (#1098)
2018-10-09 Anthony D'Atri <anthony.datri@gmail.com>
drivedb.h: (#1096)
- Samsung based SSDs: Samsung PM863a (#951, #952, #961, #962, #972)
- Intel 730 and DC S35x0/3610/3700 Series SSDs: Dell-flavor S3500
2018-10-09 Thomas Niedermeier <tniedermeier@thomas-krenn.com>
drivedb.h: Samsung PM883 and SM883 (GH pull/19)
2018-09-27 Christian Franke <franke@computer.org>
INSTALL: Update list of default ./configure options.
utility.cpp: Add check of sg_get_unaligned_[bl]e16() and *32 to
check_endianness().
utility.cpp, utility.h: Optionally use C++11 'std::regex' instead of
POSIX regex(3).
configure.ac: Add option '--with-cxx11-regex'.
utility.cpp, utility.h: Simplify 'class regular_expression', remove
unneeded flag parameters, remove unused function.
atacmds.cpp, knowndrives.cpp, os_win32.cpp, smartd.cpp: Adjust usage
accordingly.
configure.ac, utility.cpp, utility.h: Remove replacement for missing
'strtoull()'.
configure.ac: Change default for '--with-nvme-devicescan' to 'yes'
on Linux and Windows. Keep 'no' on FreeBSD, NetBSD and Darwin.
2018-09-26 Christian Franke <franke@computer.org>
configure.ac: Print warning if systemd(1) is present but
libsystemd-dev package is missing.
smartd.cpp: Notify READY=1 to systemd just before first sleep() to
ensure that the signal handlers are set.
smartd.cpp: Always ignore failure of ATA SMART ENABLE command if
'-T permissive' is specified. Useful for testing on virtual
machines.
2018-09-21 Christian Franke <franke@computer.org>
configure.ac, os_linux.cpp: Remove redundant define WITH_SELINUX.
configure.ac: Check for 'libcap-ng' only on Linux.
Rework __USE_MINGW_ANSI_STDIO test for MinGW runtime.
Print 'deprecated' warning for '--without-working-snprintf'.
Add systemd(1) notify support to smartd (#1081):
configure.ac: Add option '--with-libsystemd'.
Makefile.am: Add linker flag and man page conditional.
smartd.cpp: If environment variable NOTIFY_SOCKET is set, use
sd_notify(3) to inform the service manager about state changes.
smartd.service.in: Set 'Type=notify'.
smartd.8.in: Document new functionality.
2018-09-16 Christian Franke <franke@computer.org>
atacmds.cpp: Avoid possible virtual call in dtor
(cppcheck 1.84: virtualCallInConstructor).
os_win32.cpp: Use unsigned int for bit shifts
(cppcheck 1.84: shiftTooManyBitsSigned).
Makefile.am: Set HAVE_WORKING_SNPRINTF also in VC14 config.h.
os_netbsd.cpp: Add spaces between string literals and macros for
C++11 (g++ -Wliteral-suffix).
ataprint.cpp: Add JSON support for '-l selective'.
drivedb.h: Update or remove links in warning messages.
drivedb.h: Crucial/Micron BX300, MX1/2/3/500, M5/600, 1100 SSDs:
- Rename,
- Crucial BX300 (GH pull/16, #963),
- Crucial MX300 750GB,
- Crucial MX500 (#977, #994, #995, #1004, #1024),
- Micron M500IT (#958),
- Micron 1100 OEM (GH pull/17),
- fix name of attribute 202 and 248.
2018-09-12 Christian Franke <franke@computer.org>
ataprint.cpp: Get JSON values 'temperature.op_limit_min/max' from
Device Statistics.
atacmds.h, ataprint.cpp: Print ACS-4 max operating temperature
from SCT Status.
Makefile.am: Remove define of 'HAVE_GETOPT_LONG'.
os*.cpp: Remove remaining checks for 'HAVE_GETOPT_LONG'.
configure.ac: Remove check for 'uname()'.
os_generic.cpp, os_qnxnto.cpp: Remove function 'unsupported()'.
drivedb.h:
- HGST Deskstar NAS: *6040ALE614 (#935, #1089)
- HGST Ultrastar DC HC520 (He12) (#1086)
2018-09-12 Anthony D'Atri <anthony.datri@gmail.com>
drivedb.h: Micron 5100 Pro / 5200 SSDs (#1071)
2018-09-11 Oleksii Samorukov <samm@os2.kiev.ua>
os_freebsd.cpp: Fix build on FreeBSD 12, patch by fernape@
2018-09-10 Christian Franke <franke@computer.org>
drivedb.h:
- Seagate Enterprise Capacity 3.5 HDD: V5.1 (#1087)
- Seagate Exos X12 HDD (#1042, #1046)
- Western Digital VelociRaptor (AF): WD5000BHTZ (patch from #1041)
2018-09-10 David Purdy <david.c.purdy@gmail.com>
drivedb.h: Phison Driven SSDs: Kingston A400 (#801)
2018-09-02 Christian Franke <franke@computer.org>
dev_intelliprop.h: Fix copyright info.
ataprint.cpp, nvmeprint.cpp: Change JSON value 'power_on_hours'
to 'power_on_time.hours'. Add '.minutes' if available.
scsiprint.cpp: Add JSON values 'power_on_time.hours/minutes' from
Seagate factory lpage or from background scan lpage.
2018-08-20 Christian Franke <franke@computer.org>
Add missing license headers to some source files.
2018-08-19 Christian Franke <franke@computer.org>
Add SPDX-License-Identifier to all files with GPL header (#919).
Remove GPL headers. Remove outdated info about smartsuite.
getopt/*, regex/*: Replace with current version from glibc 2.28
(2018-08-01). Add _GETOPT/REGEX*_STANDALONE configurations.
Makefile.am, os_win32/vc14/smart*.vcxproj*: Set *_STANDALONE.
Add new files.
examplescripts/README: Update mailing list address.
os_solaris_ata.s: Remove old mailing list address.
os_win32/wbemcli_small.h: Remove this file.
The file <wbemcli.h> is usually provided by recent MinGW packages.
configure.ac: Remove check for <wbemcli.h>.
Makefile.am, os_win32/wmiquery.h, os_win32/vc14/smart*.vcxproj*:
Remove usage of 'wbemcli_small.h'.
ataprint.cpp, nvmeprint.cpp: Add JSON values 'power_cycle_count'
and 'power_on_hours'.
json.cpp, json.h: Add 'set_if_safe_*' member functions.
2018-08-13 Christian Franke <franke@computer.org>
ataprint.cpp: Add JSON support for '-l devstat'.
Add JSON support also for old SCT Status format.
2018-08-10 Christian Franke <franke@computer.org>
smartctl.cpp, os_win32/wmiquery.h: Add missing printf() format checks.
This also silences -Wformat-nonliteral warnings from clang++ 5.0.
os_win32.cpp: Increase IOCTL_ATA_PASS_THROUGH timeout to 60 seconds.
2018-08-10 Zhdan Bybin <zhdan.bybin@intel.com>
drivedb.h:
- Intel S3520 Series SSDs (#985)
- Intel S4510/S4610/S4500/S4600 Series SSDs (#912, #928, #1000)
2018-08-04 Christian Franke <franke@computer.org>
Remove int64.h, use <inttypes.h> or <stdint.h> instead.
configure.ac, utility.cpp, utility.h: Add 128-bit unsigned integer
to string conversion. Provides full integer precision if compiler
supports '__int128' (e.g. x86_64 GCC and CLang).
json.cpp, nvmeprint.cpp: Use these new functions.
Makefile.am: Adjust config-vc14 target.
2018-08-02 Christian Franke <franke@computer.org>
scsicmds.h, scsiprint.cpp: Add support for SAS host managed drives
(patch from #1045).
2018-08-01 Christian Franke <franke@computer.org>
dev_interface.cpp, scsiata.cpp, smartctl.8.in, smartd.conf.5.in:
Add option '-d scsi+TYPE' to disable SAT auto detection.
Useful in conjunction with TYPEs 'aacraid' and 'cciss' (#871).
2018-07-31 Christian Franke <franke@computer.org>
drivedb.h:
- Phison Driven SSDs: Kingston DC400 (#933, #1011), move GOODRAM to ...
- Phison Driven OEM SSDs: ... here, PC Engines msata16d (#967),
INTENSO SATA III TOP (#1053)
- USB: Iomega MDHD500-U (0x059b:0x0274) (#1003)
- USB: Freecom (0x07ab:0xfc17) (#1049)
- USB: JMicron JMS539 (0x152d:0x0539/0x2801) (patch from #970)
- USB: JMicron (0x152d:0x0561) (#945)
- USB: JMicron JMS567 (0x152d:0x2567) (#948)
- USB: JMicron (0x152d:0x578e) (#987)
json.cpp: Add missing ';' to '--json=g' output of 128-bit values.
2018-07-29 Christian Franke <franke@computer.org>
os_win32.cpp: Decode Windows Server 1803 build number.
Improve search for actual CSMI port number.
2018-06-21 Christian Franke <franke@computer.org>
os_linux.cpp: Rework handling of glob() return code.
Don't abort device scan on missing '/dev/discs' (#1036).
os_win32.cpp: Decode Windows 10 1803 build number.
Silence g++ 7.3 -Wformat-truncation warning.
2018-04-19 Christian Franke <franke@computer.org>
utility.cpp, utility.h: Use array reference for buffer parameter
of dateandtimezoneepoch(). Remove no longer used dateandtimezone().
utility.cpp: Add check of sg_get_unaligned_[bl]e64() to
check_endianness().
2018-04-16 Douglas Gilbert <dgilbert@interlog.com>
switch usage of unaligned.h to sg_unaligned.h which is functionally
the same. sg_unaligned.h is the same header used by libsgutils which
is the basis of the sg3_utils, sdparm and ddpt packages available on
many of the same architectures as smartmontools is. This change
introduces a "sg_" prefix on the inline functions defined
sg_unaligned.h . The new header has specializations for big and little
endian machines that depends on the non-standard bswap_16(), bswap_32()
and bswap_64() calls. They are defined in the byteswap.h header which is
a GNU extension. According to the 'net both gcc and clang use intrinsics
{assembler ?} to implement these calls. If the byteswap.h header is not
present on the build machine, the generic implementations will be
used for the "unaligned" family of functions. Additionally the generic
implementations can be imposed with './configure --disable-fast-lebe'.
Developers may need to use './autogen.sh' prior to their normal build
sequence. Please report any problems to the author.
2018-03-28 Christian Franke <franke@computer.org>
ataprint.cpp, nvmeprint.cpp, scsiprint.cpp:
Output JSON 'user_capacity' as 'blocks' and 'bytes'.
Handle both as unsafe ints.
smartd.cpp: Ignore remaining percentage in initial check of
self-test execution status.
scsiata.cpp: Fix device type info for 'usbcypress'.
os_linux.cpp: Fix device scan crash on missing /proc/devices.
update-smart-drivedb.in, update-smart-drivedb.8.in:
Add option '-u github'.
2018-03-20 Christian Franke <franke@computer.org>
nvmeprint.cpp: Add initial JSON support for '-i', '-H' and '-A'.
json.cpp, json.h: Add support for 64 and 128 bit unsigned
integers. Add 'set_unsafe_*()' member functions to print unsigned
integers >= 53 bit as JSON number and string.
2018-03-07 Douglas Gilbert <dgilbert@interlog.com>
smartd.cpp:
- continue to use READ CAPACITY(10) first on unseen
SCSI devices but once we discover the need for
READ CAPACITY(16) use it for subsequent accesses
dev_interface.h:
- struct scsi_device: add set_rcap16_first() and
use_rcap16() const methods
scsicmds.cpp:
- use scsi_device::set_rcap16_first() when READ
CAPACITY(10) reports 32 bits can't represent the
number of blocks
2018-03-06 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h:
- add Transcend PSD SSD family (#979)
- add Toshiba HK4R Series SSD (#898)
- extend Western Digital Re regexp (#896)
- extend Wester Digital Se regexp (#953)
- add Smartbuy ignition plus (#976)
2018-03-05 Gabriele Pohl <contact@dipohl.de>
drivedb.h:
- Add Seagate IronWolf 12TB ST12000VN0007-2GS116 (#988)
2018-03-05 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h: add Seagate Barracuda Pro family (#981)
2018-03-01 Alex Samorukov <samm@os2.kiev.ua>
os_freebsd.cpp: Fix build under -CURRENT (patch by cy@)
2018-02-28 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h:
- Add SanDisk SDSSDH2128G (#982)
2018-02-27 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h:
- extend PLEXTOR PX regexp (#934)
- add Seagate Enterprise NAS HDD family (#946)
- add SanDisk SDSA6MM-* family (#965)
- fix Seagate Laptop HDD regexp (#955)
- add Seagate Barracuda Compute series (#927)
- extend Seagate Enterprise Capacity 3.5 HDD regexp (#956)
2018-02-26 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h:
- add Seagate XF1230 SSD (GH: issues/4)
- add Intel SSD Pro 5400s Series (GH: pull/5)
- add SanDisk-SD8SN8U-256G-1006 (GH: pull/3)
- add Toshiba Q300 SSD series (#932)
- extend HGST Deskstar NAS regexp (#975)
- add KINGSTON SNS4151S316GD SSD (#902)
2018-02-20 Christian Franke <franke@computer.org>
os_netbsd.cpp: Apply patch-os_netbsd.cpp 1.1 (2017-12-15) from
pkgsrc.se/sysutils/smartmontools: Add missing <sys/stat.h>.
configure.ac, int64.h: Remove support for pre-C99 environments without
<inttypes.h> and <stdint.h>.
configure.ac: Add '-Wformat=2 -fstack-protector-strong' unless
CXXFLAGS include other '-W' or '-f' options.
2018-02-16 Christian Franke <franke@computer.org>
drivedb.h:
- USB: Default to '-d sat' for Toshiba (0x0480), Seagate (0x0bc2),
Western Digital (0x1058), Initio (0x13fd), ASMedia (0x174c).
Keep known exceptions. Merge some entries.
2018-02-08 Douglas Gilbert <dgilbert@interlog.com>
nvme on windows: just some code comments. Seems as though
W10 tries to completely neuter the idea of a pass-through.
2018-01-06 Douglas Gilbert <dgilbert@interlog.com>
scsi subsystem: improve dStrHex() signature, adjust
invocations. Adjust scsi_format_id_string() signature.
Add smartctl support for Pending Defects (sub-)log page;
seems similar to 'smartctl -l defects' but that is ATA
only. Needs to be generalized (as it will probably appear
in NVMe also).
2018-01-04 Douglas Gilbert <dgilbert@interlog.com>
scsi subsystem: preparation for decoding more log pages.
2018-01-01 Alex Samorukov <samm@os2.kiev.ua>
os_freebsd.cpp: fix build with CLANG/6. Patch provided by
Dimitry Andric, PR 224826
2018-01-01 Christian Franke <franke@computer.org>
Happy New Year! Update copyright year in version info.
2017-12-30 Douglas Gilbert <dgilbert@interlog.com>
scsi subsystem: add code to check for both log pages
and subpages, subpages were not checked for previously.
Add decoding for Format Status log page. Associated
cleanups. Tighten checking for Seagate and Hitachi
vendor specific log pages; '-T permissive' will relax
checks back to the situation before this patch
2017-12-29 Douglas Gilbert <dgilbert@interlog.com>
unaligned.h: fix inconsistency in function argument
of get_unaligned_be24()
2017-12-29 Douglas Gilbert <dgilbert@interlog.com>
Add --enable-scsi-cdb-check option to ./configure that
results in a SCSI cdb sanity check prior to SCSI generic
pass-through in Linux. [So it does not sanity check
Megaraid and 3ware (etc) pass-throughs (but could).] When
selected defines SCSI_CDB_CHECK in config.h . This may be
temporary. This patch is an attempt to catch strange
frames (perhaps SATA FIS) being sent to the SCSI
pass-through.
2017-12-29 Douglas Gilbert <dgilbert@interlog.com>
Rework scsiGetSize() and remove scsiGetProtPBInfo().
Convert scsicmds.cpp to use unaligned.h get and put.
2017-12-27 Alex Samorukov <samm@os2.kiev.ua>
Add unaligned.h header file to the Makefile.am
2017-12-27 Douglas Gilbert <dgilbert@interlog.com>
Add unaligned.h header file; has get and put variants of
unaligned be16,24,32,48,64 and le16,24,32,48,64 copies
plus all_zeros() and all_ffs() helpers. All inline.
2017-12-27 Douglas Gilbert <dgilbert@interlog.com>
Remove UINT8, INT8, UINT32 and INT32 typedefs in favour
of the types from <stdint.h>; for example uint8_t
2017-12-27 Douglas Gilbert <dgilbert@interlog.com>
nvmecmds.cpp: according to NVMe 1.3a spec, the SMART/
health information log page is global and should take
the global nsid (all ff_s). It also says the Error
info lpage is "global. Broke WD Black PCIe (NVMe)
SSD but worked on Intel SSDs. Fix; could break others.
2017-12-27 Douglas Gilbert <dgilbert@interlog.com>
os_freebsd.cpp: on error was setting set_nvme_err() to 1,
not the actual NVMe status value; fix.
2017-12-24 Alex Samorukov <samm@os2.kiev.ua>
CircleCI: add FreeBSD cross compilation
2017-12-22 Alex Samorukov <samm@os2.kiev.ua>
configure.ac: add -lsbuf to FreeBSD libs to fix static builds.
2017-12-21 Douglas Gilbert <dgilbert@interlog.com>
scsiprint.cpp: Start some JSON work. Other cleanups and helper
functions; potentially new header for those helpers.
2017-12-17 Christian Franke <franke@computer.org>
ataprint.cpp: Add JSON support for '-g all', '-l scterc' and
'-l scttemp'.
ataprint.cpp: Don't print obsolete SCT Support Level (#940).
2017-12-14 Christian Franke <franke@computer.org>
ataprint.cpp: JSON '-A' output: Add booleans and string for attribute
flags. Remove string array. Rename table.
ataprint.cpp: Add JSON support for '-l [x]error'.
2017-12-13 Christian Franke <franke@computer.org>
smartctl.cpp, smartctl.8.in: Rename '--json=a' to '--json=o'.
smartctl.cpp: Show command line error messages in JSON output.
ataprint.cpp: Add JSON support for '-l [x]selftest' and
'-l directory'.
atacmds.cpp, atacmds.h: Move self-test print functions to ...
ataprint.cpp: ... here.
smartd.cpp: Rework self-test error counting.
ataprint.cpp: Add JSON support for '-c'.
atacmds.cpp, atacmds.h: Change return type of capability checks to
bool. Declare simple checks inline.
2017-12-07 Christian Franke <franke@computer.org>
json.cpp: Avoid 'cbegin()' and 'cend()' to fix build with older
libstdc++.
json.cpp, json.h, smartctl.cpp, smartctl.8.in: Add '--json=s' option.
Outputs JSON object elements sorted by key.
Add '--json=g' option. Outputs JSON structure suitable for grep.
2017-12-05 Christian Franke <franke@computer.org>
ataprint.cpp: Add JSON support for '-l sataphy'.
smartctl.cpp: Add JSON support for '--scan'.
Add similar device info to regular JSON output.
ataprint.cpp, scsiprint.cpp: Remove now duplicate "protocol" element.
smartctl.cpp: Silence false positive warnings from clang analyzer.
2017-12-02 Christian Franke <franke@computer.org>
Add initial support for smartctl JSON output mode (#766):
json.cpp, json.h: New files with JSON support class.
Makefile.am, os_win32/vc14/smartctl.vcxproj*: Add new files.
ataprint.cpp: Add initial JSON support for -i, -H, -A and -l [x]error.
scsiprint.cpp: Add initial JSON support for -i and -H.
smartctl.cpp, smartctl.h: Add '-j, --json' option, global JSON object
and new print functions.
smartctl.8.in: Document new functionality.
atacmds.cpp: Remove no longer needed variable 'must_swap'.
os_win32.cpp: Remove include of smartctl.h, add extern declaration.
Decode Windows Server 1709 build number.
configure.ac, os_linux.cpp: Always include <sys/sysmacros.h> if available.
This silences a 'deprecated' warning from glibc 2.25 headers.
2017-11-20 Alex Samorukov <samm@os2.kiev.ua>
os_netbsd.cpp (fix regressions in smartmontools 6.6)
- fix BE platforms support, tested on sparc64 (#943)
- fix name based device type detection (#943)
- Add byte-swapping for IDENTIFY command and remove related hacks from the
atacmds.cpp (#117)
2017-11-18 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h:
- Add Swissbit C440 industrial cf card series (#942)
- Fix Innolite Satadom D150QV entry (#939)
2017-11-16 Christian Franke <franke@computer.org>
smartd.initd.in: Remove FreeBSD section.
os_linux.cpp: Add missing braces to 3ware SELinux code.
This possibly harmless bug was introduced ~10 years ago in r2510.
It is now detected by g++ 6.3 -Wmisleading-indentation warning.
update-smart-drivedb.in: Include configured PATH in help and
error messages. Allow digits in SVN Id user name.
configure.ac: Prepend '/usr/local/bin' to default for
'--with-scriptpath' (#941).
2017-11-15 Christian Franke <franke@computer.org>
smartd.cpp: Use 'sigaction()' instead of deprecated 'sigset()'
or 'signal()'.
configure.ac: Add '--with-signal-func' to select old function
if needed.
configure.ac: Remove '-with-initscriptdir=[auto|yes]' heuristics.
The default init script is no longer useful on most platforms.
INSTALL: Update related documentation.
configure.ac, Makefile.am: Use smartd.cygwin.initd.in on Cygwin.
smartd.cygwin.initd.in: New file.
smartd.initd.in: Remove Cygwin section.
configure.ac: Make some header checks platform specific.
Print '--with-nvme-devicescan' warning also on FreeBSD.
Remove '--with-solaris-sparc-ata' warning.
examplescripts/Example6: Add enhancements from Fedora package.
2017-11-13 Christian Franke <franke@computer.org>
drivedb.h:
- Western Digital Red: WD80EZZX
- USB: WD My Book (0x1058:0x25ee) (Red Hat Bugzilla 1446533)
2017-11-13 Matt Coates <me@mattjackets.com>
drivedb.h: USB: Seagate Backup Plus 4TB (0x0bc2:0xab43) (#926)
2017-11-10 Alex Samorukov <samm@os2.kiev.ua>
drivedb.h: add SanDisk iSSD SDIS6BM (#923)
2017-11-08 Christian Franke <franke@computer.org>
Makefile.am, os_win32/installer.nsi: Add VERSIONINFO resource to
installer.
os_win32/installer.nsi: Remove get/set of old 'Install_Dir' registry
entry. No longer needed for recent versions of GSmartControl.
Remove deletion of old .exe.manifest files.
Search also for 64-bit version of Notepad++.
ataprint.cpp: Fix detection of Device Statistics log with
256 sectors (#922).
os_linux.cpp: Use 'realpath()' (BSD, POSIX) instead of
'canonicalize_file_name()' (GNU extension).
This fixes build on systems with musl libc (#921).
2017-11-06 Alex Samorukov <samm@os2.kiev.ua>
os_freebsd.cpp: implement NVMe device scan (#687)
os_freebsd.cpp: show hint if /dev/nvd* is specified as device name
2017-11-05 Christian Franke <franke@computer.org>
configure.ac: Add separate version number for drivedb.h branch.
2017-11-05 Christian Franke <franke@computer.org>

241
INSTALL
View File

@ -1,10 +1,10 @@
Smartmontools installation instructions
=======================================
$Id: INSTALL 4574 2017-10-29 15:41:13Z chrfranke $
$Id: INSTALL 4880 2018-12-29 20:27:01Z chrfranke $
Please also see the smartmontools home page:
http://www.smartmontools.org/
https://www.smartmontools.org/
Table of contents:
@ -26,6 +26,9 @@ Table of contents:
[1] System requirements
=======================
Note: Some of this info is outdated as it refers to very old OS
versions.
A) Linux
Any Linux distribution will support smartmontools if it has a
@ -42,29 +45,28 @@ Table of contents:
C) Solaris
The SCSI code has been tested on a variety of Solaris 8 and 9
The SCSI code has been tested on a variety of Solaris 8 or later
systems. ATA/IDE code only works on SPARC platform. All tested
kernels worked correctly.
D) NetBSD/OpenBSD
The code was tested on a 1.6ZG (i.e., 1.6-current) system. It should
also function under 1.6.1 and later releases (unverified). Currently
it doesn't support ATA devices on 3ware RAID controllers.
also function under 1.6.1 and later releases.
E) Cygwin
The code was tested on Cygwin 2.9.0-3 x86 and x86_64. It should also
The code was tested on Cygwin 2.11.* x86 and x86_64. It should also
work on other recent releases.
Both Cygwin and Windows versions of smartmontools share the same code
to access the IDE/ATA or SCSI devices. The information in the "Windows"
section below also applies to the Cygwin version.
to access the raw devices. The information in the "Windows" section
below also applies to the Cygwin version.
F) Windows
The code was tested on Windows XP SP3, 2003, Vista, Windows 7, 8, 8.1
and Windows 10 up to 1709. Support von Windows 9x/ME and NT4 was
and Windows 10 up to 1809. Support von Windows 9x/ME and NT4 was
removed after smartmontools 5.43.
ATA or SATA devices are supported if the device driver implements
@ -77,13 +79,18 @@ Table of contents:
SCSI and USB devices are accessed through SPTI. Special driver support
is not required.
NVMe devices are supported with the Windows 10 NVMe driver or with
vendor specific drivers supporting NVME_PASS_THROUGH.
G) MacOS/Darwin
The code was tested on MacOS 10.3.4. It should work from 10.3
forwards. It doesn't support 10.2.
Only basic SMART commands are supported for ATA devices.
It's important to know that on 10.3.x, some things don't work
(see WARNINGS): due to bugs in the libraries used, you cannot run
due to bugs in the libraries used, you cannot run
a short test or switch SMART support off on a drive; if you try,
you will just run an extended test or switch SMART support on. So
don't panic when your "short" test seems to be taking hours.
@ -92,32 +99,7 @@ Table of contents:
routine runs. If your drive doesn't have it running automatically by
default, you can't run it at all.
SCSI devices are not currently supported. Detecting the power
status of a drive is also not currently supported.
To summarize this, from another point of view, the things that
are not supported fall into two categories:
* Can't be implemented easily without more kernel-level support,
so far as I know:
- running immediate offline, conveyance, or selective tests
- running any test in captive mode
- aborting tests
- switching automatic offline testing on or off
- support for SCSI
- checking the power mode [-n Directive of smartd] (this is not
completely impossible, but not by using a documented API)
* Work on 10.4 and later, but not on 10.3:
- switching off SMART (switching *on* works fine)
- switching off auto-save (but why would you want to?)
- running the short test (that leaves you with only the extended test)
However, some things do work well. For ATA devices, all the
informational output is available, unless you want something that only
an offline test updates. On many newer Mac OS systems, the
hard drive comes with the offline test switched on by default, so
even that works.
SCSI devices are not currently supported.
The OS X SAT SMART Driver provides access to SMART data for SAT capable
USB and Firewire devices:
@ -137,9 +119,10 @@ Table of contents:
=======================
Get the sources from the SVN repository:
svn co http://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools smartmontools
svn co https://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools smartmontools
Then type:
cd smartmontools
./autogen.sh
and continue with step [3] below, skipping the "unpack the tarball" step.
@ -152,7 +135,7 @@ Table of contents:
======================================
If you are NOT installing from SVN, then unpack the tarball:
tar zxvf smartmontools-5.VERSION.tar.gz
tar xvf smartmontools-VERSION.tar.gz
Then:
./configure
@ -172,26 +155,31 @@ Table of contents:
--mandir='${datarootdir}/man'
--docdir='${datarootdir}/doc/smartmontools'
--disable-sample
--with-systemdsystemunitdir=auto
--with-systemdenvfile=auto
--with-initscriptdir=auto
--disable-scsi-cdb-check
--enable-fast-lebe
--without-initscriptdir
--with-exampledir='${docdir}/examplescripts'
--with-drivedbdir='${datadir}/smartmontools'
--with-update-smart-drivedb
--with-gnupg
--with-smartdscriptdir='${sysconfdir}'
--with-smartdplugindir='${smartdscriptdir}/smartd_warning.d'
--with-scriptpath='/bin:/usr/bin'
--with-scriptpath='/usr/local/bin:/bin:/usr/bin'
--without-savestates
--without-attributelog
--with-os-deps='os_linux.o dev_areca.o' (platform specific)
--without-selinux
--with-libcap-ng=auto
--without-nvme-devicescan
--with-libsystemd=auto
--with-systemdsystemunitdir=auto
--with-systemdenvfile=auto
--with-nvme-devicescan (Linux, Windows: yes; Others: no)
--without-solaris-sparc-ata (Solaris SPARC only)
--with-working-snprintf (Windows: guessed)
--with-signal-func=sigaction
--with-working-snprintf
--with-mingw-aslr=auto (Windows only)
--with-cxx11-option=auto
--without-cxx11-regex
These will usually not overwrite existing "distribution" installations on
Linux Systems since the FHS reserves this area for use by the system
@ -200,11 +188,8 @@ Table of contents:
For different installation locations or distributions, simply add
arguments to ./configure as shown in [4] below.
If you wish to alter the default C++ compiler flags, add
CXXFLAGS='your options' to ./configure command.
The first output line of smartctl and smartd provides information
about release number, last SVN checkin date and revison, platform,
about release number, last SVN checkin date and revision, platform,
and package. The latter defaults to "(local build)" and can be
changed by the variable BUILD_INFO, for example:
make BUILD_INFO='"(Debian 5.39-2)"'
@ -215,17 +200,6 @@ Table of contents:
Note: Please send corrections/additions to:
smartmontools-support@listi.jpberlin.de
Debian:
If you don't want to overwrite any distribution package, use:
./configure
Filesystem Hierarchy Standard (FHS, http://www.pathname.com/fhs/):
./configure --sbindir=/usr/local/sbin \
--sysconfdir=/usr/local/etc \
--mandir=/usr/local/man \
--docdir=/usr/local/share/doc/smartmontools \
--with-initscriptdir=/usr/local/etc/init.d
Red Hat:
./configure --sbindir=/usr/sbin \
--sysconfdir=/etc \
@ -287,6 +261,7 @@ SuSE:
[6] Guidelines for Darwin
=========================
./configure --with-initscriptdir=/Library/StartupItems
If you'd like to build the i386 version on a powerpc machine, you can
@ -298,6 +273,7 @@ SuSE:
[7] Guidelines for NetBSD
=========================
./configure --prefix=/usr/pkg \
--docdir=/usr/pkg/share/doc/smartmontools
@ -305,7 +281,7 @@ SuSE:
==========================
smartmontools has been partially but not completely ported to
Solaris. It includes complete SCSI support but no ATA or 3ware
Solaris. It includes complete SCSI support but no ATA or NVMe
support. It can be compiled with either CC (Sun's C++ compiler)
or GNU g++.
@ -326,48 +302,13 @@ SuSE:
--docdir=/usr/share/doc/smartmontools-VERSION \
--with-initscriptdir=/etc/init.d
To start the script automatically on bootup, create hardlinks that
indicate when to start/stop in:
/etc/rc[S0123].d/
pointing to /etc/init.d/smartd. Create:
K<knum>smartd in rcS.d, rc0.d, rc1.d, rc2.d
S<snum>smartd in rc3.d
where <knum> is related to <snum> such that the higher snum is the
lower knum must be.
On usual configuration, '95' would be suitable for <snum> and '05'
for <knum> respectively. If you choose these value, you can
create hardlinks by:
cd /etc
sh -c 'for n in S 0 1 2; do ln init.d/smartd rc$n.d/K05smartd; done'
sh -c 'for n in 3 ; do ln init.d/smartd rc$n.d/S95smartd; done'
[9] Guidelines for Cygwin
=========================
Same as Red Hat:
./configure --prefix=/usr \
--sysconfdir=/etc \
--mandir='${prefix}/share/man'
OR EQUIVALENTLY
./configure --sbindir=/usr/sbin \
--sysconfdir=/etc \
--mandir=/usr/share/man \
--docdir=/usr/share/doc/smartmontools \
--with-initscriptdir=/etc/rc.d/init.d
Using DOS text file type as default for the working directories ("textmode"
mount option) is not recommended. Building the binaries and man pages using
"make" is possible, but "make dist" and related targets work only with UNIX
file type ("binmode" mount option) set. The "autogen.sh" script prints a
warning if DOS type is selected.
Files may also be checked out with a non-Cygwin SVN client which uses CR/LF
for svn:eol-style=native. The "autogen.sh" script has svn:eol-style=LF.
Bash option "-o igncr" is not required.
[10] Guidelines for Windows
===========================
@ -387,22 +328,10 @@ Cross-compile statically linked 32-bit and 64-bit versions with MinGW-w64:
./configure --build=$(./config.guess) \
--host=x86_64-w64-mingw32
Tested on Cygwin, Debian and Fedora.
Tested on Cygwin, Debian, Fedora and Ubuntu.
To build the Windows binary distribution, use:
make dist-win32
This builds the distribution in directory
./smartmontools-VERSION.win32/
and packs it into
./smartmontools-VERSION.win32.zip
To create a Windows installer, use:
To create the Windows installer, use:
make installer-win32
@ -412,12 +341,7 @@ To create a Windows installer, use:
./smartmontools-VERSION.win32-setup.exe
The installer is build using the command "makensis" from the NSIS
package. See http://nsis.sourceforge.net/ for documentation and
download location.
It is also possible to (cross-)build the installer on Linux.
This was successfully tested on Debian and Fedora with package
"nsis".
package (https://nsis.sourceforge.net/).
To create a combined 32-/64-bit installer, use this in 32-bit build
directory if 64-build directory is at ../build64:
@ -432,7 +356,7 @@ To both create and run the (interactive) installer, use:
only and cleandist-win32 for cleanup.
The binary distribution includes all documentation files converted
to DOS text file format and *.html and *.txt preformatted man pages.
to DOS text file format and *.html and *.pdf preformatted man pages.
To prepare os_win32/vc14 directory for MS Visual Studio C++ 2015 builds,
use the following on MSYS or Cygwin:
@ -444,8 +368,10 @@ use the following on MSYS or Cygwin:
The MSVC project files (os_win32/vc14/*) are included in SVN (but not
in source tarball). The target config-vc14 from a Makefile configured
for MinGW creates os_win32/vc14/{config.h,smart*.rc,svnversion.h}.
The configure skript must be run outside of the source directory to
The configure script must be run outside of the source directory to
avoid inclusion of the original config.h.
Additional MSVC related make targets are clean-vc14, distclean-vc14
and maintainer-clean-vc14.
[11] Guidelines for OS/2, eComStation
@ -459,13 +385,13 @@ To compile the OS/2 code, please run
[12] Guidelines for OpenBSD
===========================
To match the way it will installed when it becomes available as a PORT, use
the following:
./configure --prefix=/usr/local \
--sysconfdir=/etc \
--docdir=/usr/local/share/doc/smartmontools-VERSION \
--without-initscriptdir \
--enable-sample
NOTE: --enable-sample will cause the smartd.conf and smartd RC files to
@ -504,18 +430,12 @@ man smartd.conf
man smartctl
man smartd
/usr/sbin/smartctl -s on -o on -S on /dev/sda (only root can do this)
/usr/sbin/smartctl -a /dev/sda (only root can do this)
Note that the default location for the manual pages are
/usr/share/man/man5 and /usr/share/man/man8. If "man" doesn't find
them, you may need to add /usr/share/man to your MANPATH environment
variable.
sudo /usr/sbin/smartctl -x /dev/sda
Source and binary packages for Windows are available at
http://sourceforge.net/projects/smartmontools/files/
https://sourceforge.net/projects/smartmontools/files/
Refer to http://www.smartmontools.org/wiki/Download for any additional
Refer to https://www.smartmontools.org/wiki/Download for any additional
download and installation instructions.
The following files are installed if ./configure has no options:
@ -524,7 +444,7 @@ The following files are installed if ./configure has no options:
/usr/local/sbin/smartd [Executable daemon]
/usr/local/sbin/update-smart-drivedb [Drive database update script]
/usr/local/etc/smartd.conf [Configuration file for smartd daemon]
/usr/local/etc/smartd_warning.sh [Warning skript for smartd daemon]
/usr/local/etc/smartd_warning.sh [Warning script for smartd daemon]
/usr/local/share/man/man5/smartd.conf.5 [Manual page]
/usr/local/share/man/man8/smartctl.8 [Manual page]
/usr/local/share/man/man8/smartd.8 [Manual page]
@ -535,18 +455,14 @@ The following files are installed if ./configure has no options:
/usr/local/share/doc/smartmontools/INSTALL [Installation instructions: what you're reading!]
/usr/local/share/doc/smartmontools/NEWS [Significant enhancements and fixes]
/usr/local/share/doc/smartmontools/README [Overview]
/usr/local/share/doc/smartmontools/TODO [Things that need to be done/fixed]
/usr/local/share/doc/smartmontools/TODO [No longer maintained]
/usr/local/share/doc/smartmontools/smartd.conf [Example configuration file for smartd]
/usr/local/share/doc/smartmontools/examplescripts/ [Executable scripts for -M exec of smartd.conf (4 files)]
/usr/local/share/smartmontools/drivedb.h [Drive database]
Due to checks done by '--with-systemdsystemunitdir=auto' and '--with-initscriptdir=auto',
one of the following files may also be installed:
Due to checks done by '--with-systemdsystemunitdir=auto', the following file may also be installed:
/usr/local/lib/systemd/system/smartd.service [Systemd service file for smartd]
/usr/local/etc/rc.d/init.d/smartd [Init/Startup script for smartd]
/usr/local/etc/init.d/smartd [Init/Startup script for smartd]
/usr/local/etc/rc.d/smartd [Init/Startup script for smartd]
If /usr/local/etc/smartd.conf exists and differs from the
default then the default configuration file is installed as
@ -569,19 +485,6 @@ if groff is available:
make MAN2HTML='groff -man -Thtml' htmlman
Some of the source files are prepared for the documentation
generator Doxygen (http://www.doxygen.org/). If Doxygen is installed,
the command:
doxygen
creates HTML documentation in doc/html and LaTeX documentation
in doc/latex. If TeX is installed, the following command creates
a documentation file doc/latex/refman.pdf:
( cd doc/latex && make pdf )
[14] Detailed description of arguments to configure command
===========================================================
@ -601,15 +504,10 @@ Old option Replacement
--disable-savestates [no option needed]
--enable-attrbutelog --with-attributelog[=yes]
--disable-savestates [no option needed]
--with-initscriptdir[=yes] --with-initscriptdir=DIR
--with-initscriptdir=auto --with-initscriptdir=DIR
The defaults for --with-initscriptdir and --with-systemdsystemunitdir are
guessed such that the following rules apply:
- If --prefix=/usr --sysconfdir=/etc is specified, the guessed directories
should be the defaults used by the current OS or distribution.
- If --sysconfdir=/etc is NOT specified, the guessed directories should
always be below ${prefix} or below ${sysconfdir}.
Here's an example:
If you set --prefix=/home/joe and none of the other four
variables then the different directories that are used would be:
@ -619,51 +517,18 @@ variables then the different directories that are used would be:
--sysconfdir /home/joe/etc
--with-exampledir /home/joe/share/doc/smartmontools/examplescripts
--with-drivedbdir /home/joe/share/smartmontools
--with-initscriptdir [see below]
--with-initscriptdir [disabled]
--with-systemdsystemunitdir [see below]
If systemd is present (and pkg-config reports /lib/systemd/system
as the systemdsystemunitdir):
--with-initscriptdir [disabled]
--with-systemdsystemunitdir /home/joe/lib/systemd/system
else if /etc/rc.d/init.d exists:
--with-initscriptdir /home/joe/etc/rc.d/init.d
--with-systemdsystemunitdir [disabled]
else if /etc/init.d exists:
--with-initscriptdir /home/joe/etc/init.d
--with-systemdsystemunitdir [disabled]
else if /etc/rc.d exists:
--with-initscriptdir /home/joe/etc/rc.d
--with-systemdsystemunitdir [disabled]
else
--with-initscriptdir [disabled]
--with-systemdsystemunitdir [disabled]
Here are the differences with and without --enable-sample, assuming
that initscript location is set and no other options specified
(see above for details)
Case 1:
--enable-sample provided
==> Files installed are:
/usr/local/etc/smartd.conf.sample
/usr/local/etc/rc.d/init.d/smartd.sample
Case 2:
--disable-sample provided or parameter left out
==> Files installed are:
/usr/local/etc/smartd.conf
/usr/local/etc/rc.d/init.d/smartd
Additional information about using configure can be found here:
https://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts

View File

@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
#
# $Id: Makefile.am 4519 2017-10-08 15:41:54Z chrfranke $
# $Id: Makefile.am 4848 2018-12-05 18:30:46Z chrfranke $
#
@SET_MAKE@
@ -32,10 +32,10 @@ if OS_WIN32_MINGW
AM_CPPFLAGS += -I$(srcdir)/os_win32
endif
if NEED_GETOPT_LONG
AM_CPPFLAGS += -I$(srcdir)/getopt -DHAVE_GETOPT_LONG -D__GNU_LIBRARY__
AM_CPPFLAGS += -I$(srcdir)/getopt -D_GETOPT_STANDALONE
endif
if NEED_REGEX
AM_CPPFLAGS += -I$(srcdir)/regex
AM_CPPFLAGS += -I$(srcdir)/regex -D_REGEX_STANDALONE
endif
sbin_PROGRAMS = \
@ -69,7 +69,8 @@ smartctl_SOURCES = \
dev_interface.h \
dev_tunnelled.h \
drivedb.h \
int64.h \
json.cpp \
json.h \
knowndrives.cpp \
knowndrives.h \
nvmecmds.cpp \
@ -79,10 +80,12 @@ smartctl_SOURCES = \
scsicmds.cpp \
scsicmds.h \
scsiata.cpp \
scsinvme.cpp \
scsiprint.cpp \
scsiprint.h \
utility.cpp \
utility.h
utility.h \
sg_unaligned.h
smartctl_LDADD = $(os_deps) $(os_libs)
smartctl_DEPENDENCIES = $(os_deps)
@ -119,6 +122,10 @@ EXTRA_smartctl_SOURCES = \
if OS_WIN32_MINGW
smartctl_SOURCES += \
os_win32/popen_win32.cpp \
os_win32/popen.h
smartctl_LDADD += smartctl_res.o
smartctl_DEPENDENCIES += smartctl_res.o
@ -139,7 +146,6 @@ smartd_SOURCES = \
dev_interface.h \
dev_tunnelled.h \
drivedb.h \
int64.h \
knowndrives.cpp \
knowndrives.h \
nvmecmds.cpp \
@ -147,10 +153,12 @@ smartd_SOURCES = \
scsicmds.cpp \
scsicmds.h \
scsiata.cpp \
scsinvme.cpp \
utility.cpp \
utility.h
utility.h \
sg_unaligned.h
smartd_LDADD = $(os_deps) $(os_libs) $(CAPNG_LDADD)
smartd_LDADD = $(os_deps) $(os_libs) $(CAPNG_LDADD) $(SYSTEMD_LDADD)
smartd_DEPENDENCIES = $(os_deps)
EXTRA_smartd_SOURCES = \
@ -190,6 +198,8 @@ if OS_WIN32_MINGW
smartd_SOURCES += \
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
@ -207,12 +217,18 @@ if NEED_GETOPT_LONG
smartctl_SOURCES += \
getopt/getopt.c \
getopt/getopt.h \
getopt/getopt1.c
getopt/getopt1.c \
getopt/getopt_int.h \
getopt/bits/getopt_core.h \
getopt/bits/getopt_ext.h
smartd_SOURCES += \
getopt/getopt.c \
getopt/getopt.h \
getopt/getopt1.c
getopt/getopt1.c \
getopt/getopt_int.h \
getopt/bits/getopt_core.h \
getopt/bits/getopt_ext.h
endif
@ -372,6 +388,7 @@ EXTRA_DIST = \
.editorconfig \
autogen.sh \
smartd.initd.in \
smartd.cygwin.initd.in \
smartd.freebsd.initd.in \
smartd.8.in \
smartctl.8.in \
@ -395,7 +412,6 @@ EXTRA_DIST = \
os_win32/smartd_warning.cmd \
os_win32/syslogevt.mc \
os_win32/update-smart-drivedb.nsi \
os_win32/wbemcli_small.h \
os_win32/versioninfo.rc.in \
os_win32/wtssendmsg.c \
$(docs_DATA) \
@ -422,6 +438,7 @@ CLEANFILES = \
smartd.conf.5.pdf \
smartd.conf.5.txt \
smartd.initd \
smartd.cygwin.initd \
smartd.freebsd.initd \
smartd.service \
smartd_warning.sh \
@ -450,7 +467,7 @@ MAINTAINERCLEANFILES = \
$(srcdir)/missing \
$(srcdir)/m4/pkg.m4
utility.o: svnversion.h
smartctl.o utility.o: svnversion.h
if IS_SVN_BUILD
# Get version info from SVN
@ -617,6 +634,11 @@ MAN_FILTER = { \
else \
sed '/^\.\\" %IF ENABLE_CAPABILITIES/,/^\.\\" %ENDIF ENABLE_CAPABILITIES/ s,^,.\\"\# ,' ; \
fi | \
if test -n '$(SYSTEMD_LDADD)'; then \
cat; \
else \
sed '/^\.\\" %IF ENABLE_SYSTEMD_NOTIFY/,/^\.\\" %ENDIF ENABLE_SYSTEMD_NOTIFY/ s,^,.\\"\# ,' ; \
fi | \
if test '$(with_nvme_devicescan)' = 'yes'; then \
cat; \
else \
@ -888,14 +910,16 @@ $(distzip_win32): distdir.mkdir $(FILES_WIN32)
if OS_WIN32_NSIS
# Build NSIS installer
# Note: Only option character '-' is also compatible with Linux version of makensis
$(distinst_win32): os_win32/installer.nsi distdir.mkdir $(FILES_WIN32)
$(distinst_win32): os_win32/installer.nsi smartctl_res.rc distdir.mkdir $(FILES_WIN32)
test -z '$(builddir_win64)' || ( cd $(builddir_win64) && make distdir-win32 )
@date=`sed -n 's,^.*DATE[^"]*"\([^"]*\)".*$$,\1,p' svnversion.h` && \
rev=`sed -n 's,^.*REV[^"]*"\([^"]*\)".*$$,r\1,p' svnversion.h` && \
version=`sed -n 's|^ *VALUE "FileVersion", "\([0-9.]*\)".*$$|\1|p' smartctl_res.rc` && \
yy=`echo "$$date" | sed -n 's,^20\([0-9][0-9]\).*$$,\1,p'`; yy="$${yy:-XX}" && \
verstr="$(PACKAGE_VERSION) $$date $$rev "$(BUILD_INFO) && \
d64= && if [ -n '$(builddir_win64)' ]; then d64='-DINPDIR64=$(builddir_win64)/$(PACKAGE)-$(VERSION).win64'; fi && \
echo "'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSTR='$$verstr' $<" && \
'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSTR="$$verstr" $<
echo "'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSION=$$version -DYY=$$yy -DVERSTR='$$verstr' $<" && \
'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSION=$$version -DYY=$$yy -DVERSTR="$$verstr" $<
md5sum $@ > $@.md5
sha1sum $@ > $@.sha1
sha256sum $@ > $@.sha256
@ -1001,7 +1025,7 @@ config-vc$(vcver): $(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\|STRINGS_H\|UNISTD_H\|WORKING_SNPRINTF\) 1$$,/* #undef HAVE_\1 */ /* VC$(vcver) */,' \
-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 SMARTMONTOOLS_BUILD_HOST "[^-]*\)[^"]*,\1-pc-w32vc$(vcver),' $< > $@
$(srcdir)/os_win32/vc$(vcver)/svnversion.h: svnversion.h

View File

@ -15,7 +15,7 @@
@SET_MAKE@
#
# $Id: Makefile.am 4519 2017-10-08 15:41:54Z chrfranke $
# $Id: Makefile.am 4848 2018-12-05 18:30:46Z chrfranke $
#
@ -98,72 +98,84 @@ host_triplet = @host@
@ENABLE_SAVESTATES_TRUE@am__append_2 = -DSMARTMONTOOLS_SAVESTATES='"$(savestates)"'
@ENABLE_ATTRIBUTELOG_TRUE@am__append_3 = -DSMARTMONTOOLS_ATTRIBUTELOG='"$(attributelog)"'
@OS_WIN32_MINGW_TRUE@am__append_4 = -I$(srcdir)/os_win32
@NEED_GETOPT_LONG_TRUE@am__append_5 = -I$(srcdir)/getopt -DHAVE_GETOPT_LONG -D__GNU_LIBRARY__
@NEED_REGEX_TRUE@am__append_6 = -I$(srcdir)/regex
@NEED_GETOPT_LONG_TRUE@am__append_5 = -I$(srcdir)/getopt -D_GETOPT_STANDALONE
@NEED_REGEX_TRUE@am__append_6 = -I$(srcdir)/regex -D_REGEX_STANDALONE
sbin_PROGRAMS = smartctl$(EXEEXT) smartd$(EXEEXT)
@OS_WIN32_MINGW_TRUE@am__append_7 = smartctl_res.o
@OS_WIN32_MINGW_TRUE@am__append_7 = \
@OS_WIN32_MINGW_TRUE@ os_win32/popen_win32.cpp \
@OS_WIN32_MINGW_TRUE@ os_win32/popen.h
@OS_WIN32_MINGW_TRUE@am__append_8 = smartctl_res.o
@OS_WIN32_MINGW_TRUE@am__append_9 = \
@OS_WIN32_MINGW_TRUE@am__append_9 = smartctl_res.o
@OS_WIN32_MINGW_TRUE@am__append_10 = \
@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 \
@OS_WIN32_MINGW_TRUE@ os_win32/popen.h \
@OS_WIN32_MINGW_TRUE@ os_win32/syslog_win32.cpp \
@OS_WIN32_MINGW_TRUE@ os_win32/syslog.h
@OS_WIN32_MINGW_TRUE@am__append_10 = smartd_res.o
@OS_WIN32_MINGW_TRUE@am__append_11 = smartd_res.o
@NEED_GETOPT_LONG_TRUE@am__append_12 = \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt.c \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt.h \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt1.c
@OS_WIN32_MINGW_TRUE@am__append_12 = smartd_res.o
@NEED_GETOPT_LONG_TRUE@am__append_13 = \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt.c \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt.h \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt1.c
@NEED_GETOPT_LONG_TRUE@ getopt/getopt1.c \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt_int.h \
@NEED_GETOPT_LONG_TRUE@ getopt/bits/getopt_core.h \
@NEED_GETOPT_LONG_TRUE@ getopt/bits/getopt_ext.h
@NEED_REGEX_TRUE@am__append_14 = \
@NEED_REGEX_TRUE@ regex/regex.c \
@NEED_REGEX_TRUE@ regex/regex.h \
@NEED_REGEX_TRUE@ regex/regex_internal.h
@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 \
@NEED_GETOPT_LONG_TRUE@ getopt/getopt_int.h \
@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@ 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@ 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_16 = \
@NEED_REGEX_TRUE@ regex/regcomp.c \
@NEED_REGEX_TRUE@ regex/regexec.c \
@NEED_REGEX_TRUE@ regex/regex_internal.c
@NEED_REGEX_TRUE@am__append_17 = \
@NEED_REGEX_TRUE@ regex/regcomp.c \
@NEED_REGEX_TRUE@ regex/regexec.c \
@NEED_REGEX_TRUE@ regex/regex_internal.c
@OS_WIN32_TRUE@am__append_18 = \
@OS_WIN32_TRUE@ csmisas.h \
@OS_WIN32_TRUE@ os_win32/wmiquery.cpp \
@OS_WIN32_TRUE@ os_win32/wmiquery.h
@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
@OS_WIN32_TRUE@am__append_19 = \
@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 = -lole32 -loleaut32
@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_21 = -lole32 -loleaut32
@ENABLE_UPDATE_SMART_DRIVEDB_TRUE@@OS_SOLARIS_TRUE@am__append_22 = update-smart-drivedb.1m
@ENABLE_UPDATE_SMART_DRIVEDB_TRUE@@OS_SOLARIS_FALSE@am__append_23 = update-smart-drivedb.8
@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@am__append_24 = \
@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
@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@am__append_25 = \
@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@am__append_26 = \
@ENABLE_DRIVEDB_TRUE@@OS_WIN32_MINGW_TRUE@ $(exedir_win32)/drivedb.h
@OS_WIN32_MINGW_TRUE@am__append_26 = \
@OS_WIN32_MINGW_TRUE@am__append_27 = \
@OS_WIN32_MINGW_TRUE@ $(FILES_WIN32) \
@OS_WIN32_MINGW_TRUE@ defadmin.manifest \
@OS_WIN32_MINGW_TRUE@ distdir.mkdir \
@ -202,23 +214,28 @@ am__smartctl_SOURCES_DIST = smartctl.cpp smartctl.h atacmdnames.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_tunnelled.h drivedb.h \
int64.h knowndrives.cpp knowndrives.h nvmecmds.cpp nvmecmds.h \
nvmeprint.cpp nvmeprint.h scsicmds.cpp scsicmds.h scsiata.cpp \
scsiprint.cpp scsiprint.h utility.cpp utility.h \
getopt/getopt.c getopt/getopt.h getopt/getopt1.c regex/regex.c \
regex/regex.h regex/regex_internal.h csmisas.h \
os_win32/wmiquery.cpp os_win32/wmiquery.h
@NEED_GETOPT_LONG_TRUE@am__objects_1 = getopt.$(OBJEXT) \
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 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)
@NEED_REGEX_TRUE@am__objects_2 = regex.$(OBJEXT)
@OS_WIN32_TRUE@am__objects_3 = wmiquery.$(OBJEXT)
@NEED_REGEX_TRUE@am__objects_3 = regex.$(OBJEXT)
@OS_WIN32_TRUE@am__objects_4 = wmiquery.$(OBJEXT)
am_smartctl_OBJECTS = smartctl.$(OBJEXT) atacmdnames.$(OBJEXT) \
atacmds.$(OBJEXT) ataidentify.$(OBJEXT) ataprint.$(OBJEXT) \
dev_ata_cmd_set.$(OBJEXT) dev_intelliprop.$(OBJEXT) \
dev_interface.$(OBJEXT) knowndrives.$(OBJEXT) \
dev_interface.$(OBJEXT) json.$(OBJEXT) knowndrives.$(OBJEXT) \
nvmecmds.$(OBJEXT) nvmeprint.$(OBJEXT) scsicmds.$(OBJEXT) \
scsiata.$(OBJEXT) scsiprint.$(OBJEXT) utility.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3)
scsiata.$(OBJEXT) scsinvme.$(OBJEXT) scsiprint.$(OBJEXT) \
utility.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
$(am__objects_3) $(am__objects_4)
am__EXTRA_smartctl_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 \
@ -232,22 +249,26 @@ 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_tunnelled.h drivedb.h int64.h \
knowndrives.cpp knowndrives.h nvmecmds.cpp nvmecmds.h \
scsicmds.cpp scsicmds.h scsiata.cpp utility.cpp utility.h \
dev_interface.h dev_tunnelled.h drivedb.h knowndrives.cpp \
knowndrives.h nvmecmds.cpp nvmecmds.h scsicmds.cpp scsicmds.h \
scsiata.cpp scsinvme.cpp utility.cpp utility.h sg_unaligned.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 \
getopt/getopt.h getopt/getopt1.c 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_4 = daemon_win32.$(OBJEXT) \
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_5 = daemon_win32.$(OBJEXT) \
@OS_WIN32_MINGW_TRUE@ popen_win32.$(OBJEXT) \
@OS_WIN32_MINGW_TRUE@ syslog_win32.$(OBJEXT)
am_smartd_OBJECTS = smartd.$(OBJEXT) atacmdnames.$(OBJEXT) \
atacmds.$(OBJEXT) dev_ata_cmd_set.$(OBJEXT) \
dev_intelliprop.$(OBJEXT) dev_interface.$(OBJEXT) \
knowndrives.$(OBJEXT) nvmecmds.$(OBJEXT) scsicmds.$(OBJEXT) \
scsiata.$(OBJEXT) utility.$(OBJEXT) $(am__objects_4) \
$(am__objects_1) $(am__objects_2) $(am__objects_3)
scsiata.$(OBJEXT) scsinvme.$(OBJEXT) utility.$(OBJEXT) \
$(am__objects_5) $(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 \
@ -453,6 +474,7 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SYSTEMD_LDADD = @SYSTEMD_LDADD@
VERSION = @VERSION@
WINDMC = @WINDMC@
WINDRES = @WINDRES@
@ -537,7 +559,6 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
with_nvme_devicescan = @with_nvme_devicescan@
with_selinux = @with_selinux@
with_update_smart_drivedb = @with_update_smart_drivedb@
ACLOCAL_AMFLAGS = -I m4
@ -557,31 +578,32 @@ smartctl_SOURCES = smartctl.cpp smartctl.h atacmdnames.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_tunnelled.h drivedb.h \
int64.h knowndrives.cpp knowndrives.h nvmecmds.cpp nvmecmds.h \
nvmeprint.cpp nvmeprint.h scsicmds.cpp scsicmds.h scsiata.cpp \
scsiprint.cpp scsiprint.h utility.cpp utility.h \
$(am__append_12) $(am__append_14) $(am__append_18)
smartctl_LDADD = $(os_deps) $(os_libs) $(am__append_7) \
$(am__append_20)
smartctl_DEPENDENCIES = $(os_deps) $(am__append_8)
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 utility.cpp \
utility.h sg_unaligned.h $(am__append_7) $(am__append_13) \
$(am__append_15) $(am__append_19)
smartctl_LDADD = $(os_deps) $(os_libs) $(am__append_8) \
$(am__append_21)
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 \
os_netbsd.h os_openbsd.cpp os_openbsd.h os_os2.cpp os_os2.h \
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_16)
dev_legacy.cpp linux_nvme_ioctl.h megaraid.h $(am__append_17)
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_tunnelled.h drivedb.h int64.h \
knowndrives.cpp knowndrives.h nvmecmds.cpp nvmecmds.h \
scsicmds.cpp scsicmds.h scsiata.cpp utility.cpp utility.h \
$(am__append_9) $(am__append_13) $(am__append_15) \
$(am__append_19)
smartd_LDADD = $(os_deps) $(os_libs) $(CAPNG_LDADD) $(am__append_10) \
$(am__append_21)
smartd_DEPENDENCIES = $(os_deps) $(am__append_11)
dev_interface.h dev_tunnelled.h drivedb.h knowndrives.cpp \
knowndrives.h nvmecmds.cpp nvmecmds.h scsicmds.cpp scsicmds.h \
scsiata.cpp scsinvme.cpp utility.cpp utility.h sg_unaligned.h \
$(am__append_10) $(am__append_14) $(am__append_16) \
$(am__append_20)
smartd_LDADD = $(os_deps) $(os_libs) $(CAPNG_LDADD) $(SYSTEMD_LDADD) \
$(am__append_11) $(am__append_22)
smartd_DEPENDENCIES = $(os_deps) $(am__append_12)
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 \
@ -589,7 +611,7 @@ EXTRA_smartd_SOURCES = os_darwin.cpp os_darwin.h os_linux.cpp \
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_17)
netbsd_nvme_ioctl.h megaraid.h $(am__append_18)
# Exclude from source tarball
nodist_EXTRA_smartctl_SOURCES = os_solaris_ata.s
@ -601,10 +623,10 @@ nodist_EXTRA_smartd_SOURCES = os_solaris_ata.s
# 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_22)
@OS_SOLARIS_TRUE@ $(am__append_23)
# For systems that adopts traditional manner
@OS_SOLARIS_FALSE@man_MANS = smartd.conf.5 smartctl.8 smartd.8 \
@OS_SOLARIS_FALSE@ $(am__append_23)
@OS_SOLARIS_FALSE@ $(am__append_24)
docsdir = $(docdir)
docs_DATA = \
AUTHORS \
@ -635,6 +657,7 @@ EXTRA_DIST = \
.editorconfig \
autogen.sh \
smartd.initd.in \
smartd.cygwin.initd.in \
smartd.freebsd.initd.in \
smartd.8.in \
smartctl.8.in \
@ -658,7 +681,6 @@ EXTRA_DIST = \
os_win32/smartd_warning.cmd \
os_win32/syslogevt.mc \
os_win32/update-smart-drivedb.nsi \
os_win32/wbemcli_small.h \
os_win32/versioninfo.rc.in \
os_win32/wtssendmsg.c \
$(docs_DATA) \
@ -670,12 +692,12 @@ CLEANFILES = smartd.8 smartd.1m smartd.8.html smartd.8.html.tmp \
smartctl.8.html smartctl.8.html.tmp smartctl.8.pdf \
smartctl.8.txt smartd.conf.5 smartd.conf.4 smartd.conf.5.html \
smartd.conf.5.html.tmp smartd.conf.5.pdf smartd.conf.5.txt \
smartd.initd smartd.freebsd.initd smartd.service \
smartd_warning.sh svnversion.h 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_26)
smartd.initd smartd.cygwin.initd smartd.freebsd.initd \
smartd.service smartd_warning.sh svnversion.h \
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)
# 'make maintainer-clean' also removes files generated by './autogen.sh'
MAINTAINERCLEANFILES = \
@ -758,6 +780,11 @@ MAN_FILTER = { \
else \
sed '/^\.\\" %IF ENABLE_CAPABILITIES/,/^\.\\" %ENDIF ENABLE_CAPABILITIES/ s,^,.\\"\# ,' ; \
fi | \
if test -n '$(SYSTEMD_LDADD)'; then \
cat; \
else \
sed '/^\.\\" %IF ENABLE_SYSTEMD_NOTIFY/,/^\.\\" %ENDIF ENABLE_SYSTEMD_NOTIFY/ s,^,.\\"\# ,' ; \
fi | \
if test '$(with_nvme_devicescan)' = 'yes'; then \
cat; \
else \
@ -839,7 +866,7 @@ FIXHTML = sed -e '1s,^Content-type.*,,' \
@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_24)
@OS_WIN32_MINGW_TRUE@ $(am__append_25)
@OS_WIN32_MINGW_TRUE@FILES_WIN32 = $(EXEFILES_WIN32) \
@OS_WIN32_MINGW_TRUE@ $(docdir_win32)/AUTHORS.txt \
@OS_WIN32_MINGW_TRUE@ $(docdir_win32)/ChangeLog.txt \
@ -857,7 +884,7 @@ FIXHTML = sed -e '1s,^Content-type.*,,' \
@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_25)
@OS_WIN32_MINGW_TRUE@ $(am__append_26)
# Note: Only use without options to be compatible with all variants
@OS_WIN32_MINGW_TRUE@UNIX2DOS = unix2dos
@ -1103,6 +1130,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dev_legacy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/knowndrives.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nvmecmds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nvmeprint.Po@am__quote@
@ -1116,12 +1144,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_qnxnto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_solaris.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popen_win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_internal.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexec.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsiata.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsicmds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsinvme.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsiprint.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smartctl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smartd.Po@am__quote@
@ -1241,6 +1271,20 @@ regex_internal.obj: regex/regex_internal.c
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
popen_win32.o: os_win32/popen_win32.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT popen_win32.o -MD -MP -MF $(DEPDIR)/popen_win32.Tpo -c -o popen_win32.o `test -f 'os_win32/popen_win32.cpp' || echo '$(srcdir)/'`os_win32/popen_win32.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/popen_win32.Tpo $(DEPDIR)/popen_win32.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='os_win32/popen_win32.cpp' object='popen_win32.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o popen_win32.o `test -f 'os_win32/popen_win32.cpp' || echo '$(srcdir)/'`os_win32/popen_win32.cpp
popen_win32.obj: os_win32/popen_win32.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT popen_win32.obj -MD -MP -MF $(DEPDIR)/popen_win32.Tpo -c -o popen_win32.obj `if test -f 'os_win32/popen_win32.cpp'; then $(CYGPATH_W) 'os_win32/popen_win32.cpp'; else $(CYGPATH_W) '$(srcdir)/os_win32/popen_win32.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/popen_win32.Tpo $(DEPDIR)/popen_win32.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='os_win32/popen_win32.cpp' object='popen_win32.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o popen_win32.obj `if test -f 'os_win32/popen_win32.cpp'; then $(CYGPATH_W) 'os_win32/popen_win32.cpp'; else $(CYGPATH_W) '$(srcdir)/os_win32/popen_win32.cpp'; fi`
wmiquery.o: os_win32/wmiquery.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT wmiquery.o -MD -MP -MF $(DEPDIR)/wmiquery.Tpo -c -o wmiquery.o `test -f 'os_win32/wmiquery.cpp' || echo '$(srcdir)/'`os_win32/wmiquery.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wmiquery.Tpo $(DEPDIR)/wmiquery.Po
@ -1896,7 +1940,7 @@ uninstall-sysconfDATA:
echo " rm -f '$$f'"; \
rm -f "$$f"
utility.o: svnversion.h
smartctl.o utility.o: svnversion.h
# Get version info from SVN
@IS_SVN_BUILD_TRUE@svnversion.h: ChangeLog Makefile $(svn_deps)
@ -2107,14 +2151,16 @@ check:
# Build NSIS installer
# Note: Only option character '-' is also compatible with Linux version of makensis
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@$(distinst_win32): os_win32/installer.nsi distdir.mkdir $(FILES_WIN32)
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@$(distinst_win32): os_win32/installer.nsi smartctl_res.rc distdir.mkdir $(FILES_WIN32)
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ test -z '$(builddir_win64)' || ( cd $(builddir_win64) && make distdir-win32 )
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ @date=`sed -n 's,^.*DATE[^"]*"\([^"]*\)".*$$,\1,p' svnversion.h` && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ rev=`sed -n 's,^.*REV[^"]*"\([^"]*\)".*$$,r\1,p' svnversion.h` && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ version=`sed -n 's|^ *VALUE "FileVersion", "\([0-9.]*\)".*$$|\1|p' smartctl_res.rc` && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ yy=`echo "$$date" | sed -n 's,^20\([0-9][0-9]\).*$$,\1,p'`; yy="$${yy:-XX}" && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ verstr="$(PACKAGE_VERSION) $$date $$rev "$(BUILD_INFO) && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ d64= && if [ -n '$(builddir_win64)' ]; then d64='-DINPDIR64=$(builddir_win64)/$(PACKAGE)-$(VERSION).win64'; fi && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ echo "'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSTR='$$verstr' $<" && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ '$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSTR="$$verstr" $<
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ echo "'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSION=$$version -DYY=$$yy -DVERSTR='$$verstr' $<" && \
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ '$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSION=$$version -DYY=$$yy -DVERSTR="$$verstr" $<
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ md5sum $@ > $@.md5
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ sha1sum $@ > $@.sha1
@OS_WIN32_MINGW_TRUE@@OS_WIN32_NSIS_TRUE@ sha256sum $@ > $@.sha256
@ -2208,7 +2254,7 @@ check:
@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\|STRINGS_H\|UNISTD_H\|WORKING_SNPRINTF\) 1$$,/* #undef HAVE_\1 */ /* VC$(vcver) */,' \
@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 SMARTMONTOOLS_BUILD_HOST "[^-]*\)[^"]*,\1-pc-w32vc$(vcver),' $< > $@
@OS_WIN32_MINGW_TRUE@$(srcdir)/os_win32/vc$(vcver)/svnversion.h: svnversion.h

50
NEWS
View File

@ -1,10 +1,58 @@
smartmontools NEWS
------------------
$Id: NEWS 4594 2017-11-05 15:21:35Z chrfranke $
$Id: NEWS 4883 2018-12-30 14:48:54Z chrfranke $
The most up-to-date version of this file is:
https://sourceforge.net/p/smartmontools/code/HEAD/tree/trunk/smartmontools/NEWS
Date 2018-12-30
Summary: smartmontools release 7.0
-----------------------------------------------------------
- smartctl: New options '-j' and '--json[=giosu]' to enable experimental
JSON output mode. Also supports an alternative flat format suitable
for grep ('--json=g').
- smartctl '-l devstat': Fix for logs with 256 sectors.
- smartctl '-l error': Prints SCSI Pending Defects log page if supported.
- smartctl '-H': Prints SCSI Format Status log page if supported.
- smartctl '-x': Now includes '-l defects'.
- NVMe/USB: Device type '-d sntjmicron' for NVMe drives behind JMicron USB
to NVMe bridges.
- NVMe: SMART/Health Information and Error Information are always read with
broadcast NSID.
- SCSI: Various improvements for the decoding of log pages.
- SCSI: Improved handling of READ CAPACITY command.
- SCSI: Support for SAS host managed drives.
- New option '-d scsi+TYPE' to disable SAT auto detection for 'aacraid'
and 'cciss'.
- update-smart-drivedb: New option '-u github'.
- update-smart-drivedb: New signing key.
- configure: New options '--with-cxx11-regex' and '--with-libsystemd'.
- configure: Default for '--with-nvme-devicescan' is now 'yes' on Linux
and Windows.
- configure: Default for '--with-scriptpath' now includes '/usr/local/bin'.
- configure: Options '-with-initscriptdir=[auto|yes]' are no longer
supported.
- Reworked handling of unaligned LE and BE integers.
- Dropped various backward compatibility fixes for very old compilers.
- Replaced GPL header with 'SPDX-License-Identifier' in all source files.
- HDD, SSD and USB additions to drive database.
- Always use '-d sat' for USB vendor IDs with known SAT support.
- Linux: Device scan with '-d by-id' scans '/dev/disk/by-id/*' symlinks.
- Linux: Dropped device scan support for devfs.
- Linux: Fixed device scan with multiple '-d TYPE' options.
- Linux: Fixed device scan crash on missing '/proc/devices'.
- Linux: USB ID detection also for '/dev/sgN'.
- Linux: Compile fix for systems with musl libc.
- Linux smartd: Could now run as systemd service with 'Type=notify' set.
- FreeBSD: NVMe device scanning.
- FreeBSD: Various compile fixes.
- NetBSD: Fixed regression in name based device type detection.
- NetBSD big endian: Fixed regression in ATA code.
- NetBSD big endian: Fixed byte ordering of ATA IDENTIFY data from USB/SAT
drives.
- Windows: Improved search for actual CSMI port number.
- Windows: Installer includes VERSIONINFO resource.
Date 2017-11-05
Summary: smartmontools release 6.6
-----------------------------------------------------------

6
README
View File

@ -3,7 +3,7 @@ smartmontools - S.M.A.R.T. utility toolset for Darwin/Mac
OSX, FreeBSD, Linux, NetBSD, OpenBSD, Solaris, and Windows.
==========================================================
$Id: README 4431 2017-08-08 19:38:15Z chrfranke $
$Id: README 4760 2018-08-19 18:45:53Z chrfranke $
== HOME ==
The home for smartmontools is located at:
@ -20,7 +20,7 @@ You will find a mailing list for support and other questions at:
== COPYING ==
Copyright (C) 2002-9 Bruce Allen
Copyright (C) 2004-15 Christian Franke
Copyright (C) 2004-18 Christian Franke
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@ -30,6 +30,8 @@ version.
You should have received a copy of the GNU General Public License (for
example COPYING). If not, see <http://www.gnu.org/licenses/>.
SPDX-License-Identifier: GPL-2.0-or-later
== CREDITS ==
See AUTHORS file.

View File

@ -2,14 +2,7 @@
* Copyright (C) 2014 Raghava Aditya <Raghava.Aditya@pmcs.com>
* Copyright (C) 2015 Nidhi Malhotra <Nidhi.Malhotra@pmcs.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
// Check windows

View File

@ -6,21 +6,14 @@
* Copyright (C) 2003-8 Philip Williams
* Copyright (C) 2012 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "atacmdnames.h"
#include <stdlib.h>
#include <stdio.h>
const char * atacmdnames_cpp_cvsid = "$Id: atacmdnames.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * atacmdnames_cpp_cvsid = "$Id: atacmdnames.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
ATACMDNAMES_H_CVSID;
const char cmd_reserved[] = "[RESERVED]";

View File

@ -8,21 +8,13 @@
*
* Copyright (C) 2003-8 Philip Williams
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ATACMDNAMES_H_
#define ATACMDNAMES_H_
#define ATACMDNAMES_H_CVSID "$Id: atacmdnames.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define ATACMDNAMES_H_CVSID "$Id: atacmdnames.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
/* Returns the name of the command (and possibly sub-command) with the given
command code and feature register values. */

View File

@ -4,39 +4,29 @@
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2002-11 Bruce Allen
* Copyright (C) 2008-17 Christian Franke
* Copyright (C) 2008-18 Christian Franke
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include "config.h"
#include "int64.h"
#include "atacmds.h"
#include "knowndrives.h" // get_default_attr_defs()
#include "utility.h"
#include "dev_ata_cmd_set.h" // for parsed_ata_device
const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 4582 2017-11-03 20:54:56Z chrfranke $"
const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
ATACMDS_H_CVSID;
// Print ATA debug messages?
@ -52,7 +42,7 @@ bool dont_print_serial_number = false;
// SMART RETURN STATUS yields SMART_CYL_HI,SMART_CYL_LOW to indicate drive
// is healthy and SRET_STATUS_HI_EXCEEDED,SRET_STATUS_MID_EXCEEDED to
// indicate that a threshhold exceeded condition has been detected.
// indicate that a threshold exceeded condition has been detected.
// Those values (byte pairs) are placed in ATA register "LBA 23:8".
#define SRET_STATUS_HI_EXCEEDED 0x2C
#define SRET_STATUS_MID_EXCEEDED 0xF4
@ -267,7 +257,7 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
// Return a multiline string containing a list of valid arguments for
// parse_attribute_def(). The strings are preceeded by tabs and followed
// parse_attribute_def(). The strings are preceded by tabs and followed
// (except for the last) by newlines.
std::string create_vendor_attribute_arg_list()
{
@ -362,17 +352,12 @@ static void invalidate_serno(ata_identify_device * id)
sum += b[i]; sum -= b[i] = 0x00;
}
#ifndef __NetBSD__
bool must_swap = !!isbigendian();
if (must_swap)
if (isbigendian())
SWAPV(id->words088_255[255-88]);
#endif
if ((id->words088_255[255-88] & 0x00ff) == 0x00a5)
id->words088_255[255-88] += sum << 8;
#ifndef __NetBSD__
if (must_swap)
if (isbigendian())
SWAPV(id->words088_255[255-88]);
#endif
}
static const char * const commandstrings[]={
@ -778,20 +763,9 @@ static void trim(char * out, const char * in)
// Convenience function for formatting strings from ata_identify_device
void ata_format_id_string(char * out, const unsigned char * in, int n)
{
bool must_swap = true;
#ifdef __NetBSD__
/* NetBSD kernel delivers IDENTIFY data in host byte order (but all else is LE) */
// TODO: Handle NetBSD case in os_netbsd.cpp
if (isbigendian())
must_swap = !must_swap;
#endif
char tmp[65];
n = n > 64 ? 64 : n;
if (!must_swap)
strncpy(tmp, (const char *)in, n);
else
swapbytes(tmp, (const char *)in, n);
swapbytes(tmp, (const char *)in, n);
tmp[n] = '\0';
trim(out, tmp);
}
@ -873,10 +847,7 @@ int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_s
if (raw_buf)
memcpy(raw_buf, buf, sizeof(*buf));
#ifndef __NetBSD__
// if machine is big-endian, swap byte order as needed
// NetBSD kernel delivers IDENTIFY data in host byte order
// TODO: Handle NetBSD case in os_netbsd.cpp
if (isbigendian()){
// swap various capability words that are needed
unsigned i;
@ -887,7 +858,6 @@ int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_s
for (i=0; i<168; i++)
swap2((char *)(buf->words088_255+i));
}
#endif
// If there is a checksum there, validate it
if ((rawshort[255] & 0x00ff) == 0x00a5 && checksum(rawbyte))
@ -1277,7 +1247,7 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
int mode = args.span[i].mode;
uint64_t start = args.span[i].start;
uint64_t end = args.span[i].end;
if (mode == SEL_CONT) {// redo or next dependig on last test status
if (mode == SEL_CONT) {// redo or next depending on last test status
switch (sv->self_test_exec_status >> 4) {
case 1: case 2: // Aborted/Interrupted by host
pout("Continue Selective Self-Test: Redo last span\n");
@ -1293,7 +1263,7 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
if ( (mode == SEL_REDO || mode == SEL_NEXT)
&& prev_args && i < prev_args->num_spans
&& !data->span[i].start && !data->span[i].end) {
// Some drives do not preserve the selective self-test log accross
// Some drives do not preserve the selective self-test log across
// power-cyles. If old span on drive is cleared use span provided
// by caller. This is used by smartd (first span only).
data->span[i].start = prev_args->span[i].start;
@ -1760,7 +1730,7 @@ int TestTime(const ata_smart_values *data, int testtype)
// word 84 and 87. Top two bits must match the pattern 01. BEFORE
// ATA-6 these top two bits still had to match the pattern 01, but the
// remaining bits were reserved (==0).
int isSmartErrorLogCapable (const ata_smart_values * data, const ata_identify_device * identity)
bool isSmartErrorLogCapable(const ata_smart_values * data, const ata_identify_device * identity)
{
unsigned short word84=identity->command_set_extension;
unsigned short word87=identity->csf_default;
@ -1768,18 +1738,18 @@ int isSmartErrorLogCapable (const ata_smart_values * data, const ata_identify_de
int isata7=identity->major_rev_num & (0x01<<7);
if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))
return 1;
return true;
if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))
return 1;
return true;
// otherwise we'll use the poorly documented capability bit
return data->errorlog_capability & 0x01;
return !!(data->errorlog_capability & 0x01);
}
// See previous function. If the error log exists then the self-test
// log should (must?) also exist.
int isSmartTestLogCapable (const ata_smart_values * data, const ata_identify_device *identity)
bool isSmartTestLogCapable(const ata_smart_values * data, const ata_identify_device *identity)
{
unsigned short word84=identity->command_set_extension;
unsigned short word87=identity->csf_default;
@ -1787,18 +1757,18 @@ int isSmartTestLogCapable (const ata_smart_values * data, const ata_identify_dev
int isata7=identity->major_rev_num & (0x01<<7);
if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))
return 1;
return true;
if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))
return 1;
return true;
// otherwise we'll use the poorly documented capability bit
return data->errorlog_capability & 0x01;
return !!(data->errorlog_capability & 0x01);
}
int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
bool isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
{
unsigned short word84=identity->command_set_extension;
unsigned short word87=identity->csf_default;
@ -1810,7 +1780,7 @@ int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
if ((word84>>14) == 0x01)
// If bit 5 of word 84 is set to one, the device supports the
// General Purpose Logging feature set.
return (word84 & (0x01 << 5));
return !!(word84 & (0x01 << 5));
// If bit 14 of word 87 is set to one and bit 15 of word 87 is
// cleared to zero, the contents of words (87:85) contain valid
@ -1818,50 +1788,10 @@ int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
if ((word87>>14) == 0x01)
// If bit 5 of word 87 is set to one, the device supports
// the General Purpose Logging feature set.
return (word87 & (0x01 << 5));
return !!(word87 & (0x01 << 5));
// not capable
return 0;
}
// SMART self-test capability is also indicated in bit 1 of DEVICE
// IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
// However this was only introduced in ATA-6 (but self-test log was in
// ATA-5).
int isSupportExecuteOfflineImmediate(const ata_smart_values *data)
{
return data->offline_data_collection_capability & 0x01;
}
// Note in the ATA-5 standard, the following bit is listed as "Vendor
// Specific". So it may not be reliable. The only use of this that I
// have found is in IBM drives, where it is well-documented. See for
// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
int isSupportAutomaticTimer(const ata_smart_values * data)
{
return data->offline_data_collection_capability & 0x02;
}
int isSupportOfflineAbort(const ata_smart_values *data)
{
return data->offline_data_collection_capability & 0x04;
}
int isSupportOfflineSurfaceScan(const ata_smart_values * data)
{
return data->offline_data_collection_capability & 0x08;
}
int isSupportSelfTest (const ata_smart_values * data)
{
return data->offline_data_collection_capability & 0x10;
}
int isSupportConveyanceSelfTest(const ata_smart_values * data)
{
return data->offline_data_collection_capability & 0x20;
}
int isSupportSelectiveSelfTest(const ata_smart_values * data)
{
return data->offline_data_collection_capability & 0x40;
return false;
}
// Get attribute state
@ -2580,169 +2510,6 @@ int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsign
}
// Print one self-test log entry.
// Returns:
// -1: self-test failed
// 1: extended self-test completed without error
// 0: otherwise
int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
unsigned char test_status,
unsigned short timestamp,
uint64_t failing_lba,
bool print_error_only, bool & print_header)
{
// Check status and type for return value
int retval = 0;
switch (test_status >> 4) {
case 0x0:
if ((test_type & 0x0f) == 0x02)
retval = 1; // extended self-test completed without error
break;
case 0x3: case 0x4:
case 0x5: case 0x6:
case 0x7: case 0x8:
retval = -1; // self-test failed
break;
}
if (retval >= 0 && print_error_only)
return retval;
std::string msgtest;
switch (test_type) {
case 0x00: msgtest = "Offline"; break;
case 0x01: msgtest = "Short offline"; break;
case 0x02: msgtest = "Extended offline"; break;
case 0x03: msgtest = "Conveyance offline"; break;
case 0x04: msgtest = "Selective offline"; break;
case 0x7f: msgtest = "Abort offline test"; break;
case 0x81: msgtest = "Short captive"; break;
case 0x82: msgtest = "Extended captive"; break;
case 0x83: msgtest = "Conveyance captive"; break;
case 0x84: msgtest = "Selective captive"; break;
default:
if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
msgtest = strprintf("Vendor (0x%02x)", test_type);
else
msgtest = strprintf("Reserved (0x%02x)", test_type);
}
std::string msgstat;
switch (test_status >> 4) {
case 0x0: msgstat = "Completed without error"; break;
case 0x1: msgstat = "Aborted by host"; break;
case 0x2: msgstat = "Interrupted (host reset)"; break;
case 0x3: msgstat = "Fatal or unknown error"; break;
case 0x4: msgstat = "Completed: unknown failure"; break;
case 0x5: msgstat = "Completed: electrical failure"; break;
case 0x6: msgstat = "Completed: servo/seek failure"; break;
case 0x7: msgstat = "Completed: read failure"; break;
case 0x8: msgstat = "Completed: handling damage??"; break;
case 0xf: msgstat = "Self-test routine in progress"; break;
default: msgstat = strprintf("Unknown status (0x%x)", test_status >> 4);
}
// Print header once
if (print_header) {
print_header = false;
pout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n");
}
char msglba[32];
if (retval < 0 && failing_lba < 0xffffffffffffULL)
snprintf(msglba, sizeof(msglba), "%" PRIu64, failing_lba);
else {
msglba[0] = '-'; msglba[1] = 0;
}
pout("#%2u %-19s %-29s %1d0%% %8u %s\n", testnum,
msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
return retval;
}
// Print Smart self-test log, used by smartctl and smartd.
// return value is:
// bottom 8 bits: number of entries found where self-test showed an error
// remaining bits: if nonzero, power on hours of last self-test where error was found
int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
firmwarebug_defs firmwarebugs)
{
if (allentries)
pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber);
if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
if (data->mostrecenttest==0){
if (allentries)
pout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n");
return 0;
}
bool noheaderprinted = true;
int errcnt = 0, hours = 0, igncnt = 0;
int testno = 0, ext_ok_testno = -1;
// print log
for (int i = 20; i >= 0; i--) {
// log is a circular buffer
int j = (i+data->mostrecenttest)%21;
const ata_smart_selftestlog_struct * log = data->selftest_struct+j;
if (nonempty(log, sizeof(*log))) {
// count entry based on non-empty structures -- needed for
// Seagate only -- other vendors don't have blank entries 'in
// the middle'
testno++;
// T13/1321D revision 1c: (Data structure Rev #1)
//The failing LBA shall be the LBA of the uncorrectable sector
//that caused the test to fail. If the device encountered more
//than one uncorrectable sector during the test, this field
//shall indicate the LBA of the first uncorrectable sector
//encountered. If the test passed or the test failed for some
//reason other than an uncorrectable sector, the value of this
//field is undefined.
// This is true in ALL ATA-5 specs
uint64_t lba48 = (log->lbafirstfailure < 0xffffffff ? log->lbafirstfailure : 0xffffffffffffULL);
// Print entry
int state = ataPrintSmartSelfTestEntry(testno,
log->selftestnumber, log->selfteststatus,
log->timestamp, lba48, !allentries, noheaderprinted);
if (state < 0) {
// Self-test showed an error
if (ext_ok_testno < 0) {
errcnt++;
// keep track of time of most recent error
if (!hours)
hours = log->timestamp;
}
else
// Newer successful extended self-test exits
igncnt++;
}
else if (state > 0 && ext_ok_testno < 0) {
// Latest successful extended self-test
ext_ok_testno = testno;
}
}
}
if (igncnt)
pout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
igncnt, igncnt+errcnt, ext_ok_testno);
if (!allentries && !noheaderprinted)
pout("\n");
return ((hours << 8) | errcnt);
}
/////////////////////////////////////////////////////////////////////////////
// Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
// an ATA device with same behaviour
@ -2806,7 +2573,8 @@ static int name2command(const char * s)
return -1;
}
static bool matchcpy(char * dest, size_t size, const char * src, const regmatch_t & srcmatch)
static bool matchcpy(char * dest, size_t size, const char * src,
const regular_expression::match_range & srcmatch)
{
if (srcmatch.rm_so < 0)
return false;
@ -2818,7 +2586,7 @@ static bool matchcpy(char * dest, size_t size, const char * src, const regmatch_
return true;
}
static inline int matchtoi(const char * src, const regmatch_t & srcmatch, int defval)
static inline int matchtoi(const char * src, const regular_expression::match_range & srcmatch, int defval)
{
if (srcmatch.rm_so < 0)
return defval;
@ -2837,7 +2605,7 @@ parsed_ata_device::parsed_ata_device(smart_interface * intf, const char * dev_na
parsed_ata_device::~parsed_ata_device() throw()
{
close();
parsed_ata_device::close();
}
bool parsed_ata_device::is_open() const
@ -2884,7 +2652,7 @@ bool parsed_ata_device::open()
")"; // )
// Compile regex
const regular_expression regex(pattern, REG_EXTENDED);
const regular_expression regex(pattern);
// Parse buffer
const char * errmsg = 0;
@ -2894,7 +2662,7 @@ bool parsed_ata_device::open()
if (!(line[0] == 'R' || line[0] == '=' || line[0] == ' '))
continue;
const int nmatch = 1+11;
regmatch_t match[nmatch];
regular_expression::match_range match[nmatch];
if (!regex.execute(line, nmatch, match))
continue;

View File

@ -7,25 +7,13 @@
* Copyright (C) 2008-17 Christian Franke
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ATACMDS_H_
#define ATACMDS_H_
#define ATACMDS_H_CVSID "$Id: atacmds.h 4419 2017-04-17 13:20:31Z chrfranke $"
#define ATACMDS_H_CVSID "$Id: atacmds.h 4848 2018-12-05 18:30:46Z chrfranke $"
#include "dev_interface.h" // ata_device
@ -93,7 +81,7 @@ typedef enum {
// 48-bit commands
#define ATA_READ_LOG_EXT 0x2F
#define ATA_WRITE_LOG_EXT 0x3F
#define ATA_WRITE_LOG_EXT 0x3f
// ATA Specification Feature Register Values (SMART Subcommands).
// Note that some are obsolete as of ATA-7.
@ -220,7 +208,7 @@ struct ata_smart_values {
unsigned char offline_data_collection_status;
unsigned char self_test_exec_status; //IBM # segments for offline collection
unsigned short int total_time_to_complete_off_line; // IBM different
unsigned char vendor_specific_366; // Maxtor & IBM curent segment pointer
unsigned char vendor_specific_366; // Maxtor & IBM current segment pointer
unsigned char offline_data_collection_capability;
unsigned short int smart_capability;
unsigned char errorlog_capability;
@ -526,7 +514,7 @@ ASSERT_SIZEOF_STRUCT(ata_selective_self_test_log, 512);
// T13/1699-D Revision 3f (Working Draft), December 11, 2006.
// SCT Status response (read with SMART_READ_LOG page 0xe0)
// Table 182 of T13/BSR INCITS 529 (ACS-4) Revision 04, August 25, 2014
// Table 194 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
#pragma pack(1)
struct ata_sct_status_response
{
@ -547,7 +535,7 @@ struct ata_sct_status_response
signed char max_temp; // 202: Maximum temperature this power cycle
signed char life_min_temp; // 203: Minimum lifetime temperature
signed char life_max_temp; // 204: Maximum lifetime temperature
unsigned char byte205; // 205: reserved (T13/e06152r0-2: Average lifetime temperature)
signed char max_op_limit; // 205: Specified maximum operating temperature (ACS-4)
unsigned int over_limit_count; // 206-209: # intervals since last reset with temperature > Max Op Limit
unsigned int under_limit_count; // 210-213: # intervals since last reset with temperature < Min Op Limit
unsigned short smart_status; // 214-215: LBA(32:8) of SMART RETURN STATUS (0, 0x2cf4, 0xc24f) (ACS-4)
@ -855,7 +843,7 @@ int ataSmartSupport(const ata_identify_device * drive);
int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool persistent, bool set);
// Return values:
// 1: Write cache controled by ATA Set Features command
// 1: Write cache controlled by ATA Set Features command
// 2: Force enable write cache
// 3: Force disable write cache
int ataGetSetSCTWriteCache(ata_device * device, unsigned short state, bool persistent, bool set);
@ -868,25 +856,39 @@ int ataIsSmartEnabled(const ata_identify_device * drive);
int ataSmartStatus2(ata_device * device);
int isSmartErrorLogCapable(const ata_smart_values * data, const ata_identify_device * identity);
bool isSmartErrorLogCapable(const ata_smart_values * data, const ata_identify_device * identity);
int isSmartTestLogCapable(const ata_smart_values * data, const ata_identify_device * identity);
bool isSmartTestLogCapable(const ata_smart_values * data, const ata_identify_device * identity);
int isGeneralPurposeLoggingCapable(const ata_identify_device * identity);
bool isGeneralPurposeLoggingCapable(const ata_identify_device * identity);
int isSupportExecuteOfflineImmediate(const ata_smart_values * data);
// SMART self-test capability is also indicated in bit 1 of DEVICE
// IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
// However this was only introduced in ATA-6 (but self-test log was in
// ATA-5).
inline bool isSupportExecuteOfflineImmediate(const ata_smart_values *data)
{ return !!(data->offline_data_collection_capability & 0x01); }
int isSupportAutomaticTimer(const ata_smart_values * data);
// TODO: Remove uses of this check. Bit 1 is vendor specific since ATA-4.
// Automatic timer support was only documented for very old IBM drives
// (for example IBM Travelstar 40GNX).
inline bool isSupportAutomaticTimer(const ata_smart_values * data)
{ return !!(data->offline_data_collection_capability & 0x02); }
int isSupportOfflineAbort(const ata_smart_values * data);
inline bool isSupportOfflineAbort(const ata_smart_values *data)
{ return !!(data->offline_data_collection_capability & 0x04); }
int isSupportOfflineSurfaceScan(const ata_smart_values * data);
inline bool isSupportOfflineSurfaceScan(const ata_smart_values * data)
{ return !!(data->offline_data_collection_capability & 0x08); }
int isSupportSelfTest(const ata_smart_values * data);
inline bool isSupportSelfTest(const ata_smart_values * data)
{ return !!(data->offline_data_collection_capability & 0x10); }
int isSupportConveyanceSelfTest(const ata_smart_values * data);
inline bool isSupportConveyanceSelfTest(const ata_smart_values * data)
{ return !!(data->offline_data_collection_capability & 0x20); }
int isSupportSelectiveSelfTest(const ata_smart_values * data);
inline bool isSupportSelectiveSelfTest(const ata_smart_values * data)
{ return !!(data->offline_data_collection_capability & 0x40); }
inline bool isSCTCapable(const ata_identify_device *drive)
{ return !!(drive->words088_255[206-88] & 0x01); } // 0x01 = SCT support
@ -984,21 +986,6 @@ const char * get_valid_firmwarebug_args();
// This function is exported to give low-level capability
int smartcommandhandler(ata_device * device, smart_command_set command, int select, char *data);
// Print one self-test log entry.
// Returns:
// -1: failed self-test
// 1: extended self-test completed without error
// 0: otherwise
int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
unsigned char test_status,
unsigned short timestamp,
uint64_t failing_lba,
bool print_error_only, bool & print_header);
// Print Smart self-test log, used by smartctl and smartd.
int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
firmwarebug_defs firmwarebugs);
// Get capacity and sector sizes from IDENTIFY data
struct ata_size_info
{
@ -1017,17 +1004,6 @@ void ata_format_id_string(char * out, const unsigned char * in, int n);
// Utility routines.
unsigned char checksum(const void * data);
void swap2(char *location);
void swap4(char *location);
void swap8(char *location);
// Typesafe variants using overloading
inline void swapx(unsigned short * p)
{ swap2((char*)p); }
inline void swapx(unsigned int * p)
{ swap4((char*)p); }
inline void swapx(uint64_t * p)
{ swap8((char*)p); }
// Return pseudo-device to parse "smartctl -r ataioctl,2 ..." output
// and simulate an ATA device with same behaviour
ata_device * get_parsed_ata_device(smart_interface * intf, const char * dev_name);

View File

@ -3,27 +3,22 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2012-17 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2012-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
#include "ataidentify.h"
const char * ataidentify_cpp_cvsid = "$Id: ataidentify.cpp 4573 2017-10-29 15:13:58Z chrfranke $"
const char * ataidentify_cpp_cvsid = "$Id: ataidentify.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
ATAIDENTIFY_H_CVSID;
#include "int64.h"
#include "utility.h"
#include <inttypes.h>
// Table 12 of X3T10/0948D (ATA-2) Revision 4c, March 18, 1996
// Table 9 of X3T13/2008D (ATA-3) Revision 7b, January 27, 1997

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2012 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ATAIDENTIFY_H
#define ATAIDENTIFY_H
#define ATAIDENTIFY_H_CVSID "$Id: ataidentify.h 4431 2017-08-08 19:38:15Z chrfranke $"
#define ATAIDENTIFY_H_CVSID "$Id: ataidentify.h 4760 2018-08-19 18:45:53Z chrfranke $"
void ata_print_identify_data(const void * id, bool all_words, int bit_level);

File diff suppressed because it is too large Load Diff

View File

@ -4,28 +4,16 @@
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2002-09 Bruce Allen
* Copyright (C) 2008-17 Christian Franke
* Copyright (C) 2008-18 Christian Franke
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ATAPRINT_H_
#define ATAPRINT_H_
#define ATAPRINT_H_CVSID "$Id: ataprint.h 4572 2017-10-29 14:36:00Z chrfranke $\n"
#define ATAPRINT_H_CVSID "$Id: ataprint.h 4826 2018-11-02 20:09:12Z chrfranke $\n"
#include <vector>
@ -64,7 +52,6 @@ struct ata_print_options
bool devstat_all_pages, devstat_ssd_page;
std::vector<int> devstat_pages;
bool pending_defects_info;
unsigned pending_defects_log;
bool sct_temp_sts, sct_temp_hist;
@ -133,7 +120,7 @@ struct ata_print_options
smart_ext_selftest_log(0),
retry_error_log(false), retry_selftest_log(false),
devstat_all_pages(false), devstat_ssd_page(false),
pending_defects_info(false), pending_defects_log(0),
pending_defects_log(0),
sct_temp_sts(false), sct_temp_hist(false),
sct_erc_get(false),
sct_erc_set(false),

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $Id: autogen.sh 4434 2017-09-14 18:05:12Z samm2 $
# $Id: autogen.sh 4838 2018-11-27 17:27:02Z chrfranke $
#
# Generate ./configure from configure.ac and Makefile.in from Makefile.am.
# This also adds files like missing,depcomp,install-sh to the source
@ -28,7 +28,7 @@ if [ -n "$AUTOMAKE" ]; then
ver=$("$AUTOMAKE" --version) || exit 1
else
maxver=
for v in 1.15 1.14 1.13 1.12 1.11 1.10; do
for v in 1.16 1.15 1.14 1.13 1.12 1.11 1.10; do
minver=$v; test -n "$maxver" || maxver=$v
ver=$(automake-$v --version 2>/dev/null) || continue
AUTOMAKE="automake-$v"
@ -60,7 +60,7 @@ case "$ver" in
# OK
;;
1.14|1.14.1|1.15|1.15.1)
1.14|1.14.1|1.15|1.15.1|1.16|1.16.1)
# TODO: Enable 'subdir-objects' in configure.ac
# For now, suppress 'subdir-objects' forward-incompatibility warning
test -n "$warnings" || amwarnings="--warnings=no-unsupported"

View File

@ -1,3 +1,13 @@
/*
* cciss.cpp
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2007 Sergey Svishchev
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
@ -18,27 +28,18 @@
# ifndef be32toh
# define be32toh __be32_to_cpu
# endif
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# include <sys/endian.h>
# include CISS_LOCATION
# define _HAVE_CCISS
#elif defined(__FreeBSD_kernel__)
# include <endian.h>
# ifdef __GLIBC__
# include <bsd/sys/cdefs.h>
# include <stdint.h>
# endif
# include CISS_LOCATION
# define _HAVE_CCISS
#endif
#ifdef _HAVE_CCISS
#include "cciss.h"
#include "int64.h"
#include "scsicmds.h"
#include "utility.h"
const char * cciss_cpp_cvsid = "$Id: cciss.cpp 4156 2015-10-18 12:20:40Z samm2 $"
const char * cciss_cpp_cvsid = "$Id: cciss.cpp 4858 2018-12-16 17:59:59Z chrfranke $"
CCISS_H_CVSID;
typedef struct _ReportLUNdata_struct
@ -98,7 +99,7 @@ int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int re
int trunc = (iop->dxfer_len > 256) ? 1 : 0;
printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
}
return 0;
@ -116,7 +117,7 @@ int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int re
if (report > 1)
{
printf(" >>> Sense buffer, len=%d:\n", (int)len);
dStrHex((const char *)pBuf, len , 1);
dStrHex((const uint8_t *)pBuf, len , 1);
}
}
if (report)

12
cciss.h
View File

@ -1,7 +1,17 @@
/*
* cciss.h
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2007 Sergey Svishchev
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef CCISS_H_
#define CCISS_H_
#define CCISS_H_CVSID "$Id: cciss.h,v 1.1 2007/04/01 16:49:46 shattered Exp $\n"
#define CCISS_H_CVSID "$Id: cciss.h 4761 2018-08-20 19:33:04Z chrfranke $"
int cciss_io_interface(int device, int target,
struct scsi_cmnd_io * iop, int report);

View File

@ -12,6 +12,12 @@
/* Define to 1 if C++ compiler supports __attribute__((packed)) */
#undef HAVE_ATTR_PACKED
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the <cap-ng.h> header file. */
#undef HAVE_CAP_NG_H
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
@ -33,9 +39,6 @@
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if the system has the type `int64_t'. */
#undef HAVE_INT64_T
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@ -45,6 +48,9 @@
/* Define to 1 if you have the `selinux' library (-lselinux). */
#undef HAVE_LIBSELINUX
/* Define to 1 if you have the `systemd' library (-lsystemd). */
#undef HAVE_LIBSYSTEMD
/* Define to 1 if you have the `usb' library (-lusb). */
#undef HAVE_LIBUSB
@ -57,6 +63,10 @@
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if the type `long double' works and has more range or precision
than `double'. */
#undef HAVE_LONG_DOUBLE_WIDER
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@ -69,6 +79,9 @@
/* Define to 1 if you have the <selinux/selinux.h> header file. */
#undef HAVE_SELINUX_SELINUX_H
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `sigset' function. */
#undef HAVE_SIGSET
@ -84,18 +97,15 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strtoull' function. */
#undef HAVE_STRTOULL
/* Define to 1 if you have the <sys/inttypes.h> header file. */
#undef HAVE_SYS_INTTYPES_H
/* Define to 1 if you have the <sys/int_types.h> header file. */
#undef HAVE_SYS_INT_TYPES_H
/* Define to 1 if you have the <systemd/sd-daemon.h> header file. */
#undef HAVE_SYSTEMD_SD_DAEMON_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
#undef HAVE_SYS_SYSMACROS_H
/* Define to 1 if you have the <sys/tweio.h> header file. */
#undef HAVE_SYS_TWEIO_H
@ -108,21 +118,18 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if the system has the type `uint64_t'. */
#undef HAVE_UINT64_T
/* Define to 1 if you have the `uname' function. */
#undef HAVE_UNAME
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the <wbemcli.h> header file. */
#undef HAVE_WBEMCLI_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
/* Define to 1 to use generic LE/BE code instead */
#undef IGNORE_FAST_LEBE
/* Define to 1 if os_*.cpp still uses the old interface */
#undef OLD_INTERFACE
@ -150,6 +157,9 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 to enable check on each SCSI cdb */
#undef SCSI_CDB_CHECK
/* smartmontools Build Host */
#undef SMARTMONTOOLS_BUILD_HOST
@ -168,12 +178,12 @@
/* Version number of package */
#undef VERSION
/* Define to 1 to use C++11 std::regex instead of POSIX regex(3) */
#undef WITH_CXX11_REGEX
/* Define to 1 to include NVMe devices in smartd DEVICESCAN. */
#undef WITH_NVME_DEVICESCAN
/* Define to 1 if SELinux support is enabled */
#undef WITH_SELINUX
/* Define to 1 to enable legacy ATA support on Solaris SPARC. */
#undef WITH_SOLARIS_SPARC_ATA

986
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,23 @@
#
# $Id: configure.ac 4594 2017-11-05 15:21:35Z chrfranke $
# $Id: configure.ac 4883 2018-12-30 14:48:54Z chrfranke $
#
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.60])
AC_INIT(smartmontools, 6.6, smartmontools-support@listi.jpberlin.de)
AC_INIT([smartmontools], [7.0], [smartmontools-support@listi.jpberlin.de])
AM_INIT_AUTOMAKE([1.10 foreign])
smartmontools_cvs_tag=`echo '$Id: configure.ac 4594 2017-11-05 15:21:35Z chrfranke $'`
smartmontools_release_date=2017-11-05
smartmontools_release_time="15:20:58 UTC"
# Version of drive database branch
smartmontools_drivedb_version=7.0
AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args", [smartmontools Configure Arguments])
AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_DATE, "$smartmontools_release_date", [smartmontools Release Date])
AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_TIME, "$smartmontools_release_time", [smartmontools Release Time])
AC_DEFINE_UNQUOTED(CONFIG_H_CVSID, "$smartmontools_cvs_tag", [smartmontools CVS Tag])
AC_DEFINE_UNQUOTED(PACKAGE_HOMEPAGE, "http://www.smartmontools.org/", [smartmontools Home Page])
smartmontools_cvs_tag=`echo '$Id: configure.ac 4883 2018-12-30 14:48:54Z chrfranke $'`
smartmontools_release_date=2018-12-30
smartmontools_release_time="14:47:55 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])
AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_TIME, "$smartmontools_release_time", [smartmontools Release Time])
AC_DEFINE_UNQUOTED(CONFIG_H_CVSID, "$smartmontools_cvs_tag", [smartmontools CVS Tag])
AC_DEFINE_UNQUOTED(PACKAGE_HOMEPAGE, "https://www.smartmontools.org/", [smartmontools Home Page])
AC_CONFIG_SRCDIR([smartctl.cpp])
AC_CONFIG_HEADER([config.h])
@ -77,53 +80,51 @@ 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 ommitted for now, gettimeofday() provides reasonable precision
# Check omitted for now, gettimeofday() provides reasonable precision
# AC_SEARCH_LIBS(clock_gettime, rt)
dnl Checks for header files.
# Checks for header files.
AC_CHECK_HEADERS([locale.h])
AC_CHECK_HEADERS([dev/ata/atavar.h])
dnl we need [u]int64_t and friends.
AC_CHECK_HEADERS([inttypes.h]) dnl C99, UNIX98, solaris 2.6+
AC_CHECK_HEADERS([stdint.h]) dnl C99
AC_CHECK_HEADERS([sys/inttypes.h]) dnl pre-UNIX98
AC_CHECK_HEADERS([sys/int_types.h]) dnl pre-UNIX98, solaris 2.6+
dnl Check for FreeBSD twe include files...currently missing on 5.2, but should be there
AC_CHECK_HEADERS([sys/tweio.h])
AC_CHECK_HEADERS([sys/twereg.h])
dnl Check for FreeBSD twa include files...
AC_CHECK_HEADERS([sys/tw_osl_ioctl.h])
dnl This header file is needed for cciss_ioctl.h at least on SuSE LINUX
AC_CHECK_HEADERS([linux/compiler.h])
dnl Check for the FreeBSD CCISS system header and use internal one if not found
AC_CHECK_HEADERS([dev/ciss/cissio.h],
[AC_DEFINE([CISS_LOCATION],[<dev/ciss/cissio.h>],[freebsd ciss header location])],
[AC_DEFINE([CISS_LOCATION],["cissio_freebsd.h"],[freebsd ciss header location])]
)
dnl Check for Linux CCISS include file
AC_CHECK_HEADERS([linux/cciss_ioctl.h], [], [], [AC_INCLUDES_DEFAULT
AC_CHECK_HEADERS([byteswap.h], [], [], [])
case "$host" in
*-*-freebsd*|*-*-dragonfly*|*-*-kfreebsd*-gnu*)
# Check for FreeBSD twe and twa include files
AC_CHECK_HEADERS([sys/tweio.h sys/twereg.h sys/tw_osl_ioctl.h])
# Check for the FreeBSD CCISS system header and use internal one if not found
AC_CHECK_HEADERS([dev/ciss/cissio.h],
[AC_DEFINE([CISS_LOCATION],[<dev/ciss/cissio.h>],[freebsd ciss header location])],
[AC_DEFINE([CISS_LOCATION],["cissio_freebsd.h"],[freebsd ciss header location])])
;;
*-*-linux*)
# <linux/compiler.h> is needed for cciss_ioctl.h at least on SuSE LINUX
AC_CHECK_HEADERS([sys/sysmacros.h linux/compiler.h])
# Check for Linux CCISS include file
AC_CHECK_HEADERS([linux/cciss_ioctl.h], [], [], [AC_INCLUDES_DEFAULT
#ifdef HAVE_LINUX_COMPILER_H
# include <linux/compiler.h>
#endif
])
dnl Check for Windows DDK and WMI header files
AC_CHECK_HEADERS([ntdddisk.h ddk/ntdddisk.h], [], [], [AC_INCLUDES_DEFAULT
;;
*-*-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 <windows.h>
])
AC_CHECK_HEADERS([wbemcli.h])
;;
esac
dnl Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_TYPES([int64_t, uint64_t])
# Checks for typedefs, and compiler characteristics.
AC_CHECK_TYPES([__int128])
AC_TYPE_LONG_DOUBLE_WIDER
dnl Checks for library functions.
# Checks for library functions.
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([regcomp], [need_regex=no], [need_regex=yes])
AM_CONDITIONAL(NEED_REGEX, [test "$need_regex" = "yes"])
AC_CHECK_FUNCS([sigset])
AC_CHECK_FUNCS([strtoull])
AC_CHECK_FUNCS([uname])
AC_CHECK_FUNCS([clock_gettime ftime gettimeofday])
# Check byte ordering (defines WORDS_BIGENDIAN)
@ -147,74 +148,15 @@ AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(ASFLAGS)
AC_ARG_WITH(systemdsystemunitdir,
[AS_HELP_STRING([--with-systemdsystemunitdir@<:@=DIR|auto|yes|no@:>@], [Location of systemd service files [auto]])],
[], [with_systemdsystemunitdir=auto])
systemdsystemunitdir=
case "$with_systemdsystemunitdir" in
auto|yes)
if test -n "$PKG_CONFIG"; then
AC_MSG_CHECKING([for systemdsystemunitdir])
systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd 2>/dev/null`
AC_MSG_RESULT([${systemdsystemunitdir:-no}])
fi
case "$with_systemdsystemunitdir:$sysconfdir:$systemdsystemunitdir" in
yes:*:) AC_MSG_ERROR([Location of systemd service files not found]) ;;
yes:*:*|auto:*:|auto:/etc:*) ;;
*) systemdsystemunitdir='${prefix}'$systemdsystemunitdir ;;
esac ;;
no) ;;
*) systemdsystemunitdir="$with_systemdsystemunitdir" ;;
esac
AC_SUBST(systemdsystemunitdir)
AM_CONDITIONAL(INSTALL_SYSTEMDUNIT, [test -n "$systemdsystemunitdir"])
AC_ARG_WITH(systemdenvfile,
[AS_HELP_STRING([--with-systemdenvfile@<:@=FILE|auto|yes|no@:>@], [Path of systemd EnvironmentFile [auto]])],
[], [with_systemdenvfile=auto])
systemdenvfile=
case "$with_systemdenvfile:$cross_compiling:$systemdsystemunitdir" in
auto:no:?*|yes:*:?*)
AC_MSG_CHECKING([for path of systemd EnvironmentFile])
for dir in sysconfig default; do
if test -d /etc/$dir; then
systemdenvfile='${sysconfdir}'/$dir/smartmontools
break
fi
done
AC_MSG_RESULT([${systemdenvfile:-no}])
case "$with_systemdenvfile:$systemdenvfile" in
yes:) AC_MSG_ERROR([Path of systemd EnvironmentFile not found]) ;;
esac ;;
auto:*|no:*) ;;
*:*:) AC_MSG_ERROR([Location of systemd service files not found]) ;;
*) systemdenvfile="$with_systemdenvfile"
esac
AC_SUBST(systemdenvfile)
AC_ARG_WITH(initscriptdir,
[AS_HELP_STRING([--with-initscriptdir@<:@=DIR|auto|yes|no@:>@], [Location of init scripts [auto]])],
[], [with_initscriptdir=auto])
initddir=
case "$with_initscriptdir:$cross_compiling:$systemdsystemunitdir" in
auto:no:|yes:*)
AC_MSG_CHECKING([for init (rc) directory])
for dir in rc.d/init.d init.d rc.d; do
if test -d /etc/$dir; then
initddir='${sysconfdir}'/$dir
break
fi
done
AC_MSG_RESULT([${initddir:-no}])
case "$with_initscriptdir:$initddir" in
yes:) AC_MSG_ERROR([Location of init scripts not found]) ;;
esac ;;
auto:*|no:*) ;;
*) initddir="$with_initscriptdir" ;;
esac
AC_ARG_WITH(initscriptdir,
[AS_HELP_STRING([--with-initscriptdir=@<:@DIR|no@:>@], [Location of init scripts [no]])],
[ case "$withval" in
auto|yes) AC_MSG_ERROR(['--with-initscriptdir=$withval' is no longer supported]) ;;
no) ;;
*) initddir="$withval" ;;
esac
])
AC_SUBST(initddir)
AM_CONDITIONAL(INSTALL_INITSCRIPT, [test -n "$initddir"])
@ -226,6 +168,9 @@ case "${host}" in
*-apple-darwin*)
initdfile="com.smartmontools.smartd.plist"
;;
*-*-cygwin*)
initdfile="smartd.cygwin.initd"
;;
*)
initdfile="smartd.initd"
;;
@ -244,7 +189,7 @@ AC_ARG_WITH(drivedbdir,
AC_SUBST(drivedbdir)
AM_CONDITIONAL(ENABLE_DRIVEDB, [test -n "$drivedbdir"])
drivedb_version=$VERSION
drivedb_version=$smartmontools_drivedb_version
AC_ARG_WITH(update-smart_drivedb,
[AS_HELP_STRING([--with-update-smart-drivedb@<:@=yes|no|X.Y@:>@],
[Install update-smart-drivedb script (and backport it to branches/RELEASE_X_Y_DRIVEDB) [yes]])],
@ -288,9 +233,9 @@ AC_SUBST(smartdplugindir)
AC_ARG_WITH(scriptpath,
[AS_HELP_STRING([--with-scriptpath=@<:@PATH|no@:>@],
[PATH variable set within scripts [/usr/bin:/bin]])],
[PATH variable set within scripts [/usr/local/bin:/usr/bin:/bin]])],
[scriptpath=; test "$withval" != "no" && scriptpath="$withval"],
[scriptpath="/usr/bin:/bin"])
[scriptpath="/usr/local/bin:/usr/bin:/bin"])
AC_SUBST(scriptpath)
AM_CONDITIONAL(ENABLE_SCRIPTPATH, [test -n "$scriptpath"])
@ -322,6 +267,20 @@ AC_ARG_ENABLE(sample,
[smartd_suffix=;])
AC_SUBST(smartd_suffix)
AC_ARG_ENABLE([scsi-cdb-check],
[AS_HELP_STRING([--enable-scsi-cdb-check], [do sanity check on each SCSI cdb])],
[ if test "$enableval" = "yes"; then
AC_DEFINE(SCSI_CDB_CHECK, 1, [Define to 1 to enable check on each SCSI cdb])
fi
],[])
AC_ARG_ENABLE([fast-lebe],
[AS_HELP_STRING([--disable-fast-lebe], [use generic little-endian/big-endian code instead])],
[ if test "$enableval" = "no"; then
AC_DEFINE(IGNORE_FAST_LEBE, 1, [Define to 1 to use generic LE/BE code instead])
fi
],[])
AC_ARG_WITH(os-deps,
[AS_HELP_STRING([--with-os-deps='os_module.o ...'], [Specify OS dependent module(s) [guessed]])],
[ for x in $with_os_deps; do
@ -339,40 +298,94 @@ AC_ARG_WITH(selinux,
AC_CHECK_LIB(selinux, matchpathcon, [], [AC_MSG_ERROR([Missing or incorrect SELinux library files])])
fi
],[])
AC_SUBST(with_selinux)
if test "$with_selinux" = "yes"; then
AC_DEFINE(WITH_SELINUX, 1, [Define to 1 if SELinux support is enabled])
fi
AC_ARG_WITH(libcap-ng,
[AS_HELP_STRING([--with-libcap-ng@<:@=auto|yes|no@:>@], [Add Libcap-ng support to smartd [auto]])],
[], [with_libcap_ng=auto])
use_libcap_ng=no
if test "$with_libcap_ng" != "no"; then
AC_CHECK_LIB(cap-ng, capng_clear,
[AC_DEFINE(HAVE_LIBCAP_NG, 1, [Define to 1 if you have the `cap-ng' library (-lcap-ng).]) dnl `vim syntax
CAPNG_LDADD="-lcap-ng"; use_libcap_ng=yes])
if test "$use_libcap_ng" = "yes"; then
AC_CHECK_HEADER(cap-ng.h, [], [AC_MSG_ERROR([libcap-ng libraries found but headers are missing])])
elif test "$with_libcap_ng" = "yes"; then
AC_MSG_ERROR([libcap-ng support was requested but the library was not found])
fi
fi
AC_MSG_CHECKING([whether to use libcap-ng])
case "$with_libcap_ng:$host_os" in
auto:linux*|yes:*)
AC_CHECK_HEADERS([cap-ng.h], [AC_CHECK_LIB([cap-ng], [capng_clear],
[AC_DEFINE(HAVE_LIBCAP_NG, 1,
[Define to 1 if you have the `cap-ng' library (-lcap-ng).]) dnl `vim syntax
CAPNG_LDADD="-lcap-ng"; use_libcap_ng=yes],
[AC_MSG_ERROR([libcap-ng headers found but library is missing])])],
[test "$with_libcap_ng" != "yes" || AC_MSG_ERROR([Missing libcap-ng header files])])
;;
esac
AC_SUBST(CAPNG_LDADD)
AC_MSG_RESULT([$use_libcap_ng])
AC_ARG_WITH(libsystemd,
[AS_HELP_STRING([--with-libsystemd@<:@=auto|yes|no@:>@],
[Add systemd 'Type=notify' support to smartd [auto]])],
[], [with_libsystemd=auto])
use_libsystemd=no
case "$with_libsystemd:$host_os" in
auto:linux*|yes:*)
AC_CHECK_HEADERS([systemd/sd-daemon.h], [AC_CHECK_LIB([systemd], [sd_notify],
[AC_DEFINE(HAVE_LIBSYSTEMD, 1,
[Define to 1 if you have the `systemd' library (-lsystemd).]) dnl `vim syntax
SYSTEMD_LDADD="-lsystemd"; use_libsystemd=yes],
[AC_MSG_ERROR([libsystemd headers found but library is missing])])],
[test "$with_libsystemd" != "yes" || AC_MSG_ERROR([Missing libsystemd header files])])
;;
esac
AC_SUBST(SYSTEMD_LDADD)
AC_ARG_WITH(systemdsystemunitdir,
[AS_HELP_STRING([--with-systemdsystemunitdir@<:@=DIR|auto|yes|no@:>@], [Location of systemd service files [auto]])],
[], [with_systemdsystemunitdir=auto])
systemdsystemunitdir=
case "$with_systemdsystemunitdir:$use_libsystemd" in
auto:yes|yes:yes)
if test -n "$PKG_CONFIG"; then
AC_MSG_CHECKING([for systemdsystemunitdir])
systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd 2>/dev/null`
AC_MSG_RESULT([${systemdsystemunitdir:-no}])
fi
case "$with_systemdsystemunitdir:$sysconfdir:$systemdsystemunitdir" in
yes:*:) AC_MSG_ERROR([Location of systemd service files not found]) ;;
yes:*:*|auto:*:|auto:/etc:*) ;;
*) systemdsystemunitdir='${prefix}'$systemdsystemunitdir ;;
esac ;;
auto:*|no:*) ;;
*:yes) systemdsystemunitdir="$with_systemdsystemunitdir" ;;
*) AC_MSG_ERROR(['--with-systemdsystemunitdir=$with_systemdsystemunitdir' now requires '--with-libsystemd']) ;;
esac
AC_SUBST(systemdsystemunitdir)
AM_CONDITIONAL(INSTALL_SYSTEMDUNIT, [test -n "$systemdsystemunitdir"])
AC_ARG_WITH(systemdenvfile,
[AS_HELP_STRING([--with-systemdenvfile@<:@=FILE|auto|yes|no@:>@], [Path of systemd EnvironmentFile [auto]])],
[], [with_systemdenvfile=auto])
systemdenvfile=
case "$with_systemdenvfile:$cross_compiling:$systemdsystemunitdir" in
auto:no:?*|yes:*:?*)
AC_MSG_CHECKING([for path of systemd EnvironmentFile])
for dir in sysconfig default; do
if test -d /etc/$dir; then
systemdenvfile='${sysconfdir}'/$dir/smartmontools
break
fi
done
AC_MSG_RESULT([${systemdenvfile:-no}])
case "$with_systemdenvfile:$systemdenvfile" in
yes:) AC_MSG_ERROR([Path of systemd EnvironmentFile not found]) ;;
esac ;;
auto:*|no:*) ;;
*:*:) AC_MSG_ERROR([Location of systemd service files not found]) ;;
*) systemdenvfile="$with_systemdenvfile"
esac
AC_SUBST(systemdenvfile)
# TODO: Remove when NVMe support is no longer EXPERIMENTAL
AC_ARG_WITH(nvme-devicescan,
[AS_HELP_STRING([--with-nvme-devicescan@<:@=yes|no@:>@],
[Include NVMe devices in smartd DEVICESCAN [no]])])
AC_SUBST(with_nvme_devicescan)
if test "$with_nvme_devicescan" = "yes"; then
AC_DEFINE(WITH_NVME_DEVICESCAN, 1, [Define to 1 to include NVMe devices in smartd DEVICESCAN.])
fi
[Include NVMe devices in smartd DEVICESCAN [Linux,Windows:yes;Others:no]])])
AC_ARG_WITH(solaris-sparc-ata,
[AS_HELP_STRING([--with-solaris-sparc-ata@<:@=yes|no@:>@],
@ -389,40 +402,64 @@ available in the SVN repository.])
;;
esac
# Assume broken snprintf only on Windows with MSVCRT (MinGW without ANSI stdio support)
libc_have_working_snprintf=yes
AC_ARG_WITH(signal-func,
[AS_HELP_STRING([--with-signal-func=@<:@sigaction|sigset|signal@:>@],
[Function to set signal(2) action [sigaction]])],
[], [with_signal_func=sigaction])
case "$host" in
*-*-mingw*)
case " $CPPFLAGS $CXXFLAGS" in
*\ -[[DU]]__USE_MINGW_ANSI_STDIO*)
;;
*)
# Older MinGW do not properly define PRI?64 if __USE_MINGW_ANSI_STDIO is set
# Newer MinGW set __USE_MINGW_ANSI_STDIO in first C++ include which may be too late
AC_MSG_CHECKING([whether __USE_MINGW_ANSI_STDIO is defined by C++ includes])
AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
#undef __USE_MINGW_ANSI_STDIO
#include <iostream>
#ifndef __USE_MINGW_ANSI_STDIO
#error false
#endif]])],
[CXXFLAGS="-D__USE_MINGW_ANSI_STDIO $CXXFLAGS"],
[libc_have_working_snprintf=no])
AC_MSG_RESULT([$libc_have_working_snprintf])
;;
esac ;;
case "$host:$with_signal_func" in
*-*-mingw*:*) ;;
*:sigaction)
AC_CHECK_FUNCS([sigaction], [], AC_MSG_ERROR([Missing function 'sigaction()'.
Try '--with-signal-func=sigset' or '--with-signal-func=signal'.
Please send info about your system to $PACKAGE_BUGREPORT.])) ;;
*:sigset)
AC_CHECK_FUNCS([sigset], [], AC_MSG_ERROR([Missing function 'sigset()'])) ;;
*:signal) ;;
*) 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 [MinGW:guessed,others:yes]])],
[libc_have_working_snprintf=$withval])
[Function snprintf() handles output truncation as specified by C99 [yes]])],
[], [with_working_snprintf=yes])
if test "$libc_have_working_snprintf" = "yes"; then
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*)
;;
yes: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.
AC_MSG_CHECKING([whether $CXX supports __USE_MINGW_ANSI_STDIO])
save_CXXFLAGS=$CXXFLAGS
CXXFLAGS="-Wformat -Werror -D__USE_MINGW_ANSI_STDIO"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <stdio.h>
void f(char * buf1, char * buf2, size_t size) {
snprintf(buf1, size, "%lld", 42LL);
snprintf(buf2, size, "%" PRId64, (int64_t)42);
}]])],
[result=yes], [result=no])
AC_MSG_RESULT([$result])
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.
Please send info about your system to $PACKAGE_BUGREPORT.
])
fi
CXXFLAGS="-D__USE_MINGW_ANSI_STDIO $save_CXXFLAGS"
;;
esac
AC_ARG_WITH(mingw-aslr,
[AS_HELP_STRING([--with-mingw-aslr@<:@=auto|yes|low|no@:>@], [Enable ASLR for MinGW executables [auto]])],
[], [with_mingw_aslr=auto])
@ -478,7 +515,7 @@ case "$host" in
esac
AC_ARG_WITH(cxx11-option,
[AS_HELP_STRING([--with-cxx11-option@<:@=OPTION|auto|no@:>@],
[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]])],
[], [with_cxx11_option=auto])
@ -516,7 +553,7 @@ 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 checked, but not used in the actual build).
(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.
In both cases, please send info about compiler and platform to
@ -530,6 +567,22 @@ $PACKAGE_BUGREPORT - Thanks!])
;;
esac
AC_ARG_WITH(cxx11-regex,
[AS_HELP_STRING([--with-cxx11-regex@<:@=yes|no@:>@],
[Use C++11 std::regex instead of POSIX regex(3) [no]])])
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
AM_CONDITIONAL(NEED_REGEX, [test "$need_regex" = "yes"])
AC_SUBST(releaseversion,['${PACKAGE}-${VERSION}'])
AC_SUBST(smartmontools_release_date)
@ -548,19 +601,22 @@ os_win32=no
os_win32_mingw=no
os_win64=no
os_man_filter=
os_nvme_devicescan=
case "${host}" in
*-*-linux*)
os_deps='os_linux.o cciss.o dev_areca.o'
os_dnsdomainname="'dnsdomainname' 'hostname -d'"
os_nisdomainname="'nisdomainname' 'hostname -y' 'domainname'"
os_man_filter=Linux
os_nvme_devicescan=yes
;;
*-*-freebsd*|*-*-dragonfly*|*-*-kfreebsd*-gnu*)
os_deps='os_freebsd.o cciss.o dev_areca.o'
os_libs='-lcam'
os_libs='-lcam -lsbuf'
os_dltools='curl wget lynx fetch svn'
AC_CHECK_LIB(usb, libusb20_dev_get_device_desc)
os_man_filter=FreeBSD
os_nvme_devicescan=no
;;
sparc-*-solaris*)
os_deps='os_solaris.o'
@ -580,6 +636,7 @@ case "${host}" in
os_deps='os_netbsd.o'
os_libs='-lutil'
os_man_filter=NetBSD
os_nvme_devicescan=no
;;
*-*-openbsd*)
os_deps='os_openbsd.o'
@ -595,6 +652,7 @@ case "${host}" in
os_nisdomainname=
os_win32=yes
os_man_filter=Cygwin
os_nvme_devicescan=yes
;;
x86_64-*-mingw*)
os_deps='os_win32.o dev_areca.o'
@ -602,18 +660,21 @@ case "${host}" in
os_win32_mingw=yes
os_win64=yes
os_man_filter=Windows
os_nvme_devicescan=yes
;;
*-*-mingw*)
os_deps='os_win32.o dev_areca.o'
os_win32=yes
os_win32_mingw=yes
os_man_filter=Windows
os_nvme_devicescan=yes
;;
*-*-darwin*)
os_deps='os_darwin.o'
os_libs='-framework CoreFoundation -framework IOKit'
os_darwin=yes
os_man_filter=Darwin
os_nvme_devicescan=no
;;
*-*-nto-qnx*)
os_deps='os_qnxnto.o'
@ -641,6 +702,19 @@ else
fi
AC_MSG_RESULT([$os_new_interface])
# TODO: Remove when NVMe support is no longer EXPERIMENTAL
case "$os_nvme_devicescan:${with_nvme_devicescan+set}" in
no:|yes:)
AC_MSG_CHECKING([whether NVMe device scanning could be safely enabled])
with_nvme_devicescan=$os_nvme_devicescan
AC_MSG_RESULT([$os_nvme_devicescan])
os_nvme_devicescan=used ;;
esac
AC_SUBST(with_nvme_devicescan)
if test "$with_nvme_devicescan" = "yes"; then
AC_DEFINE(WITH_NVME_DEVICESCAN, 1, [Define to 1 to include NVMe devices in smartd DEVICESCAN.])
fi
AC_SUBST([os_deps])
AC_SUBST([os_libs])
AC_SUBST([os_dltools])
@ -668,6 +742,7 @@ AM_CONDITIONAL(OS_WIN32_NSIS, [test -n "$MAKENSIS"])
AM_CONDITIONAL(OS_WIN64, [test "$os_win64" = "yes"])
if test "$GXX" = "yes"; then
orig_CXXFLAGS=$CXXFLAGS
# Add -Wall and -W[extra] if its not already specified
case " $CXXFLAGS " in
*\ -Wall\ *) ;;
@ -678,19 +753,16 @@ if test "$GXX" = "yes"; then
*) CXXFLAGS="$CXXFLAGS -W" ;;
esac
# Add -Wformat=2 (GCC 3.0) -fstack-protector[-strong] (GCC 4.1[4.9]) if supported
# and CXXFLAGS was not set in configure cmdline (TODO: -Wformat-signedness)
case "${ac_test_CXXFLAGS+set}:$ac_test_CXXFLAGS" in
set:)
for option in "-Wformat=2" "-fstack-protector-strong" "-fstack-protector"; do
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])
AC_MSG_RESULT([$res])
done
;;
esac
# 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
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])
AC_MSG_RESULT([$res])
done
else
# We are NOT using gcc, so enable host-specific compiler flags
case "${host}" in
@ -769,7 +841,9 @@ info=`
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"
if test "$drivedb_version" != "$VERSION"; then
if test "$drivedb_version" = "$smartmontools_drivedb_version"; then
echo "database update branch: branches/$DRIVEDB_BRANCH"
else
echo "... backported to: branches/$DRIVEDB_BRANCH"
fi
echo "download tools: \`eval eval eval echo $os_dltools\`"
@ -798,12 +872,12 @@ info=`
echo "PATH within scripts: [[inherited]]"
fi
if test -n "$initddir"; then
echo "smartd initd script: \`eval eval eval echo $initddir\`/${initdfile}"
echo "smartd initd script: \`eval eval eval echo $initddir\`/smartd"
elif test -z "$systemdsystemunitdir"; then
echo "smartd initd script: [[disabled]]"
fi
if test -n "$systemdsystemunitdir"; then
echo "smartd systemd file: \`eval eval eval echo $systemdsystemunitdir\`/smartd.service"
echo "smartd service file: \`eval eval eval echo $systemdsystemunitdir\`/smartd.service"
if test -n "$systemdenvfile"; then
echo "smartd environ file: \`eval eval eval echo $systemdenvfile\`"
else
@ -820,14 +894,13 @@ info=`
else
echo "smartd attribute logs: [[disabled]]"
fi
echo "libcap-ng support: $use_libcap_ng"
case "$host_os" in
linux*) echo "SELinux support: ${with_selinux-no}" ;;
esac
case "$host_os" in
linux*|darwin*|netbsd*|cygwin*)
echo "NVMe DEVICESCAN: ${with_nvme_devicescan-no}" ;;
linux*)
echo "SELinux support: ${with_selinux-no}"
echo "libcap-ng support: $use_libcap_ng"
echo "systemd notify support: $use_libsystemd" ;;
esac
echo "NVMe DEVICESCAN: ${with_nvme_devicescan-[[not implemented]]}"
;;
esac
echo "-----------------------------------------------------------------------------"
@ -838,27 +911,39 @@ $info
])
# TODO: Remove when NVMe support is no longer EXPERIMENTAL
case "$host_os:${with_nvme_devicescan+set}" in
linux*:|darwin*:|netbsd*:|cygwin*:|mingw*:)
AC_MSG_WARN([
case "$os_nvme_devicescan:$with_nvme_devicescan" in
used:yes) AC_MSG_WARN([
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.
]) ;;
used:no) AC_MSG_WARN([
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.
])
;;
]) ;;
esac
# TODO: Remove after smartmontools 6.6
case "$host:${with_solaris_sparc_ata+set}" in
sparc-*-solaris*:)
AC_MSG_WARN([
Legacy ATA support is no longer enabled by default on Solaris SPARC.
The required source file 'os_solaris_ata.s' is no longer included in
the source tarball but still available in the SVN repository.
Use option '--with-solaris-sparc-ata' to enable legacy ATA support.
Use option '--without-solaris-sparc-ata' to suppress this warning.
# TODO: Remove after smartmontools 6.7
if test "$with_working_snprintf" != "yes"; 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.
])
;;
fi
case "$host_os:$with_libsystemd:$use_libsystemd:$PKG_CONFIG" in
linux*:auto:no:?*)
if $PKG_CONFIG systemd >/dev/null 2>&1; then
AC_MSG_WARN([
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.
])
fi ;;
esac

View File

@ -5,23 +5,15 @@
*
* Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include "dev_interface.h"
#include "dev_areca.h"
const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 4582 2017-11-03 20:54:56Z chrfranke $"
const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
DEV_ARECA_H_CVSID;
#include "atacmds.h"
@ -131,8 +123,8 @@ int generic_areca_device::arcmsr_command_handler(unsigned long arcmsr_cmd, unsig
struct scsi_cmnd_io iop;
int dir = DXFER_TO_DEVICE;
UINT8 cdb[10]={0};
UINT8 sense[32]={0};
uint8_t cdb[10]={0};
uint8_t sense[32]={0};
unsigned char *areca_return_packet;
int total = 0;

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DEV_ARECA_H
#define DEV_ARECA_H
#define DEV_ARECA_H_CVSID "$Id: dev_areca.h 4146 2015-10-17 12:12:49Z chrfranke $"
#define DEV_ARECA_H_CVSID "$Id: dev_areca.h 4760 2018-08-19 18:45:53Z chrfranke $"
/////////////////////////////////////////////////////////////////////////////
/// Areca RAID support

View File

@ -3,26 +3,19 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2008 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2008-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include "atacmds.h"
#include "dev_ata_cmd_set.h"
#include <errno.h>
const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
DEV_ATA_CMD_SET_H_CVSID;

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2008 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#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 4431 2017-08-08 19:38:15Z chrfranke $"
#define DEV_ATA_CMD_SET_H_CVSID "$Id: dev_ata_cmd_set.h 4760 2018-08-19 18:45:53Z chrfranke $"
#include "atacmds.h" // smart_command_set
#include "dev_interface.h"

View File

@ -5,25 +5,18 @@
*
* Copyright (C) 2016 Casey Biemiller <cbiemiller@intelliprop.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include "atacmds.h" //ATTR_PACKED and ASSERT_SIZEOF_STRUCT
#include "dev_interface.h"
#include "dev_intelliprop.h"
#include "dev_tunnelled.h"
#include <errno.h>
const char * dev_intelliprop_cpp_cvsid = "$Id: dev_intelliprop.cpp 4370 2017-01-11 20:35:38Z chrfranke $"
const char * dev_intelliprop_cpp_cvsid = "$Id: dev_intelliprop.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
DEV_INTELLIPROP_H_CVSID;
//Vendor Specific log addresses

View File

@ -3,22 +3,15 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2016 Casey Biemiller <cbiemiller@intelliprop.com>
*
* 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 4370 2017-01-11 20:35:38Z chrfranke $"
#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);

View File

@ -3,24 +3,18 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2008-16 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2008-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.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
#include "utility.h"
#include <errno.h>
@ -33,7 +27,7 @@
#include <sys/timeb.h>
#endif
const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 4848 2018-12-05 18:30:46Z chrfranke $"
DEV_INTERFACE_H_CVSID;
/////////////////////////////////////////////////////////////////////////////
@ -203,6 +197,38 @@ bool ata_device::ata_identify_is_cached() const
return false;
}
/////////////////////////////////////////////////////////////////////////////
// scsi_device
bool scsi_device::scsi_pass_through_and_check(scsi_cmnd_io * iop,
const char * msg)
{
// Provide sense buffer
unsigned char sense[32] = {0, };
iop->sensep = sense;
iop->max_sense_len = sizeof(sense);
iop->timeout = SCSI_TIMEOUT_DEFAULT;
// Run cmd
if (!scsi_pass_through(iop)) {
if (scsi_debugmode > 0)
pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
msg, get_errno(), get_errmsg());
return false;
}
// Check sense
scsi_sense_disect sinfo;
scsi_do_sense_disect(iop, &sinfo);
int err = scsiSimpleSenseFilter(&sinfo);
if (err) {
if (scsi_debugmode > 0)
pout("%sscsi error: %s\n", msg, scsiErrString(err));
return set_err(EIO, "scsi error %s", scsiErrString(err));
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
// nvme_device
@ -282,8 +308,9 @@ std::string smart_interface::get_valid_dev_types_str()
{
// default
std::string s =
"ata, scsi, nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], "
"usbjmicron[,p][,x][,N], usbprolific, usbsunplus, intelliprop,N[+TYPE]";
"ata, scsi[+TYPE], nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], "
"usbjmicron[,p][,x][,N], usbprolific, usbsunplus, sntjmicron[,NSID], "
"intelliprop,N[+TYPE]";
// append custom
std::string s2 = get_valid_custom_dev_types_str();
if (!s2.empty()) {
@ -400,8 +427,9 @@ smart_device * smart_interface::get_smart_device(const char * name, const char *
dev = get_nvme_device(name, type, nsid);
}
else if ( ((!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3])))
|| (!strncmp(type, "usb", 3)))) {
else if ( (str_starts_with(type, "sat") && (!type[3] || strchr(",+", type[3])))
|| str_starts_with(type, "scsi+")
|| str_starts_with(type, "usb") ) {
// Split "sat...+base..." -> ("sat...", "base...")
unsigned satlen = strcspn(type, "+");
std::string sattype(type, satlen);
@ -423,6 +451,16 @@ smart_device * smart_interface::get_smart_device(const char * name, const char *
return get_sat_device(sattype.c_str(), basedev.release()->to_scsi());
}
else if (str_starts_with(type, "snt")) {
smart_device_auto_ptr basedev( get_smart_device(name, "scsi") );
if (!basedev) {
set_err(EINVAL, "Type '%s': %s", type, get_errmsg());
return 0;
}
return get_snt_device(type, basedev.release()->to_scsi());
}
else if (str_starts_with(type, "intelliprop")) {
// Parse "intelliprop,N[+base...]"
unsigned phydrive = ~0; int n = -1; char c = 0;
@ -457,6 +495,12 @@ smart_device * smart_interface::get_smart_device(const char * name, const char *
return dev;
}
bool smart_interface::scan_smart_devices(smart_device_list & /*devlist*/,
const char * /*type*/, const char * /*pattern*/ /* = 0 */)
{
return set_err(ENOSYS);
}
bool smart_interface::scan_smart_devices(smart_device_list & devlist,
const smart_devtype_list & types, const char * pattern /* = 0 */)
{
@ -491,3 +535,12 @@ std::string smart_interface::get_valid_custom_dev_types_str()
{
return "";
}
smart_device * smart_interface::get_scsi_passthrough_device(const char * type, scsi_device * scsidev)
{
if (!strncmp(type, "snt", 3)) {
return get_snt_device(type, scsidev);
}
return get_sat_device(type, scsidev);
}

View File

@ -3,22 +3,15 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2008-16 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2008-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DEV_INTERFACE_H
#define DEV_INTERFACE_H
#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 4283 2016-04-10 12:55:59Z chrfranke $\n"
#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 4848 2018-12-05 18:30:46Z chrfranke $\n"
#include "utility.h"
@ -252,7 +245,7 @@ private:
// Number of objects.
static int s_num_objects;
// Prevent copy/assigment
// Prevent copy/assignment
smart_device(const smart_device &);
void operator=(const smart_device &);
};
@ -591,6 +584,18 @@ public:
/// Returns false on error.
virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
// Call scsi_pass_through and check sense.
bool scsi_pass_through_and_check(scsi_cmnd_io * iop,
const char * msg = "");
/// Always try READ CAPACITY(10) (rcap10) first but once we know
/// rcap16 is needed, use it instead.
void set_rcap16_first()
{ rcap16_first = true; }
bool use_rcap16() const
{ return rcap16_first; }
protected:
/// Hide/unhide SCSI interface.
void hide_scsi(bool hide = true)
@ -598,8 +603,12 @@ protected:
/// Default constructor, registers device as SCSI.
scsi_device()
: smart_device(never_called)
: smart_device(never_called),
rcap16_first(false)
{ hide_scsi(false); }
private:
bool rcap16_first;
};
@ -848,7 +857,7 @@ public:
private:
std::vector<smart_device *> m_list;
// Prevent copy/assigment
// Prevent copy/assignment
smart_device_list(const smart_device_list &);
void operator=(const smart_device_list &);
};
@ -956,8 +965,9 @@ public:
/// specified by some optional 'pattern'.
/// Use platform specific default if 'type' is empty or 0.
/// Return false on error.
/// Default implementation returns false;
virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
const char * pattern = 0) = 0;
const char * pattern = 0);
/// Fill 'devlist' with devices of all 'types' with device names
/// specified by some optional 'pattern'.
@ -992,6 +1002,11 @@ protected:
/// Default implementation returns empty string.
virtual std::string get_valid_custom_dev_types_str();
/// Return ATA->SCSI of NVMe->SCSI filter for a SAT, SNT or USB 'type'.
/// Uses get_sat_device and get_snt_device.
/// Return 0 and delete 'scsidev' on error.
virtual smart_device * get_scsi_passthrough_device(const char * type, scsi_device * scsidev);
/// Return ATA->SCSI filter for a SAT or USB 'type'.
/// Device 'scsidev' is used for SCSI access.
/// Return 0 and delete 'scsidev' on error.
@ -999,6 +1014,13 @@ protected:
virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
//{ implemented in scsiata.cpp }
/// Return NVMe->SCSI filter for a SNT or USB 'type'.
/// Device 'scsidev' is used for SCSI access.
/// Return 0 and delete 'scsidev' on error.
/// Override only if platform needs special handling.
virtual nvme_device * get_snt_device(const char * type, scsi_device * scsidev);
//{ implemented in scsinvme.cpp }
public:
/// Try to detect a SAT device behind a SCSI interface.
/// Inquiry data can be passed if available.
@ -1026,7 +1048,7 @@ private:
friend smart_interface * smi(); // below
static smart_interface * s_instance; ///< Pointer to the interface object.
// Prevent copy/assigment
// Prevent copy/assignment
smart_interface(const smart_interface &);
void operator=(const smart_interface &);
};

View File

@ -3,20 +3,13 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2008-16 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2008-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include "utility.h"
#include "atacmds.h"
#include "scsicmds.h"
@ -25,7 +18,7 @@
#include <errno.h>
const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
DEV_INTERFACE_H_CVSID;
/////////////////////////////////////////////////////////////////////////////

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2008 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DEV_TUNNELLED_H
#define DEV_TUNNELLED_H
#define DEV_TUNNELLED_H_CVSID "$Id: dev_tunnelled.h 4431 2017-08-08 19:38:15Z chrfranke $"
#define DEV_TUNNELLED_H_CVSID "$Id: dev_tunnelled.h 4848 2018-12-05 18:30:46Z chrfranke $"
#include "dev_interface.h"
@ -71,6 +64,14 @@ protected:
m_tunnel_dev(tunnel_dev)
{ }
// For nvme_device
explicit tunnelled_device(tunnel_device_type * tunnel_dev, unsigned nsid)
: smart_device(smart_device::never_called),
BaseDev(nsid),
tunnelled_device_base(tunnel_dev),
m_tunnel_dev(tunnel_dev)
{ }
public:
virtual void release(const smart_device * dev)
{

864
drivedb.h

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,28 @@
#! /bin/sh
# Send mail
echo "$SMARTD_MESSAGE" | mail -s "$SMARTD_FAILTYPE" "$SMARTD_ADDRESS"
if which mail >/dev/null 2>&1
then
echo "$SMARTD_MESSAGE" | mail -s "$SMARTD_FAILTYPE" "$SMARTD_ADDRESS"
fi
# Notify desktop user
MESSAGE="WARNING: Your hard drive is failing"
MESSAGE="SMART Disk monitor:"
case "$SMARTD_FAILTYPE" in
"EmailTest"|"Health"|"Temperature"|"Usage")
;;
*)
# "CurrentPendingSector", // 10
# "OfflineUncorrectableSector", // 11
# "FailedReadSmartErrorLog", // 7
# "ErrorCount", // 4
# "FailedReadSmartData", // 6
# "FailedHealthCheck", // 5
# "FailedOpenDevice", // 9
# "SelfTest", // 3
# "FailedReadSmartSelfTestLog", // 8
exit 0
esac
# direct write to terminals, do not use 'wall', because we don't want its ugly header
for t in $(who | awk '{ print $2; }' | grep -e '^tty' -e '^pts/')

View File

@ -1,22 +1,12 @@
# Home page: http://www.smartmontools.org
#
# $Id: README 4120 2015-08-27 16:12:21Z samm2 $
# $Id: README 4760 2018-08-19 18:45:53Z chrfranke $
#
# Copyright (C) 2003-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
# Copyright (C) 2009-14 Christian Franke <smartmontools-support@lists.sourceforge.net>
# Copyright (C) 2003-08 Bruce Allen
# Copyright (C) 2009-18 Christian Franke
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2, or (at your option) any later
# version.
#
# You should have received a copy of the GNU General Public License (for
# example COPYING). If not, see <http://www.gnu.org/licenses/>.
# SPDX-License-Identifier: GPL-2.0-or-later
#
# This code was originally developed as a Senior Thesis by Michael Cornwell
# at the Concurrent Systems Laboratory (now part of the Storage Systems
# Research Center), Jack Baskin School of Engineering, University of
# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
This directory contains executable shell scripts, that are intended for
use with the
@ -30,7 +20,7 @@ smartd and smartd.conf.
should display those pages on your system.
If you wish to contribute additional scripts to this collection,
please email them to <smartmontools-support@lists.sourceforge.net>,
please email them to <smartmontools-support@listi.jpberlin.de>,
and include a brief description to use below.
The files contained in this directory are:

View File

@ -148,8 +148,10 @@ struct nvme_pt_command {
#include <dev/nvme/nvme.h>
#endif
#if __FreeBSD_version < 1200058
#define nvme_completion_is_error(cpl) \
((cpl)->status.sc != 0 || (cpl)->status.sct != 0)
#endif
#define NVME_CTRLR_PREFIX "/dev/nvme"
#define NVME_NS_PREFIX "ns"

96
getopt/bits/getopt_core.h Normal file
View File

@ -0,0 +1,96 @@
/* Declarations for getopt (basic, portable features only).
Copyright (C) 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_CORE_H
#define _GETOPT_CORE_H 1
/* This header should not be used directly; include getopt.h or
unistd.h instead. Unlike most bits headers, it does not have
a protective #error, because the guard macro for getopt.h in
gnulib is not fixed. */
__BEGIN_DECLS
/* For communication from 'getopt' to the caller.
When 'getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when 'ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to 'getopt'.
On entry to 'getopt', zero means this is the first call; initialize.
When 'getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, 'optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message 'getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, 'optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in 'optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU 'getopt'.
The argument '--' causes premature termination of argument
scanning, explicitly telling 'getopt' that there are no more
options.
If OPTS begins with '-', then non-option arguments are treated as
arguments to the option '\1'. This behavior is specific to the GNU
'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in
the environment, then do not permute arguments.
For standards compliance, the 'argv' argument has the type
char *const *, but this is inaccurate; if argument permutation is
enabled, the argv array (not the strings it points to) must be
writable. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW __nonnull ((2, 3));
__END_DECLS
#endif /* getopt_core.h */

77
getopt/bits/getopt_ext.h Normal file
View File

@ -0,0 +1,77 @@
/* Declarations for getopt (GNU extensions).
Copyright (C) 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_EXT_H
#define _GETOPT_EXT_H 1
/* This header should not be used directly; include getopt.h instead.
Unlike most bits headers, it does not have a protective #error,
because the guard macro for getopt.h in gnulib is not fixed. */
__BEGIN_DECLS
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of 'struct option' terminated by an element containing a name which is
zero.
The field 'has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field 'flag' is not NULL, it points to a variable that is set
to the value given in the field 'val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an 'int' to
a compiled-in constant, such as set a value from 'optarg', set the
option's 'flag' field to zero and its 'val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero 'flag' field, 'getopt'
returns the contents of the 'val' field. */
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the 'has_arg' field of 'struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW __nonnull ((2, 3));
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW __nonnull ((2, 3));
__END_DECLS
#endif /* getopt_ext.h */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
/* Declarations for getopt.
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
Copyright (C) 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Unlike the bulk of the getopt implementation, this file is NOT part
of gnulib; gnulib also has a getopt.h but it is different.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@ -13,169 +15,53 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA. */
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifndef __need_getopt
# define _GETOPT_H 1
#ifndef _GETOPT_STANDALONE
#include <features.h>
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
// From <sys/cdefs.h>:
#ifndef __BEGIN_DECLS
# ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
# else
char *name;
# define __BEGIN_DECLS
# define __END_DECLS
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
# ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
extern int getopt_long (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
#endif
#ifndef __THROW
# ifdef __cplusplus
# define __THROW throw()
# elif defined(__GNUC__)
# define __THROW __attribute__ ((__nothrow__))
# else
# define __THROW
# endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif
#ifndef __nonnull
# ifdef __GNUC__
# define __nonnull(x) __attribute__ ((__nonnull__ x))
# else
# define __nonnull(x)
# endif
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
/* The type of the 'argv' argument to getopt_long and getopt_long_only
is properly 'char **', since both functions may write to the array
(in order to move all the options to the beginning). However, for
compatibility with old versions of LSB, glibc has to use 'char *const *'
instead. */
#ifndef __getopt_argv_const
# define __getopt_argv_const const
#endif
#include <bits/getopt_core.h>
#include <bits/getopt_ext.h>
#endif /* getopt.h */

View File

@ -1,7 +1,7 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Copyright (C) 1987-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@ -14,68 +14,31 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#if !defined(_LIBC) && !defined(_GETOPT_STANDALONE)
# include <config.h>
#endif
#ifdef _LIBC
# include <getopt.h>
#else
# include "getopt.h"
#endif
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
#include "getopt.h"
#include "getopt_int.h"
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 0, 0);
}
int
_getopt_long_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
0, d, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
@ -84,31 +47,31 @@ getopt_long (argc, argv, options, long_options, opt_index)
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
getopt_long_only (int argc, char *__getopt_argv_const *argv,
const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 1, 0);
}
# ifdef _LIBC
libc_hidden_def (getopt_long)
libc_hidden_def (getopt_long_only)
# endif
int
_getopt_long_only_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
1, d, 0);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
#include <stdlib.h>
int
main (argc, argv)
int argc;
char **argv;
main (int argc, char **argv)
{
int c;
int digit_optind = 0;
@ -117,7 +80,7 @@ main (argc, argv)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
static const struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
@ -167,11 +130,11 @@ main (argc, argv)
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
printf ("option c with value '%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
printf ("option d with value '%s'\n", optarg);
break;
case '?':

118
getopt/getopt_int.h Normal file
View File

@ -0,0 +1,118 @@
/* Internal declarations for getopt.
Copyright (C) 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
#include <getopt.h>
extern int _getopt_internal (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct);
/* Reentrant versions which can handle parsing multiple argument
vectors at the same time. */
/* Describe how to deal with options that follow non-option ARGV-elements.
REQUIRE_ORDER means don't recognize them as options; stop option
processing when the first non-option is seen. This is what POSIX
specifies should happen.
PERMUTE means permute the contents of ARGV as we scan, so that
eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written
to expect this.
RETURN_IN_ORDER is an option available to programs that were
written to expect options and other ARGV-elements in any order
and that care about the ordering of the two. We describe each
non-option ARGV-element as if it were the argument of an option
with character code 1.
The special argument '--' forces an end of option-scanning regardless
of the value of 'ordering'. In the case of RETURN_IN_ORDER, only
'--' can cause 'getopt' to return -1 with 'optind' != ARGC. */
enum __ord
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
};
/* Data type for reentrant functions. */
struct _getopt_data
{
/* These have exactly the same meaning as the corresponding global
variables, except that they are used for the reentrant
versions of getopt. */
int optind;
int opterr;
int optopt;
char *optarg;
/* Internal members. */
/* True if the internal members have been initialized. */
int __initialized;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
char *__nextchar;
/* See __ord above. */
enum __ord __ordering;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. 'first_nonopt' is the index in ARGV of the first
of them; 'last_nonopt' is the index after the last of them. */
int __first_nonopt;
int __last_nonopt;
};
/* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data,
int __posixly_correct);
extern int _getopt_long_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
extern int _getopt_long_only_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,
struct _getopt_data *__data);
#endif /* getopt_int.h */

517
json.cpp Normal file
View File

@ -0,0 +1,517 @@
/*
* json.cpp
*
* Home page of code is: https://www.smartmontools.org
*
* Copyright (C) 2017-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
#include "json.h"
const char * json_cvsid = "$Id: json.cpp 4830 2018-11-02 21:21:48Z chrfranke $"
JSON_H_CVSID;
#include "sg_unaligned.h"
#include "utility.h" // uint128_*()
#include <inttypes.h>
#include <stdexcept>
static void jassert_failed(int line, const char * expr)
{
char msg[128];
// Avoid __FILE__ as it may break reproducible builds
snprintf(msg, sizeof(msg), "json.cpp(%d): Assertion failed: %s", line, expr);
throw std::logic_error(msg);
}
#define jassert(expr) (!(expr) ? jassert_failed(__LINE__, #expr) : (void)0)
static void check_key(const char * key)
{
// 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)
: m_js(js)
{
check_key(key);
m_path.push_back(node_info(key));
}
json::ref::ref(const ref & base, const char * key)
: m_js(base.m_js), m_path(base.m_path)
{
check_key(key);
m_path.push_back(node_info(key));
}
json::ref::ref(const ref & base, int index)
: m_js(base.m_js), m_path(base.m_path)
{
jassert(0 <= index && index < 10000); // Limit: large arrays not supported
m_path.push_back(node_info(index));
}
json::ref::ref(const ref & base, const char * /*dummy*/, const char * key_suffix)
: m_js(base.m_js), m_path(base.m_path)
{
int n = (int)m_path.size(), i;
for (i = n; --i >= 0; ) {
std::string & base_key = m_path[i].key;
if (base_key.empty())
continue; // skip array
base_key += key_suffix;
break;
}
jassert(i >= 0); // Limit: top level element must be an object
}
void json::ref::operator=(bool value)
{
m_js.set_bool(m_path, value);
}
void json::ref::operator=(long long value)
{
m_js.set_int64(m_path, (int64_t)value);
}
void json::ref::operator=(unsigned long long value)
{
m_js.set_uint64(m_path, (uint64_t)value);
}
void json::ref::operator=(int value)
{
operator=((long long)value);
}
void json::ref::operator=(unsigned value)
{
operator=((unsigned long long)value);
}
void json::ref::operator=(long value)
{
operator=((long long)value);
}
void json::ref::operator=(unsigned long value)
{
operator=((unsigned long long)value);
}
void json::ref::operator=(const std::string & value)
{
m_js.set_string(m_path, value);
}
void json::ref::operator=(const char * value)
{
jassert(value); // Limit: null not supported
operator=(std::string(value));
}
void json::ref::set_uint128(uint64_t value_hi, uint64_t value_lo)
{
if (!value_hi)
operator=((unsigned long long)value_lo);
else
m_js.set_uint128(m_path, value_hi, value_lo);
}
bool json::ref::set_if_safe_uint64(uint64_t value)
{
if (!is_safe_uint(value))
return false;
operator=((unsigned long long)value);
return true;
}
bool json::ref::set_if_safe_uint128(uint64_t value_hi, uint64_t value_lo)
{
if (value_hi)
return false;
return set_if_safe_uint64(value_lo);
}
bool json::ref::set_if_safe_le128(const void * pvalue)
{
return set_if_safe_uint128(sg_get_unaligned_le64((const uint8_t *)pvalue + 8),
sg_get_unaligned_le64( pvalue ));
}
void json::ref::set_unsafe_uint64(uint64_t value)
{
// Output as number "KEY"
operator=((unsigned long long)value);
if (!m_js.m_verbose && is_safe_uint(value))
return;
// Output as string "KEY_s"
char s[32];
snprintf(s, sizeof(s), "%" PRIu64, value);
with_suffix("_s") = s;
}
void json::ref::set_unsafe_uint128(uint64_t value_hi, uint64_t value_lo)
{
if (!m_js.m_verbose && !value_hi)
set_unsafe_uint64(value_lo);
else {
// Output as number "KEY", string "KEY_s" and LE byte array "KEY_le[]"
m_js.m_uint128_output = true;
set_uint128(value_hi, value_lo);
char s[64];
with_suffix("_s") = uint128_hilo_to_str(s, value_hi, value_lo);
ref le = with_suffix("_le");
for (int i = 0; i < 8; i++) {
uint64_t v = (value_lo >> (i << 3));
if (!v && !value_hi)
break;
le[i] = v & 0xff;
}
for (int i = 0; i < 8; i++) {
uint64_t v = value_hi >> (i << 3);
if (!v)
break;
le[8 + i] = v & 0xff;
}
}
}
void json::ref::set_unsafe_le128(const void * pvalue)
{
set_unsafe_uint128(sg_get_unaligned_le64((const uint8_t *)pvalue + 8),
sg_get_unaligned_le64( pvalue ));
}
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_)
{
}
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)
{
if (m_use_map)
m_key_iter = node_p->key2index.begin();
}
bool json::node::const_iterator::at_end() const
{
if (m_use_map)
return (m_key_iter == m_node_p->key2index.end());
else
return (m_child_idx >= m_node_p->childs.size());
}
unsigned json::node::const_iterator::array_index() const
{
jassert(m_node_p->type == nt_array);
return m_child_idx;
}
void json::node::const_iterator::operator++()
{
if (m_use_map)
++m_key_iter;
else
++m_child_idx;
}
const json::node * json::node::const_iterator::operator*() const
{
if (m_use_map)
return m_node_p->childs[m_key_iter->second];
else
return m_node_p->childs[m_child_idx];
}
json::node * json::find_or_create_node(const json::node_path & path, node_type type)
{
node * p = &m_root_node;
for (unsigned i = 0; i < path.size(); i++) {
const node_info & pi = path[i];
if (!pi.key.empty()) {
// Object
if (p->type == nt_unset)
p->type = nt_object;
else
jassert(p->type == nt_object); // Limit: type change not supported
// Existing or new object element?
node::keymap::iterator ni = p->key2index.find(pi.key);
node * p2;
if (ni != p->key2index.end()) {
// Object element exists
p2 = p->childs[ni->second];
}
else {
// Create new object element
p->key2index[pi.key] = (unsigned)p->childs.size();
p2 = new node(pi.key);
p->childs.push_back(p2);
}
jassert(p2 && p2->key == pi.key);
p = p2;
}
else {
// Array
if (p->type == nt_unset)
p->type = nt_array;
else
jassert(p->type == nt_array); // Limit: type change not supported
node * p2;
// Existing or new array element?
if (pi.index < (int)p->childs.size()) {
// Array index exists
p2 = p->childs[pi.index];
if (!p2) // Already created ?
p->childs[pi.index] = p2 = new node;
}
else {
// Grow array, fill gap, create new element
p->childs.resize(pi.index + 1);
p->childs[pi.index] = p2 = new node;
}
jassert(p2 && p2->key.empty());
p = p2;
}
}
if ( p->type == nt_unset
|| ( nt_int <= p->type && p->type <= nt_uint128
&& nt_int <= type && type <= nt_uint128))
p->type = type;
else
jassert(p->type == type); // Limit: type change not supported
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)
return;
find_or_create_node(path, nt_bool)->intval = (value ? 1 : 0);
}
void json::set_int64(const node_path & path, int64_t value)
{
if (!m_enabled)
return;
find_or_create_node(path, nt_int)->intval = (uint64_t)value;
}
void json::set_uint64(const node_path & path, uint64_t value)
{
if (!m_enabled)
return;
find_or_create_node(path, nt_uint)->intval = value;
}
void json::set_uint128(const node_path & path, uint64_t value_hi, uint64_t value_lo)
{
if (!m_enabled)
return;
node * p = find_or_create_node(path, nt_uint128);
p->intval_hi = value_hi;
p->intval = value_lo;
}
void json::set_string(const node_path & path, const std::string & value)
{
if (!m_enabled)
return;
find_or_create_node(path, nt_string)->strval = value;
}
static void print_string(FILE * f, const char * s)
{
putc('"', f);
for (int i = 0; s[i]; i++) {
char c = s[i];
if (c == '"' || c == '\\')
putc('\\', f);
else if (c == '\t') {
putc('\\', f); c = 't';
}
else if ((unsigned char)c < ' ')
c = '?'; // Not ' '-'~', '\t' or UTF-8
putc(c, f);
}
putc('"', f);
}
void json::print_json(FILE * f, bool pretty, bool sorted, const node * p, int level)
{
if (!p->key.empty())
fprintf(f, "\"%s\":%s", p->key.c_str(), (pretty ? " " : ""));
switch (p->type) {
case nt_object:
case nt_array:
putc((p->type == nt_object ? '{' : '['), f);
if (!p->childs.empty()) {
bool first = true;
for (node::const_iterator it(p, sorted); !it.at_end(); ++it) {
if (!first)
putc(',', f);
if (pretty)
fprintf(f, "\n%*s", (level + 1) * 2, "");
const node * p2 = *it;
if (!p2) {
// Unset element of sparse array
jassert(p->type == nt_array);
fputs("null", f);
}
else {
// Recurse
print_json(f, pretty, sorted, p2, level + 1);
}
first = false;
}
if (pretty)
fprintf(f, "\n%*s", level * 2, "");
}
putc((p->type == nt_object ? '}' : ']'), f);
break;
case nt_bool:
fputs((p->intval ? "true" : "false"), f);
break;
case nt_int:
fprintf(f, "%" PRId64, (int64_t)p->intval);
break;
case nt_uint:
fprintf(f, "%" PRIu64, p->intval);
break;
case nt_uint128:
{
char buf[64];
fputs(uint128_hilo_to_str(buf, p->intval_hi, p->intval), f);
}
break;
case nt_string:
print_string(f, p->strval.c_str());
break;
default: jassert(false);
}
}
void json::print_flat(FILE * f, bool sorted, const node * p, std::string & path)
{
switch (p->type) {
case nt_object:
case nt_array:
fprintf(f, "%s = %s;\n", path.c_str(), (p->type == nt_object ? "{}" : "[]"));
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) {
char buf[10]; snprintf(buf, sizeof(buf), "[%u]", it.array_index());
path += buf;
}
else {
path += '.'; path += p2->key;
}
if (!p2) {
// Unset element of sparse array
jassert(p->type == nt_array);
fprintf(f, "%s = null;\n", path.c_str());
}
else {
// Recurse
print_flat(f, sorted, p2, path);
}
path.erase(len);
}
}
break;
case nt_bool:
fprintf(f, "%s = %s;\n", path.c_str(), (p->intval ? "true" : "false"));
break;
case nt_int:
fprintf(f, "%s = %" PRId64 ";\n", path.c_str(), (int64_t)p->intval);
break;
case nt_uint:
fprintf(f, "%s = %" PRIu64 ";\n", path.c_str(), p->intval);
break;
case nt_uint128:
{
char buf[64];
fprintf(f, "%s = %s;\n", path.c_str(),
uint128_hilo_to_str(buf, p->intval_hi, p->intval));
}
break;
case nt_string:
fprintf(f, "%s = ", path.c_str());
print_string(f, p->strval.c_str());
fputs(";\n", f);
break;
default: jassert(false);
}
}
void json::print(FILE * f, const print_options & options) const
{
if (m_root_node.type == nt_unset)
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.sorted, &m_root_node, path);
}
}

195
json.h Normal file
View File

@ -0,0 +1,195 @@
/*
* json.h
*
* Home page of code is: https://www.smartmontools.org
*
* Copyright (C) 2017-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef JSON_H_CVSID
#define JSON_H_CVSID "$Id: json.h 4825 2018-10-25 19:47:35Z chrfranke $"
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
/// Create and print JSON output.
class json
{
private:
struct node_info
{
std::string key;
int index;
node_info()
: index(0) { }
explicit node_info(const char * key_)
: key(key_), index(0) { }
explicit node_info(int index_)
: index(index_) { }
};
typedef std::vector<node_info> 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
{
public:
/// Return reference to object element.
ref operator[](const char * key) const
{ return ref(*this, key); };
/// Return reference to array element.
ref operator[](int index) const
{ return ref(*this, index); };
// Assignment operators create or change element.
void operator=(bool value);
void operator=(int value);
void operator=(unsigned value);
void operator=(long value);
void operator=(unsigned long value);
void operator=(long long value);
void operator=(unsigned long long value);
void operator=(const char * value);
void operator=(const std::string & value);
/// Return reference to element with KEY_SUFFIX appended to last key.
ref with_suffix(const char * key_suffix) const
{ return ref(*this, "", key_suffix); }
void set_uint128(uint64_t value_hi, uint64_t value_lo);
// Output only if safe integer.
bool set_if_safe_uint64(uint64_t value);
bool set_if_safe_uint128(uint64_t value_hi, uint64_t value_lo);
bool set_if_safe_le128(const void * pvalue);
// If unsafe integer, output also as string with key "NUMBER_s".
void set_unsafe_uint64(uint64_t value);
void set_unsafe_uint128(uint64_t value_hi, uint64_t value_lo);
void set_unsafe_le128(const void * pvalue);
private:
friend class json;
ref(json & js, const char * key);
ref(const ref & base, const char * key);
ref(const ref & base, int index);
ref(const ref & base, const char * /*dummy*/, const char * key_suffix);
json & m_js;
node_path m_path;
};
/// Return reference to element of top level object.
ref operator[](const char * key)
{ return ref(*this, key); };
/// Enable/disable JSON output.
void enable(bool yes = true)
{ m_enabled = yes; }
/// Return true if enabled.
bool is_enabled() const
{ return m_enabled; }
/// Enable/disable extra string output for safe integers also.
void set_verbose(bool yes = true)
{ m_verbose = yes; }
/// Return true if any 128-bit value has been output.
bool has_uint128_output() const
{ return m_uint128_output; }
/// 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) { }
};
/// 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();
explicit node(const std::string & key_);
~node();
node_type type;
uint64_t intval, intval_hi;
std::string strval;
std::string key;
std::vector<node *> childs;
typedef std::map<std::string, unsigned> keymap;
keymap key2index;
class const_iterator
{
public:
const_iterator(const node * node_p, bool sorted);
bool at_end() const;
unsigned array_index() const;
void operator++();
const node * operator*() const;
private:
const node * m_node_p;
bool m_use_map;
unsigned m_child_idx;
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;
node m_root_node;
node * find_or_create_node(const node_path & path, node_type type);
void set_bool(const node_path & path, bool value);
void set_int64(const node_path & path, int64_t value);
void set_uint64(const node_path & path, uint64_t value);
void set_uint128(const node_path & path, uint64_t value_hi, uint64_t value_lo);
void set_string(const node_path & path, const std::string & value);
static void print_json(FILE * f, bool pretty, bool sorted, const node * p, int level);
static void print_flat(FILE * f, bool sorted, const node * p, std::string & path);
};
#endif // JSON_H_CVSID

View File

@ -4,20 +4,13 @@
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2003-11 Philip Williams, Bruce Allen
* Copyright (C) 2008-16 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2008-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include <stdio.h>
#include "atacmds.h"
#include "knowndrives.h"
@ -32,7 +25,7 @@
#include <stdexcept>
const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 4208 2016-01-22 19:45:35Z chrfranke $"
const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
KNOWNDRIVES_H_CVSID;
#define MODEL_STRING_LENGTH 40
@ -166,7 +159,7 @@ static inline dbentry_type get_dbentry_type(const drive_settings * dbentry)
// Compile regular expression, print message on failure.
static bool compile(regular_expression & regex, const char *pattern)
{
if (!regex.compile(pattern, REG_EXTENDED)) {
if (!regex.compile(pattern)) {
pout("Internal error: unable to compile regular expression \"%s\": %s\n"
"Please inform smartmontools developers at " PACKAGE_BUGREPORT "\n",
pattern, regex.get_errmsg());
@ -723,7 +716,7 @@ static parse_ptr get_token(parse_ptr src, token_info & token, const char * path,
}
token.value += c;
}
// Lookahead to detect string constant concatentation
// Lookahead to detect string constant concatenation
src = skip_white(++src, path, line);
} while (*src == '"');
break;
@ -783,7 +776,7 @@ static bool parse_drive_database(parse_ptr src, drive_database & db, const char
case 1: case 2:
if (!token.value.empty()) {
regular_expression regex;
if (!regex.compile(token.value.c_str(), REG_EXTENDED)) {
if (!regex.compile(token.value.c_str())) {
pout("%s(%d): Error in regular expression: %s\n", path, token.line, regex.get_errmsg());
ok = false;
}

View File

@ -6,20 +6,13 @@
* Copyright (C) 2003-11 Philip Williams, Bruce Allen
* Copyright (C) 2008-15 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KNOWNDRIVES_H_
#define KNOWNDRIVES_H_
#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 4162 2015-10-31 16:36:16Z chrfranke $\n"
#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
// Structure to store drive database entries, see drivedb.h for a description.
struct drive_settings {

View File

@ -1,3 +1,13 @@
/*
* megaraid.h
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2008 Jordan Hargrave
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
int megaraid_io_interface(int device, int target, struct scsi_cmnd_io *, int);
#undef u32

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2016 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "nvmecmds.h"
const char * nvmecmds_cvsid = "$Id: nvmecmds.cpp 4313 2016-05-01 16:17:53Z chrfranke $"
const char * nvmecmds_cvsid = "$Id: nvmecmds.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
NVMECMDS_H_CVSID;
#include "dev_interface.h"
@ -56,7 +49,7 @@ static void debug_hex_dump(const void * data, unsigned size)
sz = size;
}
dStrHex(p, sz, 0);
dStrHex((const uint8_t *)p, sz, 0);
if (sz < size)
pout(" ...\n");
}
@ -196,7 +189,8 @@ bool nvme_read_id_ns(nvme_device * device, unsigned nsid, 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 nvme_read_log_page(nvme_device * device, unsigned char lid, void * data,
unsigned size, bool broadcast_nsid)
{
if (!(4 <= size && size <= 0x4000 && (size % 4) == 0))
throw std::logic_error("nvme_read_log_page(): invalid size");
@ -204,7 +198,7 @@ bool nvme_read_log_page(nvme_device * device, unsigned char lid, void * data, un
memset(data, 0, size);
nvme_cmd_in in;
in.set_data_in(nvme_admin_get_log_page, data, size);
in.nsid = device->get_nsid();
in.nsid = broadcast_nsid ? 0xffffffff : device->get_nsid();
in.cdw10 = lid | (((size / 4) - 1) << 16);
return nvme_pass_through(device, in);
@ -213,7 +207,7 @@ bool nvme_read_log_page(nvme_device * device, unsigned char lid, void * data, un
// Read NVMe Error Information Log.
bool nvme_read_error_log(nvme_device * device, nvme_error_log_page * error_log, unsigned num_entries)
{
if (!nvme_read_log_page(device, 0x01, error_log, num_entries * sizeof(*error_log)))
if (!nvme_read_log_page(device, 0x01, error_log, num_entries * sizeof(*error_log), true))
return false;
if (isbigendian()) {
@ -234,7 +228,7 @@ bool nvme_read_error_log(nvme_device * device, nvme_error_log_page * 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)))
if (!nvme_read_log_page(device, 0x02, &smart_log, sizeof(smart_log), true))
return false;
if (isbigendian()) {

View File

@ -3,29 +3,22 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2016 Christian Franke
* Copyright (C) 2016-18 Christian Franke
*
* Original code from <linux/nvme.h>:
* Copyright (C) 2011-2014 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef NVMECMDS_H
#define NVMECMDS_H
#define NVMECMDS_H_CVSID "$Id: nvmecmds.h 4488 2017-09-25 11:54:15Z samm2 $"
#define NVMECMDS_H_CVSID "$Id: nvmecmds.h 4842 2018-12-02 16:07:26Z chrfranke $"
#include "int64.h"
#include <stdint.h>
// The code below was orginally imported from <linux/nvme.h> include file from
// The code below was originally imported from <linux/nvme.h> include file from
// Linux kernel sources. Types from <linux/types.h> were replaced.
// Symbol names are unchanged but placed in a namespace to allow inclusion
// of the original <linux/nvme.h>.
@ -33,19 +26,6 @@ namespace smartmontools {
////////////////////////////////////////////////////////////////////////////
// BEGIN: From <linux/nvme.h>
/*
* Definitions for the NVM Express interface
* Copyright (c) 2011-2014, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
struct nvme_error_log_page {
uint64_t error_count;
@ -248,7 +228,8 @@ bool nvme_read_id_ctrl(nvme_device * device, smartmontools::nvme_id_ctrl & id_ct
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 nvme_read_log_page(nvme_device * device, unsigned char lid, void * data,
unsigned size, bool broadcast_nsid);
// Read NVMe Error Information Log.
bool nvme_read_error_log(nvme_device * device, smartmontools::nvme_error_log_page * error_log,

View File

@ -3,31 +3,28 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2016-17 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2016-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
#include "nvmeprint.h"
const char * nvmeprint_cvsid = "$Id: nvmeprint.cpp 4580 2017-11-03 19:41:14Z chrfranke $"
const char * nvmeprint_cvsid = "$Id: nvmeprint.cpp 4859 2018-12-16 18:09:44Z chrfranke $"
NVMEPRINT_H_CVSID;
#include "int64.h"
#include "utility.h"
#include "dev_interface.h"
#include "nvmecmds.h"
#include "atacmds.h" // dont_print_serial_number
#include "scsicmds.h" // dStrHex()
#include "smartctl.h"
#include "sg_unaligned.h"
#include <inttypes.h>
using namespace smartmontools;
@ -58,9 +55,11 @@ static const char * le128_to_str(char (& str)[64], uint64_t hi, uint64_t lo, uns
}
}
else {
// More than 64-bit, print approximate value, prepend ~ flag
snprintf(str, sizeof(str), "~%.0f",
hi * (0xffffffffffffffffULL + 1.0) + lo);
// More than 64-bit, prepend '~' flag on low precision
int i = 0;
if (uint128_to_str_precision_bits() < 128)
str[i++] = '~';
uint128_hilo_to_str(str + i, (int)sizeof(str) - i, hi, lo);
}
return str;
@ -88,6 +87,13 @@ static const char * lbacap_to_str(char (& str)[64], uint64_t lba_cnt, int lba_bi
return le128_to_str(str, (lba_cnt >> (64 - lba_bits)), (lba_cnt << lba_bits), 1);
}
// Output capacity specified as 64bit LBA count to JSON
static void lbacap_to_js(const json::ref & jref, uint64_t lba_cnt, int lba_bits)
{
jref["blocks"].set_unsafe_uint64(lba_cnt);
jref["bytes"].set_unsafe_uint128((lba_cnt >> (64 - lba_bits)), (lba_cnt << lba_bits));
}
// Format a Kelvin temperature value in Celsius.
static const char * kelvin_to_str(char (& str)[64], int k)
{
@ -98,73 +104,96 @@ static const char * kelvin_to_str(char (& str)[64], int k)
return str;
}
static inline unsigned le16_to_uint(const unsigned char (& val)[2])
{
return ((val[1] << 8) | val[0]);
}
static void print_drive_info(const nvme_id_ctrl & id_ctrl, const nvme_id_ns & id_ns,
unsigned nsid, bool show_all)
{
char buf[64];
pout("Model Number: %s\n", format_char_array(buf, id_ctrl.mn));
if (!dont_print_serial_number)
pout("Serial Number: %s\n", format_char_array(buf, id_ctrl.sn));
pout("Firmware Version: %s\n", format_char_array(buf, id_ctrl.fr));
jout("Model Number: %s\n", format_char_array(buf, id_ctrl.mn));
jglb["model_name"] = buf;
if (!dont_print_serial_number) {
jout("Serial Number: %s\n", format_char_array(buf, id_ctrl.sn));
jglb["serial_number"] = buf;
}
jout("Firmware Version: %s\n", format_char_array(buf, id_ctrl.fr));
jglb["firmware_version"] = buf;
// Vendor and Subsystem IDs are usually equal
if (show_all || id_ctrl.vid != id_ctrl.ssvid) {
pout("PCI Vendor ID: 0x%04x\n", id_ctrl.vid);
pout("PCI Vendor Subsystem ID: 0x%04x\n", id_ctrl.ssvid);
jout("PCI Vendor ID: 0x%04x\n", id_ctrl.vid);
jout("PCI Vendor Subsystem ID: 0x%04x\n", id_ctrl.ssvid);
}
else {
pout("PCI Vendor/Subsystem ID: 0x%04x\n", id_ctrl.vid);
jout("PCI Vendor/Subsystem ID: 0x%04x\n", id_ctrl.vid);
}
jglb["nvme_pci_vendor"]["id"] = id_ctrl.vid;
jglb["nvme_pci_vendor"]["subsystem_id"] = id_ctrl.ssvid;
pout("IEEE OUI Identifier: 0x%02x%02x%02x\n",
jout("IEEE OUI Identifier: 0x%02x%02x%02x\n",
id_ctrl.ieee[2], id_ctrl.ieee[1], id_ctrl.ieee[0]);
jglb["nvme_ieee_oui_identifier"] = sg_get_unaligned_le(3, id_ctrl.ieee);
// Capacity info is optional for devices without namespace management
if (show_all || le128_is_non_zero(id_ctrl.tnvmcap) || le128_is_non_zero(id_ctrl.unvmcap)) {
pout("Total NVM Capacity: %s\n", le128_to_str(buf, id_ctrl.tnvmcap, 1));
pout("Unallocated NVM Capacity: %s\n", le128_to_str(buf, id_ctrl.unvmcap, 1));
jout("Total NVM Capacity: %s\n", le128_to_str(buf, id_ctrl.tnvmcap, 1));
jglb["nvme_total_capacity"].set_unsafe_le128(id_ctrl.tnvmcap);
jout("Unallocated NVM Capacity: %s\n", le128_to_str(buf, id_ctrl.unvmcap, 1));
jglb["nvme_unallocated_capacity"].set_unsafe_le128(id_ctrl.unvmcap);
}
pout("Controller ID: %d\n", id_ctrl.cntlid);
jout("Controller ID: %d\n", id_ctrl.cntlid);
jglb["nvme_controller_id"] = id_ctrl.cntlid;
// Print namespace info if available
pout("Number of Namespaces: %u\n", id_ctrl.nn);
jout("Number of Namespaces: %u\n", id_ctrl.nn);
jglb["nvme_number_of_namespaces"] = id_ctrl.nn;
if (nsid && id_ns.nsze) {
const char * align = &(" "[nsid < 10 ? 0 : (nsid < 100 ? 1 : 2)]);
int fmt_lba_bits = id_ns.lbaf[id_ns.flbas & 0xf].ds;
json::ref jrns = jglb["nvme_namespaces"][0];
jrns["id"] = nsid;
// Size and Capacity are equal if thin provisioning is not supported
if (show_all || id_ns.ncap != id_ns.nsze || (id_ns.nsfeat & 0x01)) {
pout("Namespace %u Size: %s%s\n", nsid, align,
jout("Namespace %u Size: %s%s\n", nsid, align,
lbacap_to_str(buf, id_ns.nsze, fmt_lba_bits));
pout("Namespace %u Capacity: %s%s\n", nsid, align,
jout("Namespace %u Capacity: %s%s\n", nsid, align,
lbacap_to_str(buf, id_ns.ncap, fmt_lba_bits));
}
else {
pout("Namespace %u Size/Capacity: %s%s\n", nsid, align,
jout("Namespace %u Size/Capacity: %s%s\n", nsid, align,
lbacap_to_str(buf, id_ns.nsze, fmt_lba_bits));
}
lbacap_to_js(jrns["size"], id_ns.nsze, fmt_lba_bits);
lbacap_to_js(jrns["capacity"], id_ns.ncap, fmt_lba_bits);
lbacap_to_js(jglb["user_capacity"], id_ns.ncap, fmt_lba_bits); // TODO: use nsze?
// Utilization may be always equal to Capacity if thin provisioning is not supported
if (show_all || id_ns.nuse != id_ns.ncap || (id_ns.nsfeat & 0x01))
pout("Namespace %u Utilization: %s%s\n", nsid, align,
jout("Namespace %u Utilization: %s%s\n", nsid, align,
lbacap_to_str(buf, id_ns.nuse, fmt_lba_bits));
lbacap_to_js(jrns["utilization"], id_ns.nuse, fmt_lba_bits);
pout("Namespace %u Formatted LBA Size: %s%u\n", nsid, align, (1U << fmt_lba_bits));
jout("Namespace %u Formatted LBA Size: %s%u\n", nsid, align, (1U << fmt_lba_bits));
jrns["formatted_lba_size"] = (1U << fmt_lba_bits);
jglb["logical_block_size"] = (1U << fmt_lba_bits);
if (show_all || nonempty(id_ns.eui64, sizeof(id_ns.eui64)))
pout("Namespace %u IEEE EUI-64: %s%02x%02x%02x %02x%02x%02x%02x%02x\n",
if (show_all || nonempty(id_ns.eui64, sizeof(id_ns.eui64))) {
jout("Namespace %u IEEE EUI-64: %s%02x%02x%02x %02x%02x%02x%02x%02x\n",
nsid, align, id_ns.eui64[0], id_ns.eui64[1], id_ns.eui64[2], id_ns.eui64[3],
id_ns.eui64[4], id_ns.eui64[5], id_ns.eui64[6], id_ns.eui64[7]);
jrns["eui64"]["oui"] = sg_get_unaligned_be(3, id_ns.eui64);
jrns["eui64"]["ext_id"] = sg_get_unaligned_be(5, id_ns.eui64 + 3);
}
}
char td[DATEANDEPOCHLEN]; dateandtimezone(td);
pout("Local Time is: %s\n", td);
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;
}
// Format scaled power value.
@ -270,60 +299,101 @@ static void print_drive_capabilities(const nvme_id_ctrl & id_ctrl, const nvme_id
static void print_critical_warning(unsigned char w)
{
pout("SMART overall-health self-assessment test result: %s\n",
jout("SMART overall-health self-assessment test result: %s\n",
(!w ? "PASSED" : "FAILED!"));
jglb["smart_status"]["passed"] = !w;
json::ref jref = jglb["smart_status"]["nvme"];
jref["value"] = w;
if (w) {
if (w & 0x01)
pout("- available spare has fallen below threshold\n");
jout("- available spare has fallen below threshold\n");
jref["spare_below_threshold"] = !!(w & 0x01);
if (w & 0x02)
pout("- temperature is above or below threshold\n");
jout("- temperature is above or below threshold\n");
jref["temperature_above_or_below_threshold"] = !!(w & 0x02);
if (w & 0x04)
pout("- NVM subsystem reliability has been degraded\n");
jout("- NVM subsystem reliability has been degraded\n");
jref["reliability_degraded"] = !!(w & 0x04);
if (w & 0x08)
pout("- media has been placed in read only mode\n");
jout("- media has been placed in read only mode\n");
jref["media_read_only"] = !!(w & 0x08);
if (w & 0x10)
pout("- volatile memory backup device has failed\n");
jout("- volatile memory backup device has failed\n");
jref["volatile_memory_backup_failed"] = !!(w & 0x10);
if (w & ~0x1f)
pout("- unknown critical warning(s) (0x%02x)\n", w & ~0x1f);
jout("- unknown critical warning(s) (0x%02x)\n", w & ~0x1f);
jref["other"] = w & ~0x1f;
}
pout("\n");
jout("\n");
}
static void print_smart_log(const nvme_smart_log & smart_log, unsigned nsid,
static void print_smart_log(const nvme_smart_log & smart_log,
const nvme_id_ctrl & id_ctrl, bool show_all)
{
json::ref jref = jglb["nvme_smart_health_information_log"];
char buf[64];
pout("SMART/Health Information (NVMe Log 0x02, NSID 0x%x)\n", nsid);
pout("Critical Warning: 0x%02x\n", smart_log.critical_warning);
pout("Temperature: %s\n",
kelvin_to_str(buf, le16_to_uint(smart_log.temperature)));
pout("Available Spare: %u%%\n", smart_log.avail_spare);
pout("Available Spare Threshold: %u%%\n", smart_log.spare_thresh);
pout("Percentage Used: %u%%\n", smart_log.percent_used);
pout("Data Units Read: %s\n", le128_to_str(buf, smart_log.data_units_read, 1000*512));
pout("Data Units Written: %s\n", le128_to_str(buf, smart_log.data_units_written, 1000*512));
pout("Host Read Commands: %s\n", le128_to_str(buf, smart_log.host_reads));
pout("Host Write Commands: %s\n", le128_to_str(buf, smart_log.host_writes));
pout("Controller Busy Time: %s\n", le128_to_str(buf, smart_log.ctrl_busy_time));
pout("Power Cycles: %s\n", le128_to_str(buf, smart_log.power_cycles));
pout("Power On Hours: %s\n", le128_to_str(buf, smart_log.power_on_hours));
pout("Unsafe Shutdowns: %s\n", le128_to_str(buf, smart_log.unsafe_shutdowns));
pout("Media and Data Integrity Errors: %s\n", le128_to_str(buf, smart_log.media_errors));
pout("Error Information Log Entries: %s\n", le128_to_str(buf, smart_log.num_err_log_entries));
jout("SMART/Health Information (NVMe Log 0x02)\n");
jout("Critical Warning: 0x%02x\n", smart_log.critical_warning);
jref["critical_warning"] = smart_log.critical_warning;
int k = sg_get_unaligned_le16(smart_log.temperature);
jout("Temperature: %s\n", kelvin_to_str(buf, k));
if (k) {
jref["temperature"] = k - 273;
jglb["temperature"]["current"] = k - 273;
}
jout("Available Spare: %u%%\n", smart_log.avail_spare);
jref["available_spare"] = smart_log.avail_spare;
jout("Available Spare Threshold: %u%%\n", smart_log.spare_thresh);
jref["available_spare_threshold"] = smart_log.spare_thresh;
jout("Percentage Used: %u%%\n", smart_log.percent_used);
jref["percentage_used"] = smart_log.percent_used;
jout("Data Units Read: %s\n", le128_to_str(buf, smart_log.data_units_read, 1000*512));
jref["data_units_read"].set_unsafe_le128(smart_log.data_units_read);
jout("Data Units Written: %s\n", le128_to_str(buf, smart_log.data_units_written, 1000*512));
jref["data_units_written"].set_unsafe_le128(smart_log.data_units_written);
jout("Host Read Commands: %s\n", le128_to_str(buf, smart_log.host_reads));
jref["host_reads"].set_unsafe_le128(smart_log.host_reads);
jout("Host Write Commands: %s\n", le128_to_str(buf, smart_log.host_writes));
jref["host_writes"].set_unsafe_le128(smart_log.host_writes);
jout("Controller Busy Time: %s\n", le128_to_str(buf, smart_log.ctrl_busy_time));
jref["controller_busy_time"].set_unsafe_le128(smart_log.ctrl_busy_time);
jout("Power Cycles: %s\n", le128_to_str(buf, smart_log.power_cycles));
jref["power_cycles"].set_unsafe_le128(smart_log.power_cycles);
jglb["power_cycle_count"].set_if_safe_le128(smart_log.power_cycles);
jout("Power On Hours: %s\n", le128_to_str(buf, smart_log.power_on_hours));
jref["power_on_hours"].set_unsafe_le128(smart_log.power_on_hours);
jglb["power_on_time"]["hours"].set_if_safe_le128(smart_log.power_on_hours);
jout("Unsafe Shutdowns: %s\n", le128_to_str(buf, smart_log.unsafe_shutdowns));
jref["unsafe_shutdowns"].set_unsafe_le128(smart_log.unsafe_shutdowns);
jout("Media and Data Integrity Errors: %s\n", le128_to_str(buf, smart_log.media_errors));
jref["media_errors"].set_unsafe_le128(smart_log.media_errors);
jout("Error Information Log Entries: %s\n", le128_to_str(buf, smart_log.num_err_log_entries));
jref["num_err_log_entries"].set_unsafe_le128(smart_log.num_err_log_entries);
// Temperature thresholds are optional
if (show_all || id_ctrl.wctemp || smart_log.warning_temp_time)
pout("Warning Comp. Temperature Time: %d\n", smart_log.warning_temp_time);
if (show_all || id_ctrl.cctemp || smart_log.critical_comp_time)
pout("Critical Comp. Temperature Time: %d\n", smart_log.critical_comp_time);
if (show_all || id_ctrl.wctemp || smart_log.warning_temp_time) {
jout("Warning Comp. Temperature Time: %d\n", smart_log.warning_temp_time);
jref["warning_temp_time"] = smart_log.warning_temp_time;
}
if (show_all || id_ctrl.cctemp || smart_log.critical_comp_time) {
jout("Critical Comp. Temperature Time: %d\n", smart_log.critical_comp_time);
jref["critical_comp_time"] = smart_log.critical_comp_time;
}
// Temperature sensors are optional
for (int i = 0; i < 8; i++) {
if (show_all || smart_log.temp_sensor[i])
pout("Temperature Sensor %d: %s\n", i + 1,
kelvin_to_str(buf, smart_log.temp_sensor[i]));
int k = smart_log.temp_sensor[i];
if (show_all || k) {
jout("Temperature Sensor %d: %s\n", i + 1,
kelvin_to_str(buf, k));
if (k)
jref["temperature_sensors"][i] = k - 273;
}
}
if (show_all || smart_log.thm_temp1_trans_count)
pout("Thermal Temp. 1 Transition Count: %d\n", smart_log.thm_temp1_trans_count);
@ -396,7 +466,7 @@ int nvmePrintMain(nvme_device * device, const nvme_print_options & options)
// Read Identify Controller always
nvme_id_ctrl id_ctrl;
if (!nvme_read_id_ctrl(device, id_ctrl)) {
pout("Read NVMe Identify Controller failed: %s\n", device->get_errmsg());
jerr("Read NVMe Identify Controller failed: %s\n", device->get_errmsg());
return FAILID;
}
@ -418,7 +488,7 @@ int nvmePrintMain(nvme_device * device, const nvme_print_options & options)
else {
// Identify current namespace
if (!nvme_read_id_ns(device, nsid, id_ns)) {
pout("Read NVMe Identify Namespace 0x%x failed: %s\n", nsid, device->get_errmsg());
jerr("Read NVMe Identify Namespace 0x%x failed: %s\n", nsid, device->get_errmsg());
return FAILID;
}
}
@ -439,7 +509,7 @@ int nvmePrintMain(nvme_device * device, const nvme_print_options & options)
if (options.smart_check_status || options.smart_vendor_attrib) {
nvme_smart_log smart_log;
if (!nvme_read_smart_log(device, smart_log)) {
pout("Read NVMe SMART/Health Information failed: %s\n\n", device->get_errmsg());
jerr("Read NVMe SMART/Health Information failed: %s\n\n", device->get_errmsg());
return FAILSMART;
}
@ -450,7 +520,7 @@ int nvmePrintMain(nvme_device * device, const nvme_print_options & options)
}
if (options.smart_vendor_attrib) {
print_smart_log(smart_log, device->get_nsid(), id_ctrl, show_all);
print_smart_log(smart_log, id_ctrl, show_all);
}
}
@ -462,7 +532,7 @@ int nvmePrintMain(nvme_device * device, const nvme_print_options & options)
reinterpret_cast<nvme_error_log_page *>(error_log_buf.data());
if (!nvme_read_error_log(device, error_log, num_entries)) {
pout("Read Error Information Log failed: %s\n\n", device->get_errmsg());
jerr("Read Error Information Log failed: %s\n\n", device->get_errmsg());
return retval | FAILSMART;
}
@ -473,10 +543,22 @@ int nvmePrintMain(nvme_device * device, const nvme_print_options & options)
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);
if (!nvme_read_log_page(device, options.log_page, log_buf.data(), size)) {
pout("Read NVMe Log 0x%02x failed: %s\n\n", options.log_page, device->get_errmsg());
switch (options.log_page) {
case 1:
case 2:
case 3:
broadcast_nsid = true;
break;
default:
broadcast_nsid = false;
break;
}
if (!nvme_read_log_page(device, options.log_page, log_buf.data(),
size, broadcast_nsid)) {
jerr("Read NVMe Log 0x%02x failed: %s\n\n", options.log_page, device->get_errmsg());
return retval | FAILSMART;
}

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2016 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef NVMEPRINT_H
#define NVMEPRINT_H
#define NVMEPRINT_H_CVSID "$Id: nvmeprint.h 4311 2016-04-27 21:03:01Z chrfranke $"
#define NVMEPRINT_H_CVSID "$Id: nvmeprint.h 4760 2018-08-19 18:45:53Z chrfranke $"
#include "nvmecmds.h"

View File

@ -6,14 +6,7 @@
* Copyright (C) 2004-8 Geoffrey Keating <geoffk@geoffk.org>
* Copyright (C) 2014 Alex Samorukov <samm@os2.kiev.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* along with smartmontools. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <stdbool.h>
@ -35,7 +28,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include "config.h"
#include "int64.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "nvmecmds.h"
@ -45,23 +38,17 @@
#define ARGUSED(x) ((void)(x))
// Needed by '-V' option (CVS versioning) of smartd/smartctl
const char *os_darwin_cpp_cvsid="$Id: os_darwin.cpp 4552 2017-10-11 10:11:35Z samm2 $" \
ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
const char *os_darwin_cpp_cvsid="$Id: os_darwin.cpp 4831 2018-11-09 07:18:23Z samm2 $" \
ATACMDS_H_CVSID CONFIG_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// examples for smartctl
static const char smartctl_examples[] =
"=================================================== SMARTCTL EXAMPLES =====\n\n"
" smartctl -a disk0 (Prints all SMART information)\n\n"
" smartctl -t long /dev/disk0 (Executes extended disk self-test)\n\n"
#ifdef HAVE_GETOPT_LONG
" smartctl --smart=on --saveauto=on /dev/rdisk0 (Enables SMART on first disk)\n\n"
" smartctl --attributes --log=selftest --quietmode=errorsonly /dev/disk0\n"
" (Prints Self-Test & Attribute errors)\n\n"
#else
" smartctl -s on -S on /dev/rdisk0 (Enables SMART on first disk)\n\n"
" smartctl -A -l selftest -q errorsonly /dev/disk0\n"
" (Prints Self-Test & Attribute errors)\n\n"
#endif
" smartctl -a IOService:/MacRISC2PE/pci@f4000000/AppleMacRiscPCI/ata-6@D/AppleKauaiATA/ATADeviceNub@0/IOATABlockStorageDriver/IOATABlockStorageDevice\n"
" (You can use IOService: ...)\n\n"
" smartctl -c IODeviceTree:/pci@f4000000/ata-6@D/@0:0\n"
@ -78,7 +65,7 @@ static struct {
IONVMeSMARTInterface **smartIfNVMe;
} devices[20];
const char * dev_darwin_cpp_cvsid = "$Id: os_darwin.cpp 4552 2017-10-11 10:11:35Z samm2 $"
const char * dev_darwin_cpp_cvsid = "$Id: os_darwin.cpp 4831 2018-11-09 07:18:23Z samm2 $"
DEV_INTERFACE_H_CVSID;
/////////////////////////////////////////////////////////////////////////////
@ -367,9 +354,9 @@ static int make_device_names (char*** devlist, const char* name) {
{
for (index = 0; index < result; index++)
if ((*devlist)[index])
free ((*devlist)[index]);
free (*devlist);
}
free ((*devlist)[index]);
free (*devlist);
}
if(!result) // no devs found
return 0;
@ -416,7 +403,7 @@ bool darwin_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
int rc = 0;
if (! ifp)
return -1;
return false;
smartIf = *ifp;
clear_err(); errno = 0;
do {
@ -470,8 +457,9 @@ bool darwin_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
err = -1; // thresholds exceeded condition
out.out_regs.lba_high = 0x2c; out.out_regs.lba_mid = 0xf4;
}
else
else {
out.out_regs.lba_high = 0xc2; out.out_regs.lba_mid = 0x4f;
}
break;
}
else err = 0;
@ -570,7 +558,7 @@ bool darwin_nvme_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out
unsigned int page = in.cdw10 & 0xff;
if (! ifp)
return -1;
return false;
smartIfNVMe = *ifp;
// currently only GetIdentifyData and SMARTReadData are supported
switch (in.opcode) {

View File

@ -5,26 +5,13 @@
*
* Copyright (C) 2004-8 Geoff Keating <geoffk@geoffk.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_DARWIN_H_
#define OS_DARWIN_H_
#define OS_DARWIN_H_CVSID "$Id: os_darwin.h 4438 2017-09-20 18:00:42Z samm2 $\n"
#define OS_DARWIN_H_CVSID "$Id: os_darwin.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
#define kIOATABlockStorageDeviceClass "IOATABlockStorageDevice"

View File

@ -5,16 +5,10 @@
*
* Copyright (C) 2003-10 Eduard Martinescu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
@ -37,7 +31,7 @@
#include <sys/utsname.h>
#include "config.h"
#include "int64.h"
// set by /usr/include/sys/ata.h, suppress warning
#undef ATA_READ_LOG_EXT
#include "atacmds.h"
@ -80,8 +74,8 @@
#define PATHINQ_SETTINGS_SIZE 128
#endif
const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 4425 2017-04-24 16:34:16Z samm2 $" \
ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 4848 2018-12-05 18:30:46Z chrfranke $" \
ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
#define NO_RETURN 0
#define BAD_SMART 1
@ -484,7 +478,7 @@ bool freebsd_nvme_device::open()
}
nsid = 0xFFFFFFFF; // broadcast id
}
else if (sscanf(dev, NVME_CTRLR_PREFIX"%d"NVME_NS_PREFIX"%d%c",
else if (sscanf(dev, NVME_CTRLR_PREFIX"%d" NVME_NS_PREFIX "%d%c",
&ctrlid, &nsid, &tmp) == 2)
{
if(ctrlid < 0 || nsid < 0) {
@ -519,8 +513,14 @@ bool freebsd_nvme_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out
{
// nvme_passthru_cmd pt;
struct nvme_pt_command pt;
struct nvme_completion *cp_p;
memset(&pt, 0, sizeof(pt));
#if __FreeBSD_version >= 1200058 && __FreeBSD_version < 1200081
pt.cmd.opc_fuse = NVME_CMD_SET_OPC(in.opcode);
#else
pt.cmd.opc = in.opcode;
#endif
pt.cmd.opc = in.opcode;
pt.cmd.nsid = in.nsid;
pt.buf = in.buffer;
@ -538,10 +538,14 @@ bool freebsd_nvme_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out
if (status < 0)
return set_err(errno, "NVME_PASSTHROUGH_CMD: %s", strerror(errno));
out.result=pt.cpl.cdw0; // Command specific result (DW0)
cp_p = &pt.cpl;
out.result=cp_p->cdw0; // Command specific result (DW0)
if (nvme_completion_is_error(&pt.cpl))
return set_nvme_err(out, nvme_completion_is_error(&pt.cpl));
if (nvme_completion_is_error(cp_p)) { /* ignore DNR and More bits */
uint16_t nvme_status = ((cp_p->status.sct << 8) | cp_p->status.sc) & 0x3ff;
return set_nvme_err(out, nvme_status);
}
return true;
}
@ -609,7 +613,7 @@ bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_ou
if (m_disknum < 0) {
printwarning(NO_DISK_3WARE,NULL);
return -1;
return false;
}
memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
@ -1071,7 +1075,7 @@ bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
/* datalen */ iop->dxfer_len,
/* senselen */ iop->max_sense_len,
/* cdblen */ iop->cmnd_len,
/* timout (converted to seconds) */ iop->timeout*1000);
/* timeout (converted to seconds) */ iop->timeout*1000);
memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
if (cam_send_ccb(m_camdev,ccb) < 0) {
@ -1447,6 +1451,8 @@ protected:
virtual smart_device * get_custom_smart_device(const char * name, const char * type);
virtual std::string get_valid_custom_dev_types_str();
private:
bool get_nvme_devlist(smart_device_list & devlist, const char * type);
};
@ -1716,6 +1722,12 @@ bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
return false;
}
#ifdef WITH_NVME_DEVICESCAN // TODO: Remove when NVMe support is no longer EXPERIMENTAL
bool scan_nvme = !type || !strcmp(type, "nvme");
#else
bool scan_nvme = type && !strcmp(type, "nvme");
#endif
// Make namelists
char * * atanames = 0; int numata = 0;
if (!type || !strcmp(type, "ata")) {
@ -1758,9 +1770,31 @@ bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
devlist.push_back(scsidev);
}
}
if (scan_nvme)
get_nvme_devlist(devlist, type);
return true;
}
bool freebsd_smart_interface::get_nvme_devlist(smart_device_list & devlist,
const char * type)
{
char ctrlpath[64];
for (int ctrlr = 0;; ctrlr++) {
sprintf(ctrlpath, "%s%d", NVME_CTRLR_PREFIX, ctrlr);
int fd = ::open(ctrlpath, O_RDWR);
if (fd < 0)
break;
::close(fd);
nvme_device * nvmedev = get_nvme_device(ctrlpath, type, 0);
if (nvmedev)
devlist.push_back(nvmedev);
else
break;
}
return true;
}
#if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
static char done[USB_MAX_DEVICES];
@ -1979,7 +2013,7 @@ smart_device * freebsd_smart_interface::autodetect_smart_device(const char * nam
if(usbdevlist(bus,vendor_id, product_id, version)){
const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
if (usbtype)
return get_sat_device(usbtype, new freebsd_scsi_device(this, test_name, ""));
return get_scsi_passthrough_device(usbtype, new freebsd_scsi_device(this, test_name, ""));
}
return 0;
}
@ -2004,6 +2038,8 @@ smart_device * freebsd_smart_interface::autodetect_smart_device(const char * nam
// form /dev/nvme* or nvme*
if(!strncmp("/dev/nvme", test_name, strlen("/dev/nvme")))
return new freebsd_nvme_device(this, name, "", 0 /* use default nsid */);
if(!strncmp("/dev/nvd", test_name, strlen("/dev/nvd")))
set_err(EINVAL, "To monitor NVMe disks use /dev/nvme* device names");
// device type unknown
return 0;

View File

@ -5,20 +5,7 @@
*
* Copyright (C) 2003-8 Eduard Martinescu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/*-
@ -82,7 +69,7 @@
#ifndef OS_FREEBSD_H_
#define OS_FREEBSD_H_
#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 4431 2017-08-08 19:38:15Z chrfranke $"
#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 4760 2018-08-19 18:45:53Z chrfranke $"
#define MAX_NUM_DEV 26

View File

@ -5,16 +5,9 @@
*
* Copyright (C) YEAR YOUR_NAME
* Copyright (C) 2003-8 Bruce Allen
* Copyright (C) 2008 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2008-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@ -53,8 +46,7 @@
replace the 'stub' function calls provided in this file.
Provide the functions defined in this file by fleshing out the
skeletons below. You can entirely eliminate the function
'unsupported()'.
skeletons below.
[5] Contact smartmontools-support@listi.jpberlin.de to see
about checking your code into the smartmontools CVS archive.
@ -71,7 +63,6 @@
// These are needed to define prototypes and structures for the
// functions defined below
#include "int64.h"
#include "atacmds.h"
#include "utility.h"
@ -83,60 +74,18 @@
// should have one *_H_CVSID macro appearing below for each file
// appearing with #include "*.h" above. Please list these (below) in
// alphabetic/dictionary order.
const char * os_XXXX_cpp_cvsid="$Id: os_generic.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_GENERIC_H_CVSID UTILITY_H_CVSID;
const char * os_XXXX_cpp_cvsid="$Id: os_generic.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
ATACMDS_H_CVSID CONFIG_H_CVSID OS_GENERIC_H_CVSID UTILITY_H_CVSID;
// This is here to prevent compiler warnings for unused arguments of
// functions.
#define ARGUSED(x) ((void)(x))
// Please eliminate the following block: both the #include and
// the 'unsupported()' function. They are only here to warn
// unsuspecting users that their Operating System is not supported! If
// you wish, you can use a similar warning mechanism for any of the
// functions in this file that you can not (or choose not to)
// implement.
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif
static void unsupported(){
static int warninggiven;
if (!warninggiven) {
char *osname;
#ifdef HAVE_UNAME
struct utsname ostype;
uname(&ostype);
osname=ostype.sysname;
#else
osname="host's";
#endif
pout("\n"
"############################################################################\n"
"WARNING: smartmontools has not been ported to the %s Operating System.\n"
"Please see the files os_generic.cpp and os_generic.h for porting instructions.\n"
"############################################################################\n\n",
osname);
warninggiven=1;
}
return;
}
// End of the 'unsupported()' block that you should eliminate.
// print examples for smartctl. You should modify this function so
// that the device paths are sensible for your OS, and to eliminate
// unsupported commands (eg, 3ware controllers).
static void print_smartctl_examples(){
printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
#ifdef HAVE_GETOPT_LONG
printf(
printf("=================================================== SMARTCTL EXAMPLES =====\n\n"
" smartctl -a /dev/hda (Prints all SMART information)\n\n"
" smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n"
" (Enables SMART on first disk)\n\n"
@ -146,17 +95,6 @@ static void print_smartctl_examples(){
" smartctl -a --device=3ware,2 /dev/sda\n"
" (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
);
#else
printf(
" smartctl -a /dev/hda (Prints all SMART information)\n"
" smartctl -s on -o on -S on /dev/hda (Enables SMART on first disk)\n"
" smartctl -t long /dev/hda (Executes extended disk self-test)\n"
" smartctl -A -l selftest -q errorsonly /dev/hda\n"
" (Prints Self-Test & Attribute errors)\n"
" smartctl -a -d 3ware,2 /dev/sda\n"
" (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
);
#endif
return;
}
@ -213,8 +151,6 @@ ata_device * generic_smart_interface::get_ata_device(const char * name, const ch
{
ARGUSED(name);
ARGUSED(type);
unsupported();
return NULL;
}
@ -224,8 +160,6 @@ scsi_device * generic_smart_interface::get_scsi_device(const char * name, const
{
ARGUSED(name);
ARGUSED(type);
unsupported();
return NULL;
}
@ -234,9 +168,7 @@ scsi_device * generic_smart_interface::get_scsi_device(const char * name, const
smart_device * generic_smart_interface::autodetect_smart_device(const char * name)
{
ARGUSED(name);
// for the given name return the apropriate device type
unsupported();
// for the given name return the appropriate device type
return NULL;
}
@ -248,8 +180,6 @@ bool generic_smart_interface::scan_smart_devices(smart_device_list & devlist,
ARGUSED(devlist);
ARGUSED(type);
ARGUSED(pattern);
unsupported();
return false;
}
@ -259,8 +189,6 @@ smart_device * generic_smart_interface::get_custom_smart_device(const char * nam
{
ARGUSED(name);
ARGUSED(type);
unsupported();
return NULL;
}

View File

@ -6,26 +6,13 @@
* Copyright (C) YEAR YOUR_NAME
* Copyright (C) 2003-8 Bruce Allen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
// In the three following lines, change 'GENERIC' to your OS name
#ifndef OS_GENERIC_H_
#define OS_GENERIC_H_
#define OS_GENERIC_H_CVSID "$Id: os_generic.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_GENERIC_H_CVSID "$Id: os_generic.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
// Additional material should start here. Note: to keep the '-V' CVS
// reporting option working as intended, you should only #include

View File

@ -5,7 +5,7 @@
*
* Copyright (C) 2003-11 Bruce Allen
* Copyright (C) 2003-11 Doug Gilbert <dgilbert@interlog.com>
* Copyright (C) 2008-16 Christian Franke
* Copyright (C) 2008-18 Christian Franke
*
* Original AACRaid code:
* Copyright (C) 2014 Raghava Aditya <raghava.aditya@pmcs.com>
@ -26,7 +26,7 @@
*
* Copyright (C) 1999-2003 3ware Inc.
*
* Kernel compatablity By: Andre Hedrick <andre@suse.com>
* Kernel compatibility By: Andre Hedrick <andre@suse.com>
* Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
*
* Other ars of this file are derived from code that was
@ -34,19 +34,7 @@
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
// This file contains the linux-specific IOCTL parts of
@ -74,14 +62,16 @@
#include <sys/uio.h>
#include <sys/types.h>
#include <dirent.h>
#ifndef makedev // old versions of types.h do not include sysmacros.h
#ifdef HAVE_SYS_SYSMACROS_H
// glibc 2.25: The inclusion of <sys/sysmacros.h> by <sys/types.h> is
// deprecated. A warning is printed if major(), minor() or makedev()
// is used but <sys/sysmacros.h> is not included.
#include <sys/sysmacros.h>
#endif
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
#include <selinux/selinux.h>
#endif
#include "int64.h"
#include "atacmds.h"
#include "os_linux.h"
#include "scsicmds.h"
@ -89,6 +79,7 @@
#include "cciss.h"
#include "megaraid.h"
#include "aacraid.h"
#include "nvmecmds.h"
#include "dev_interface.h"
#include "dev_ata_cmd_set.h"
@ -103,7 +94,7 @@
#define ARGUSED(x) ((void)(x))
const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 4582 2017-11-03 20:54:56Z chrfranke $"
const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 4854 2018-12-11 20:32:29Z chrfranke $"
OS_LINUX_H_CVSID;
extern unsigned char failuretest_permissive;
@ -538,6 +529,22 @@ static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
struct sg_io_hdr io_hdr_v3;
struct sg_io_v4 io_hdr_v4;
#ifdef SCSI_CDB_CHECK
bool ok = is_scsi_cdb(iop->cmnd, iop->cmnd_len);
if (! ok) {
int n = iop->cmnd_len;
const unsigned char * ucp = iop->cmnd;
pout(">>>>>>>> %s: cdb seems invalid, opcode=0x%x, len=%d, cdb:\n",
__func__, ((n > 0) ? ucp[0] : 0), n);
if (n > 0) {
if (n > 16)
pout(" <<truncating to first 16 bytes>>\n");
dStrHex((const uint8_t *)ucp, ((n > 16) ? 16 : n), 1);
}
}
#endif
if (report > 0) {
int k, j;
const unsigned char * ucp = iop->cmnd;
@ -557,8 +564,7 @@ static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
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((const char *)iop->dxferp,
(trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
else
snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
@ -678,8 +684,7 @@ static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
if (len > 0) {
pout(" Incoming data, len=%d%s:\n", len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex((const char*)iop->dxferp, (trunc ? 256 : len),
1);
dStrHex(iop->dxferp, (trunc ? 256 : len), 1);
} else
pout(" Incoming data trimmed to nothing by resid\n");
}
@ -713,7 +718,7 @@ static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
if (report > 1) {
pout(" >>> Sense buffer, len=%d:\n",
(int)iop->resp_sense_len);
dStrHex((const char *)iop->sensep, iop->resp_sense_len , 1);
dStrHex(iop->sensep, iop->resp_sense_len , 1);
}
}
if (report) {
@ -739,7 +744,7 @@ struct linux_ioctl_send_command
{
int inbufsize;
int outbufsize;
UINT8 buff[MAX_DXFER_LEN + 16];
uint8_t buff[MAX_DXFER_LEN + 16];
};
/* The Linux SCSI_IOCTL_SEND_COMMAND ioctl is primitive and it doesn't
@ -771,8 +776,7 @@ static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report)
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((const char *)iop->dxferp,
(trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
else
snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
@ -820,8 +824,7 @@ static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report)
pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex((const char*)iop->dxferp,
(trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
}
return 0;
@ -837,7 +840,7 @@ static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report)
iop->resp_sense_len = len;
if (report > 1) {
pout(" >>> Sense buffer, len=%d:\n", (int)len);
dStrHex((const char *)wrk.buff, len , 1);
dStrHex(wrk.buff, len , 1);
}
}
if (report) {
@ -894,7 +897,7 @@ static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop,
sg_io_state = SG_IO_UNSUPP;
/* FALLTHRU */
case SG_IO_UNSUPP:
/* depricated SCSI_IOCTL_SEND_COMMAND ioctl */
/* deprecated SCSI_IOCTL_SEND_COMMAND ioctl */
return sisc_cmnd_io(dev_fd, iop, report);
case SG_IO_USE_V3:
case SG_IO_USE_V4:
@ -1059,8 +1062,7 @@ bool linux_aacraid_device::scsi_pass_through(scsi_cmnd_io *iop)
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((const char *)iop->dxferp,
(trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
else
snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
@ -1292,29 +1294,31 @@ bool linux_megaraid_device::open()
int err = errno;
linux_smart_device::close();
return set_err(err, "can't get bus number");
} // we dont need this device anymore
} // we don't need this device anymore
linux_smart_device::close();
}
/* Perform mknod of device ioctl node */
FILE * fp = fopen("/proc/devices", "r");
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));
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));
if(report > 0)
pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
if (n1 >= 0 || errno == EEXIST)
break;
if (fp) {
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));
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));
if(report > 0)
pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
if (n1 >= 0 || errno == EEXIST)
break;
}
}
fclose(fp);
}
fclose(fp);
/* Open Device IOCTL node */
if ((m_fd = ::open("/dev/megaraid_sas_ioctl_node", O_RDWR)) >= 0) {
@ -1363,8 +1367,7 @@ bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
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((const char *)iop->dxferp,
(trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
else
snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
@ -1588,7 +1591,7 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
struct stat stat_buf;
FILE *file;
int retval = 0;
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
security_context_t orig_context = NULL;
security_context_t node_context = NULL;
int selinux_enabled = is_selinux_enabled();
@ -1618,7 +1621,7 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
pout("No major number for /dev/%s listed in /proc/devices. Is the %s driver loaded?\n", nodename, driver_name);
return 2;
}
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
/* Prepare a database of contexts for files in /dev
* and save the current context */
if (selinux_enabled) {
@ -1626,16 +1629,17 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
pout("Error initializing contexts database for /dev");
if (getfscreatecon(&orig_context) < 0) {
pout("Error retrieving original SELinux fscreate context");
if (selinux_enforced)
if (selinux_enforced) {
matchpathcon_fini();
return 6;
}
}
}
#endif
/* Now check if nodes are correct */
for (index=0; index<16; index++) {
snprintf(nodestring, sizeof(nodestring), "/dev/%s%d", nodename, index);
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
/* Get context of the node and set it as the default */
if (selinux_enabled) {
if (matchpathcon(nodestring, S_IRUSR | S_IWUSR, &node_context) < 0) {
@ -1664,7 +1668,7 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
retval = 3;
break;
} else {
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
if (selinux_enabled && node_context) {
freecon(node_context);
node_context = NULL;
@ -1696,7 +1700,7 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
break;
}
}
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
if (selinux_enabled && node_context) {
freecon(node_context);
node_context = NULL;
@ -1704,7 +1708,7 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
#endif
}
#ifdef WITH_SELINUX
#ifdef HAVE_LIBSELINUX
if (selinux_enabled) {
if(setfscreatecon(orig_context) < 0) {
pout("Error re-setting original fscreate context");
@ -2264,8 +2268,8 @@ int linux_marvell_device::ata_command_interface(smart_command_set command, int s
break;
default:
pout("Unrecognized command %d in mvsata_os_specific_handler()\n", command);
EXIT(1);
break;
errno = EINVAL;
return -1;
}
// There are two different types of ioctls(). The HDIO_DRIVE_TASK
// one is this:
@ -2744,17 +2748,21 @@ static bool read_id(const std::string & path, unsigned short & id)
return ok;
}
// Get USB bridge ID for "sdX"
// Get USB bridge ID for "sdX" or "sgN"
static bool get_usb_id(const char * name, unsigned short & vendor_id,
unsigned short & product_id, unsigned short & version)
{
// Only "sdX" supported
if (!(!strncmp(name, "sd", 2) && !strchr(name, '/')))
// Only "sdX" or "sgN" supported
if (!(name[0] == 's' && (name[1] == 'd' || name[1] == 'g') && !strchr(name, '/')))
return false;
// Start search at dir referenced by symlink "/sys/block/sdX/device"
// Start search at dir referenced by symlink
// "/sys/block/sdX/device" or
// "/sys/class/scsi_generic/sgN"
// -> "/sys/devices/.../usb*/.../host*/target*/..."
std::string dir = strprintf("/sys/block/%s/device", name);
std::string dir = strprintf("/sys/%s/%s%s",
(name[1] == 'd' ? "block" : "class/scsi_generic"), name,
(name[1] == 'd' ? "/device" : ""));
// Stop search at "/sys/devices"
struct stat st;
@ -2793,8 +2801,8 @@ public:
virtual std::string get_app_examples(const char * appname);
virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
const char * pattern = 0);
virtual bool scan_smart_devices(smart_device_list & devlist,
const smart_devtype_list & types, const char * pattern = 0);
protected:
virtual ata_device * get_ata_device(const char * name, const char * type);
@ -2811,9 +2819,11 @@ protected:
virtual std::string get_valid_custom_dev_types_str();
private:
bool get_dev_list(smart_device_list & devlist, const char * pattern,
bool scan_ata, bool scan_scsi, bool scan_nvme,
const char * req_type, bool autodetect);
static const int devxy_to_n_max = 103; // Max value of devxy_to_n() below
void get_dev_list(smart_device_list & devlist, const char * pattern,
bool scan_scsi, bool (* p_dev_sdxy_seen)[devxy_to_n_max+1],
bool scan_nvme, const char * req_type, bool autodetect);
bool get_dev_megasas(smart_device_list & devlist);
smart_device * missing_option(const char * opt);
@ -2838,35 +2848,64 @@ std::string linux_smart_interface::get_app_examples(const char * appname)
return "";
}
// we are going to take advantage of the fact that Linux's devfs will only
// have device entries for devices that exist.
bool linux_smart_interface::get_dev_list(smart_device_list & devlist,
const char * pattern, bool scan_ata, bool scan_scsi, bool scan_nvme,
const char * req_type, bool autodetect)
// "/dev/sdXY" -> 0-103
// "/dev/disk/by-id/NAME" -> "../../sdXY" -> 0-103
// Other -> -1
static int devxy_to_n(const char * name, bool debug)
{
const char * xy;
char dest[256];
if (str_starts_with(name, "/dev/sd")) {
// Assume "/dev/sdXY"
xy = name + sizeof("/dev/sd") - 1;
}
else {
// Assume "/dev/disk/by-id/NAME", check link target
int sz = readlink(name, dest, sizeof(dest)-1);
if (!(0 < sz && sz < (int)sizeof(dest)))
return -1;
dest[sz] = 0;
if (!str_starts_with(dest, "../../sd"))
return -1;
if (debug)
pout("%s -> %s\n", name, dest);
xy = dest + sizeof("../../sd") - 1;
}
char x = xy[0];
if (!('a' <= x && x <= 'z'))
return -1;
char y = xy[1];
if (!y)
// "[a-z]" -> 0-25
return x - 'a';
if (!(x <= 'c' && 'a' <= y && y <= 'z' && !xy[2]))
return -1;
// "[a-c][a-z]" -> 26-103
return (x - 'a' + 1) * ('z' - 'a' + 1) + (y - 'a');
}
void linux_smart_interface::get_dev_list(smart_device_list & devlist,
const char * pattern, bool scan_scsi, bool (* p_dev_sdxy_seen)[devxy_to_n_max+1],
bool scan_nvme, const char * req_type, bool autodetect)
{
bool debug = (ata_debugmode || scsi_debugmode || nvme_debugmode);
// Use glob to look for any directory entries matching the pattern
glob_t globbuf;
memset(&globbuf, 0, sizeof(globbuf));
int retglob = glob(pattern, GLOB_ERR, NULL, &globbuf);
if (retglob) {
// glob failed: free memory and return
// glob failed: free memory and return
globfree(&globbuf);
if (retglob==GLOB_NOMATCH){
pout("glob(3) found no matches for pattern %s\n", pattern);
return true;
}
if (debug)
pout("glob(3) error %d for pattern %s\n", retglob, pattern);
if (retglob==GLOB_NOSPACE)
set_err(ENOMEM, "glob(3) ran out of memory matching pattern %s", pattern);
#ifdef GLOB_ABORTED // missing in old versions of glob.h
else if (retglob==GLOB_ABORTED)
set_err(EINVAL, "glob(3) aborted matching pattern %s", pattern);
#endif
else
set_err(EINVAL, "Unexplained error in glob(3) of pattern %s", pattern);
return false;
if (retglob == GLOB_NOSPACE)
throw std::bad_alloc();
return;
}
// did we find too many paths?
@ -2878,64 +2917,40 @@ bool linux_smart_interface::get_dev_list(smart_device_list & devlist,
n = max_pathc;
}
// now step through the list returned by glob. If not a link, copy
// to list. If it is a link, evaluate it and see if the path ends
// in "disc".
for (int i = 0; i < n; i++){
// see if path is a link
char linkbuf[1024];
int retlink = readlink(globbuf.gl_pathv[i], linkbuf, sizeof(linkbuf)-1);
// now step through the list returned by glob.
for (int i = 0; i < n; i++) {
const char * name = globbuf.gl_pathv[i];
char tmpname[1024]={0};
const char * name = 0;
bool is_scsi = scan_scsi;
// if not a link (or a strange link), keep it
if (retlink<=0 || retlink>1023)
name = globbuf.gl_pathv[i];
else {
// or if it's a link that points to a disc, follow it
linkbuf[retlink] = 0;
const char *p;
if ((p=strrchr(linkbuf, '/')) && !strcmp(p+1, "disc"))
// This is the branch of the code that gets followed if we are
// using devfs WITH traditional compatibility links. In this
// case, we add the traditional device name to the list that
// is returned.
name = globbuf.gl_pathv[i];
else {
// This is the branch of the code that gets followed if we are
// using devfs WITHOUT traditional compatibility links. In
// this case, we check that the link to the directory is of
// the correct type, and then append "disc" to it.
bool match_ata = strstr(linkbuf, "ide");
bool match_scsi = strstr(linkbuf, "scsi");
if (((match_ata && scan_ata) || (match_scsi && scan_scsi)) && !(match_ata && match_scsi)) {
is_scsi = match_scsi;
snprintf(tmpname, sizeof(tmpname), "%s/disc", globbuf.gl_pathv[i]);
name = tmpname;
}
if (p_dev_sdxy_seen) {
// Follow "/dev/disk/by-id/*" symlink and check for duplicate "/dev/sdXY"
int dev_n = devxy_to_n(name, debug);
if (!(0 <= dev_n && dev_n <= devxy_to_n_max))
continue;
if ((*p_dev_sdxy_seen)[dev_n]) {
if (debug)
pout("%s: duplicate, ignored\n", name);
continue;
}
(*p_dev_sdxy_seen)[dev_n] = true;
}
if (name) {
// Found a name, add device to list.
smart_device * dev;
if (autodetect)
dev = autodetect_smart_device(name);
else if (is_scsi)
dev = new linux_scsi_device(this, name, req_type, true /*scanning*/);
else if (scan_nvme)
dev = new linux_nvme_device(this, name, req_type, 0 /* use default nsid */);
else
dev = new linux_ata_device(this, name, req_type);
if (dev) // autodetect_smart_device() may return nullptr.
devlist.push_back(dev);
smart_device * dev;
if (autodetect) {
dev = autodetect_smart_device(name);
if (!dev)
continue;
}
else if (scan_scsi)
dev = new linux_scsi_device(this, name, req_type, true /*scanning*/);
else if (scan_nvme)
dev = new linux_nvme_device(this, name, req_type, 0 /* use default nsid */);
else
dev = new linux_ata_device(this, name, req_type);
devlist.push_back(dev);
}
// free memory
globfree(&globbuf);
return true;
}
// getting devices from LSI SAS MegaRaid, if available
@ -2947,6 +2962,8 @@ bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist)
char line[128];
bool scan_megasas = false;
FILE * fp = fopen("/proc/devices", "r");
if (!fp)
return false;
while (fgets(line, sizeof(line), fp) != NULL) {
n1=0;
if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
@ -2993,53 +3010,69 @@ bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist)
}
bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist,
const char * type, const char * pattern /*= 0*/)
const smart_devtype_list & types, const char * pattern /*= 0*/)
{
if (pattern) {
set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
return false;
if (pattern)
return set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
// Scan type list
bool by_id = false;
const char * type_ata = 0, * type_scsi = 0, * type_sat = 0, * type_nvme = 0;
for (unsigned i = 0; i < types.size(); i++) {
const char * type = types[i].c_str();
if (!strcmp(type, "by-id"))
by_id = true;
else if (!strcmp(type, "ata"))
type_ata = "ata";
else if (!strcmp(type, "scsi"))
type_scsi = "scsi";
else if (!strcmp(type, "sat"))
type_sat = "sat";
else if (!strcmp(type, "nvme"))
type_nvme = "nvme";
else
return set_err(EINVAL, "Invalid type '%s', valid arguments are: by-id, ata, scsi, sat, nvme",
type);
}
if (!type)
type = "";
bool scan_ata = (!*type || !strcmp(type, "ata" ));
// "sat" detection will be later handled in linux_scsi_device::autodetect_open()
bool scan_scsi = (!*type || !strcmp(type, "scsi") || !strcmp(type, "sat"));
// Use default if no type specified
if (!(type_ata || type_scsi || type_sat || type_nvme)) {
type_ata = type_scsi = type_sat = "";
#ifdef WITH_NVME_DEVICESCAN // TODO: Remove when NVMe support is no longer EXPERIMENTAL
bool scan_nvme = (!*type || !strcmp(type, "nvme"));
#else
bool scan_nvme = ( !strcmp(type, "nvme"));
type_nvme = "";
#endif
if (!(scan_ata || scan_scsi || scan_nvme)) {
set_err(EINVAL, "Invalid type '%s', valid arguments are: ata, scsi, sat, nvme", type);
return false;
}
if (scan_ata)
get_dev_list(devlist, "/dev/hd[a-t]", true, false, false, type, false);
if (scan_scsi) {
bool autodetect = !*type; // Try USB autodetection if no type specifed
get_dev_list(devlist, "/dev/sd[a-z]", false, true, false, type, autodetect);
// Support up to 104 devices
get_dev_list(devlist, "/dev/sd[a-c][a-z]", false, true, false, type, autodetect);
if (type_ata)
get_dev_list(devlist, "/dev/hd[a-t]", false, 0, false, type_ata, false);
if (type_scsi || type_sat) {
// "sat" detection will be later handled in linux_scsi_device::autodetect_open()
const char * type_scsi_sat = ((type_scsi && type_sat) ? "" // detect both
: (type_scsi ? type_scsi : type_sat));
bool autodetect = !*type_scsi_sat; // If no type specified, detect USB also
bool dev_sdxy_seen[devxy_to_n_max+1] = {false, };
bool (*p_dev_sdxy_seen)[devxy_to_n_max+1] = 0;
if (by_id) {
// Scan unique symlinks first
get_dev_list(devlist, "/dev/disk/by-id/*", true, &dev_sdxy_seen, false,
type_scsi_sat, autodetect);
p_dev_sdxy_seen = &dev_sdxy_seen; // Check for duplicates below
}
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 device list from the megaraid device
get_dev_megasas(devlist);
}
if (scan_nvme) {
get_dev_list(devlist, "/dev/nvme[0-9]", false, false, true, type, false);
get_dev_list(devlist, "/dev/nvme[1-9][0-9]", false, false, true, type, false);
if (type_nvme) {
get_dev_list(devlist, "/dev/nvme[0-9]", false, 0, true, type_nvme, false);
get_dev_list(devlist, "/dev/nvme[1-9][0-9]", false, 0, true, type_nvme, false);
}
// if we found traditional links, we are done
if (devlist.size() > 0)
return true;
// else look for devfs entries without traditional links
// TODO: Add udev support
return get_dev_list(devlist, "/dev/discs/disc*", scan_ata, scan_scsi, false, type, false);
return true;
}
ata_device * linux_smart_interface::get_ata_device(const char * name, const char * type)
@ -3176,7 +3209,7 @@ static bool is_hpsa(const char * name)
{
char path[128];
snprintf(path, sizeof(path), "/sys/block/%s/device", name);
char * syshostpath = canonicalize_file_name(path);
char * syshostpath = realpath(path, (char *)0);
if (!syshostpath)
return false;
@ -3264,7 +3297,7 @@ smart_device * linux_smart_interface::autodetect_smart_device(const char * name)
// Return SAT/USB device for this type
// (Note: linux_scsi_device::autodetect_open() will not be called in this case)
return get_sat_device(usbtype, new linux_scsi_device(this, name, ""));
return get_scsi_passthrough_device(usbtype, new linux_scsi_device(this, name, ""));
}
// Fail if hpsa driver

View File

@ -14,31 +14,17 @@
*
* Copyright (C) 1999-2003 3ware Inc.
*
* Kernel compatablity By: Andre Hedrick <andre@suse.com>
* Kernel compatibility By: Andre Hedrick <andre@suse.com>
* Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_LINUX_H_
#define OS_LINUX_H_
#define OS_LINUX_H_CVSID "$Id: os_linux.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_LINUX_H_CVSID "$Id: os_linux.h 4842 2018-12-02 16:07:26Z chrfranke $\n"
/*
The following definitions/macros/prototypes are used for three

View File

@ -6,19 +6,11 @@
* Copyright (C) 2003-8 Sergey Svishchev
* Copyright (C) 2016 Kimihiro Nonaka
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "utility.h"
@ -26,40 +18,16 @@
#include <sys/drvctlio.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
// 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 4431 2017-08-08 19:38:15Z chrfranke $"
const char * os_netbsd_cpp_cvsid = "$Id: os_netbsd.cpp 4780 2018-09-16 15:03:22Z chrfranke $"
OS_NETBSD_H_CVSID;
enum warnings {
BAD_SMART, MAX_MSG
};
/* 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) and twa(4) devices (3ware Escalade, Apache)\n",
};
if (msgNo >= 0 && msgNo <= MAX_MSG) {
if (!printed[msgNo]) {
printed[msgNo] = 1;
pout("%s", message[msgNo]);
if (extra)
pout("%s", extra);
}
}
return;
}
#define ARGUSED(x) ((void)(x))
/////////////////////////////////////////////////////////////////////////////
@ -206,7 +174,7 @@ bool netbsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
req.sec_count = in.in_regs.sector_count;
req.sec_num = in.in_regs.lba_low;
req.head = in.in_regs.device;
req.cylinder = le16toh(in.in_regs.lba_mid | (in.in_regs.lba_high << 8));
req.cylinder = in.in_regs.lba_mid | (in.in_regs.lba_high << 8);
switch (in.direction) {
case ata_cmd_in::no_data:
@ -237,41 +205,14 @@ bool netbsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
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 = le16toh(req.cylinder);
out.out_regs.lba_high = le16toh(req.cylinder) >> 8;
out.out_regs.lba_mid = req.cylinder;
out.out_regs.lba_high = req.cylinder >> 8;
out.out_regs.status = req.command;
// Command specific processing
if (in.in_regs.command == ATA_SMART_CMD
&& in.in_regs.features == ATA_SMART_STATUS
&& in.out_needed.lba_high)
{
unsigned const char normal_lo=0x4f, normal_hi=0xc2;
unsigned const char failed_lo=0xf4, failed_hi=0x2c;
// Cyl low and Cyl high unchanged means "Good SMART status"
if (!(out.out_regs.lba_mid==normal_lo && out.out_regs.lba_high==normal_hi)
// These values mean "Bad SMART status"
&& !(out.out_regs.lba_mid==failed_lo && out.out_regs.lba_high==failed_hi))
{
// We haven't gotten output that makes sense; print out some debugging info
char buf[512];
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)(le16toh(req.cylinder) & 0xff),
(int)((le16toh(req.cylinder) >> 8) & 0xff),
(int)req.error);
printwarning(BAD_SMART,buf);
out.out_regs.lba_high = failed_hi;
out.out_regs.lba_mid = failed_lo;
}
/* Undo byte-swapping for IDENTIFY */
if (in.in_regs.command == ATA_IDENTIFY_DEVICE && isbigendian()) {
for (int i = 0; i < 256; i+=2)
swap2 ((char *)req.databuf + i);
}
return true;
}
@ -319,7 +260,7 @@ bool netbsd_nvme_device::open()
}
nsid = 0xFFFFFFFF; // broadcast id
}
else if (sscanf(dev, NVME_PREFIX"%d"NVME_NS_PREFIX"%d%c",
else if (sscanf(dev, NVME_PREFIX "%d" NVME_NS_PREFIX "%d%c",
&ctrlid, &nsid, &tmp) == 2)
{
if(ctrlid < 0 || nsid <= 0) {
@ -595,21 +536,13 @@ std::string netbsd_smart_interface::get_app_examples(const char * appname)
p = 'a' + getrawpartition();
return strprintf(
"=================================================== SMARTCTL EXAMPLES =====\n\n"
#ifdef HAVE_GETOPT_LONG
"=================================================== 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"
#else
" 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"
#endif
, p, p, p, p);
}
return "";
@ -717,7 +650,7 @@ bool netbsd_smart_interface::get_nvme_devlist(smart_device_list & devlist,
uint32_t n = 0;
for (int nsid = 1; n < laa.l_children; nsid++) {
snprintf(nspath, sizeof(nspath), NVME_PREFIX"%d"NVME_NS_PREFIX"%d",
snprintf(nspath, sizeof(nspath), NVME_PREFIX "%d" NVME_NS_PREFIX "%d",
ctrl, nsid);
if (stat(nspath, &sb) == -1 || !S_ISCHR(sb.st_mode))
break;
@ -754,7 +687,7 @@ bool netbsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
#ifdef WITH_NVME_DEVICESCAN // TODO: Remove when NVMe support is no longer EXPERIMENTAL
bool scan_nvme = !*type || !strcmp(type, "nvme");
#else
bool scan_nvme = !strcmp(type, "nvme");
bool scan_nvme = !strcmp(type, "nvme");
#endif
// Make namelists
@ -834,25 +767,30 @@ smart_device * netbsd_smart_interface::autodetect_smart_device(const char * name
}
}
if (str_starts_with(test_name, net_dev_raw_prefix)) {
if (str_starts_with(test_name, net_dev_raw_prefix))
test_name += strlen(net_dev_raw_prefix);
if (!strncmp(net_dev_ata_disk, test_name, strlen(net_dev_ata_disk)))
return get_ata_device(test_name, "ata");
if (!strncmp(net_dev_scsi_disk, test_name, strlen(net_dev_scsi_disk))) {
else if (str_starts_with(test_name, net_dev_prefix))
test_name += strlen(net_dev_prefix);
else
return 0; // device is not starting with /dev/ or /dev/r*
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 device
return get_scsi_device(test_name, "scsi");
}
if (!strncmp(net_dev_scsi_tape, test_name, strlen(net_dev_scsi_tape)))
return get_scsi_device(test_name, "scsi");
} else if (str_starts_with(test_name, net_dev_prefix)) {
if (!strncmp(NVME_PREFIX, test_name, strlen(NVME_PREFIX)))
return get_nvme_device(test_name, "nvme", 0 /* use default nsid */);
return get_scsi_device(name, "scsi");
}
if (!strncmp(net_dev_scsi_tape, test_name, strlen(net_dev_scsi_tape)))
return get_scsi_device(name, "scsi");
if (!strncmp(net_dev_nvme_ctrl, test_name, strlen(net_dev_nvme_ctrl)))
return get_nvme_device(name, "nvme", 0 /* use default nsid */);
// device type unknown
return 0;
}

View File

@ -5,26 +5,13 @@
*
* Copyright (C) 2003-8 Sergey Svishchev
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_NETBSD_H_
#define OS_NETBSD_H_
#define OS_NETBSD_H_CVSID "$Id: os_netbsd.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_NETBSD_H_CVSID "$Id: os_netbsd.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
#include <sys/device.h>
#include <sys/param.h>

View File

@ -7,19 +7,11 @@
*
* Derived from os_netbsd.cpp by Sergey Svishchev, Copyright (C) 2003-8
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "int64.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "utility.h"
@ -27,7 +19,7 @@
#include <errno.h>
const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
OS_OPENBSD_H_CVSID;
enum warnings {
@ -41,7 +33,7 @@ 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 currentlly support twe(4) devices (3ware Escalade)\n",
PACKAGE_STRING " does not currently support twe(4) devices (3ware Escalade)\n",
};
if (msgNo >= 0 && msgNo <= MAX_MSG) {
@ -420,9 +412,8 @@ print_smartctl_examples()
char p;
p = 'a' + getrawpartition();
printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
#ifdef HAVE_GETOPT_LONG
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"
@ -431,15 +422,5 @@ print_smartctl_examples()
" (Prints Self-Test & Attribute errors)\n",
p, p, p, p
);
#else
printf(
" 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
);
#endif
return;
}

View File

@ -7,26 +7,13 @@
*
* Derived from os_netbsd.c by Sergey Svishchev, Copyright (C) 2003-8
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_OPENBSD_H_
#define OS_OPENBSD_H_
#define OS_OPENBSD_H_CVSID "$Id: os_openbsd.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_OPENBSD_H_CVSID "$Id: os_openbsd.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
/* from NetBSD: atareg.h,v 1.17, by Manuel Bouyer */
/* Actually fits _perfectly_ into OBSDs wdcreg.h, but... */

View File

@ -5,14 +5,7 @@
*
* Copyright (C) 2004-8 Yuri Dario
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/*
@ -23,7 +16,6 @@
// These are needed to define prototypes for the functions defined below
#include "config.h"
#include "int64.h"
#include <ctype.h>
#include <errno.h>
@ -35,7 +27,7 @@
#include "os_os2.h"
// Needed by '-V' option (CVS versioning) of smartd/smartctl
const char *os_XXXX_c_cvsid="$Id: os_os2.cpp 4431 2017-08-08 19:38:15Z chrfranke $" \
const char *os_XXXX_c_cvsid="$Id: os_os2.cpp 4842 2018-12-02 16:07:26Z chrfranke $" \
ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// global handle to device driver
@ -45,9 +37,7 @@ static HFILE hDevice;
// that the device paths are sensible for your OS, and to eliminate
// unsupported commands (eg, 3ware controllers).
void print_smartctl_examples(){
printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
#ifdef HAVE_GETOPT_LONG
printf(
printf("=================================================== SMARTCTL EXAMPLES =====\n\n"
" smartctl -a hd0 (Prints all SMART information)\n\n"
" smartctl --smart=on --offlineauto=on --saveauto=on hd0\n"
" (Enables SMART on first disk)\n\n"
@ -55,16 +45,6 @@ void print_smartctl_examples(){
" smartctl --attributes --log=selftest --quietmode=errorsonly hd0\n"
" (Prints Self-Test & Attribute errors)\n"
);
#else
printf(
" smartctl -a hd0 (Prints all SMART on first disk with DANIS506)\n"
" smartctl -a ahci0 (Prints all SMART on first disk with OS2AHCI)\n"
" smartctl -s on -o on -S on hd0 (Enables SMART on first disk)\n"
" smartctl -t long hd0 (Executes extended disk self-test)\n"
" smartctl -A -l selftest -q errorsonly hd0\n"
" (Prints Self-Test & Attribute errors)\n"
);
#endif
return;
}
@ -394,7 +374,7 @@ static int dani_ioctl( int device, void* arg)
return 0;
}
// Interface to ATA devices. See os_linux.cpp for the cannonical example.
// Interface to ATA devices. See os_linux.cpp for the canonical example.
// DETAILED DESCRIPTION OF ARGUMENTS
// device: is the integer handle provided by deviceopen()
// command: defines the different operations, see atacmds.h

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2004-8 Yuri Dario
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_OS2_H_
#define OS_OS2_H_
#define OS_XXXX_H_CVSID "$Id: os_os2.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_XXXX_H_CVSID "$Id: os_os2.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
// Additional material should start here. Note: to keep the '-V' CVS
// reporting option working as intended, you should only #include

View File

@ -1,11 +1,18 @@
/*
* os_qnxnto.cpp
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2007 Joerg Hering
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
// This is needed for the various HAVE_* macros and PROJECT_* macros.
#include "config.h"
// These are needed to define prototypes and structures for the
// functions defined below
#include "int64.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "utility.h"
@ -19,66 +26,25 @@
// should have one *_H_CVSID macro appearing below for each file
// appearing with #include "*.h" above. Please list these (below) in
// alphabetic/dictionary order.
const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \
ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_QNXNTO_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 4842 2018-12-02 16:07:26Z chrfranke $" \
ATACMDS_H_CVSID CONFIG_H_CVSID OS_QNXNTO_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// This is here to prevent compiler warnings for unused arguments of
// functions.
#define ARGUSED(x) ((void)(x))
// Please eliminate the following block: both the #include and
// the 'unsupported()' function. They are only here to warn
// unsuspecting users that their Operating System is not supported! If
// you wish, you can use a similar warning mechanism for any of the
// functions in this file that you can not (or choose not to)
// implement.
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif
//----------------------------------------------------------------------------------------------
// private Functions
static int ata_sense_data(void *sdata,int *error,int *key,int *asc,int *ascq);
static int ata_interpret_sense(struct cam_pass_thru *cpt,void *sense,int *status,int rcount);
static int ata_pass_thru(int fd,struct cam_pass_thru *pcpt);
//----------------------------------------------------------------------------------------------
static void unsupported(){
static int warninggiven;
if (!warninggiven) {
char *osname;
#ifdef HAVE_UNAME
struct utsname ostype;
uname(&ostype);
osname=ostype.sysname;
#else
osname="host's";
#endif
pout("\n"
"############################################################################\n"
"WARNING: smartmontools has not been ported to the %s Operating System.\n"
"Please see the files os_generic.cpp and os_generic.h for porting instructions.\n"
"############################################################################\n\n",
osname);
warninggiven=1;
}
return;
}
// End of the 'unsupported()' block that you should eliminate.
// print examples for smartctl. You should modify this function so
// that the device paths are sensible for your OS, and to eliminate
// unsupported commands (eg, 3ware controllers).
void print_smartctl_examples(){
printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
#ifdef HAVE_GETOPT_LONG
printf(
printf("=================================================== SMARTCTL EXAMPLES =====\n\n"
" smartctl -a /dev/hd0 (Prints all SMART information)\n\n"
" smartctl --smart=on --offlineauto=on --saveauto=on /dev/hd0\n"
" (Enables SMART on first disk)\n\n"
@ -88,17 +54,6 @@ void print_smartctl_examples(){
" smartctl -a --device=3ware,2 /dev/sda\n"
" (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
);
#else
printf(
" smartctl -a /dev/hd0 (Prints all SMART information)\n"
" smartctl -s on -o on -S on /dev/hd0 (Enables SMART on first disk)\n"
" smartctl -t long /dev/hd0 (Executes extended disk self-test)\n"
" smartctl -A -l selftest -q errorsonly /dev/hd0\n"
" (Prints Self-Test & Attribute errors)\n"
" smartctl -a -d 3ware,2 /dev/sda\n"
" (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
);
#endif
return;
}
@ -134,7 +89,6 @@ int len,dev_prefix_len;
int make_device_names (char*** devlist, const char* name) {
ARGUSED(devlist);
ARGUSED(name);
unsupported();
return 0;
}
@ -159,7 +113,7 @@ int deviceclose(int fd)
return(close(fd));
}
//----------------------------------------------------------------------------------------------
// Interface to ATA devices. See os_linux.cpp for the cannonical example.
// Interface to ATA devices. See os_linux.cpp for the canonical example.
// DETAILED DESCRIPTION OF ARGUMENTS
// device: is the integer handle provided by deviceopen()
// command: defines the different operations, see atacmds.h
@ -377,7 +331,6 @@ int do_scsi_cmnd_io(int fd,struct scsi_cmnd_io * iop,int report)
ARGUSED(fd);
ARGUSED(iop);
ARGUSED(report);
unsupported();
return -ENOSYS;
}
//----------------------------------------------------------------------------------------------

View File

@ -1,29 +1,16 @@
/*
* os_generic.h
* os_qnxnto.h
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) Joerg Hering
* Copyright (C) 2007 Joerg Hering
* Copyright (C) 2003-8 Bruce Allen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_QNXNTO_H_
#define OS_QNXNTO_H_
#define OS_QNXNTO_H_CVSID "$Id: os_qnxnto.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_QNXNTO_H_CVSID "$Id: os_qnxnto.h 4761 2018-08-20 19:33:04Z chrfranke $\n"
// Additional material should start here. Note: to keep the '-V' CVS
// reporting option working as intended, you should only #include

View File

@ -6,15 +6,7 @@
* Copyright (C) 2003-08 SAWADA Keiji
* Copyright (C) 2003-15 Casper Dik
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <stdlib.h>
@ -27,7 +19,7 @@
// These are needed to define prototypes for the functions defined below
#include "config.h"
#include "int64.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "utility.h"
@ -37,8 +29,8 @@
#define ARGUSED(x) ((void)(x))
const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp 4253 2016-03-26 19:47:47Z chrfranke $" \
ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_SOLARIS_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
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];
@ -70,9 +62,7 @@ int printwarning(int which){
// print examples for smartctl
void print_smartctl_examples(){
printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
#ifdef HAVE_GETOPT_LONG
printf(
printf("=================================================== SMARTCTL EXAMPLES =====\n\n"
" smartctl -a /dev/rdsk/c0t0d0s0 (Prints all SMART information)\n\n"
" smartctl --smart=on --offlineauto=on --saveauto=on /dev/rdsk/c0t0d0s0\n"
" (Enables SMART on first disk)\n\n"
@ -80,15 +70,6 @@ void print_smartctl_examples(){
" smartctl --attributes --log=selftest --quietmode=errorsonly /dev/rdsk/c0t0d0s0\n"
" (Prints Self-Test & Attribute errors)\n"
);
#else
printf(
" smartctl -a /dev/rdsk/c0t0d0s0 (Prints all SMART information)\n"
" smartctl -s on -o on -S on /dev/rdsk/c0t0d0s0 (Enables SMART on first disk)\n"
" smartctl -t long /dev/rdsk/c0t0d0s0 (Executes extended disk self-test)\n"
" smartctl -A -l selftest -q errorsonly /dev/rdsk/c0t0d0s0\n"
" (Prints Self-Test & Attribute errors)\n"
);
#endif
return;
}
@ -320,8 +301,8 @@ int ata_command_interface(int fd, smart_command_set command, int select, char *d
return smart_status_check(fd);
default:
pout("Unrecognized command %d in ata_command_interface() of os_solaris.c\n", command);
EXIT(1);
break;
errno = EINVAL;
return -1;
}
#else /* WITH_SOLARIS_SPARC_ATA */
ARGUSED(fd); ARGUSED(command); ARGUSED(select); ARGUSED(data);
@ -363,7 +344,7 @@ int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
pout(" Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex((char *)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
}
memset(&uscsi, 0, sizeof (uscsi));
@ -420,7 +401,7 @@ int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
iop->sensep[12], iop->sensep[13]);
if (report > 1) {
pout(" >>> Sense buffer, len=%d:\n", len);
dStrHex((const char *)iop->sensep, ((len > 252) ? 252 : len) , 1);
dStrHex(iop->sensep, ((len > 252) ? 252 : len) , 1);
}
} else if (iop->scsi_status)
pout(" status=%x\n", iop->scsi_status);
@ -432,7 +413,7 @@ int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
trunc = (len > 256) ? 1 : 0;
pout(" Incoming data, len=%d%s:\n", len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex((char *)iop->dxferp, (trunc ? 256 : len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : len) , 1);
}
}
}

View File

@ -6,26 +6,13 @@
* Copyright (C) 2003-8 SAWADA Keiji
* Copyright (C) 2003-8 Casper Dik
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_SOLARIS_H_
#define OS_SOLARIS_H_
#define OS_SOLARIS_H_CVSID "$Id: os_solaris.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define OS_SOLARIS_H_CVSID "$Id: os_solaris.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
// Additional material should start here. Note: to keep the '-V' CVS
// reporting option working as intended, you should only #include

View File

@ -3,7 +3,7 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2004-17 Christian Franke
* Copyright (C) 2004-18 Christian Franke
*
* Original AACRaid code:
* Copyright (C) 2015 Nidhi Malhotra <nidhi.malhotra@pmcs.com>
@ -11,32 +11,27 @@
* Original Areca code:
* Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#define WINVER 0x0502
#define _WIN32_WINNT WINVER
#include "int64.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "nvmecmds.h"
#include "utility.h"
#include "smartctl.h" // TODO: Do not use smartctl only variables here
#include "dev_interface.h"
#include "dev_ata_cmd_set.h"
#include "dev_areca.h"
#include "os_win32/wmiquery.h"
#include "os_win32/popen.h"
// TODO: Move from smartctl.h to other include file
extern unsigned char failuretest_permissive;
#include <errno.h>
@ -112,7 +107,7 @@
#define strnicmp strncasecmp
#endif
const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 4559 2017-10-22 16:17:50Z chrfranke $";
const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 4848 2018-12-05 18:30:46Z chrfranke $";
/////////////////////////////////////////////////////////////////////////////
// Windows I/O-controls, some declarations are missing in the include files
@ -553,7 +548,7 @@ static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX * ata_version
assert(num_out == sizeof(GETVERSIONINPARAMS));
if (ata_debugmode > 1) {
pout(" SMART_GET_VERSION suceeded, bytes returned: %u\n"
pout(" SMART_GET_VERSION succeeded, bytes returned: %u\n"
" Vers = %d.%d, Caps = 0x%x, DeviceMap = 0x%02x\n",
(unsigned)num_out, vers.bVersion, vers.bRevision,
(unsigned)vers.fCapabilities, vers.bIDEDeviceMap);
@ -647,7 +642,7 @@ static int smart_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned dat
}
if (ata_debugmode > 1) {
pout(" %s suceeded, bytes returned: %u (buffer %u)\n", name,
pout(" %s succeeded, bytes returned: %u (buffer %u)\n", name,
(unsigned)num_out, (unsigned)outpar->cBufferSize);
print_ide_regs_io(regs, (regs->bFeaturesReg == ATA_SMART_STATUS ?
(const IDEREGS *)(outpar->bBuffer) : NULL));
@ -736,7 +731,7 @@ static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, u
}
if (ata_debugmode > 1) {
pout(" IOCTL_IDE_PASS_THROUGH suceeded, bytes returned: %u (buffer %u)\n",
pout(" IOCTL_IDE_PASS_THROUGH succeeded, bytes returned: %u (buffer %u)\n",
(unsigned)num_out, (unsigned)buf->DataBufferSize);
print_ide_regs_io(regs, &buf->IdeReg);
}
@ -777,7 +772,7 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev
//ab.apt.PathId = 0;
//ab.apt.TargetId = 0;
//ab.apt.Lun = 0;
ab.apt.TimeOutValue = 10;
ab.apt.TimeOutValue = 60; // seconds
unsigned size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf);
ab.apt.DataBufferOffset = size;
@ -853,7 +848,7 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev
}
if (ata_debugmode > 1) {
pout(" IOCTL_ATA_PASS_THROUGH suceeded, bytes returned: %u\n", (unsigned)num_out);
pout(" IOCTL_ATA_PASS_THROUGH succeeded, bytes returned: %u\n", (unsigned)num_out);
print_ide_regs_io(regs, ctfregs);
}
*regs = *ctfregs;
@ -984,7 +979,7 @@ static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS * regs, cha
}
if (ata_debugmode > 1) {
pout(" IOCTL_SCSI_MINIPORT_%s suceeded, bytes returned: %u (buffer %u)\n", name,
pout(" IOCTL_SCSI_MINIPORT_%s succeeded, bytes returned: %u (buffer %u)\n", name,
(unsigned)num_out, (unsigned)sb.params.out.cBufferSize);
print_ide_regs_io(regs, (code == IOCTL_SCSI_MINIPORT_RETURN_STATUS ?
(const IDEREGS *)(sb.params.out.bBuffer) : 0));
@ -1051,7 +1046,7 @@ static int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS * regs, char * d
memcpy(data, sb.buffer, datasize);
if (ata_debugmode > 1) {
pout(" ATA via IOCTL_SCSI_MINIPORT suceeded, bytes returned: %u\n", (unsigned)num_out);
pout(" ATA via IOCTL_SCSI_MINIPORT succeeded, bytes returned: %u\n", (unsigned)num_out);
print_ide_regs_io(regs, &sb.regs);
}
*regs = sb.regs;
@ -1092,7 +1087,7 @@ static int update_3ware_devicemap_ioctl(HANDLE hdevice)
return -1;
}
if (ata_debugmode > 1)
pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT suceeded\n");
pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT succeeded\n");
return 0;
}
@ -1143,7 +1138,7 @@ static int storage_query_property_ioctl(HANDLE hdevice, STORAGE_DEVICE_DESCRIPTO
// IOCTL_STORAGE_PREDICT_FAILURE
// Call IOCTL_STORAGE_PREDICT_FAILURE, return PredictFailure value
// or -1 on error, opionally return VendorSpecific data.
// or -1 on error, optionally return VendorSpecific data.
// (This works without admin rights)
static int storage_predict_failure_ioctl(HANDLE hdevice, char * data = 0)
@ -1307,7 +1302,7 @@ static bool get_usb_id(int phydrive, int logdrive,
std::string prev_usb_ant;
std::string prev_ant, ant, dep;
const regular_expression regex("^.*PnPEntity\\.DeviceID=\"([^\"]*)\"", REG_EXTENDED);
const regular_expression regex("^.*PnPEntity\\.DeviceID=\"([^\"]*)\"");
while (we.next(wo)) {
prev_ant = ant;
@ -1319,7 +1314,7 @@ static bool get_usb_id(int phydrive, int logdrive,
pout(" %s:\n", ant.c_str());
// Extract DeviceID
regmatch_t match[2];
regular_expression::match_range match[2];
if (!(regex.execute(dep.c_str(), 2, match) && match[1].rm_so >= 0)) {
if (debug)
pout(" | (\"%s\")\n", dep.c_str());
@ -1600,7 +1595,7 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
// 3ware RAID if vendor id present
m_is_3ware = (vers_ex.wIdentifier == SMART_VENDOR_3WARE);
unsigned long portmap = 0;
unsigned portmap = 0;
if (port >= 0 && devmap >= 0) {
// 3ware RAID: check vendor id
if (!m_is_3ware) {
@ -1623,14 +1618,13 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
{
// 3ware RAID: update devicemap first
if (!update_3ware_devicemap_ioctl(h)) {
if ( smart_get_version(h, &vers_ex) >= 0
&& vers_ex.wIdentifier == SMART_VENDOR_3WARE )
portmap = vers_ex.dwDeviceMapEx;
}
// Check port existence
if (!(portmap & (1L << port))) {
if (!(portmap & (1U << port))) {
if (!is_permissive()) {
close();
return set_err(ENOENT, "%s: Port %d is empty or does not exist", devpath, port);
@ -2065,13 +2059,14 @@ int csmi_device::get_phy_info(CSMI_SAS_PHY_INFO & phy_info, port_2_index_map & p
}
// Create port -> index map
// IRST Release
// Phy[i].Value 9.x 10.4 14.8 15.2
// ---------------------------------------------------
// bPortIdentifier 0xff 0xff port 0x00
// Identify.bPhyIdentifier port port port port
// Attached.bPhyIdentifier 0x00 0x00 0x00 port
// Empty ports in Phy[]? no ? yes yes
// IRST Release
// Phy[i].Value 9.x 10.x 14.8 15.2 16.0
// ----------------------------------------------------------
// bPortIdentifier 0xff 0xff port 0x00 port
// Identify.bPhyIdentifier index? index? index index port
// Attached.bPhyIdentifier 0x00 0x00 0x00 index 0x00
//
// Empty ports with hotplug support may appear in Phy[].
int number_of_ports;
for (int mode = 0; ; mode++) {
@ -2079,14 +2074,15 @@ int csmi_device::get_phy_info(CSMI_SAS_PHY_INFO & phy_info, port_2_index_map & p
p2i[i] = -1;
number_of_ports = 0;
bool unique = true;
bool found = false;
for (int i = 0; i < max_number_of_ports; i++) {
const CSMI_SAS_PHY_ENTITY & pe = phy_info.Phy[i];
if (pe.Identify.bDeviceType == CSMI_SAS_NO_DEVICE_ATTACHED)
continue;
// Use a bPhyIdentifier or the bPortIdentifier if unique,
// otherwise use table index
// Try to detect which field contains the actual port number.
// Use a bPhyIdentifier or the bPortIdentifier if unique
// and not always identical to table index, otherwise use index.
int port;
switch (mode) {
case 0: port = pe.Attached.bPhyIdentifier; break;
@ -2095,16 +2091,18 @@ int csmi_device::get_phy_info(CSMI_SAS_PHY_INFO & phy_info, port_2_index_map & p
default: port = i; break;
}
if (!(port < max_number_of_ports && p2i[port] == -1)) {
unique = false;
found = false;
break;
}
p2i[port] = i;
if (number_of_ports <= port)
number_of_ports = port + 1;
if (port != i)
found = true;
}
if (unique || mode > 2)
if (found || mode > 2)
break;
}
@ -2164,7 +2162,7 @@ unsigned csmi_device::get_ports_used()
continue;
}
ports_used |= (1 << p);
ports_used |= (1U << p);
}
return ports_used;
@ -2558,63 +2556,6 @@ static int get_clipboard(char * data, int datasize)
}
// Run a command, write stdout to dataout
// TODO: Combine with daemon_win32.cpp:daemon_spawn()
static int run_cmd(const char * cmd, char * dataout, int outsize)
{
// Create stdout pipe
SECURITY_ATTRIBUTES sa = {sizeof(sa), 0, TRUE};
HANDLE pipe_out_w, h;
if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize))
return -1;
HANDLE self = GetCurrentProcess();
HANDLE pipe_out_r;
if (!DuplicateHandle(self, h, self, &pipe_out_r,
GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
CloseHandle(pipe_out_w);
return -1;
}
HANDLE pipe_err_w;
if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
return -1;
}
// Create process
STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
si.hStdInput = INVALID_HANDLE_VALUE;
si.hStdOutput = pipe_out_w; si.hStdError = pipe_err_w;
si.dwFlags = STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
if (!CreateProcess(
NULL, const_cast<char *>(cmd),
NULL, NULL, TRUE/*inherit*/,
CREATE_NO_WINDOW/*do not create a new console window*/,
NULL, NULL, &si, &pi)) {
CloseHandle(pipe_err_w); CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
return -1;
}
CloseHandle(pi.hThread);
CloseHandle(pipe_err_w); CloseHandle(pipe_out_w);
// Copy stdout to output buffer
int i = 0;
while (i < outsize) {
DWORD num_read;
if (!ReadFile(pipe_out_r, dataout+i, outsize-i, &num_read, NULL) || num_read == 0)
break;
i += num_read;
}
CloseHandle(pipe_out_r);
// Wait for process
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
return i;
}
static const char * findstr(const char * str, const char * sub)
{
const char * s = strstr(str, sub);
@ -2641,7 +2582,11 @@ bool win_tw_cli_device::open()
snprintf(cmd, sizeof(cmd), "tw_cli /%s show all", name+n1);
if (ata_debugmode > 1)
pout("%s: Run: \"%s\"\n", name, cmd);
size = run_cmd(cmd, buffer, sizeof(buffer));
FILE * f = popen(cmd, "rb");
if (f) {
size = fread(buffer, 1, sizeof(buffer), f);
pclose(f);
}
}
else {
return set_err(EINVAL);
@ -3495,8 +3440,7 @@ bool win_aacraid_device::scsi_pass_through(struct scsi_cmnd_io *iop)
j += 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((const char *)iop->dxferp,
(trunc ? 256 : (int)iop->dxfer_len) , 1);
dStrHex(iop->dxferp, (trunc ? 256 : (int)iop->dxfer_len) , 1);
}
else
j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
@ -3601,7 +3545,7 @@ bool win_aacraid_device::scsi_pass_through(struct scsi_cmnd_io *iop)
int trunc = (iop->dxfer_len > 256) ? 1 : 0;
pout(" Incoming data, len=%d, resid=%d%s:\n", (int)iop->dxfer_len, iop->resid,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex((CHAR*)pDataIO, (trunc ? 256 : (int)(iop->dxfer_len)) , 1);
dStrHex((const uint8_t *)pDataIO, (trunc ? 256 : (int)(iop->dxfer_len)) , 1);
}
return true;
}
@ -3671,7 +3615,12 @@ bool win_nvme_device::open_scsi(int n)
return true;
}
// Check if NVMe pass-through works
// Check if NVMe DeviceIoControl(IOCTL_SCSI_MINIPORT) pass-through works.
// On Win10 and later that returns false with an errorNumber of 1
// ("Incorrect function"). Win10 has new pass-through:
// DeviceIoControl(IOCTL_STORAGE_PROTOCOL_COMMAND). However for commonly
// requested NVMe commands like Identify and Get Features Microsoft want
// "Protocol specific queries" sent.
bool win_nvme_device::probe()
{
smartmontools::nvme_id_ctrl id_ctrl;
@ -3897,7 +3846,7 @@ bool win10_nvme_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out &
STORAGE_PROTOCOL_SPECIFIC_QUERY_WITH_BUFFER * spsq =
reinterpret_cast<STORAGE_PROTOCOL_SPECIFIC_QUERY_WITH_BUFFER *>(spsq_raw_buf.data());
// Set NVMe specifc STORAGE_PROPERTY_QUERY
// Set NVMe specific STORAGE_PROPERTY_QUERY
spsq->PropertyQuery.QueryType = PropertyStandardQuery;
spsq->ProtocolSpecific.ProtocolType = win10::ProtocolTypeNvme;
@ -3997,7 +3946,7 @@ protected:
virtual std::string get_valid_custom_dev_types_str();
private:
ata_device * get_usb_device(const char * name, int phydrive, int logdrive = -1);
smart_device * get_usb_device(const char * name, int phydrive, int logdrive = -1);
};
@ -4031,10 +3980,7 @@ std::string win_smart_interface::get_os_version_str()
assert(vptr == vstr+strlen(vstr) && vptr+vlen+1 == vstr+sizeof(vstr));
// Starting with Windows 8.1, GetVersionEx() does no longer report the
// actual OS version, see:
// http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
// RtlGetVersion() is not affected
// actual OS version. RtlGetVersion() is not affected.
LONG /*NTSTATUS*/ (WINAPI /*NTAPI*/ * RtlGetVersion_p)(LPOSVERSIONINFOEXW) =
(LONG (WINAPI *)(LPOSVERSIONINFOEXW))
GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion");
@ -4074,12 +4020,21 @@ std::string win_smart_interface::get_os_version_str()
case 14393: w = "w10-1607"; break;
case 15063: w = "w10-1703"; break;
case 16299: w = "w10-1709"; break;
default: w = "w10"; build = vi.dwBuildNumber; break;
case 17134: w = "w10-1803"; break;
case 17763: w = "w10-1809"; break;
default: w = "w10";
build = vi.dwBuildNumber; break;
} break;
case 0xa0<<1 | 1:
switch (vi.dwBuildNumber) {
case 14393: w = "2016-1607"; break;
default: w = "2016"; build = vi.dwBuildNumber; break;
case 14393: w = "2016"; break;
case 16299: w = "2016-1709"; break;
case 17134: w = "2016-1803"; break;
case 17763: w = "2019"; break;
default: w = (vi.dwBuildNumber < 17763
? "2016"
: "2019");
build = vi.dwBuildNumber; break;
} break;
}
}
@ -4095,11 +4050,11 @@ std::string win_smart_interface::get_os_version_str()
(vi.dwPlatformId==VER_PLATFORM_WIN32_NT ? "nt" : "??"),
(unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
else if (build)
snprintf(vptr, vlen, "-%s%s-b%u", w, w64, build);
snprintf(vptr, vlen, "-%s-b%u%s", w, build, w64);
else if (vi.wServicePackMinor)
snprintf(vptr, vlen, "-%s%s-sp%u.%u", w, w64, vi.wServicePackMajor, vi.wServicePackMinor);
snprintf(vptr, vlen, "-%s-sp%u.%u%s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);
else if (vi.wServicePackMajor)
snprintf(vptr, vlen, "-%s%s-sp%u", w, w64, vi.wServicePackMajor);
snprintf(vptr, vlen, "-%s-sp%u%s", w, vi.wServicePackMajor, w64);
else
snprintf(vptr, vlen, "-%s%s", w, w64);
return vstr;
@ -4326,9 +4281,12 @@ static win_dev_type get_controller_type(HANDLE hdevice, bool admin, GETVERSIONIN
case BusTypeUsb:
return DEV_USB;
case 0x11: // BusTypeNVMe?
case 0x11: // BusTypeNvme
return DEV_NVME;
case 0x12: //BusTypeSCM
case 0x13: //BusTypeUfs
case 0x14: //BusTypeMax,
default:
return DEV_UNKNOWN;
}
@ -4407,7 +4365,7 @@ static win_dev_type get_dev_type(const char * name, int & phydrive, int & logdri
}
ata_device * win_smart_interface::get_usb_device(const char * name,
smart_device * win_smart_interface::get_usb_device(const char * name,
int phydrive, int logdrive /* = -1 */)
{
// Get USB bridge ID
@ -4423,7 +4381,7 @@ ata_device * win_smart_interface::get_usb_device(const char * name,
return 0;
// Return SAT/USB device for this type
return get_sat_device(usbtype, new win_scsi_device(this, name, ""));
return get_scsi_passthrough_device(usbtype, new win_scsi_device(this, name, ""));
}
smart_device * win_smart_interface::autodetect_smart_device(const char * name)
@ -4520,7 +4478,7 @@ bool win_smart_interface::scan_smart_devices(smart_device_list & devlist,
}
}
char name[20];
char name[32];
if (ata || scsi || sat || usb || nvme) {
// Scan up to 128 drives and 2 3ware controllers
@ -4555,7 +4513,7 @@ bool win_smart_interface::scan_smart_devices(smart_device_list & devlist,
// Add physical drives
int len = strlen(name);
for (unsigned int pi = 0; pi < 32; pi++) {
if (vers_ex.dwDeviceMapEx & (1L << pi)) {
if (vers_ex.dwDeviceMapEx & (1U << pi)) {
snprintf(name+len, sizeof(name)-1-len, ",%u", pi);
devlist.push_back( new win_ata_device(this, name, "ata") );
}
@ -4619,7 +4577,7 @@ bool win_smart_interface::scan_smart_devices(smart_device_list & devlist,
continue;
for (int pi = 0; pi < 32; pi++) {
if (!(ports_used & (1 << pi)))
if (!(ports_used & (1U << pi)))
continue;
snprintf(name, sizeof(name)-1, "/dev/csmi%d,%d", i, pi);
devlist.push_back( new win_csmi_device(this, name, "ata") );

View File

@ -3,16 +3,9 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2004-14 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2004-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#define WINVER 0x0600
@ -20,7 +13,7 @@
#include "daemon_win32.h"
const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
DAEMON_WIN32_H_CVSID;
#include <stdio.h>
@ -464,120 +457,6 @@ int daemon_detach(const char * ident)
}
/////////////////////////////////////////////////////////////////////////////
// Spawn a command and redirect <inpbuf >outbuf
// return command's exitcode or -1 on error
int daemon_spawn(const char * cmd,
const char * inpbuf, int inpsize,
char * outbuf, int outsize )
{
HANDLE self = GetCurrentProcess();
// Create stdin pipe with inheritable read side
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
HANDLE pipe_inp_r, pipe_inp_w, h;
if (!CreatePipe(&pipe_inp_r, &h, &sa/*inherit*/, inpsize*2+13))
return -1;
if (!DuplicateHandle(self, h, self, &pipe_inp_w,
0, FALSE/*!inherit*/, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
CloseHandle(pipe_inp_r);
return -1;
}
// Create stdout pipe with inheritable write side
memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
HANDLE pipe_out_w;
if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) {
CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
return -1;
}
HANDLE pipe_out_r;
if (!DuplicateHandle(self, h, self, &pipe_out_r,
GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
CloseHandle(pipe_out_w); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
return -1;
}
// Create stderr handle as dup of stdout write side
HANDLE pipe_err_w;
if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
return -1;
}
// Create process with pipes as stdio
STARTUPINFO si;
memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
si.hStdInput = pipe_inp_r;
si.hStdOutput = pipe_out_w;
si.hStdError = pipe_err_w;
si.dwFlags = STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
if (!CreateProcessA(
NULL, (char*)cmd,
NULL, NULL, TRUE/*inherit*/,
CREATE_NO_WINDOW, // DETACHED_PROCESS does not work
NULL, NULL, &si, &pi)) {
CloseHandle(pipe_err_w);
CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
return -1;
}
CloseHandle(pi.hThread);
// Close inherited handles
CloseHandle(pipe_inp_r);
CloseHandle(pipe_out_w);
CloseHandle(pipe_err_w);
// Copy inpbuf to stdin
// convert \n => \r\n
DWORD num_io;
int i;
for (i = 0; i < inpsize; ) {
int len = 0;
while (i+len < inpsize && inpbuf[i+len] != '\n')
len++;
if (len > 0)
WriteFile(pipe_inp_w, inpbuf+i, len, &num_io, NULL);
i += len;
if (i < inpsize) {
WriteFile(pipe_inp_w, "\r\n", 2, &num_io, NULL);
i++;
}
}
CloseHandle(pipe_inp_w);
// Copy stdout to output buffer until full, rest to /dev/null
// convert \r\n => \n
for (i = 0; ; ) {
char buf[256];
if (!ReadFile(pipe_out_r, buf, sizeof(buf), &num_io, NULL) || num_io == 0)
break;
for (int j = 0; i < outsize-1 && j < (int)num_io; j++) {
if (buf[j] != '\r')
outbuf[i++] = buf[j];
}
}
outbuf[i] = 0;
CloseHandle(pipe_out_r);
// Wait for process exitcode
DWORD exitcode = 42;
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &exitcode);
CloseHandle(pi.hProcess);
return exitcode;
}
/////////////////////////////////////////////////////////////////////////////
// Initd Functions
@ -985,7 +864,7 @@ static int svcadm_main(const char * ident, const daemon_winsvc_options * svc_opt
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
NULL/*no load ordering*/, NULL/*no tag id*/,
""/*no depedencies*/, NULL/*local system account*/, NULL/*no pw*/))) {
""/*no dependencies*/, NULL/*local system account*/, NULL/*no pw*/))) {
if ((err = GetLastError()) == ERROR_SERVICE_EXISTS)
puts(" the service is already installed");
else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)

View File

@ -3,22 +3,15 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2004-12 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2004-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DAEMON_WIN32_H
#define DAEMON_WIN32_H
#define DAEMON_WIN32_H_CVSID "$Id: daemon_win32.h 4431 2017-08-08 19:38:15Z chrfranke $"
#define DAEMON_WIN32_H_CVSID "$Id: daemon_win32.h 4818 2018-10-17 05:32:17Z chrfranke $"
#include <signal.h>
@ -59,9 +52,4 @@ int daemon_enable_console(const char * title);
// Detach from console
int daemon_detach(const char * ident);
// Spawn a process and redirect stdio
int daemon_spawn(const char * cmd,
const char * inpbuf, int inpsize,
char * outbuf, int outsize );
#endif // DAEMON_WIN32_H

View File

@ -5,15 +5,9 @@
;
; Copyright (C) 2006-17 Christian Franke
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
; SPDX-License-Identifier: GPL-2.0-or-later
;
; You should have received a copy of the GNU General Public License
; (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
;
; $Id: installer.nsi 4575 2017-10-29 16:06:18Z chrfranke $
; $Id: installer.nsi 4760 2018-08-19 18:45:53Z chrfranke $
;
@ -47,6 +41,19 @@ InstallColors /windows
;InstallDir "$PROGRAMFILES\smartmontools"
;InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation"
!ifdef VERSION
VIProductVersion "${VERSION}"
VIAddVersionKey /LANG=1033-English "CompanyName" "www.smartmontools.org"
VIAddVersionKey /LANG=1033-English "FileDescription" "SMART Monitoring Tools"
VIAddVersionKey /LANG=1033-English "FileVersion" "${VERSION}"
!ifdef YY
VIAddVersionKey /LANG=1033-English "LegalCopyright" "(C) 2002-20${YY}, Bruce Allen, Christian Franke, www.smartmontools.org"
!endif
VIAddVersionKey /LANG=1033-English "OriginalFilename" "${OUTFILE}"
VIAddVersionKey /LANG=1033-English "ProductName" "smartmontools"
VIAddVersionKey /LANG=1033-English "ProductVersion" "${VERSION}"
!endif
Var EDITOR
!ifdef INPDIR64
@ -229,18 +236,16 @@ Section "Uninstaller" UNINST_SECTION
CreateDirectory "$INSTDIR"
; Keep old Install_Dir registry entry for GSmartControl
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GSmartControl" "InstallLocation"
ReadRegStr $1 HKLM "Software\smartmontools" "Install_Dir"
${If} "$0$1" != ""
WriteRegStr HKLM "Software\smartmontools" "Install_Dir" "$INSTDIR"
${EndIf}
; Remove old "Install_Dir" registry entry (smartmontools < r3911/6.3)
; No longer needed for GSmartControl
DeleteRegKey HKLM "Software\smartmontools" ; TODO: Remove after smartmontools 6.7
; Write uninstall keys and program
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "DisplayName" "smartmontools"
!ifdef VERSTR
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "DisplayVersion" "${VERSTR}"
!endif
; Important: GSmartControl (>= 1.0.0) reads "InstallLocation" to detect location of bin\smartctl-nc.exe
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation" "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "UninstallString" '"$INSTDIR\uninst-smartmontools.exe"'
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "Publisher" "smartmontools.org"
@ -272,7 +277,6 @@ Section "Start Menu Shortcuts" MENU_SECTION
${OrIf} ${FileExists} "$INSTDIR\bin\smartd.exe"
SetOutPath "$INSTDIR\bin"
!insertmacro FileExe "bin\runcmdu.exe" ""
Delete "$INSTDIR\bin\runcmdu.exe.manifest" ; TODO: Remove after smartmontools 6.5
${EndIf}
; smartctl
@ -419,9 +423,8 @@ Section "Uninstall"
${EndIf}
${EndIf}
; Remove installer registry keys
; Remove installer registry key
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools"
DeleteRegKey HKLM "Software\smartmontools"
; Remove conf file ?
${If} ${FileExists} "$INSTDIR\bin\smartd.conf"
@ -464,9 +467,7 @@ Section "Uninstall"
Delete "$INSTDIR\bin\drivedb.h.old"
Delete "$INSTDIR\bin\update-smart-drivedb.exe"
Delete "$INSTDIR\bin\runcmda.exe"
Delete "$INSTDIR\bin\runcmda.exe.manifest" ; TODO: Remove after smartmontools 6.5
Delete "$INSTDIR\bin\runcmdu.exe"
Delete "$INSTDIR\bin\runcmdu.exe.manifest" ; TODO: Remove after smartmontools 6.5
Delete "$INSTDIR\bin\wtssendmsg.exe"
Delete "$INSTDIR\doc\AUTHORS.txt"
Delete "$INSTDIR\doc\ChangeLog.txt"
@ -540,14 +541,11 @@ Function .onInit
${If} $INSTDIR == "" ; /D=PATH option not specified ?
ReadRegStr $INSTDIR HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation"
${If} $INSTDIR == "" ; Not already installed ?
ReadRegStr $INSTDIR HKLM "Software\smartmontools" "Install_Dir"
${If} $INSTDIR == "" ; Not already installed (smartmontools < r3911/6.3) ?
StrCpy $INSTDIR "$PROGRAMFILES\smartmontools"
StrCpy $INSTDIR "$PROGRAMFILES\smartmontools"
!ifdef INPDIR64
StrCpy $INSTDIR32 $INSTDIR
StrCpy $INSTDIR64 "$PROGRAMFILES64\smartmontools"
StrCpy $INSTDIR32 $INSTDIR
StrCpy $INSTDIR64 "$PROGRAMFILES64\smartmontools"
!endif
${EndIf}
${EndIf}
${EndIf}
@ -569,10 +567,13 @@ Function .onInit
!insertmacro AdjustSectionSize ${SMARTCTL_NC_SECTION}
!endif
; Use Notepad++ if installed
; Use 32-bit or 64-bit Notepad++ if installed
StrCpy $EDITOR "$PROGRAMFILES\Notepad++\notepad++.exe"
${IfNot} ${FileExists} "$EDITOR"
StrCpy $EDITOR "notepad.exe"
StrCpy $EDITOR "$PROGRAMFILES64\Notepad++\notepad++.exe"
${IfNot} ${FileExists} "$EDITOR"
StrCpy $EDITOR "notepad.exe"
${EndIf}
${EndIf}
Call ParseCmdLine
@ -685,7 +686,6 @@ Function CheckRunCmdA
StrCpy $runcmda "t"
SetOutPath "$INSTDIR\bin"
!insertmacro FileExe "bin\runcmda.exe" ""
Delete "$INSTDIR\bin\runcmda.exe.manifest" ; TODO: Remove after smartmontools 6.5
${EndIf}
FunctionEnd

55
os_win32/popen.h Normal file
View File

@ -0,0 +1,55 @@
/*
* os_win32/popen.h
*
* Home page of code is: https://www.smartmontools.org
*
* Copyright (C) 2018 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef POPEN_H
#define POPEN_H
#define POPEN_H_CVSID "$Id: popen.h 4818 2018-10-17 05:32:17Z chrfranke $"
#include <stdio.h>
// MinGW <stdio.h> defines these to _popen/_pclose
#undef popen
#undef pclose
#ifdef __cplusplus
extern "C" {
#endif
// popen(3) reimplementation for Windows
//
// The _popen() from MSVCRT is not useful as it always opens a new
// console window if parent process has none.
//
// Differences to popen(3):
// - Only modes "r[bt]" are supported
// - stdin and stderr from parent are not inherited to child process
// but redirected to null device
// - Only one child process can be run at a time
FILE * popen(const char * command, const char * mode);
int pclose(FILE * f);
#ifdef __cplusplus
}
#endif
// wait(3) macros from <sys/wait.h>
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0x00)
#define WIFSIGNALED(status) (((status) & 0xff) != 0x00)
#define WIFSTOPPED(status) (0)
#define WEXITSTATUS(status) ((status) >> 8)
#define WTERMSIG(status) ((status) & 0xff)
#define WSTOPSIG(status) (0)
#endif // WIFEXITED
#endif // POPEN_H

176
os_win32/popen_win32.cpp Normal file
View File

@ -0,0 +1,176 @@
/*
* os_win32/popen_win32.cpp
*
* Home page of code is: https://www.smartmontools.org
*
* Copyright (C) 2018 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 $"
POPEN_H_CVSID;
#include <errno.h>
#include <fcntl.h>
#include <io.h> // _open_osfhandle()
#include <signal.h> // SIGSEGV
#include <stdlib.h>
#include <string.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static FILE * s_popen_file;
static HANDLE s_popen_process;
extern "C"
FILE * popen(const char * command, const char * mode)
{
// Fail if previous run is still in progress
if (s_popen_file) {
errno = EEXIST;
return (FILE *)0;
}
// mode "w" is not implemented
if (!(mode[0] == 'r' && (!mode[1] || !mode[2]))) {
errno = EINVAL;
return (FILE *)0;
}
// Set flags for text or binary mode
// Note: _open_osfhandle() ignores _fmode and defaults to O_BINARY
int oflags; const char * fomode;
switch (mode[1]) {
case 0:
case 't':
oflags = O_RDONLY|O_TEXT;
fomode = "rt";
break;
case 'b':
oflags = O_RDONLY|O_BINARY;
fomode = "rb";
break;
default:
errno = EINVAL;
return (FILE *)0;
}
// Create stdout pipe with inheritable write end
HANDLE pipe_out_r, pipe_out_w;
if (!CreatePipe(&pipe_out_r, &pipe_out_w, (SECURITY_ATTRIBUTES *)0, 1024)) {
errno = EMFILE;
return (FILE *)0;
}
if (!SetHandleInformation(pipe_out_w, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
errno = EMFILE;
return (FILE *)0;
}
// Connect pipe read end to new FD
int fd = _open_osfhandle((intptr_t)pipe_out_r, oflags);
if (fd < 0) {
CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
return (FILE *)0;
}
// Connect FD to new FILE
FILE * f = fdopen(fd, fomode);
if (!f) {
int err = errno;
close(fd); // CloseHandle(pipe_out_r)
CloseHandle(pipe_out_w);
errno = err;
return (FILE *)0;
}
// Build command line "cmd /c COMMAND"
int cmdlen = strlen(command);
char * shellcmd = (char *)malloc(7 + cmdlen + 1);
if (!shellcmd) {
fclose(f); // CloseHandle(pipe_out_r)
CloseHandle(pipe_out_w);
errno = ENOMEM;
return (FILE *)0;
}
memcpy(shellcmd, "cmd /c ", 7);
memcpy(shellcmd + 7, command, cmdlen + 1);
// 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);
// Set stdio handles
STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
si.hStdInput = null_in;
si.hStdOutput = pipe_out_w;
si.hStdError = null_err;
si.dwFlags = STARTF_USESTDHANDLES;
// 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
);
free(shellcmd);
// Close inherited handles
CloseHandle(null_err);
CloseHandle(null_in);
CloseHandle(pipe_out_w);
if (!ok) {
fclose(f); // CloseHandle(pipe_out_r)
errno = ENOENT;
return (FILE *)0;
}
// Store process and FILE for pclose()
CloseHandle(pi.hThread);
s_popen_process = pi.hProcess;
s_popen_file = f;
return f;
}
extern "C"
int pclose(FILE * f)
{
if (f != s_popen_file) {
errno = EBADF;
return -1;
}
fclose(f);
s_popen_file = 0;
// Wait for process exitcode
DWORD exitcode = 42;
bool ok = ( WaitForSingleObject(s_popen_process, INFINITE) == WAIT_OBJECT_0
&& GetExitCodeProcess(s_popen_process, &exitcode));
CloseHandle(s_popen_process);
s_popen_process = 0;
if (!ok) {
errno = ECHILD;
return -1;
}
// Modify exitcode for wait(3) macros
if (exitcode >> 23)
return ((exitcode << 9) >> 1) | SIGSEGV;
else
return exitcode << 8;
}

View File

@ -5,17 +5,10 @@
*
* Copyright (C) 2011 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
char svnid[] = "$Id: runcmd.c 4431 2017-08-08 19:38:15Z chrfranke $";
char svnid[] = "$Id: runcmd.c 4760 2018-08-19 18:45:53Z chrfranke $";
#include <stdio.h>
#include <windows.h>

View File

@ -5,15 +5,9 @@
#
# Copyright (C) 2016 Christian Franke
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# SPDX-License-Identifier: GPL-2.0-or-later
#
# You should have received a copy of the GNU General Public License
# (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
#
# $Id: smartd_mailer.ps1 4338 2016-09-07 19:31:28Z chrfranke $
# $Id: smartd_mailer.ps1 4760 2018-08-19 18:45:53Z chrfranke $
#
$ErrorActionPreference = "Stop"

View File

@ -6,15 +6,9 @@
::
:: Copyright (C) 2012-17 Christian Franke
::
:: This program is free software; you can redistribute it and/or modify
:: it under the terms of the GNU General Public License as published by
:: the Free Software Foundation; either version 2, or (at your option)
:: any later version.
:: SPDX-License-Identifier: GPL-2.0-or-later
::
:: You should have received a copy of the GNU General Public License
:: (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
::
:: $Id: smartd_warning.cmd 4569 2017-10-25 20:13:11Z chrfranke $
:: $Id: smartd_warning.cmd 4760 2018-08-19 18:45:53Z chrfranke $
::
verify other 2>nul

View File

@ -5,21 +5,13 @@
*
* Copyright (C) 2004-8 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef SYSLOG_H
#define SYSLOG_H
#define SYSLOG_H_CVSID "$Id: syslog.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define SYSLOG_H_CVSID "$Id: syslog.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
#include <stdarg.h>

View File

@ -5,14 +5,7 @@
*
* Copyright (C) 2004-15 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
// Win32 Emulation of syslog() for smartd
@ -33,7 +26,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // RegisterEventSourceA(), ReportEventA(), ...
const char *syslog_win32_cpp_cvsid = "$Id: syslog_win32.cpp 4149 2015-10-17 15:38:01Z chrfranke $"
const char *syslog_win32_cpp_cvsid = "$Id: syslog_win32.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
SYSLOG_H_CVSID;
#ifdef _MSC_VER

View File

@ -5,18 +5,10 @@
; *
; * Copyright (C) 2004-10 Christian Franke
; *
; * This program is free software; you can redistribute it and/or modify
; * it under the terms of the GNU General Public License as published by
; * the Free Software Foundation; either version 2, or (at your option)
; * any later version.
; *
; * You should have received a copy of the GNU General Public License
; * (for example COPYING); if not, write to the Free Software Foundation,
; * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; *
; * SPDX-License-Identifier: GPL-2.0-or-later
; */
;
;// $Id: syslogevt.mc 4431 2017-08-08 19:38:15Z chrfranke $
;// $Id: syslogevt.mc 4760 2018-08-19 18:45:53Z chrfranke $
;
;// Use message compiler "mc" or "windmc" to generate
;// syslogevt.rc, syslogevt.h, msg00001.bin

View File

@ -5,15 +5,9 @@
;
; Copyright (C) 2011-13 Christian Franke
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
; SPDX-License-Identifier: GPL-2.0-or-later
;
; You should have received a copy of the GNU General Public License
; (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
;
; $Id: update-smart-drivedb.nsi 4431 2017-08-08 19:38:15Z chrfranke $
; $Id: update-smart-drivedb.nsi 4760 2018-08-19 18:45:53Z chrfranke $
;

View File

@ -5,14 +5,7 @@
*
* Copyright (C) 2011-13 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
@ -23,7 +16,7 @@
#include <stdio.h>
const char * wmiquery_cpp_cvsid = "$Id: wmiquery.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
const char * wmiquery_cpp_cvsid = "$Id: wmiquery.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
WMIQUERY_H_CVSID;

View File

@ -3,28 +3,17 @@
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2011-15 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) 2011-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef WMIQUERY_H
#define WMIQUERY_H
#define WMIQUERY_H_CVSID "$Id: wmiquery.h 4152 2015-10-17 16:08:21Z chrfranke $"
#define WMIQUERY_H_CVSID "$Id: wmiquery.h 4760 2018-08-19 18:45:53Z chrfranke $"
#ifdef HAVE_WBEMCLI_H
#include <wbemcli.h>
#else
#include "wbemcli_small.h"
#endif
#include <string>
@ -168,11 +157,13 @@ public:
/// Execute query, get result list.
/// Return false on error.
bool vquery(wbem_enumerator & result, const char * qstr, va_list args) /*const*/;
bool vquery(wbem_enumerator & result, const char * qstr, va_list args) /*const*/
__attribute_format_printf(3, 0);
/// Execute query, get single result object.
/// Return false on error or result size != 1.
bool vquery1(wbem_object & obj, const char * qstr, va_list args) /*const*/;
bool vquery1(wbem_object & obj, const char * qstr, va_list args) /*const*/
__attribute_format_printf(3, 0);
/// Version of vquery() with printf() formatting.
bool query(wbem_enumerator & result, const char * qstr, ...) /*const*/

View File

@ -5,20 +5,13 @@
*
* Copyright (C) 2012 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#define WINVER 0x0500
#define _WIN32_WINNT WINVER
char svnid[] = "$Id: wtssendmsg.c 4431 2017-08-08 19:38:15Z chrfranke $";
char svnid[] = "$Id: wtssendmsg.c 4760 2018-08-19 18:45:53Z chrfranke $";
#include <stdio.h>
#include <string.h>
@ -30,7 +23,7 @@ char svnid[] = "$Id: wtssendmsg.c 4431 2017-08-08 19:38:15Z chrfranke $";
static int usage()
{
printf("wtssendmsg $Revision: 4431 $ - Display a message box on client desktops\n"
printf("wtssendmsg $Revision: 4760 $ - Display a message box on client desktops\n"
"Copyright (C) 2012 Christian Franke, smartmontools.org\n\n"
"Usage: wtssendmsg [-cas] [-v] [\"Caption\"] \"Message\"|-\n"
" wtssendmsg -v\n\n"

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 2002-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@ -14,36 +14,56 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA. */
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if !defined(_LIBC) && !defined(_REGEX_STANDALONE)
# include <config.h>
# if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
# endif
# if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
# pragma GCC diagnostic ignored "-Wold-style-definition"
# pragma GCC diagnostic ignored "-Wtype-limits"
# endif
#endif
/* Make sure no one compiles this code with a C++ compiler. */
#if defined __cplusplus && defined _LIBC
# error "This is C code, use a C compiler"
#endif
#ifdef _LIBC
/* We have to keep the namespace clean. */
# define regfree(preg) __regfree (preg)
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
# define regerror(errcode, preg, errbuf, errbuf_size) \
# define regfree(preg) __regfree (preg)
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
# define regerror(errcode, preg, errbuf, errbuf_size) \
__regerror(errcode, preg, errbuf, errbuf_size)
# define re_set_registers(bu, re, nu, st, en) \
# define re_set_registers(bu, re, nu, st, en) \
__re_set_registers (bu, re, nu, st, en)
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
# define re_match(bufp, string, size, pos, regs) \
# define re_match(bufp, string, size, pos, regs) \
__re_match (bufp, string, size, pos, regs)
# define re_search(bufp, string, size, startpos, range, regs) \
# define re_search(bufp, string, size, startpos, range, regs) \
__re_search (bufp, string, size, startpos, range, regs)
# define re_compile_pattern(pattern, length, bufp) \
# define re_compile_pattern(pattern, length, bufp) \
__re_compile_pattern (pattern, length, bufp)
# define re_set_syntax(syntax) __re_set_syntax (syntax)
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
# define re_set_syntax(syntax) __re_set_syntax (syntax)
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
# include "../locale/localeinfo.h"
#endif
/* POSIX says that <sys/types.h> must be included (by the caller) before
<regex.h>. */
#include <sys/types.h>
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
GNU regex allows. Include it before <regex.h>, which correctly
#undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h>
#include <regex.h>
#include "regex_internal.h"

View File

@ -1,7 +1,6 @@
/* Definitions for data structures and routines for the regular
expression library.
Copyright (C) 1985,1989-93,1995-98,2000,2001,2002
Free Software Foundation, Inc.
Copyright (C) 1985, 1989-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -15,25 +14,47 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA. */
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _REGEX_H
#define _REGEX_H 1
#include <sys/types.h>
/* Allow the use in C++ code. */
#ifdef __cplusplus
extern "C" {
#endif
/* POSIX says that <sys/types.h> must be included (by the caller) before
<regex.h>. */
/* Define __USE_GNU to declare GNU extensions that violate the
POSIX name space rules. */
#if defined(_GNU_SOURCE) || defined(_REGEX_STANDALONE)
# define __USE_GNU 1
#endif
#ifdef _REGEX_LARGE_OFFSETS
/* Use types and values that are wide enough to represent signed and
unsigned byte offsets in memory. This currently works only when
the regex code is used outside of the GNU C library; it is not yet
supported within glibc itself, and glibc users should not define
_REGEX_LARGE_OFFSETS. */
/* The type of object sizes. */
typedef size_t __re_size_t;
/* The type of object sizes, in places where the traditional code
uses unsigned long int. */
typedef size_t __re_long_size_t;
#else
/* The traditional GNU regex implementation mishandles strings longer
than INT_MAX. */
typedef unsigned int __re_size_t;
typedef unsigned long int __re_long_size_t;
#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && (defined VMS || defined _MSC_VER)
/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
should be there. Same for Microsoft Visual C++ 6.0 */
# include <stddef.h>
#endif
/* The following two types have to be signed and unsigned integer type
@ -50,34 +71,35 @@ typedef unsigned long int active_reg_t;
add or remove a bit, only one other definition need change. */
typedef unsigned long int reg_syntax_t;
#ifdef __USE_GNU
/* If this bit is not set, then \ inside a bracket expression is literal.
If set, then such a \ quotes the following character. */
#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
/* If this bit is not set, then + and ? are operators, and \+ and \? are
literals.
If set, then \+ and \? are operators and + and ? are literals. */
#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
/* If this bit is set, then character classes are supported. They are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
/* If this bit is set, then ^ and $ are always anchors (outside bracket
expressions, of course).
If this bit is not set, then it depends:
^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator.
^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator.
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
POSIX draft 11.2 says that * etc. in leading positions is undefined.
We already implemented a previous draft which made those constructs
invalid, though, so we haven't changed the code back. */
#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
/* If this bit is set, then special characters are always special
regardless of where they are in the pattern.
@ -85,71 +107,71 @@ typedef unsigned long int reg_syntax_t;
some contexts; otherwise they are ordinary. Specifically,
* + ? and intervals are only special when not after the beginning,
open-group, or alternation operator. */
#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
immediately after an alternation or begin-group operator. */
#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
/* If this bit is set, then . matches newline.
If not set, then it doesn't. */
#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
/* If this bit is set, then . doesn't match NUL.
If not set, then it does. */
#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
/* If this bit is set, nonmatching lists [^...] do not match newline.
If not set, they do. */
#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
/* If this bit is set, either \{...\} or {...} defines an
interval, depending on RE_NO_BK_BRACES.
If not set, \{, \}, {, and } are literals. */
#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
/* If this bit is set, +, ? and | aren't recognized as operators.
If not set, they are. */
#define RE_LIMITED_OPS (RE_INTERVALS << 1)
# define RE_LIMITED_OPS (RE_INTERVALS << 1)
/* If this bit is set, newline is an alternation operator.
If not set, newline is literal. */
#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
/* If this bit is set, then '{...}' defines an interval, and \{ and \}
are literals.
If not set, then `\{...\}' defines an interval. */
#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
If not set, then '\{...\}' defines an interval. */
# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals.
If not set, \(...\) defines a group, and ( and ) are literals. */
#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
/* If this bit is set, then \<digit> matches <digit>.
If not set, then \<digit> is a back-reference. */
#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
/* If this bit is set, then | is an alternation operator, and \| is literal.
If not set, then \| is an alternation operator, and | is literal. */
#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
/* If this bit is set, then an ending range point collating higher
than the starting range point, as in [z-a], is invalid.
If not set, then when ending range point collates higher than the
starting range point, the range is ignored. */
#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
/* If this bit is set, then an unmatched ) is ordinary.
If not set, then an unmatched ) is invalid. */
#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, succeed as soon as we match the whole pattern,
without further backtracking. */
#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
/* If this bit is set, do not process the GNU regex operators.
If not set, then the GNU regex operators are recognized. */
#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
/* If this bit is set, turn on internal regex debugging.
If not set, and debugging was on, turn it off.
@ -157,16 +179,30 @@ typedef unsigned long int reg_syntax_t;
We define this bit always, so that all that's needed to turn on
debugging is to recompile regex.c; the calling code can always have
this bit set, and it won't affect anything in the normal case. */
#define RE_DEBUG (RE_NO_GNU_OPS << 1)
# define RE_DEBUG (RE_NO_GNU_OPS << 1)
/* If this bit is set, a syntactically invalid interval is treated as
a string of ordinary characters. For example, the ERE 'a{1' is
treated as 'a\{1'. */
#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
for ^, because it is difficult to scan the regex backwards to find
whether ^ should be special. */
# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
/* If this bit is set, then \{ cannot be first in a regex or
immediately after an alternation, open-group or \} operator. */
# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
/* If this bit is set, then no_sub will be set to 1 during
re_compile_pattern. */
# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
#endif
/* This global variable defines the particular regexp syntax to use (for
some interfaces). When a regexp is compiled, the syntax used is
@ -174,63 +210,64 @@ typedef unsigned long int reg_syntax_t;
already-compiled regexps. */
extern reg_syntax_t re_syntax_options;
#ifdef __USE_GNU
/* Define combinations of the above bits for the standard possibilities.
(The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */
#define RE_SYNTAX_EMACS 0
# define RE_SYNTAX_EMACS 0
#define RE_SYNTAX_AWK \
# define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
| RE_CHAR_CLASSES \
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
#define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
| RE_CONTEXT_INVALID_OPS ))
# define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INVALID_INTERVAL_ORD) \
& ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \
| RE_CONTEXT_INVALID_OPS ))
#define RE_SYNTAX_POSIX_AWK \
# define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INTERVALS | RE_NO_GNU_OPS)
#define RE_SYNTAX_GREP \
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
| RE_NEWLINE_ALT)
#define RE_SYNTAX_EGREP \
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
#define RE_SYNTAX_POSIX_EGREP \
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
| RE_INTERVALS | RE_NO_GNU_OPS \
| RE_INVALID_INTERVAL_ORD)
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
# define RE_SYNTAX_GREP \
((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \
& ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL))
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
# define RE_SYNTAX_EGREP \
((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \
& ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL))
/* POSIX grep -E behavior is no longer incompatible with GNU. */
# define RE_SYNTAX_POSIX_EGREP \
RE_SYNTAX_EGREP
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
#define _RE_SYNTAX_POSIX_COMMON \
# define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
#define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
# define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
# define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
#define RE_SYNTAX_POSIX_EXTENDED \
# define RE_SYNTAX_POSIX_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
@ -238,24 +275,35 @@ extern reg_syntax_t re_syntax_options;
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
removed and RE_NO_BK_REFS is added. */
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */
/* Maximum number of duplicates an interval can allow. Some systems
(erroneously) define this in other header files, but we want our
/* Maximum number of duplicates an interval can allow. POSIX-conforming
systems might define this in <limits.h>, but we want our
value, so remove any previous define. */
#ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# ifdef _REGEX_INCLUDE_LIMITS_H
# include <limits.h>
# endif
# ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# endif
/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored
the counter as a 2-byte signed integer. This is no longer true, so
RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to
((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined.
However, there would be a huge performance problem if someone
actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains
its historical value. */
# define RE_DUP_MAX (0x7fff)
#endif
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
#define RE_DUP_MAX (0x7fff)
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */
/* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */
@ -263,19 +311,19 @@ extern reg_syntax_t re_syntax_options;
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
#define REG_ICASE (REG_EXTENDED << 1)
#define REG_ICASE (1 << 1)
/* If this bit is set, then anchors do not match at newline
characters in the string.
If not set, then anchors do match at newlines. */
#define REG_NEWLINE (REG_ICASE << 1)
#define REG_NEWLINE (1 << 2)
/* If this bit is set, then report only success or fail in regexec.
If not set, then returns differ between not matching and errors. */
#define REG_NOSUB (REG_NEWLINE << 1)
#define REG_NOSUB (1 << 3)
/* POSIX `eflags' bits (i.e., information for regexec). */
/* POSIX 'eflags' bits (i.e., information for regexec). */
/* If this bit is set, then the beginning-of-line operator doesn't match
the beginning of the string (presumably because it's not the
@ -287,143 +335,184 @@ extern reg_syntax_t re_syntax_options;
/* Like REG_NOTBOL, except for the end-of-line. */
#define REG_NOTEOL (1 << 1)
/* Use PMATCH[0] to delimit the start and end of the search in the
buffer. */
#define REG_STARTEND (1 << 2)
/* If any error codes are removed, changed, or added, update the
`re_error_msg' table in regex.c. */
'__re_error_msgid' table in regcomp.c. */
typedef enum
{
#ifdef _XOPEN_SOURCE
REG_ENOSYS = -1, /* This will never happen for this implementation. */
#endif
REG_NOERROR = 0, /* Success. */
REG_NOMATCH, /* Didn't find a match (for regexec). */
_REG_ENOSYS = -1, /* This will never happen for this implementation. */
_REG_NOERROR = 0, /* Success. */
_REG_NOMATCH, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
REG_BADPAT, /* Invalid pattern. */
REG_ECOLLATE, /* Not implemented. */
REG_ECTYPE, /* Invalid character class name. */
REG_EESCAPE, /* Trailing backslash. */
REG_ESUBREG, /* Invalid back reference. */
REG_EBRACK, /* Unmatched left bracket. */
REG_EPAREN, /* Parenthesis imbalance. */
REG_EBRACE, /* Unmatched \{. */
REG_BADBR, /* Invalid contents of \{\}. */
REG_ERANGE, /* Invalid range end. */
REG_ESPACE, /* Ran out of memory. */
REG_BADRPT, /* No preceding re for repetition op. */
_REG_BADPAT, /* Invalid pattern. */
_REG_ECOLLATE, /* Invalid collating element. */
_REG_ECTYPE, /* Invalid character class name. */
_REG_EESCAPE, /* Trailing backslash. */
_REG_ESUBREG, /* Invalid back reference. */
_REG_EBRACK, /* Unmatched left bracket. */
_REG_EPAREN, /* Parenthesis imbalance. */
_REG_EBRACE, /* Unmatched \{. */
_REG_BADBR, /* Invalid contents of \{\}. */
_REG_ERANGE, /* Invalid range end. */
_REG_ESPACE, /* Ran out of memory. */
_REG_BADRPT, /* No preceding re for repetition op. */
/* Error codes we've added. */
REG_EEND, /* Premature end. */
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
_REG_EEND, /* Premature end. */
_REG_ESIZE, /* Too large (e.g., repeat count too large). */
_REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
} reg_errcode_t;
#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
# define REG_ENOSYS _REG_ENOSYS
#endif
#define REG_NOERROR _REG_NOERROR
#define REG_NOMATCH _REG_NOMATCH
#define REG_BADPAT _REG_BADPAT
#define REG_ECOLLATE _REG_ECOLLATE
#define REG_ECTYPE _REG_ECTYPE
#define REG_EESCAPE _REG_EESCAPE
#define REG_ESUBREG _REG_ESUBREG
#define REG_EBRACK _REG_EBRACK
#define REG_EPAREN _REG_EPAREN
#define REG_EBRACE _REG_EBRACE
#define REG_BADBR _REG_BADBR
#define REG_ERANGE _REG_ERANGE
#define REG_ESPACE _REG_ESPACE
#define REG_BADRPT _REG_BADRPT
#define REG_EEND _REG_EEND
#define REG_ESIZE _REG_ESIZE
#define REG_ERPAREN _REG_ERPAREN
/* This data structure represents a compiled pattern. Before calling
the pattern compiler, the fields `buffer', `allocated', `fastmap',
`translate', and `no_sub' can be set. After the pattern has been
compiled, the `re_nsub' field is available. All other fields are
private to the regex routines. */
the pattern compiler, the fields 'buffer', 'allocated', 'fastmap',
and 'translate' can be set. After the pattern has been compiled,
the fields 're_nsub', 'not_bol' and 'not_eol' are available. All
other fields are private to the regex routines. */
#ifndef RE_TRANSLATE_TYPE
# define RE_TRANSLATE_TYPE char *
# define __RE_TRANSLATE_TYPE unsigned char *
# ifdef __USE_GNU
# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE
# endif
#endif
#ifdef __USE_GNU
# define __REPB_PREFIX(name) name
#else
# define __REPB_PREFIX(name) __##name
#endif
struct re_pattern_buffer
{
/* [[[begin pattern_buffer]]] */
/* Space that holds the compiled pattern. It is declared as
`unsigned char *' because its elements are
sometimes used as array indexes. */
unsigned char *buffer;
/* Space that holds the compiled pattern. The type
'struct re_dfa_t' is private and is not declared here. */
struct re_dfa_t *__REPB_PREFIX(buffer);
/* Number of bytes to which `buffer' points. */
unsigned long int allocated;
/* Number of bytes to which 'buffer' points. */
__re_long_size_t __REPB_PREFIX(allocated);
/* Number of bytes actually used in `buffer'. */
unsigned long int used;
/* Number of bytes actually used in 'buffer'. */
__re_long_size_t __REPB_PREFIX(used);
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t syntax;
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t __REPB_PREFIX(syntax);
/* Pointer to a fastmap, if any, otherwise zero. re_search uses
the fastmap, if there is one, to skip over impossible
starting points for matches. */
char *fastmap;
/* Pointer to a fastmap, if any, otherwise zero. re_search uses the
fastmap, if there is one, to skip over impossible starting points
for matches. */
char *__REPB_PREFIX(fastmap);
/* Either a translate table to apply to all characters before
comparing them, or zero for no translation. The translation
is applied to a pattern when it is compiled and to a string
when it is matched. */
RE_TRANSLATE_TYPE translate;
/* Either a translate table to apply to all characters before
comparing them, or zero for no translation. The translation is
applied to a pattern when it is compiled and to a string when it
is matched. */
__RE_TRANSLATE_TYPE __REPB_PREFIX(translate);
/* Number of subexpressions found by the compiler. */
/* Number of subexpressions found by the compiler. */
size_t re_nsub;
/* Zero if this pattern cannot match the empty string, one else.
Well, in truth it's used only in `re_search_2', to see
whether or not we should use the fastmap, so we don't set
this absolutely perfectly; see `re_compile_fastmap' (the
`duplicate' case). */
unsigned can_be_null : 1;
/* Zero if this pattern cannot match the empty string, one else.
Well, in truth it's used only in 're_search_2', to see whether or
not we should use the fastmap, so we don't set this absolutely
perfectly; see 're_compile_fastmap' (the "duplicate" case). */
unsigned __REPB_PREFIX(can_be_null) : 1;
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
for `max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#define REGS_UNALLOCATED 0
#define REGS_REALLOCATE 1
#define REGS_FIXED 2
unsigned regs_allocated : 2;
/* If REGS_UNALLOCATED, allocate space in the 'regs' structure
for 'max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#ifdef __USE_GNU
# define REGS_UNALLOCATED 0
# define REGS_REALLOCATE 1
# define REGS_FIXED 2
#endif
unsigned __REPB_PREFIX(regs_allocated) : 2;
/* Set to zero when `regex_compile' compiles a pattern; set to one
by `re_compile_fastmap' if it updates the fastmap. */
unsigned fastmap_accurate : 1;
/* Set to zero when 're_compile_pattern' compiles a pattern; set to
one by 're_compile_fastmap' if it updates the fastmap. */
unsigned __REPB_PREFIX(fastmap_accurate) : 1;
/* If set, `re_match_2' does not return information about
subexpressions. */
unsigned no_sub : 1;
/* If set, 're_match_2' does not return information about
subexpressions. */
unsigned __REPB_PREFIX(no_sub) : 1;
/* If set, a beginning-of-line anchor doesn't match at the
beginning of the string. */
unsigned not_bol : 1;
/* If set, a beginning-of-line anchor doesn't match at the beginning
of the string. */
unsigned __REPB_PREFIX(not_bol) : 1;
/* Similarly for an end-of-line anchor. */
unsigned not_eol : 1;
/* Similarly for an end-of-line anchor. */
unsigned __REPB_PREFIX(not_eol) : 1;
/* If true, an anchor at a newline matches. */
unsigned newline_anchor : 1;
/* [[[end pattern_buffer]]] */
/* If true, an anchor at a newline matches. */
unsigned __REPB_PREFIX(newline_anchor) : 1;
};
typedef struct re_pattern_buffer regex_t;
/* Type for byte offsets within the string. POSIX mandates this. */
#ifdef _REGEX_LARGE_OFFSETS
/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as
ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t
is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not
visible here, so use ssize_t. */
typedef ssize_t regoff_t;
#else
/* The traditional GNU regex implementation mishandles strings longer
than INT_MAX. */
typedef int regoff_t;
#endif
#ifdef __USE_GNU
/* This is the structure we store register match data in. See
regex.texinfo for a full description of what registers match. */
struct re_registers
{
unsigned num_regs;
__re_size_t num_regs;
regoff_t *start;
regoff_t *end;
};
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
`re_match_2' returns information about at least this many registers
the first time a `regs' structure is passed. */
#ifndef RE_NREGS
# define RE_NREGS 30
/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
're_match_2' returns information about at least this many registers
the first time a 'regs' structure is passed. */
# ifndef RE_NREGS
# define RE_NREGS 30
# endif
#endif
/* POSIX specification for registers. Aside from the different names than
`re_registers', POSIX uses an array of structures, instead of a
're_registers', POSIX uses an array of structures, instead of a
structure of arrays. */
typedef struct
{
@ -433,38 +522,27 @@ typedef struct
/* Declarations for routines. */
/* To avoid duplicating every routine declaration -- once with a
prototype (if we are ANSI), and once without (if we aren't) -- we
use the following macro to declare argument types. This
unfortunately clutters up the declarations a bit, but I think it's
worth it. */
#if defined(__STDC__) || defined(__cplusplus)
# define _RE_ARGS(args) args
#else /* not __STDC__ */
# define _RE_ARGS(args) ()
#endif /* not __STDC__ */
#ifdef __USE_GNU
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
You can also simply assign to the 're_syntax_options' variable. */
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
extern const char *re_compile_pattern
_RE_ARGS ((const char *pattern, size_t length,
struct re_pattern_buffer *buffer));
and syntax given by the global 're_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not.
To free the allocated storage, you must call 'regfree' on BUFFER.
Note that the translate table must either have been initialized by
'regcomp', with a malloc'ed value, or set to NULL before calling
'regfree'. */
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
struct re_pattern_buffer *__buffer);
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
/* Search in the string STRING (with length LENGTH) for the pattern
@ -472,91 +550,105 @@ extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
extern int re_search
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, int range, struct re_registers *regs));
extern regoff_t re_search (struct re_pattern_buffer *__buffer,
const char *__String, regoff_t __length,
regoff_t __start, regoff_t __range,
struct re_registers *__regs);
/* Like `re_search', but search in the concatenation of STRING1 and
/* Like 're_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
extern int re_search_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, int range, struct re_registers *regs, int stop));
extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
const char *__string1, regoff_t __length1,
const char *__string2, regoff_t __length2,
regoff_t __start, regoff_t __range,
struct re_registers *__regs,
regoff_t __stop);
/* Like `re_search', but return how many characters in STRING the regexp
/* Like 're_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
extern int re_match
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, struct re_registers *regs));
extern regoff_t re_match (struct re_pattern_buffer *__buffer,
const char *__String, regoff_t __length,
regoff_t __start, struct re_registers *__regs);
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
extern int re_match_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, struct re_registers *regs, int stop));
/* Relates to 're_match' as 're_search_2' relates to 're_search'. */
extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
const char *__string1, regoff_t __length1,
const char *__string2, regoff_t __length2,
regoff_t __start, struct re_registers *__regs,
regoff_t __stop);
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
allocated with malloc, and must each be at least `NUM_REGS * sizeof
allocated with malloc, and must each be at least 'NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
unsigned num_regs, regoff_t *starts, regoff_t *ends));
extern void re_set_registers (struct re_pattern_buffer *__buffer,
struct re_registers *__regs,
__re_size_t __num_regs,
regoff_t *__starts, regoff_t *__ends);
#endif /* Use GNU */
#if defined _REGEX_RE_COMP || defined _LIBC
#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC)
# ifndef _CRAY
/* 4.2 bsd compatibility. */
extern char *re_comp _RE_ARGS ((const char *));
extern int re_exec _RE_ARGS ((const char *));
extern char *re_comp (const char *);
extern int re_exec (const char *);
# endif
#endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have
"restrict", and "configure" may have defined "restrict". */
#ifndef __restrict
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
# if defined restrict || 199901L <= __STDC_VERSION__
# define __restrict restrict
# else
# define __restrict
# endif
/* For plain 'restrict', use glibc's __restrict if defined.
Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have
"restrict", and "configure" may have defined "restrict".
Other compilers use __restrict, __restrict__, and _Restrict, and
'configure' might #define 'restrict' to those words, so pick a
different name. */
#ifndef _Restrict_
# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
# define _Restrict_ __restrict
# elif 199901L <= __STDC_VERSION__ || defined restrict
# define _Restrict_ restrict
# else
# define _Restrict_
# endif
#endif
/* gcc 3.1 and up support the [restrict] syntax. */
#ifndef __restrict_arr
# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) && !defined(__WIN32__)
# define __restrict_arr __restrict
/* For [restrict], use glibc's __restrict_arr if available.
Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */
#ifndef _Restrict_arr_
# ifdef __restrict_arr
# define _Restrict_arr_ __restrict_arr
# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
&& !defined __GNUG__)
# define _Restrict_arr_ _Restrict_
# else
# define __restrict_arr
# define _Restrict_arr_
# endif
#endif
/* POSIX compatibility. */
extern int regcomp _RE_ARGS ((regex_t *__restrict __preg,
const char *__restrict __pattern,
int __cflags));
extern int regcomp (regex_t *_Restrict_ __preg,
const char *_Restrict_ __pattern,
int __cflags);
extern int regexec _RE_ARGS ((const regex_t *__restrict __preg,
const char *__restrict __string, size_t __nmatch,
regmatch_t __pmatch[__restrict_arr],
int __eflags));
extern int regexec (const regex_t *_Restrict_ __preg,
const char *_Restrict_ __String, size_t __nmatch,
regmatch_t __pmatch[_Restrict_arr_],
int __eflags);
extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
char *__errbuf, size_t __errbuf_size));
extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg,
char *_Restrict_ __errbuf, size_t __errbuf_size);
extern void regfree _RE_ARGS ((regex_t *__preg));
extern void regfree (regex_t *__preg);
#ifdef __cplusplus
@ -564,11 +656,3 @@ extern void regfree _RE_ARGS ((regex_t *__preg));
#endif /* C++ */
#endif /* regex.h */
/*
Local variables:
make-backup-files: t
version-control: t
trim-versions-without-asking: nil
End:
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,17 +4,9 @@
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2006-15 Douglas Gilbert <dgilbert@interlog.com>
* Copyright (C) 2009-17 Christian Franke
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Copyright (C) 2009-18 Christian Franke
*
* SPDX-License-Identifier: GPL-2.0-or-later
* The code in this file is based on the SCSI to ATA Translation (SAT)
* draft found at http://www.t10.org . The original draft used for this
* code is sat-r08.pdf which is not too far away from becoming a
@ -43,7 +35,7 @@
* Note that in the latter case, this code does not solve the
* addressing issue (i.e. which SATA disk to address behind the logical
* SCSI (RAID) interface).
*
*
*/
#include <stdio.h>
@ -53,7 +45,7 @@
#include <errno.h>
#include "config.h"
#include "int64.h"
#include "scsicmds.h"
#include "atacmds.h" // ataReadHDIdentity()
#include "knowndrives.h" // lookup_usb_device()
@ -61,8 +53,9 @@
#include "dev_interface.h"
#include "dev_ata_cmd_set.h" // ata_device_with_command_set
#include "dev_tunnelled.h" // tunnelled_device<>
#include "sg_unaligned.h"
const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 4386 2017-01-28 16:35:06Z chrfranke $";
const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 4848 2018-12-05 18:30:46Z chrfranke $";
/* This is a slightly stretched SCSI sense "descriptor" format header.
The addition is to allow the 0x70 and 0x71 response codes. The idea
@ -112,8 +105,14 @@ class sat_device
virtual public /*implements*/ scsi_device
{
public:
enum sat_scsi_mode {
sat_always,
sat_auto,
scsi_always
};
sat_device(smart_interface * intf, scsi_device * scsidev,
const char * req_type, int passthrulen = 0, bool enable_auto = false);
const char * req_type, sat_scsi_mode mode = sat_always, int passthrulen = 0);
virtual ~sat_device() throw();
@ -125,27 +124,28 @@ public:
private:
int m_passthrulen;
bool m_enable_auto;
sat_scsi_mode m_mode;
};
sat_device::sat_device(smart_interface * intf, scsi_device * scsidev,
const char * req_type, int passthrulen /* = 0 */, bool enable_auto /* = false */)
const char * req_type, sat_scsi_mode mode /* = sat_always */,
int passthrulen /* = 0 */)
: smart_device(intf, scsidev->get_dev_name(),
(enable_auto ? "sat,auto" : "sat"), req_type),
(mode == sat_always ? "sat" : mode == sat_auto ? "sat,auto" : "scsi"), req_type),
tunnelled_device<ata_device, scsi_device>(scsidev),
m_passthrulen(passthrulen),
m_enable_auto(enable_auto)
m_mode(mode)
{
if (enable_auto)
if (mode != sat_always)
hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
else
hide_scsi(); // ATA always
if (strcmp(scsidev->get_dev_type(), "scsi"))
set_info().dev_type += strprintf("+%s", scsidev->get_dev_type());
set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(),
(enable_auto ? "SCSI/" : ""));
set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
(mode == sat_always ? "SAT" : mode == sat_auto ? "SCSI/SAT" : "SCSI"));
}
sat_device::~sat_device() throw()
@ -240,7 +240,7 @@ sat_device::~sat_device() throw()
// RETURN VALUES
// -1 if the command failed
// 0 if the command succeeded,
// STATUS_CHECK routine:
// STATUS_CHECK routine:
// -1 if the command failed
// 0 if the command succeeded and disk SMART status is "OK"
// 1 if the command succeeded and disk SMART status is "FAILING"
@ -410,7 +410,7 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
scsiErrString(status));
if (ardp && (scsi_debugmode > 1)) {
pout("Values from ATA Return Descriptor are:\n");
dStrHex((const char *)ardp, ard_len, 1);
dStrHex((const uint8_t *)ardp, ard_len, 1);
}
}
if (t_dir && (t_length > 0) && (in.direction == ata_cmd_in::data_in))
@ -423,7 +423,7 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
if (ardp) {
if (scsi_debugmode > 1) {
pout("Values from ATA Return Descriptor are:\n");
dStrHex((const char *)ardp, ard_len, 1);
dStrHex((const uint8_t *)ardp, ard_len, 1);
}
// Set output registers
ata_out_regs & lo = out.out_regs;
@ -467,7 +467,7 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
* count_upper_nonzero or lba_upper_nonzero are set
* involves fetching the SCSI ATA PASS-THROUGH
* Results log page and decoding the descriptor with
* the matching log_index field. Painful. */
* the matching log_index field. Painful. */
}
}
}
@ -481,7 +481,7 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
if (scsi_debugmode > 0) {
if (sense_descriptor && ardp) {
pout("Values from ATA Return Descriptor are:\n");
dStrHex((const char *)ardp, ard_len, 1);
dStrHex((const uint8_t *)ardp, ard_len, 1);
} else if (! sense_descriptor) {
pout("Values from ATA fixed format sense are:\n");
pout(" Error: 0x%x\n", io_hdr.sensep[3]);
@ -509,7 +509,7 @@ bool sat_device::scsi_pass_through(scsi_cmnd_io * iop)
smart_device * sat_device::autodetect_open()
{
if (!open() || !m_enable_auto)
if (!open() || m_mode != sat_auto)
return this;
scsi_device * scsidev = get_tunnel_dev();
@ -547,7 +547,7 @@ smart_device * sat_device::autodetect_open()
static bool has_sat_pass_through(ata_device * dev, bool packet_interface = false)
{
/* Note: malloc() ensures 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 */
char *data = (char *)malloc(512);
ata_cmd_in in;
@ -596,40 +596,6 @@ static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
return 1;
}
// Call scsi_pass_through and check sense.
// TODO: Provide as member function of class scsi_device (?)
static bool scsi_pass_through_and_check(scsi_device * scsidev, scsi_cmnd_io * iop,
const char * msg = "")
{
// Provide sense buffer
unsigned char sense[32] = {0, };
iop->sensep = sense;
iop->max_sense_len = sizeof(sense);
iop->timeout = SCSI_TIMEOUT_DEFAULT;
// Run cmd
if (!scsidev->scsi_pass_through(iop)) {
if (scsi_debugmode > 0)
pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
msg, scsidev->get_errno(), scsidev->get_errmsg());
return false;
}
// Check sense
scsi_sense_disect sinfo;
scsi_do_sense_disect(iop, &sinfo);
int err = scsiSimpleSenseFilter(&sinfo);
if (err) {
if (scsi_debugmode > 0)
pout("%sscsi error: %s\n", msg, scsiErrString(err));
return scsidev->set_err(EIO, "scsi error %s", scsiErrString(err));
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
namespace sat {
@ -657,7 +623,7 @@ protected:
usbcypress_device::usbcypress_device(smart_interface * intf, scsi_device * scsidev,
const char * req_type, unsigned char signature)
: smart_device(intf, scsidev->get_dev_name(), "sat", req_type),
: smart_device(intf, scsidev->get_dev_name(), "usbcypress", req_type),
tunnelled_device<ata_device_with_command_set, scsi_device>(scsidev),
m_signature(signature)
{
@ -831,7 +797,7 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele
// if there is a sense the command failed or the
// device doesn't support usbcypress
if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION &&
if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION &&
sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
return -1;
}
@ -849,7 +815,7 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele
cdb[2] = (1<<0); /* ask read taskfile */
memset(sense, 0, sizeof(sense));
/* transfert 8 bytes */
/* transfer 8 bytes */
memset(&io_hdr, 0, sizeof(io_hdr));
io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
io_hdr.dxfer_len = ard_len;
@ -872,7 +838,7 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele
}
// if there is a sense the command failed or the
// device doesn't support usbcypress
if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION &&
if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION &&
sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
return -1;
}
@ -880,7 +846,7 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele
if (scsi_debugmode > 1) {
pout("Values from ATA Return Descriptor are:\n");
dStrHex((const char *)ardp, ard_len, 1);
dStrHex((const uint8_t *)ardp, ard_len, 1);
}
if (ATA_CHECK_POWER_MODE == ata_command)
@ -897,7 +863,7 @@ int usbcypress_device::ata_command_interface(smart_command_set command, int sele
pout("Retry without other disc access\n");
pout("Please get assistance from " PACKAGE_HOMEPAGE "\n");
pout("Values from ATA Return Descriptor are:\n");
dStrHex((const char *)ardp, ard_len, 1);
dStrHex((const uint8_t *)ardp, ard_len, 1);
return -1;
}
}
@ -1079,8 +1045,7 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
cdb[ 0] = 0xdf;
cdb[ 1] = (rwbit ? 0x10 : 0x00);
cdb[ 2] = 0x00;
cdb[ 3] = (unsigned char)(io_hdr.dxfer_len >> 8);
cdb[ 4] = (unsigned char)(io_hdr.dxfer_len );
sg_put_unaligned_be16(io_hdr.dxfer_len, cdb + 3);
cdb[ 5] = in.in_regs.features;
cdb[ 6] = in.in_regs.sector_count;
cdb[ 7] = in.in_regs.lba_low;
@ -1096,7 +1061,7 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
scsi_device * scsidev = get_tunnel_dev();
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbjmicron_device::ata_pass_through: "))
return set_err(scsidev->get_err());
@ -1151,11 +1116,9 @@ bool usbjmicron_device::get_registers(unsigned short addr,
cdb[ 0] = 0xdf;
cdb[ 1] = 0x10;
cdb[ 2] = 0x00;
cdb[ 3] = (unsigned char)(size >> 8);
cdb[ 4] = (unsigned char)(size );
sg_put_unaligned_be16(size, cdb + 3);
cdb[ 5] = 0x00;
cdb[ 6] = (unsigned char)(addr >> 8);
cdb[ 7] = (unsigned char)(addr );
sg_put_unaligned_be16(addr, cdb + 6);
cdb[ 8] = 0x00;
cdb[ 9] = 0x00;
cdb[10] = 0x00;
@ -1173,7 +1136,7 @@ bool usbjmicron_device::get_registers(unsigned short addr,
io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
scsi_device * scsidev = get_tunnel_dev();
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbjmicron_device::get_registers: "))
return set_err(scsidev->get_err());
@ -1267,10 +1230,7 @@ bool usbprolific_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o
cdb[ 3] = in.in_regs.features; // Feature register (SMART command)
cdb[ 4] = 0x06; // Check Word (VendorID magic, Prolific: 0x067B)
cdb[ 5] = 0x7B; // Check Word (VendorID magic, Prolific: 0x067B)
cdb[ 6] = (unsigned char)(io_hdr.dxfer_len >> 24); // Length MSB
cdb[ 7] = (unsigned char)(io_hdr.dxfer_len >> 16); // Length ...
cdb[ 8] = (unsigned char)(io_hdr.dxfer_len >> 8); // Length ...
cdb[ 9] = (unsigned char)(io_hdr.dxfer_len ); // Length LSB
sg_put_unaligned_be32(io_hdr.dxfer_len, cdb + 6);
cdb[10] = in.in_regs.sector_count; // Sector Count
cdb[11] = in.in_regs.lba_low; // LBA Low (7:0)
cdb[12] = in.in_regs.lba_mid; // LBA Mid (15:8)
@ -1283,7 +1243,7 @@ bool usbprolific_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o
io_hdr.cmnd_len = 16;
scsi_device * scsidev = get_tunnel_dev();
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbprolific_device::ata_pass_through: "))
return set_err(scsidev->get_err());
@ -1302,7 +1262,7 @@ bool usbprolific_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o
io_hdr.cmnd = cdb;
io_hdr.cmnd_len = sizeof(cdb);
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbprolific_device::scsi_pass_through (get registers): "))
return set_err(scsidev->get_err());
@ -1390,7 +1350,7 @@ bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
io_hdr.cmnd_len = sizeof(cdb);
scsi_device * scsidev = get_tunnel_dev();
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbsunplus_device::scsi_pass_through (presetting): "))
return set_err(scsidev->get_err());
}
@ -1437,7 +1397,7 @@ bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
io_hdr.cmnd_len = sizeof(cdb);
scsi_device * scsidev = get_tunnel_dev();
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbsunplus_device::scsi_pass_through: "))
// Returns sense key 0x03 (medium error) on ATA command error
return set_err(scsidev->get_err());
@ -1457,7 +1417,7 @@ bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
io_hdr.cmnd = cdb;
io_hdr.cmnd_len = sizeof(cdb);
if (!scsi_pass_through_and_check(scsidev, &io_hdr,
if (!scsidev->scsi_pass_through_and_check(&io_hdr,
"usbsunplus_device::scsi_pass_through (get registers): "))
return set_err(scsidev->get_err());
@ -1494,10 +1454,10 @@ ata_device * smart_interface::get_sat_device(const char * type, scsi_device * sc
if (!strncmp(type, "sat", 3)) {
const char * t = type + 3;
bool enable_auto = false;
sat_device::sat_scsi_mode mode = sat_device::sat_always;
if (!strncmp(t, ",auto", 5)) {
t += 5;
enable_auto = true;
mode = sat_device::sat_auto;
}
int ptlen = 0, n = -1;
if (*t && !(sscanf(t, ",%d%n", &ptlen, &n) == 1 && n == (int)strlen(t)
@ -1505,7 +1465,11 @@ ata_device * smart_interface::get_sat_device(const char * type, scsi_device * sc
set_err(EINVAL, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
return 0;
}
satdev = new sat_device(this, scsidev, type, ptlen, enable_auto);
satdev = new sat_device(this, scsidev, type, mode, ptlen);
}
else if (!strcmp(type, "scsi")) {
satdev = new sat_device(this, scsidev, type, sat_device::scsi_always);
}
else if (!strncmp(type, "usbcypress", 10)) {
@ -1567,7 +1531,9 @@ ata_device * smart_interface::autodetect_sat_device(scsi_device * scsidev,
return 0;
// SAT ?
if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) { // TODO: Linux-specific?
if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) {
// TODO: Linux-specific? No, all SAT standards say the 'T10 Vendor
// Identification' field shall be 'ATA '.
ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
if (has_sat_pass_through(atadev.get()))
return atadev.release(); // Detected SAT

File diff suppressed because it is too large Load Diff

View File

@ -5,21 +5,10 @@
*
* Copyright (C) 2002-8 Bruce Allen
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
* Copyright (C) 2003-15 Douglas Gilbert <dgilbert@interlog.com>
* Copyright (C) 2003-18 Douglas Gilbert <dgilbert@interlog.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* SPDX-License-Identifier: GPL-2.0-or-later
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* N.B. What was formerly known as "SMART" are now called "informational
* exceptions" in recent t10.org drafts (i.e. recent SCSI).
@ -30,10 +19,11 @@
#ifndef SCSICMDS_H_
#define SCSICMDS_H_
#define SCSICMDS_H_CVSID "$Id: scsicmds.h 4557 2017-10-19 19:17:29Z samm2 $\n"
#define SCSICMDS_H_CVSID "$Id: scsicmds.h 4842 2018-12-02 16:07:26Z chrfranke $\n"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
/* #define SCSI_DEBUG 1 */ /* Comment out to disable command debugging */
@ -102,10 +92,6 @@
#define SAT_ATA_PASSTHROUGH_16 0x85
#endif
typedef unsigned char UINT8;
typedef signed char INT8;
typedef unsigned int UINT32;
typedef int INT32;
#define DXFER_NONE 0
#define DXFER_FROM_DEVICE 1
@ -113,97 +99,144 @@ typedef int INT32;
struct scsi_cmnd_io
{
UINT8 * cmnd; /* [in]: ptr to SCSI command block (cdb) */
uint8_t * cmnd; /* [in]: ptr to SCSI command block (cdb) */
size_t cmnd_len; /* [in]: number of bytes in SCSI command */
int dxfer_dir; /* [in]: DXFER_NONE, DXFER_FROM_DEVICE, or
DXFER_TO_DEVICE */
UINT8 * dxferp; /* [in]: ptr to outgoing or incoming data buffer */
uint8_t * dxferp; /* [in]: ptr to outgoing or incoming data buffer */
size_t dxfer_len; /* [in]: bytes to be transferred to/from dxferp */
UINT8 * sensep; /* [in]: ptr to sense buffer, filled when
uint8_t * sensep; /* [in]: ptr to sense buffer, filled when
CHECK CONDITION status occurs */
size_t max_sense_len; /* [in]: max number of bytes to write to sensep */
unsigned timeout; /* [in]: seconds, 0-> default timeout (60 seconds?) */
size_t resp_sense_len; /* [out]: sense buffer length written */
UINT8 scsi_status; /* [out]: 0->ok, 2->CHECK CONDITION, etc ... */
uint8_t scsi_status; /* [out]: 0->ok, 2->CHECK CONDITION, etc ... */
int resid; /* [out]: Number of bytes requested to be transferred
less actual number transferred (0 if not
supported) */
};
struct scsi_sense_disect {
UINT8 resp_code;
UINT8 sense_key;
UINT8 asc;
UINT8 ascq;
uint8_t resp_code;
uint8_t sense_key;
uint8_t asc;
uint8_t ascq;
int progress; /* -1 -> N/A, 0-65535 -> available */
};
/* Useful data from Informational Exception Control mode page (0x1c) */
#define SCSI_IECMP_RAW_LEN 64
struct scsi_iec_mode_page {
UINT8 requestedCurrent;
UINT8 gotCurrent;
UINT8 requestedChangeable;
UINT8 gotChangeable;
UINT8 modese_len; /* 0 (don't know), 6 or 10 */
UINT8 raw_curr[SCSI_IECMP_RAW_LEN];
UINT8 raw_chg[SCSI_IECMP_RAW_LEN];
uint8_t requestedCurrent;
uint8_t gotCurrent;
uint8_t requestedChangeable;
uint8_t gotChangeable;
uint8_t modese_len; /* 0 (don't know), 6 or 10 */
uint8_t raw_curr[SCSI_IECMP_RAW_LEN];
uint8_t raw_chg[SCSI_IECMP_RAW_LEN];
};
/* Carrier for Error counter log pages (e.g. read, write, verify ...) */
struct scsiErrorCounter {
UINT8 gotPC[7];
UINT8 gotExtraPC;
uint8_t gotPC[7];
uint8_t gotExtraPC;
uint64_t counter[8];
};
/* Carrier for Non-medium error log page */
struct scsiNonMediumError {
UINT8 gotPC0;
UINT8 gotExtraPC;
uint8_t gotPC0;
uint8_t gotExtraPC;
uint64_t counterPC0;
UINT8 gotTFE_H;
uint8_t gotTFE_H;
uint64_t counterTFE_H; /* Track following errors [Hitachi] */
UINT8 gotPE_H;
uint8_t gotPE_H;
uint64_t counterPE_H; /* Positioning errors [Hitachi] */
};
struct scsi_readcap_resp {
uint64_t num_lblocks; /* Number of Logical Blocks on device */
uint32_t lb_size; /* should be available in all non-error cases */
/* following fields from READ CAPACITY(16) or set to 0 */
uint8_t prot_type; /* 0, 1, 2 or 3 protection type, deduced from
* READ CAPACITY(16) P_TYPE and PROT_EN fields */
uint8_t p_i_exp; /* Protection information Intervals Exponent */
uint8_t lb_p_pb_exp;/* Logical Blocks per Physical Block Exponent */
bool lbpme; /* Logical Block Provisioning Management Enabled */
bool lbprz; /* Logical Block Provisioning Read Zeros */
uint16_t l_a_lba; /* Lowest Aligned Logical Block Address */
};
/* 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
/* ANSI SCSI-3 Log Pages retrieved by LOG SENSE. */
#define SUPPORTED_LPAGES 0x00
#define BUFFER_OVERRUN_LPAGE 0x01
#define WRITE_ERROR_COUNTER_LPAGE 0x02
#define READ_ERROR_COUNTER_LPAGE 0x03
#define READ_REVERSE_ERROR_COUNTER_LPAGE 0x04
#define VERIFY_ERROR_COUNTER_LPAGE 0x05
#define NON_MEDIUM_ERROR_LPAGE 0x06
#define LAST_N_ERROR_LPAGE 0x07
#define FORMAT_STATUS_LPAGE 0x08
#define LB_PROV_LPAGE 0x0c /* SBC-3 */
#define TEMPERATURE_LPAGE 0x0d
#define STARTSTOP_CYCLE_COUNTER_LPAGE 0x0e
#define APPLICATION_CLIENT_LPAGE 0x0f
#define SELFTEST_RESULTS_LPAGE 0x10
#define SS_MEDIA_LPAGE 0x11 /* SBC-3 */
#define BACKGROUND_RESULTS_LPAGE 0x15 /* SBC-3 */
#define NONVOL_CACHE_LPAGE 0x17 /* SBC-3 */
#define PROTOCOL_SPECIFIC_LPAGE 0x18
#define IE_LPAGE 0x2f
/* Transport protocol identifiers or just Protocol identifiers */
#define SCSI_TPROTO_FCP 0
#define SCSI_TPROTO_SPI 1
#define SCSI_TPROTO_SSA 2
#define SCSI_TPROTO_1394 3
#define SCSI_TPROTO_SRP 4 /* SCSI over RDMA */
#define SCSI_TPROTO_ISCSI 5
#define SCSI_TPROTO_SAS 6
#define SCSI_TPROTO_ADT 7
#define SCSI_TPROTO_ATA 8
#define SCSI_TPROTO_UAS 9 /* USB attached SCSI */
#define SCSI_TPROTO_SOP 0xa /* SCSI over PCIe */
#define SCSI_TPROTO_PCIE 0xb /* includes NVMe */
#define SCSI_TPROTO_NONE 0xf
/* SCSI Log Pages retrieved by LOG SENSE. 0x0 to 0x3f, 0x30 to 0x3e vendor */
#define SUPPORTED_LPAGES 0x00
#define BUFFER_OVERRUN_LPAGE 0x01
#define WRITE_ERROR_COUNTER_LPAGE 0x02
#define READ_ERROR_COUNTER_LPAGE 0x03
#define READ_REVERSE_ERROR_COUNTER_LPAGE 0x04
#define VERIFY_ERROR_COUNTER_LPAGE 0x05
#define NON_MEDIUM_ERROR_LPAGE 0x06
#define LAST_N_ERROR_EVENTS_LPAGE 0x07
#define FORMAT_STATUS_LPAGE 0x08
#define LAST_N_DEFERRED_LPAGE 0x0b /* or async events */
#define LB_PROV_LPAGE 0x0c /* SBC-3 */
#define TEMPERATURE_LPAGE 0x0d
#define STARTSTOP_CYCLE_COUNTER_LPAGE 0x0e
#define APPLICATION_CLIENT_LPAGE 0x0f
#define SELFTEST_RESULTS_LPAGE 0x10
#define SS_MEDIA_LPAGE 0x11 /* SBC-3 */
#define BACKGROUND_RESULTS_LPAGE 0x15 /* SBC-3 */
#define ATA_PT_RESULTS_LPAGE 0x16 /* SAT */
#define NONVOL_CACHE_LPAGE 0x17 /* SBC-3 */
#define PROTOCOL_SPECIFIC_LPAGE 0x18
#define GEN_STATS_PERF_LPAGE 0x19
#define POWER_COND_TRANS_LPAGE 0x1a
#define IE_LPAGE 0x2f
/* SCSI Log subpages (8 bits), added spc4r05 2006, standardized SPC-4 2015 */
#define NO_SUBPAGE_L_SPAGE 0x0 /* 0x0-0x3f,0x0 */
#define LAST_N_INQ_DAT_L_SPAGE 0x1 /* 0xb,0x1 */
#define LAST_N_MODE_PG_L_SPAGE 0x2 /* 0xb,0x2 */
#define ENVIRO_REP_L_SPAGE 0x1 /* 0xd,0x1 */
#define ENVIRO_LIMITS_L_SPAGE 0x2 /* 0xd,0x2 */
#define UTILIZATION_L_SPAGE 0x1 /* 0xe,0x1 */
#define ZB_DEV_STATS_L_SPAGE 0x1 /* 0x14,0x1 */
#define PEND_DEFECTS_L_SPAGE 0x1 /* 0x15,0x1 */
#define BACKGROUND_OP_L_SPAGE 0x2 /* 0x15,0x2 */
#define LPS_MISALIGN_L_SPAGE 0x3 /* 0x15,0x3 */
#define SUPP_SPAGE_L_SPAGE 0xff /* 0x0,0xff pages+subpages */
/* Seagate vendor specific log pages. */
#define SEAGATE_CACHE_LPAGE 0x37
#define SEAGATE_FACTORY_LPAGE 0x3e
#define SEAGATE_CACHE_LPAGE 0x37
#define SEAGATE_FACTORY_LPAGE 0x3e
/* Log page response lengths */
#define LOG_RESP_SELF_TEST_LEN 0x194
/* See the SSC-2 document at www.t10.org . Earler note: From IBM
/* See the SSC-2 document at www.t10.org . Earlier note: From IBM
Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
#define TAPE_ALERTS_LPAGE 0x2e
@ -290,7 +323,7 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
#define SIMPLE_ERR_TRY_AGAIN 8 /* some warning, try again */
#define SIMPLE_ERR_MEDIUM_HARDWARE 9 /* medium or hardware error */
#define SIMPLE_ERR_UNKNOWN 10 /* unknown sense value */
#define SIMPLE_ERR_ABORTED_COMMAND 11 /* most likely transport error */
#define SIMPLE_ERR_ABORTED_COMMAND 11 /* probably transport error */
/* defines for functioncode parameter in SENDDIAGNOSTIC function */
@ -336,6 +369,22 @@ private:
extern supported_vpd_pages * supported_vpd_pages_p;
/* This is a heuristic that takes into account the command bytes and length
* to decide whether the presented unstructured sequence of bytes could be
* a SCSI command. If so it returns true otherwise false. Vendor specific
* SCSI commands (i.e. opcodes from 0xc0 to 0xff), if presented, are assumed
* to follow SCSI conventions (i.e. length of 6, 10, 12 or 16 bytes). The
* only SCSI commands considered above 16 bytes of length are the Variable
* Length Commands (opcode 0x7f) and the XCDB wrapped commands (opcode 0x7e).
* Both have an inbuilt length field which can be cross checked with clen.
* No NVMe commands (64 bytes long plus some extra added by some OSes) have
* opcodes 0x7e or 0x7f yet. ATA is register based but SATA has FIS
* structures that are sent across the wire. The FIS register structure is
* used to move a command from a SATA host to device, but the ATA 'command'
* is not the first byte. So it is harder to say what will happen if a
* FIS structure is presented as a SCSI command, hopefully there is a low
* probability this function will yield true in that case. */
bool is_scsi_cdb(const uint8_t * cdbp, int clen);
// Print SCSI debug messages?
extern unsigned char scsi_debugmode;
@ -358,46 +407,51 @@ int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
/* STANDARD SCSI Commands */
int scsiTestUnitReady(scsi_device * device);
int scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen);
int scsiStdInquiry(scsi_device * device, uint8_t *pBuf, int bufLen);
int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen);
int scsiInquiryVpd(scsi_device * device, int vpd_page, uint8_t *pBuf,
int bufLen);
int scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
int bufLen, int known_resp_len);
int scsiLogSense(scsi_device * device, int pagenum, int subpagenum,
uint8_t *pBuf, int bufLen, int known_resp_len);
int scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
int subpagenum, UINT8 *pBuf, int bufLen);
int subpagenum, uint8_t *pBuf, int bufLen);
int scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
UINT8 *pBuf, int bufLen);
uint8_t *pBuf, int bufLen);
int scsiModeSelect(scsi_device * device, int sp, UINT8 *pBuf, int bufLen);
int scsiModeSelect(scsi_device * device, int sp, uint8_t *pBuf, int bufLen);
int scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
UINT8 *pBuf, int bufLen);
uint8_t *pBuf, int bufLen);
int scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen);
int scsiModeSelect10(scsi_device * device, int sp, uint8_t *pBuf, int bufLen);
int scsiModePageOffset(const UINT8 * resp, int len, int modese_len);
int scsiModePageOffset(const uint8_t * resp, int len, int modese_len);
int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info);
int scsiRequestSense(scsi_device * device,
struct scsi_sense_disect * sense_info);
int scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf, int bufLen);
int scsiSendDiagnostic(scsi_device * device, int functioncode, uint8_t *pBuf,
int bufLen);
int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format,
UINT8 *pBuf, int bufLen);
int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist,
int dl_format, uint8_t *pBuf, int bufLen);
int scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
int dl_format, int addrDescIndex, UINT8 *pBuf, int bufLen);
int dl_format, int addrDescIndex, uint8_t *pBuf,
int bufLen);
int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbp,
unsigned int * lb_sizep);
int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen);
int scsiReadCapacity16(scsi_device * device, uint8_t *pBuf, int bufLen);
/* SMART specific commands */
int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage, UINT8 *asc,
UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp);
int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp,
uint8_t *triptemp);
int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp,
int modese_len);
@ -420,13 +474,12 @@ int scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp,
int * haw_zbcp);
int scsiGetSetCache(scsi_device * device, int modese_len, short int * wce,
short int * rcd);
uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep,
int * lb_per_pb_expp);
int scsiGetProtPBInfo(scsi_device * device, unsigned char * rc16_12_31p);
uint64_t scsiGetSize(scsi_device * device, bool avoid_rcap16,
struct scsi_readcap_resp * srrp);
/* T10 Standard IE Additional Sense Code strings taken from t10.org */
const char* scsiGetIEString(UINT8 asc, UINT8 ascq);
int scsiGetTemp(scsi_device * device, UINT8 *currenttemp, UINT8 *triptemp);
const char* scsiGetIEString(uint8_t asc, uint8_t ascq);
int scsiGetTemp(scsi_device * device, uint8_t *currenttemp, uint8_t *triptemp);
int scsiSmartDefaultSelfTest(scsi_device * device);
@ -439,18 +492,16 @@ int scsiSmartSelfTestAbort(scsi_device * device);
const char * scsiTapeAlertsTapeDevice(unsigned short code);
const char * scsiTapeAlertsChangerDevice(unsigned short code);
const char * scsi_get_opcode_name(UINT8 opcode);
void scsi_format_id_string(char * out, const unsigned char * in, int n);
const char * scsi_get_opcode_name(uint8_t opcode);
void scsi_format_id_string(char * out, const uint8_t * in, int n);
void dStrHex(const char* str, int len, int no_ascii);
inline void dStrHex(const unsigned char* str, int len, int no_ascii)
{ dStrHex((const char *)str, len, no_ascii); }
void dStrHex(const uint8_t * up, int len, int no_ascii);
/* Attempt to find the first SCSI sense data descriptor that matches the
given 'desc_type'. If found return pointer to start of sense data
descriptor; otherwise (including fixed format sense data) returns NULL. */
const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
int sense_len, int desc_type);
int sense_len, int desc_type);
/* SCSI command transmission interface function declaration. Its

259
scsinvme.cpp Normal file
View File

@ -0,0 +1,259 @@
/*
* scsinvme.cpp
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2018 Harry Mallon <hjmallon@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
*/
#include "config.h"
#include "dev_interface.h"
#include "dev_tunnelled.h"
#include "scsicmds.h"
#include "sg_unaligned.h"
#include "utility.h"
#include <errno.h>
// SNT (SCSI NVMe Translation) namespace and prefix
namespace snt {
#define SNT_JMICRON_NVME_SIGNATURE 0x454d564eu // 'NVME' reversed (little endian)
#define SNT_JMICRON_CDB_LEN 12
#define SNT_JMICRON_NVM_CMD_LEN 512
class sntjmicron_device
: public tunnelled_device<
/*implements*/ nvme_device,
/*by tunnelling through a*/ scsi_device
>
{
public:
sntjmicron_device(smart_interface * intf, scsi_device * scsidev,
const char * req_type, unsigned nsid);
virtual ~sntjmicron_device() throw();
virtual bool open();
virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out);
private:
enum {
proto_nvm_cmd = 0x0, proto_non_data = 0x1, proto_dma_in = 0x2,
proto_dma_out = 0x3, proto_response = 0xF
};
};
sntjmicron_device::sntjmicron_device(smart_interface * intf, scsi_device * scsidev,
const char * req_type, unsigned nsid)
: smart_device(intf, scsidev->get_dev_name(), "sntjmicron", req_type),
tunnelled_device<nvme_device, scsi_device>(scsidev, nsid)
{
set_info().info_name = strprintf("%s [USB NVMe JMicron]", scsidev->get_info_name());
}
sntjmicron_device::~sntjmicron_device() throw()
{
}
bool sntjmicron_device::open()
{
// Open USB first
if (!tunnelled_device<nvme_device, scsi_device>::open())
return false;
// No sure how multiple namespaces come up on device so we
// cannot detect e.g. /dev/sdX is NSID 2.
// Set to broadcast if not available
if (!get_nsid()) {
set_nsid(0xFFFFFFFF);
}
return true;
}
// cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
// cdb[1]: [ is admin cmd: 1 ] [ protocol : 7 ]
// cdb[2]: reserved
// cdb[3]: parameter list length (23:16)
// cdb[4]: parameter list length (15:08)
// cdb[5]: parameter list length (07:00)
// cdb[6]: reserved
// cdb[7]: reserved
// cdb[8]: reserved
// cdb[9]: reserved
// cdb[10]: reserved
// cdb[11]: CONTROL (?)
bool sntjmicron_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out)
{
/* Only admin commands used */
bool admin = true;
// 1: "NVM Command Set Payload"
{
unsigned char cdb[SNT_JMICRON_CDB_LEN] = { 0 };
cdb[0] = SAT_ATA_PASSTHROUGH_12;
cdb[1] = (admin ? 0x80 : 0x00) | proto_nvm_cmd;
sg_put_unaligned_be24(SNT_JMICRON_NVM_CMD_LEN, &cdb[3]);
unsigned nvm_cmd[SNT_JMICRON_NVM_CMD_LEN / sizeof(unsigned)] = { 0 };
nvm_cmd[0] = SNT_JMICRON_NVME_SIGNATURE;
// nvm_cmd[1]: reserved
nvm_cmd[2] = in.opcode; // More of CDW0 may go in here in future
nvm_cmd[3] = in.nsid;
// nvm_cmd[4-5]: reserved
// nvm_cmd[6-7]: metadata pointer
// nvm_cmd[8-11]: data ptr (?)
nvm_cmd[12] = in.cdw10;
nvm_cmd[13] = in.cdw11;
nvm_cmd[14] = in.cdw12;
nvm_cmd[15] = in.cdw13;
nvm_cmd[16] = in.cdw14;
nvm_cmd[17] = in.cdw15;
// nvm_cmd[18-127]: reserved
if (isbigendian())
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));
io_nvm.cmnd = cdb;
io_nvm.cmnd_len = SNT_JMICRON_CDB_LEN;
io_nvm.dxfer_dir = DXFER_TO_DEVICE;
io_nvm.dxferp = (uint8_t *)nvm_cmd;
io_nvm.dxfer_len = SNT_JMICRON_NVM_CMD_LEN;
scsi_device * scsidev = get_tunnel_dev();
if (!scsidev->scsi_pass_through_and_check(&io_nvm,
"sntjmicron_device::nvme_pass_through:NVM: "))
return set_err(scsidev->get_err());
}
// 2: DMA or Non-Data
{
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));
io_data.cmnd = cdb;
io_data.cmnd_len = SNT_JMICRON_CDB_LEN;
switch (in.direction()) {
case nvme_cmd_in::no_data:
cdb[1] = (admin ? 0x80 : 0x00) | proto_non_data;
io_data.dxfer_dir = DXFER_NONE;
break;
case nvme_cmd_in::data_out:
cdb[1] = (admin ? 0x80 : 0x00) | proto_dma_out;
sg_put_unaligned_be24(in.size, &cdb[3]);
io_data.dxfer_dir = DXFER_TO_DEVICE;
io_data.dxferp = (uint8_t *)in.buffer;
io_data.dxfer_len = in.size;
break;
case nvme_cmd_in::data_in:
cdb[1] = (admin ? 0x80 : 0x00) | proto_dma_in;
sg_put_unaligned_be24(in.size, &cdb[3]);
io_data.dxfer_dir = DXFER_FROM_DEVICE;
io_data.dxferp = (uint8_t *)in.buffer;
io_data.dxfer_len = in.size;
memset(in.buffer, 0, in.size);
break;
case nvme_cmd_in::data_io:
default:
return set_err(EINVAL);
}
scsi_device * scsidev = get_tunnel_dev();
if (!scsidev->scsi_pass_through_and_check(&io_data,
"sntjmicron_device::nvme_pass_through:Data: "))
return set_err(scsidev->get_err());
}
// 3: "Return Response Information"
{
unsigned char cdb[SNT_JMICRON_CDB_LEN] = { 0 };
cdb[0] = SAT_ATA_PASSTHROUGH_12;
cdb[1] = (admin ? 0x80 : 0x00) | proto_response;
sg_put_unaligned_be24(SNT_JMICRON_NVM_CMD_LEN, &cdb[3]);
unsigned nvm_reply[SNT_JMICRON_NVM_CMD_LEN / sizeof(unsigned)] = { 0 };
scsi_cmnd_io io_reply;
memset(&io_reply, 0, sizeof(io_reply));
io_reply.cmnd = cdb;
io_reply.cmnd_len = SNT_JMICRON_CDB_LEN;
io_reply.dxfer_dir = DXFER_FROM_DEVICE;
io_reply.dxferp = (uint8_t *)nvm_reply;
io_reply.dxfer_len = SNT_JMICRON_NVM_CMD_LEN;
scsi_device * scsidev = get_tunnel_dev();
if (!scsidev->scsi_pass_through_and_check(&io_reply,
"sntjmicron_device::nvme_pass_through:Reply: "))
return set_err(scsidev->get_err());
if (isbigendian())
for (unsigned i = 0; i < (SNT_JMICRON_NVM_CMD_LEN / sizeof(uint32_t)); i++)
swapx(&nvm_reply[i]);
if (nvm_reply[0] != SNT_JMICRON_NVME_SIGNATURE)
return set_err(EIO, "Out of spec JMicron NVMe reply");
int status = nvm_reply[5] >> 17;
if (status > 0)
return set_nvme_err(out, status);
out.result = nvm_reply[2];
}
return true;
}
} // namespace snt
using namespace snt;
nvme_device * smart_interface::get_snt_device(const char * type, scsi_device * scsidev)
{
if (!scsidev)
throw std::logic_error("smart_interface: get_snt_device() called with scsidev=0");
// Take temporary ownership of 'scsidev' to delete it on error
scsi_device_auto_ptr scsidev_holder(scsidev);
nvme_device * sntdev = 0;
// TODO: Remove this and adjust drivedb entry accordingly when no longer EXPERIMENTAL
if (!strcmp(type, "sntjmicron#please_try")) {
set_err(EINVAL, "USB to NVMe bridge [please try '-d sntjmicron' and report result to: "
PACKAGE_BUGREPORT "]");
return 0;
}
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);
if (!(n1 == len || n2 == len)) {
set_err(EINVAL, "Invalid NVMe namespace id in '%s'", type);
return 0;
}
sntdev = new sntjmicron_device(this, scsidev, type, nsid);
}
else {
set_err(EINVAL, "Unknown SNT device type '%s'", type);
return 0;
}
// 'scsidev' is now owned by 'sntdev'
scsidev_holder.release();
return sntdev;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,29 +7,16 @@
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
*
* Additional SCSI work:
* Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
* Copyright (C) 2003-18 Douglas Gilbert <dgilbert@interlog.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef SCSI_PRINT_H_
#define SCSI_PRINT_H_
#define SCSIPRINT_H_CVSID "$Id: scsiprint.h 4431 2017-08-08 19:38:15Z chrfranke $\n"
#define SCSIPRINT_H_CVSID "$Id: scsiprint.h 4760 2018-08-19 18:45:53Z chrfranke $\n"
// Options for scsiPrintMain
struct scsi_print_options

489
sg_unaligned.h Normal file
View File

@ -0,0 +1,489 @@
#ifndef SG_UNALIGNED_H
#define SG_UNALIGNED_H
/*
* Copyright (c) 2014-2018 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
*/
#include <stdbool.h>
#include <stdint.h> /* for uint8_t and friends */
#include <string.h> /* for memcpy */
#ifdef __cplusplus
extern "C" {
#endif
/* These inline functions convert integers (always unsigned) to byte streams
* and vice versa. They have two goals:
* - change the byte ordering of integers between host order and big
* endian ("_be") or little endian ("_le")
* - copy the big or little endian byte stream so it complies with any
* alignment that host integers require
*
* Host integer to given endian byte stream is a "_put_" function taking
* two arguments (integer and pointer to byte stream) returning void.
* Given endian byte stream to host integer is a "_get_" function that takes
* one argument and returns an integer of appropriate size (uint32_t for 24
* bit operations, uint64_t for 48 bit operations).
*
* Big endian byte format "on the wire" is the default used by SCSI
* standards (www.t10.org). Big endian is also the network byte order.
* Little endian is used by ATA, PCI and NVMe.
*/
/* The generic form of these routines was borrowed from the Linux kernel,
* via mhvtl. There is a specialised version of the main functions for
* little endian or big endian provided that not-quite-standard defines for
* endianness are available from the compiler and the <byteswap.h> header
* (a GNU extension) has been detected by ./configure . To force the
* generic version, use './configure --disable-fast-lebe ' . */
/* Note: Assumes that the source and destination locations do not overlap.
* An example of overlapping source and destination:
* sg_put_unaligned_le64(j, ((uint8_t *)&j) + 1);
* Best not to do things like that.
*/
#ifdef HAVE_CONFIG_H
#include "config.h" /* need this to see if HAVE_BYTESWAP_H */
#endif
#undef GOT_UNALIGNED_SPECIALS /* just in case */
#if defined(__BYTE_ORDER__) && defined(HAVE_BYTESWAP_H) && \
! defined(IGNORE_FAST_LEBE)
#if defined(__LITTLE_ENDIAN__) || (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define GOT_UNALIGNED_SPECIALS 1
#include <byteswap.h> /* for bswap_16(), bswap_32() and bswap_64() */
// #warning ">>>>>> Doing Little endian special unaligneds"
static inline uint16_t sg_get_unaligned_be16(const void *p)
{
uint16_t u;
memcpy(&u, p, 2);
return bswap_16(u);
}
static inline uint32_t sg_get_unaligned_be32(const void *p)
{
uint32_t u;
memcpy(&u, p, 4);
return bswap_32(u);
}
static inline uint64_t sg_get_unaligned_be64(const void *p)
{
uint64_t u;
memcpy(&u, p, 8);
return bswap_64(u);
}
static inline void sg_put_unaligned_be16(uint16_t val, void *p)
{
uint16_t u = bswap_16(val);
memcpy(p, &u, 2);
}
static inline void sg_put_unaligned_be32(uint32_t val, void *p)
{
uint32_t u = bswap_32(val);
memcpy(p, &u, 4);
}
static inline void sg_put_unaligned_be64(uint64_t val, void *p)
{
uint64_t u = bswap_64(val);
memcpy(p, &u, 8);
}
static inline uint16_t sg_get_unaligned_le16(const void *p)
{
uint16_t u;
memcpy(&u, p, 2);
return u;
}
static inline uint32_t sg_get_unaligned_le32(const void *p)
{
uint32_t u;
memcpy(&u, p, 4);
return u;
}
static inline uint64_t sg_get_unaligned_le64(const void *p)
{
uint64_t u;
memcpy(&u, p, 8);
return u;
}
static inline void sg_put_unaligned_le16(uint16_t val, void *p)
{
memcpy(p, &val, 2);
}
static inline void sg_put_unaligned_le32(uint32_t val, void *p)
{
memcpy(p, &val, 4);
}
static inline void sg_put_unaligned_le64(uint64_t val, void *p)
{
memcpy(p, &val, 8);
}
#elif defined(__BIG_ENDIAN__) || (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define GOT_UNALIGNED_SPECIALS 1
#include <byteswap.h>
// #warning ">>>>>> Doing BIG endian special unaligneds"
static inline uint16_t sg_get_unaligned_le16(const void *p)
{
uint16_t u;
memcpy(&u, p, 2);
return bswap_16(u);
}
static inline uint32_t sg_get_unaligned_le32(const void *p)
{
uint32_t u;
memcpy(&u, p, 4);
return bswap_32(u);
}
static inline uint64_t sg_get_unaligned_le64(const void *p)
{
uint64_t u;
memcpy(&u, p, 8);
return bswap_64(u);
}
static inline void sg_put_unaligned_le16(uint16_t val, void *p)
{
uint16_t u = bswap_16(val);
memcpy(p, &u, 2);
}
static inline void sg_put_unaligned_le32(uint32_t val, void *p)
{
uint32_t u = bswap_32(val);
memcpy(p, &u, 4);
}
static inline void sg_put_unaligned_le64(uint64_t val, void *p)
{
uint64_t u = bswap_64(val);
memcpy(p, &u, 8);
}
static inline uint16_t sg_get_unaligned_be16(const void *p)
{
uint16_t u;
memcpy(&u, p, 2);
return u;
}
static inline uint32_t sg_get_unaligned_be32(const void *p)
{
uint32_t u;
memcpy(&u, p, 4);
return u;
}
static inline uint64_t sg_get_unaligned_be64(const void *p)
{
uint64_t u;
memcpy(&u, p, 8);
return u;
}
static inline void sg_put_unaligned_be16(uint16_t val, void *p)
{
memcpy(p, &val, 2);
}
static inline void sg_put_unaligned_be32(uint32_t val, void *p)
{
memcpy(p, &val, 4);
}
static inline void sg_put_unaligned_be64(uint64_t val, void *p)
{
memcpy(p, &val, 8);
}
#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
#endif /* #if defined __BYTE_ORDER__ && defined <byteswap.h> &&
* ! defined IGNORE_FAST_LEBE */
#ifndef GOT_UNALIGNED_SPECIALS
/* Now we have no tricks left, so use the only way this can be done
* correctly in C safely: lots of shifts. */
// #warning ">>>>>> Doing GENERIC unaligneds"
static inline uint16_t sg_get_unaligned_be16(const void *p)
{
return ((const uint8_t *)p)[0] << 8 | ((const uint8_t *)p)[1];
}
static inline uint32_t sg_get_unaligned_be32(const void *p)
{
return ((const uint8_t *)p)[0] << 24 | ((const uint8_t *)p)[1] << 16 |
((const uint8_t *)p)[2] << 8 | ((const uint8_t *)p)[3];
}
static inline uint64_t sg_get_unaligned_be64(const void *p)
{
return (uint64_t)sg_get_unaligned_be32(p) << 32 |
sg_get_unaligned_be32((const uint8_t *)p + 4);
}
static inline void sg_put_unaligned_be16(uint16_t val, void *p)
{
((uint8_t *)p)[0] = (uint8_t)(val >> 8);
((uint8_t *)p)[1] = (uint8_t)val;
}
static inline void sg_put_unaligned_be32(uint32_t val, void *p)
{
sg_put_unaligned_be16(val >> 16, p);
sg_put_unaligned_be16(val, (uint8_t *)p + 2);
}
static inline void sg_put_unaligned_be64(uint64_t val, void *p)
{
sg_put_unaligned_be32(val >> 32, p);
sg_put_unaligned_be32(val, (uint8_t *)p + 4);
}
static inline uint16_t sg_get_unaligned_le16(const void *p)
{
return ((const uint8_t *)p)[1] << 8 | ((const uint8_t *)p)[0];
}
static inline uint32_t sg_get_unaligned_le32(const void *p)
{
return ((const uint8_t *)p)[3] << 24 | ((const uint8_t *)p)[2] << 16 |
((const uint8_t *)p)[1] << 8 | ((const uint8_t *)p)[0];
}
static inline uint64_t sg_get_unaligned_le64(const void *p)
{
return (uint64_t)sg_get_unaligned_le32((const uint8_t *)p + 4) << 32 |
sg_get_unaligned_le32(p);
}
static inline void sg_put_unaligned_le16(uint16_t val, void *p)
{
((uint8_t *)p)[0] = val & 0xff;
((uint8_t *)p)[1] = val >> 8;
}
static inline void sg_put_unaligned_le32(uint32_t val, void *p)
{
sg_put_unaligned_le16(val >> 16, (uint8_t *)p + 2);
sg_put_unaligned_le16(val, p);
}
static inline void sg_put_unaligned_le64(uint64_t val, void *p)
{
sg_put_unaligned_le32(val >> 32, (uint8_t *)p + 4);
sg_put_unaligned_le32(val, p);
}
#endif /* #ifndef GOT_UNALIGNED_SPECIALS */
/* Following are lesser used conversions that don't have specializations
* for endianness; big endian first. In summary these are the 24, 48 bit and
* given-length conversions plus the "nz" conditional put conversions. */
/* Now big endian, get 24+48 then put 24+48 */
static inline uint32_t sg_get_unaligned_be24(const void *p)
{
return ((const uint8_t *)p)[0] << 16 | ((const uint8_t *)p)[1] << 8 |
((const uint8_t *)p)[2];
}
/* Assume 48 bit value placed in uint64_t */
static inline uint64_t sg_get_unaligned_be48(const void *p)
{
return (uint64_t)sg_get_unaligned_be16(p) << 32 |
sg_get_unaligned_be32((const uint8_t *)p + 2);
}
/* Returns 0 if 'num_bytes' is less than or equal to 0 or greater than
* 8 (i.e. sizeof(uint64_t)). Else returns result in uint64_t which is
* an 8 byte unsigned integer. */
static inline uint64_t sg_get_unaligned_be(int num_bytes, const void *p)
{
if ((num_bytes <= 0) || (num_bytes > (int)sizeof(uint64_t)))
return 0;
else {
const uint8_t * xp = (const uint8_t *)p;
uint64_t res = *xp;
for (++xp; num_bytes > 1; ++xp, --num_bytes)
res = (res << 8) | *xp;
return res;
}
}
static inline void sg_put_unaligned_be24(uint32_t val, void *p)
{
((uint8_t *)p)[0] = (val >> 16) & 0xff;
((uint8_t *)p)[1] = (val >> 8) & 0xff;
((uint8_t *)p)[2] = val & 0xff;
}
/* Assume 48 bit value placed in uint64_t */
static inline void sg_put_unaligned_be48(uint64_t val, void *p)
{
sg_put_unaligned_be16(val >> 32, p);
sg_put_unaligned_be32(val, (uint8_t *)p + 2);
}
/* Now little endian, get 24+48 then put 24+48 */
static inline uint32_t sg_get_unaligned_le24(const void *p)
{
return (uint32_t)sg_get_unaligned_le16(p) |
((const uint8_t *)p)[2] << 16;
}
/* Assume 48 bit value placed in uint64_t */
static inline uint64_t sg_get_unaligned_le48(const void *p)
{
return (uint64_t)sg_get_unaligned_le16((const uint8_t *)p + 4) << 32 |
sg_get_unaligned_le32(p);
}
static inline void sg_put_unaligned_le24(uint32_t val, void *p)
{
((uint8_t *)p)[2] = (val >> 16) & 0xff;
((uint8_t *)p)[1] = (val >> 8) & 0xff;
((uint8_t *)p)[0] = val & 0xff;
}
/* Assume 48 bit value placed in uint64_t */
static inline void sg_put_unaligned_le48(uint64_t val, void *p)
{
((uint8_t *)p)[5] = (val >> 40) & 0xff;
((uint8_t *)p)[4] = (val >> 32) & 0xff;
((uint8_t *)p)[3] = (val >> 24) & 0xff;
((uint8_t *)p)[2] = (val >> 16) & 0xff;
((uint8_t *)p)[1] = (val >> 8) & 0xff;
((uint8_t *)p)[0] = val & 0xff;
}
/* Returns 0 if 'num_bytes' is less than or equal to 0 or greater than
* 8 (i.e. sizeof(uint64_t)). Else returns result in uint64_t which is
* an 8 byte unsigned integer. */
static inline uint64_t sg_get_unaligned_le(int num_bytes, const void *p)
{
if ((num_bytes <= 0) || (num_bytes > (int)sizeof(uint64_t)))
return 0;
else {
const uint8_t * xp = (const uint8_t *)p + (num_bytes - 1);
uint64_t res = *xp;
for (--xp; num_bytes > 1; --xp, --num_bytes)
res = (res << 8) | *xp;
return res;
}
}
/* Since cdb and parameter blocks are often memset to zero before these
* unaligned function partially fill them, then check for a val of zero
* and ignore if it is with these variants. First big endian, then little */
static inline void sg_nz_put_unaligned_be16(uint16_t val, void *p)
{
if (val)
sg_put_unaligned_be16(val, p);
}
static inline void sg_nz_put_unaligned_be24(uint32_t val, void *p)
{
if (val) {
((uint8_t *)p)[0] = (val >> 16) & 0xff;
((uint8_t *)p)[1] = (val >> 8) & 0xff;
((uint8_t *)p)[2] = val & 0xff;
}
}
static inline void sg_nz_put_unaligned_be32(uint32_t val, void *p)
{
if (val)
sg_put_unaligned_be32(val, p);
}
static inline void sg_nz_put_unaligned_be64(uint64_t val, void *p)
{
if (val)
sg_put_unaligned_be64(val, p);
}
static inline void sg_nz_put_unaligned_le16(uint16_t val, void *p)
{
if (val)
sg_put_unaligned_le16(val, p);
}
static inline void sg_nz_put_unaligned_le24(uint32_t val, void *p)
{
if (val) {
((uint8_t *)p)[2] = (val >> 16) & 0xff;
((uint8_t *)p)[1] = (val >> 8) & 0xff;
((uint8_t *)p)[0] = val & 0xff;
}
}
static inline void sg_nz_put_unaligned_le32(uint32_t val, void *p)
{
if (val)
sg_put_unaligned_le32(val, p);
}
static inline void sg_nz_put_unaligned_le64(uint64_t val, void *p)
{
if (val)
sg_put_unaligned_le64(val, p);
}
#ifdef __cplusplus
}
#endif
#endif /* SG_UNALIGNED_H */

View File

@ -1,21 +1,10 @@
.ig
Copyright (C) 2002-10 Bruce Allen
Copyright (C) 2004-17 Christian Franke
Copyright (C) 2004-18 Christian Franke
$Id: smartctl.8.in 4588 2017-11-04 15:15:32Z chrfranke $
SPDX-License-Identifier: GPL-2.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
You should have received a copy of the GNU General Public License
(for example COPYING); If not, see <http://www.gnu.org/licenses/>.
This code was originally developed as a Senior Thesis by Michael Cornwell
at the Concurrent Systems Laboratory (now part of the Storage Systems
Research Center), Jack Baskin School of Engineering, University of
California, Santa Cruz. http://ssrc.soe.ucsc.edu/
$Id: smartctl.8.in 4882 2018-12-29 21:26:45Z chrfranke $
..
.\" Macros borrowed from pages generated with Pod::Man
@ -165,7 +154,6 @@ scsi controller "\\\\.\\Scsi[0\-9]:".
For SATA or SAS disks behind an Areca controller use
\fB"/dev/arcmsr[0\-9]"\fP, see \*(Aq\-d areca,N[/E]\*(Aq below.
.Sp
[NEW EXPERIMENTAL SMARTCTL FEATURE]
Use the forms \fB"/dev/nvme[0\-9]"\fP (broadcast namespace) or
\fB"/dev/nvme[0\-9]n[1\-9]"\fP (specific namespace 1\-9) for first,
second, ..., NVMe device.
@ -228,10 +216,8 @@ If \*(Aq\-n\*(Aq (see below) is specified, the power mode of the drive is
printed.
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.Sp
[NVMe]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
For NVMe devices the information is obtained from the Identify Controller
and the Identify Namespace data structure.
[NVMe] For NVMe devices the information is obtained from the Identify
Controller and the Identify Namespace data structure.
.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.TP
.B \-\-identify[=[w][nvb]]
@ -273,7 +259,7 @@ For ATA devices this is equivalent to
.br
\*(Aq\-H \-i \-g all \-g wcreorder \-c \-A \-f brief \-l xerror,error
\-l xselftest,selftest \-l selective \-l directory \-l scttemp \-l scterc
\-l devstat \-l sataphy\*(Aq.
\-l devstat \-l defects \-l sataphy\*(Aq.
.br
and for SCSI, this is equivalent to
.br
@ -304,7 +290,6 @@ For example:
smartctl \-\-scan\-open \-\- \-a \-W 4,45,50 \-m admin@work > smartd.conf
.Ve
.Sp
[NEW EXPERIMENTAL SMARTCTL FEATURE]
Multiple \*(Aq\-d TYPE\*(Aq options may be specified with
\*(Aq\-\-scan[\-open]\*(Aq to combine the scan results of more than one TYPE.
.TP
@ -315,6 +300,48 @@ info.
.TP
.B RUN-TIME BEHAVIOR OPTIONS:
.TP
.B \-j, \-\-json[=cgiosuv]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
Enables JSON 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:
.br
\*(Aqc\*(Aq: Outputs \fBc\fRompact format without extra spaces and newlines.
By default, output is pretty-printed.
.br
\*(Aqg\*(Aq: Outputs JSON structure as single assignments to allow the usage
of \fBg\fRrep.
Each assignment reflects the absolute path of a value.
The syntax is compatible with \fBgron\fR:
.br
\*(Aqjson.KEY1[INDEX2].KEY3 = VALUE;\*(Aq.
.br
\*(Aqo\*(Aq: Includes the full \fBo\fRriginal plaintext \fBo\fRutput of
\fBsmartctl\fR as a JSON array \*(Aqsmartctl.output[]\*(Aq.
.br
\*(Aqs\*(Aq: Outputs JSON object elements \fBs\fRorted by key.
By default, object elements are ordered as generated internally.
.br
\*(Aqv\*(Aq: Enables \fBv\fRerbose output of possible unsafe integers.
If specified, values which may exceed JSON safe integer (53-bit) range are
always output as a number (with some \*(AqKEY\*(Aq) and a string
(\*(AqKEY_s\*(Aq), regardless of the actual value.
Values which may exceed 64-bit range are also output as a little endian
byte array (\*(AqKEY_le\*(Aq).
By default, the additional elements are only output if the value actually
exceeds the range.
.Sp
The following two arguments are primarily indented for development:
.br
\*(Aqi\*(Aq: Includes lines from the plaintext output which print info already
\fBi\fRmplemented for JSON output.
The lines appear as objects with key \*(Aqsmartctl_NNNN_i\*(Aq.
.br
\*(Aqu\*(Aq: Includes lines from the plaintext output which print info still
\fBu\fRnimplemented for JSON output.
The lines appear as objects with key \*(Aqsmartctl_NNNN_u\*(Aq.
.TP
.B \-q TYPE, \-\-quietmode=TYPE
Specifies that \fBsmartctl\fP should run in one of the quiet modes
described here. The valid arguments to this option are:
@ -347,7 +374,7 @@ This is the default.
.Sp
.I test
\- prints the guessed TYPE, then opens the device and prints the
(possibly changed) TYPE name and then exists without performing
(possibly changed) TYPE name and then exits without performing
any further commands.
.Sp
.I ata
@ -364,8 +391,7 @@ from issuing ATA commands to a SCSI device.
.\" %ENDIF NOT OS Darwin
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.I nvme[,NSID]
\- [NEW EXPERIMENTAL SMARTCTL FEATURE]
the device type is NVM Express (NVMe).
\- the device type is NVM Express (NVMe).
The optional parameter NSID specifies the namespace id (in hex) passed
to the driver.
Use 0xffffffff for the broadcast namespace id.
@ -422,6 +448,14 @@ PL2571/2771/2773/2775 USB to SATA bridge.
\- this device type is for SATA disks that are behind a SunplusIT USB to SATA
bridge.
.Sp
.I sntjmicron[,NSID]
\- [NEW EXPERIMENTAL SMARTCTL FEATURE]
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
.\" %ENDIF NOT OS Darwin
.\" %IF OS Linux
.I marvell
@ -454,7 +488,7 @@ For PERC5/6 controllers: \fBmegaraid_sas_ioctlN\fP
.\" %IF OS Linux Windows Cygwin
.I aacraid,H,L,ID
\- [Linux, Windows and Cygwin only] the device consists of one or more
SCSI/SAS disks connected to an AacRaid controller.
SCSI/SAS or SATA disks connected to an AacRaid controller.
The non-negative integers H,L,ID (Host number, Lun, ID) denote which disk
on the controller is monitored.
Use syntax such as:
@ -463,6 +497,9 @@ Use syntax such as:
.br
\fBsmartctl \-a \-d aacraid,1,0,4 /dev/sdb\fP
.Sp
Option \*(Aq\-d sat,auto+...\*(Aq is implicitly enabled to detect SATA disks.
Use \*(Aq\-d scsi+aacraid,H,L,ID\*(Aq to disable it.
.Sp
.\" %ENDIF OS Linux Windows Cygwin
.\" %IF OS Linux
On Linux, the following entry in /proc/devices must exist: \fBaac\fP.
@ -574,6 +611,9 @@ SATA disks connected to a cciss RAID controller.
The non-negative integer N (in the range from 0 to 15 inclusive) denotes
which disk on the controller is monitored.
.Sp
Option \*(Aq\-d sat,auto+...\*(Aq is implicitly enabled to detect SATA disks.
Use \*(Aq\-d scsi+cciss,N\*(Aq to disable it.
.Sp
To look at disks behind HP Smart Array controllers, use syntax
such as:
.\" %ENDIF OS FreeBSD Linux
@ -717,8 +757,7 @@ send to, or received from the device.
.Sp
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.I nvmeioctl
\- [NEW EXPERIMENTAL SMARTCTL FEATURE]
report only ioctl() transactions with NVMe devices.
\- report only ioctl() transactions with NVMe devices.
.Sp
.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
Any argument may include a positive integer to specify the level of detail
@ -1038,9 +1077,7 @@ This means that each alert condition is reported only once by \fBsmartctl\fP
for each initiator for each activation of the condition.
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.Sp
[NVMe]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
NVMe status is obtained by reading the "Critical Warning" byte from
[NVMe] NVMe status is obtained by reading the "Critical Warning" byte from
the SMART/Health Information log.
.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.TP
@ -1053,10 +1090,8 @@ scanning, and so on. If the device can carry out self-tests, this
option also shows the estimated time required to run those tests.
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.Sp
[NVMe]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
Prints various NVMe device capabilities obtained from the Identify Controller
and the Identify Namespace data structure.
[NVMe] Prints various NVMe device capabilities obtained from the Identify
Controller and the Identify Namespace data structure.
.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.TP
.B \-A, \-\-attributes
@ -1156,9 +1191,7 @@ The attributes are output in a relatively free format (compared with ATA
disk attributes).
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.Sp
[NVMe]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
For NVMe devices the attributes are obtained from the SMART/Health
[NVMe] For NVMe devices the attributes are obtained from the SMART/Health
Information log.
.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.TP
@ -1170,9 +1203,9 @@ Information log.
This is the default unless the \*(Aq\-x\*(Aq option is specified.
.Sp
.I brief
\- New format which fits into 80 colums (except in some rare cases).
\- New format which fits into 80 columns (except in some rare cases).
This format also decodes four additional attribute flags.
This is the default if the \*(Aq'\-x\*(Aq option is specified.
This is the default if the \*(Aq\-x\*(Aq option is specified.
.Sp
.I hex,id
\- Print all attribute IDs as hexadecimal numbers.
@ -1267,9 +1300,7 @@ The verify row is only output if it has an element other than zero.
.Sp
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.I error[,NUM]
\- [NVMe]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
prints the NVMe Error Information log.
\- [NVMe] prints the NVMe Error Information log.
Only the 16 most recent log entries are printed by default.
This number can be changed by the optional parameter NUM.
The maximum number of log entries is vendor specific
@ -1475,10 +1506,8 @@ writes a binary representation of the one sector log 0x11
.Sp
.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
.I nvmelog,PAGE,SIZE
\- [NVMe only]
[NEW EXPERIMENTAL SMARTCTL FEATURE]
prints a hex dump of the first SIZE bytes from the NVMe log with
identifier PAGE.
\- [NVMe only] prints a hex dump of the first SIZE bytes from the NVMe
log with identifier PAGE.
PAGE is a hexadecimal number in the range from 0x1 to 0xff.
SIZE is a hexadecimal number in the range from 0x4 to 0x4000 (16 KiB).
\fBWARNING: Do not specify the identifier of an unknown log page.
@ -1734,7 +1763,7 @@ accordingly.
.I xerrorlba
\- Fixes LBA byte ordering in Extended Comprehensive SMART error log.
Some disks use little endian byte ordering instead of ATA register
ordering to specifiy the LBA addresses in the log entries.
ordering to specify the LBA addresses in the log entries.
.Sp
.I swapid
\- Fixes byte swapped ATA identify strings (device name, serial number,
@ -2379,4 +2408,4 @@ Links to these and other documents may be found on the Links page of the
.SH PACKAGE VERSION
CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV
.br
$Id: smartctl.8.in 4588 2017-11-04 15:15:32Z chrfranke $
$Id: smartctl.8.in 4882 2018-12-29 21:26:45Z chrfranke $

View File

@ -4,25 +4,17 @@
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2002-11 Bruce Allen
* Copyright (C) 2008-17 Christian Franke
* Copyright (C) 2008-18 Christian Franke
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
@ -31,8 +23,6 @@
#include <stdexcept>
#include <getopt.h>
#include "config.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -41,7 +31,6 @@
#include <sys/param.h>
#endif
#include "int64.h"
#include "atacmds.h"
#include "dev_interface.h"
#include "ataprint.h"
@ -51,17 +40,26 @@
#include "nvmeprint.h"
#include "smartctl.h"
#include "utility.h"
#include "svnversion.h"
const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 4585 2017-11-04 13:41:03Z chrfranke $"
const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 4871 2018-12-27 20:03:12Z chrfranke $"
CONFIG_H_CVSID SMARTCTL_H_CVSID;
// Globals to control printing
bool printing_is_switchable = false;
bool printing_is_off = false;
// Control JSON output
json jglb;
static bool print_as_json = false;
static json::print_options print_as_json_options;
static bool print_as_json_output = false;
static bool print_as_json_impl = false;
static bool print_as_json_unimpl = false;
static void printslogan()
{
pout("%s\n", format_version_info("smartctl").c_str());
jout("%s\n", format_version_info("smartctl").c_str());
}
static void UsageSummary()
@ -70,13 +68,47 @@ static void UsageSummary()
return;
}
static void js_initialize(int argc, char **argv, bool verbose)
{
if (jglb.is_enabled())
return;
jglb.enable();
if (verbose)
jglb.set_verbose();
// Major.minor version of JSON format
jglb["json_format_version"][0] = 1;
jglb["json_format_version"][1] = 0;
// Smartctl version info
json::ref jref = jglb["smartctl"];
int ver[3] = { 0, 0, 0 };
sscanf(PACKAGE_VERSION, "%d.%d.%d", ver, ver+1, ver+2);
jref["version"][0] = ver[0];
jref["version"][1] = ver[1];
if (ver[2] > 0)
jref["version"][2] = ver[2];
#ifdef SMARTMONTOOLS_SVN_REV
jref["svn_revision"] = SMARTMONTOOLS_SVN_REV;
#endif
jref["platform_info"] = smi()->get_os_version_str();
#ifdef BUILD_INFO
jref["build_info"] = BUILD_INFO;
#endif
jref["argv"][0] = "smartctl";
for (int i = 1; i < argc; i++)
jref["argv"][i] = argv[i];
}
static std::string getvalidarglist(int opt);
/* void prints help information for command syntax */
static void Usage()
{
printf("Usage: smartctl [options] device\n\n");
printf(
pout("Usage: smartctl [options] device\n\n");
pout(
"============================================ SHOW INFORMATION OPTIONS =====\n\n"
" -h, --help, --usage\n"
" Display this help and exit\n\n"
@ -98,8 +130,10 @@ static void Usage()
" --scan-open\n"
" Scan for devices and try to open each device\n\n"
);
printf(
pout(
"================================== SMARTCTL RUN-TIME BEHAVIOR OPTIONS =====\n\n"
" -j, --json[=[cgiosuv]]\n"
" Print output in JSON 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"
@ -114,7 +148,7 @@ static void Usage()
" -n MODE[,STATUS], --nocheck=MODE[,STATUS] (ATA)\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 ?
printf(
pout(
"============================== DEVICE FEATURE ENABLE/DISABLE COMMANDS =====\n\n"
" -s VALUE, --smart=VALUE\n"
" Enable/disable SMART on device (on/off)\n\n"
@ -128,7 +162,7 @@ static void Usage()
" standby,[N|off|now], wcache,[on|off], rcache,[on|off],\n"
" wcreorder,[on|off[,p]], wcache-sct,[ata|on|off[,p]]\n\n"
);
printf(
pout(
"======================================= READ AND DISPLAY DATA OPTIONS =====\n\n"
" -H, --health\n"
" Show device SMART health status\n\n"
@ -158,13 +192,13 @@ static void Usage()
get_drivedb_path_add()
);
#ifdef SMARTMONTOOLS_DRIVEDBDIR
printf(
pout(
"\n"
" and then %s",
get_drivedb_path_default()
);
#endif
printf(
pout(
"]\n\n"
"============================================ DEVICE SELF-TEST OPTIONS =====\n\n"
" -t TEST, --test=TEST\n"
@ -177,7 +211,7 @@ static void Usage()
);
std::string examples = smi()->get_app_examples("smartctl");
if (!examples.empty())
printf("%s\n", examples.c_str());
pout("%s\n", examples.c_str());
}
// Values for --long only options, see parse_options()
@ -231,6 +265,8 @@ static std::string getvalidarglist(int opt)
"wcache-sct,[ata|on|off[,p]]";
case 's':
return getvalidarglist(opt_smart)+", "+getvalidarglist(opt_set);
case 'j':
return "c, g, i, o, s, u, v";
case opt_identify:
return "n, wn, w, v, wv, wb";
case 'v':
@ -244,7 +280,7 @@ static std::string getvalidarglist(int opt)
static void printvalidarglistmessage(int opt)
{
if (opt=='v'){
pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n",
jerr("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n",
create_vendor_attribute_arg_list().c_str());
}
else {
@ -252,7 +288,7 @@ static void printvalidarglistmessage(int opt)
// need to figure out which to get the formatting right.
std::string s = getvalidarglist(opt);
char separator = strchr(s.c_str(), '\n') ? '\n' : ' ';
pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, s.c_str(), separator);
jerr("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, s.c_str(), separator);
}
return;
@ -269,12 +305,12 @@ static void scan_devices(const smart_devtype_list & types, bool with_open, char
/* Takes command options and sets features to be run */
static const char * parse_options(int argc, char** argv,
static int parse_options(int argc, char** argv, const char * & type,
ata_print_options & ataopts, scsi_print_options & scsiopts,
nvme_print_options & nvmeopts, bool & print_type_only)
{
// Please update getvalidarglist() if you edit shortopts
const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:g:";
const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:g:j";
// Please update getvalidarglist() if you edit longopts
struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
@ -307,6 +343,7 @@ static const char * parse_options(int argc, char** argv,
{ "drivedb", required_argument, 0, 'B' },
{ "format", required_argument, 0, 'f' },
{ "get", required_argument, 0, 'g' },
{ "json", optional_argument, 0, 'j' },
{ "identify", optional_argument, 0, opt_identify },
{ "set", required_argument, 0, opt_set },
{ "scan", no_argument, 0, opt_scan },
@ -318,7 +355,6 @@ static const char * parse_options(int argc, char** argv,
memset(extraerror, 0, sizeof(extraerror));
opterr=optopt=0;
const char * type = 0; // set to -d optarg
smart_devtype_list scan_types; // multiple -d TYPE options for --scan
bool use_default_db = true; // set false on '-B FILE'
bool output_format_set = false; // set true on '-f FORMAT'
@ -330,12 +366,19 @@ static const char * parse_options(int argc, char** argv,
char *arg;
while ((optchar = getopt_long(argc, argv, shortopts, longopts, 0)) != -1) {
// Clang analyzer: Workaround for false positive messages
// 'Dereference of null pointer' and 'Null pointer argument'
bool optarg_is_set = !!optarg;
#ifdef __clang_analyzer__
if (!optarg_is_set) optarg = (char *)"";
#endif
switch (optchar){
case 'V':
printing_is_off = false;
pout("%s", format_version_info("smartctl", true /*full*/).c_str());
EXIT(0);
break;
return 0;
case 'q':
if (!strcmp(optarg,"errorsonly")) {
printing_is_switchable = true;
@ -635,7 +678,7 @@ static const char * parse_options(int argc, char** argv,
case opt_identify:
ataopts.identify_word_level = ataopts.identify_bit_level = 0;
if (optarg) {
if (optarg_is_set) {
for (int i = 0; optarg[i]; i++) {
switch (optarg[i]) {
case 'w': ataopts.identify_word_level = 1; break;
@ -677,8 +720,7 @@ static const char * parse_options(int argc, char** argv,
ataopts.sct_erc_get = true;
ataopts.sct_wcache_reorder_get = true;
ataopts.devstat_all_pages = true;
// ataopts.pending_defects_log = 31; // TODO: Add if no longer EXPERIMENTAL
ataopts.pending_defects_info = true; // TODO: Remove then
ataopts.pending_defects_log = 31;
ataopts.sataphy = true;
ataopts.get_set_used = true;
ataopts.get_aam = ataopts.get_apm = true;
@ -699,7 +741,7 @@ static const char * parse_options(int argc, char** argv,
printslogan();
pout("The valid arguments to -v are:\n\thelp\n%s\n",
create_vendor_attribute_arg_list().c_str());
EXIT(0);
return 0;
}
if (!parse_attribute_def(optarg, ataopts.attribute_defs, PRIOR_USER))
badarg = true;
@ -713,14 +755,14 @@ static const char * parse_options(int argc, char** argv,
ataopts.show_presets = true;
} else if (!strcmp(optarg, "showall")) {
if (!init_drive_database(use_default_db))
EXIT(FAILCMD);
return FAILCMD;
if (optind < argc) { // -P showall MODEL [FIRMWARE]
int cnt = showmatchingpresets(argv[optind], (optind+1<argc ? argv[optind+1] : NULL));
EXIT(cnt); // report #matches
return (cnt >= 0 ? cnt : 0);
}
if (showallpresets())
EXIT(FAILCMD); // report regexp syntax error
EXIT(0);
return FAILCMD; // report regexp syntax error
return 0;
} else {
badarg = true;
}
@ -863,15 +905,14 @@ static const char * parse_options(int argc, char** argv,
else
use_default_db = false;
if (!read_drive_database(path))
EXIT(FAILCMD);
return FAILCMD;
}
break;
case 'h':
printing_is_off = false;
printslogan();
Usage();
EXIT(0);
break;
return 0;
case 'g':
case_s_continued: // -s, see above
@ -1047,6 +1088,33 @@ static const char * parse_options(int argc, char** argv,
scan = optchar;
break;
case 'j':
{
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_output = false;
print_as_json_impl = print_as_json_unimpl = false;
bool json_verbose = false;
if (optarg_is_set) {
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 '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;
default: badarg = true;
}
}
}
js_initialize(argc, argv, json_verbose);
}
break;
case '?':
default:
printing_is_off = false;
@ -1057,31 +1125,31 @@ static const char * parse_options(int argc, char** argv,
if (arg[1] == '-' && optchar != 'h') {
// Iff optopt holds a valid option then argument must be missing.
if (optopt && (optopt >= opt_scan || strchr(shortopts, optopt))) {
pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2);
jerr("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2);
printvalidarglistmessage(optopt);
} else
pout("=======> UNRECOGNIZED OPTION: %s\n",arg+2);
jerr("=======> UNRECOGNIZED OPTION: %s\n",arg+2);
if (extraerror[0])
pout("=======> %s", extraerror);
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
if (0 < optopt && optopt < '~') {
// Iff optopt holds a valid option then argument must be
// missing. Note (BA) this logic seems to fail using Solaris
// getopt!
if (strchr(shortopts, optopt) != NULL) {
pout("=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt);
jerr("=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt);
printvalidarglistmessage(optopt);
} else
pout("=======> UNRECOGNIZED OPTION: %c\n",optopt);
jerr("=======> UNRECOGNIZED OPTION: %c\n",optopt);
if (extraerror[0])
pout("=======> %s", extraerror);
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
Usage();
EXIT(0);
return 0;
} // closes switch statement to process command-line options
// Check to see if option had an unrecognized or incorrect argument.
@ -1091,15 +1159,16 @@ static const char * parse_options(int argc, char** argv,
// here, but we just print the short form. Please fix this if you know
// a clean way to do it.
char optstr[] = { (char)optchar, 0 };
pout("=======> INVALID ARGUMENT TO -%s: %s\n",
jerr("=======> INVALID ARGUMENT TO -%s: %s\n",
(optchar == opt_identify ? "-identify" :
optchar == opt_set ? "-set" :
optchar == opt_smart ? "-smart" : optstr), optarg);
optchar == opt_smart ? "-smart" :
optchar == 'j' ? "-json" : optstr), optarg);
printvalidarglistmessage(optchar);
if (extraerror[0])
pout("=======> %s", extraerror);
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
}
@ -1107,9 +1176,9 @@ static const char * parse_options(int argc, char** argv,
if (scan) {
// Read or init drive database to allow USB ID check.
if (!init_drive_database(use_default_db))
EXIT(FAILCMD);
return FAILCMD;
scan_devices(scan_types, (scan == opt_scan_open), argv + optind);
EXIT(0);
return 0;
}
// At this point we have processed all command-line options. If the
@ -1122,18 +1191,18 @@ static const char * parse_options(int argc, char** argv,
if (scan_types.size() > 1) {
printing_is_off = false;
printslogan();
pout("ERROR: multiple -d TYPE options are only allowed with --scan\n");
jerr("ERROR: multiple -d TYPE options are only allowed with --scan\n");
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
// error message if user has asked for more than one test
if (testcnt > 1) {
printing_is_off = false;
printslogan();
pout("\nERROR: smartctl can only run a single test type (or abort) at a time.\n");
jerr("\nERROR: smartctl can only run a single test type (or abort) at a time.\n");
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
// error message if user has set selective self-test options without
@ -1143,11 +1212,11 @@ static const char * parse_options(int argc, char** argv,
printing_is_off = false;
printslogan();
if (ataopts.smart_selective_args.pending_time)
pout("\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n");
jerr("\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n");
else
pout("\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n");
jerr("\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n");
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
// If captive option was used, change test type if appropriate.
@ -1176,51 +1245,154 @@ static const char * parse_options(int argc, char** argv,
// Warn if the user has provided no device name
if (argc-optind<1){
pout("ERROR: smartctl requires a device name as the final command-line argument.\n\n");
jerr("ERROR: smartctl requires a device name as the final command-line argument.\n\n");
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
// Warn if the user has provided more than one device name
if (argc-optind>1){
int i;
pout("ERROR: smartctl takes ONE device name as the final command-line argument.\n");
jerr("ERROR: smartctl takes ONE device name as the final command-line argument.\n");
pout("You have provided %d device names:\n",argc-optind);
for (i=0; i<argc-optind; i++)
pout("%s\n",argv[optind+i]);
UsageSummary();
EXIT(FAILCMD);
return FAILCMD;
}
// Read or init drive database
if (!init_drive_database(use_default_db))
EXIT(FAILCMD);
return FAILCMD;
return type;
// No error, continue in main_worker()
return -1;
}
// Printing function (controlled by global printing_is_off)
// [From GLIBC Manual: Since the prototype doesn't specify types for
// optional arguments, in a call to a variadic function the default
// argument promotions are performed on the optional argument
// values. This means the objects of type char or short int (whether
// signed or not) are promoted to either int or unsigned int, as
// appropriate.]
void pout(const char *fmt, ...){
va_list ap;
// initialize variable argument list
va_start(ap,fmt);
if (printing_is_off) {
va_end(ap);
return;
}
// Printing functions
// print out
vprintf(fmt,ap);
__attribute_format_printf(3, 0)
static void vjpout(bool is_js_impl, const char * msg_severity,
const char *fmt, va_list ap)
{
if (!print_as_json) {
// Print out directly
vprintf(fmt, ap);
fflush(stdout);
}
else {
// Add lines to JSON output
static char buf[1024];
static char * bufnext = buf;
vsnprintf(bufnext, sizeof(buf) - (bufnext - buf), fmt, ap);
for (char * p = buf, *q; ; p = q) {
if (!(q = strchr(p, '\n'))) {
// Keep remaining line for next call
for (bufnext = buf; *p; bufnext++, p++)
*bufnext = *p;
break;
}
*q++ = 0; // '\n' -> '\0'
static int lineno = 0;
lineno++;
if (print_as_json_output) {
// Collect full output in array
static int outindex = 0;
jglb["smartctl"]["output"][outindex++] = p;
}
if (!*p)
continue; // Skip empty line
if (msg_severity) {
// Collect non-empty messages in array
static int errindex = 0;
json::ref jref = jglb["smartctl"]["messages"][errindex++];
jref["string"] = p;
jref["severity"] = msg_severity;
}
if ( ( is_js_impl && print_as_json_impl )
|| (!is_js_impl && print_as_json_unimpl)) {
// Add (un)implemented non-empty lines to global object
jglb[strprintf("smartctl_%04d_%c", lineno,
(is_js_impl ? 'i' : 'u')).c_str()] = p;
}
}
}
}
// Default: print to stdout
// --json: ignore
// --json=o: append to "output" array
// --json=u: add "smartctl_NNNN_u" element(s)
void pout(const char *fmt, ...)
{
if (printing_is_off)
return;
if (print_as_json && !(print_as_json_output
|| print_as_json_impl || print_as_json_unimpl))
return;
va_list ap;
va_start(ap, fmt);
vjpout(false, 0, fmt, ap);
va_end(ap);
}
// Default: Print to stdout
// --json: ignore
// --json=o: append to "output" array
// --json=i: add "smartctl_NNNN_i" element(s)
void jout(const char *fmt, ...)
{
if (printing_is_off)
return;
if (print_as_json && !(print_as_json_output
|| print_as_json_impl || print_as_json_unimpl))
return;
va_list ap;
va_start(ap, fmt);
vjpout(true, 0, fmt, ap);
va_end(ap);
}
// Default: print to stdout
// --json: append to "messages"
// --json=o: append to "output" array
// --json=i: add "smartctl_NNNN_i" element(s)
void jinf(const char *fmt, ...)
{
if (printing_is_off)
return;
va_list ap;
va_start(ap, fmt);
vjpout(true, "information", fmt, ap);
va_end(ap);
}
void jwrn(const char *fmt, ...)
{
if (printing_is_off)
return;
va_list ap;
va_start(ap, fmt);
vjpout(true, "warning", fmt, ap);
va_end(ap);
}
void jerr(const char *fmt, ...)
{
if (printing_is_off)
return;
va_list ap;
va_start(ap, fmt);
vjpout(true, "error", fmt, ap);
va_end(ap);
fflush(stdout);
return;
}
// Globals to set failuretest() policy
@ -1237,7 +1409,7 @@ void failuretest(failure_type type, int returnvalue)
if (!failuretest_conservative)
return;
pout("An optional SMART command failed: exiting. Remove '-T conservative' option to continue.\n");
EXIT(returnvalue);
throw int(returnvalue);
}
// If this is an error in a "mandatory" SMART command
@ -1245,7 +1417,7 @@ void failuretest(failure_type type, int returnvalue)
if (failuretest_permissive--)
return;
pout("A mandatory SMART command failed: exiting. To continue, add one or more '-T permissive' options.\n");
EXIT(returnvalue);
throw int(returnvalue);
}
throw std::logic_error("failuretest: Unknown type");
@ -1263,7 +1435,7 @@ void checksumwarning(const char * string)
// user has asked us to fail on checksum errors
if (checksum_err_mode == CHECKSUM_ERR_EXIT)
EXIT(FAILSMART);
throw int(FAILSMART);
}
// Return info string about device protocol
@ -1280,6 +1452,15 @@ static const char * get_protocol_info(const smart_device * dev)
}
}
// Add JSON device info
static void js_device_info(const json::ref & jref, const smart_device * dev)
{
jref["name"] = dev->get_dev_name();
jref["info_name"] = dev->get_info_name();
jref["type"] = dev->get_dev_type();
jref["protocol"] = get_protocol_info(dev);
}
// Device scan
// smartctl [-d type] --scan[-open] -- [PATTERN] [smartd directive ...]
void scan_devices(const smart_devtype_list & types, bool with_open, char ** argv)
@ -1303,27 +1484,31 @@ void scan_devices(const smart_devtype_list & types, bool with_open, char ** argv
for (unsigned i = 0; i < devlist.size(); i++) {
smart_device_auto_ptr dev( devlist.release(i) );
json::ref jref = jglb["devices"][i];
if (with_open) {
printing_is_off = dont_print;
dev.replace ( dev->autodetect_open() );
printing_is_off = false;
if (!dev->is_open()) {
pout("# %s -d %s # %s, %s device open failed: %s\n", dev->get_dev_name(),
dev->get_dev_type(), dev->get_info_name(),
get_protocol_info(dev.get()), dev->get_errmsg());
continue;
}
}
pout("%s -d %s", dev->get_dev_name(), dev->get_dev_type());
js_device_info(jref, dev.get());
if (with_open && !dev->is_open()) {
jout("# %s -d %s # %s, %s device open failed: %s\n", dev->get_dev_name(),
dev->get_dev_type(), dev->get_info_name(),
get_protocol_info(dev.get()), dev->get_errmsg());
jref["open_error"] = dev->get_errmsg();
continue;
}
jout("%s -d %s", dev->get_dev_name(), dev->get_dev_type());
if (!argv[ai])
pout(" # %s, %s device\n", dev->get_info_name(), get_protocol_info(dev.get()));
jout(" # %s, %s device\n", dev->get_info_name(), get_protocol_info(dev.get()));
else {
for (int j = ai; argv[j]; j++)
pout(" %s", argv[j]);
pout("\n");
jout(" %s", argv[j]);
jout("\n");
}
if (dev->is_open())
@ -1343,11 +1528,16 @@ static int main_worker(int argc, char **argv)
return 1;
// Parse input arguments
const char * type = 0;
ata_print_options ataopts;
scsi_print_options scsiopts;
nvme_print_options nvmeopts;
bool print_type_only = false;
const char * type = parse_options(argc, argv, ataopts, scsiopts, nvmeopts, print_type_only);
{
int status = parse_options(argc, argv, type, ataopts, scsiopts, nvmeopts, print_type_only);
if (status >= 0)
return status;
}
const char * name = argv[argc-1];
@ -1366,7 +1556,7 @@ static int main_worker(int argc, char **argv)
dev = smi()->get_smart_device(name, type);
if (!dev) {
pout("%s: %s\n", name, smi()->get_errmsg());
jerr("%s: %s\n", name, smi()->get_errmsg());
if (type)
printvalidarglistmessage('d');
else
@ -1381,7 +1571,7 @@ static int main_worker(int argc, char **argv)
dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev.get()));
if (dev->is_ata() && ataopts.powermode>=2 && dev->is_powered_down()) {
pout("Device is in STANDBY (OS) mode, exit(%d)\n", ataopts.powerexit);
jinf("Device is in STANDBY (OS) mode, exit(%d)\n", ataopts.powerexit);
return ataopts.powerexit;
}
@ -1400,14 +1590,17 @@ static int main_worker(int argc, char **argv)
dev->get_info_name(), oldinfo.dev_type.c_str(), dev->get_dev_type());
}
if (!dev->is_open()) {
pout("Smartctl open device: %s failed: %s\n", dev->get_info_name(), dev->get_errmsg());
jerr("Smartctl open device: %s failed: %s\n", dev->get_info_name(), dev->get_errmsg());
return FAILDEV;
}
// Add JSON info similar to --scan output
js_device_info(jglb["device"], dev.get());
// now call appropriate ATA or SCSI routine
int retval = 0;
if (print_type_only)
pout("%s: Device of type '%s' [%s] opened\n",
jout("%s: Device of type '%s' [%s] opened\n",
dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev.get()));
else if (dev->is_ata())
retval = ataPrintMain(dev->to_ata(), ataopts);
@ -1431,12 +1624,19 @@ int main(int argc, char **argv)
bool badcode = false;
try {
// Do the real work ...
status = main_worker(argc, argv);
}
catch (int ex) {
// EXIT(status) arrives here
status = ex;
try {
// Do the real work ...
status = main_worker(argc, argv);
}
catch (int ex) {
// Exit status from checksumwarning() and failuretest() arrives here
status = ex;
}
// Print JSON if enabled
if (jglb.has_uint128_output())
jglb["smartctl"]["uint128_precision_bits"] = uint128_to_str_precision_bits();
jglb["smartctl"]["exit_status"] = status;
jglb.print(stdout, print_as_json_options);
}
catch (const std::bad_alloc & /*ex*/) {
// Memory allocation failed (also thrown by std::operator new)

Some files were not shown because too many files have changed in this diff Show More