mirror of
https://git.proxmox.com/git/mirror_smartmontools-debian
synced 2025-12-29 07:54:53 +00:00
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:
parent
a818ba584c
commit
ff28b140e6
4
AUTHORS
4
AUTHORS
@ -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
893
ChangeLog
@ -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
241
INSTALL
@ -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
|
||||
|
||||
56
Makefile.am
56
Makefile.am
@ -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
|
||||
|
||||
218
Makefile.in
218
Makefile.in
@ -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
50
NEWS
@ -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
6
README
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]";
|
||||
|
||||
@ -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. */
|
||||
|
||||
296
atacmds.cpp
296
atacmds.cpp
@ -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;
|
||||
|
||||
|
||||
86
atacmds.h
86
atacmds.h
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
1653
ataprint.cpp
1653
ataprint.cpp
File diff suppressed because it is too large
Load Diff
21
ataprint.h
21
ataprint.h
@ -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),
|
||||
|
||||
@ -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"
|
||||
|
||||
27
cciss.cpp
27
cciss.cpp
@ -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
12
cciss.h
@ -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);
|
||||
|
||||
56
config.h.in
56
config.h.in
@ -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
|
||||
|
||||
|
||||
487
configure.ac
487
configure.ac
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
11
dev_areca.h
11
dev_areca.h
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 &);
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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/')
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
96
getopt/bits/getopt_core.h
Normal 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
77
getopt/bits/getopt_ext.h
Normal 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 */
|
||||
1399
getopt/getopt.c
1399
getopt/getopt.c
File diff suppressed because it is too large
Load Diff
194
getopt/getopt.h
194
getopt/getopt.h
@ -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 */
|
||||
|
||||
117
getopt/getopt1.c
117
getopt/getopt1.c
@ -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
118
getopt/getopt_int.h
Normal 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
517
json.cpp
Normal 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
195
json.h
Normal 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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
10
megaraid.h
10
megaraid.h
@ -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
|
||||
|
||||
22
nvmecmds.cpp
22
nvmecmds.cpp
@ -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()) {
|
||||
|
||||
33
nvmecmds.h
33
nvmecmds.h
@ -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,
|
||||
|
||||
242
nvmeprint.cpp
242
nvmeprint.cpp
@ -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;
|
||||
}
|
||||
|
||||
|
||||
11
nvmeprint.h
11
nvmeprint.h
@ -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"
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
17
os_darwin.h
17
os_darwin.h
@ -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"
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
17
os_freebsd.h
17
os_freebsd.h
@ -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
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
17
os_generic.h
17
os_generic.h
@ -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
|
||||
|
||||
389
os_linux.cpp
389
os_linux.cpp
@ -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
|
||||
|
||||
20
os_linux.h
20
os_linux.h
@ -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
|
||||
|
||||
126
os_netbsd.cpp
126
os_netbsd.cpp
@ -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;
|
||||
}
|
||||
|
||||
17
os_netbsd.h
17
os_netbsd.h
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
17
os_openbsd.h
17
os_openbsd.h
@ -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... */
|
||||
|
||||
28
os_os2.cpp
28
os_os2.cpp
@ -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
|
||||
|
||||
11
os_os2.h
11
os_os2.h
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
21
os_qnxnto.h
21
os_qnxnto.h
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
os_solaris.h
17
os_solaris.h
@ -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
|
||||
|
||||
196
os_win32.cpp
196
os_win32.cpp
@ -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") );
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
55
os_win32/popen.h
Normal 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
176
os_win32/popen_win32.cpp
Normal 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;
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 $
|
||||
;
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
|
||||
@ -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*/
|
||||
|
||||
@ -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"
|
||||
|
||||
3016
regex/regcomp.c
3016
regex/regcomp.c
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
|
||||
|
||||
580
regex/regex.h
580
regex/regex.h
@ -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
3643
regex/regexec.c
3643
regex/regexec.c
File diff suppressed because it is too large
Load Diff
144
scsiata.cpp
144
scsiata.cpp
@ -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
|
||||
|
||||
663
scsicmds.cpp
663
scsicmds.cpp
File diff suppressed because it is too large
Load Diff
235
scsicmds.h
235
scsicmds.h
@ -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
259
scsinvme.cpp
Normal 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;
|
||||
}
|
||||
982
scsiprint.cpp
982
scsiprint.cpp
File diff suppressed because it is too large
Load Diff
19
scsiprint.h
19
scsiprint.h
@ -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
489
sg_unaligned.h
Normal 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 */
|
||||
125
smartctl.8.in
125
smartctl.8.in
@ -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 $
|
||||
|
||||
430
smartctl.cpp
430
smartctl.cpp
@ -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
Loading…
Reference in New Issue
Block a user