]> git.proxmox.com Git - mirror_smartmontools-debian.git/commitdiff
Imported Upstream version 5.41+svn3365
authorGiuseppe Iuculano <iuculano@debian.org>
Sun, 19 Jun 2011 15:15:57 +0000 (17:15 +0200)
committerGiuseppe Iuculano <iuculano@debian.org>
Sun, 19 Jun 2011 15:15:57 +0000 (17:15 +0200)
26 files changed:
CHANGELOG
INSTALL
Makefile.am
NEWS
atacmds.cpp
atacmds.h
ataprint.cpp
ataprint.h
configure.in
drivedb.h
knowndrives.cpp
os_freebsd.cpp
os_linux.cpp
os_win32.cpp
os_win32/installer.nsi
scsicmds.cpp
scsicmds.h
scsiprint.cpp
smartctl.8.in
smartctl.cpp
smartd.cpp
smartd.freebsd.initd.in [new file with mode: 0644]
smartd.initd.in [changed mode: 0755->0644]
smartd.service.in [new file with mode: 0644]
utility.cpp
utility.h

index b71494899a289bfbccba852daf3367a75fce0040..120ae90d5dde4f2ddb59e15d8b8bf1a849db2db6 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG 3296 2011-03-16 22:17:51Z chrfranke $
+$Id: CHANGELOG 3365 2011-06-09 18:47:31Z chrfranke $
 
 The most recent version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/CHANGELOG?view=markup
@@ -41,6 +41,214 @@ Maintainers / Developers Key (alphabetic order):
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+smartmontools 5.41 2011-06-09
+
+  [MS] drivedb.h: revert attribute 190 to default for Samsung SSD controllers,
+       some 470 series SSDs seem to have some temperature information at
+       this location.
+
+  [MS] drivedb.h update:
+       add attribute details for Samsung controllers, centralize entries
+
+  [MS] drivedb.h update:
+       add attribute details for JMicron JMF61x controllers
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add OCZ DENEVA
+
+  [CF] os_win32.cpp: Ignore vendor ID "ATA" if returned by
+       IOCTL_STORAGE_QUERY_PROPERTY.
+
+  [CF] Add ATA NCQ commands to error register decoding.
+
+  [CF] Re-enable '--with-initscriptdir=auto' as default.
+       Change search for initddir and systemdsystemunitdir such that
+       default ./configure does never overwrite system files.
+
+  [MS] drivedb.h update:
+       disentangle Transcend SSD versions
+
+  [MS] drivedb.h update:
+       add attribute details for Crucial C300
+
+  [MS] smartd.initd.in:
+       fix for debian, cleanup. Based on patch of CF.
+
+  [AS] --with-initscriptdir default changed to "no" from "auto" to avoid 
+       filesystem pollution.
+
+  [MS] drivedb.h cleanup:
+       harmonize family names, add AF information into name
+
+  [MS] drivedb.h update:
+       - OCZ Vertex 3
+       - Seagate Barracuda Green 1TB variant
+
+  [CF] Windows: Avoid '%n' printf format specifier because it is always
+       disabled in recent versions of msvcrt.dll.  This fixes truncation
+       of smartd warning email (ticket #174).
+
+  [MS] smartd.initd.in:
+       cleanup, provide targets "reload" and "report" for all platforms
+
+  [CF] drivedb.h update:
+       - JMicron based SSD (JMicron JMF602?): rename from
+         Kingston SSDNow V Series, move Transcend IDE and SATA
+         entries to here.
+
+  [CF] Support ':BYTEORDER' for all attribute print formats.
+
+  [CF] drivedb.h update:
+       - Kingston SSDNow V Series SSDs (ticket #171)
+
+  [CF] Increase size of drive database option parse buffer
+       to allow long '-v N,FORMAT:BYTEORDER,NAME' options.
+
+  [MS] drivedb.h update:
+       - Western Digital Scorpio Blue Advanced Format variants
+
+  [MS] drivedb.h update:
+       correct typo for Cowon iAudio X5
+
+  [MS] drivedb.h USB updates:
+       - Maxtor OneTouch 200GB (unsupported)
+       - LaCie Little Disk
+
+  [AS] FreeBSD: Added native rc.conf style script to the package. 
+       Modifications to the configure script to use correct template and
+       path.
+
+  [AS] freebsd_os.cpp:
+       Fix memory leak in the ata detection code (added free())
+       Using bzero in cam code to clear structure (fixing varnish varning)
+
+  [MS] drivedb.h update:
+       Kingston SSDNow S100 Series
+
+  [MS] drivedb.h USB update:
+       - Samsung S1 Portable
+       - LaCie rikiki USB 3.0
+       - Seagate FreeAgent GoFlex USB 3.0
+       - Cowon iAudio X5
+       - Oxford OXU921DS chip (unsupported)
+
+  [CF] Windows: Add debug output of SCSI sense data.
+
+  [CF] Add 'smartd.service' file for systemd.
+       Add configure option '--with-systemdsystemunitdir'.
+       Disable initd script if systemd is used.
+
+  [MS] drivedb.h update:
+       - Western Digital AV-25 family
+
+  [MS] drivedb.h update:
+       JMicron based SSDs: Add
+         Kingston SSDNow V, Kingston SSDNow V+100, TOSHIBA THNS128GG4BBAA,
+         APPLE SSD TS*, ADATA S596 Turbo
+
+  [CF] drivedb.h update:
+       - Intel 510 Series SSDs (ticket #170)
+
+  [CF] smartctl: Don't issue SMART DISABLE command to 3ware controllers
+       when the port number was not specified (ticket #165).
+
+  [CF] Use get_errmsg() from device instead of errno or syserror() for
+       printing error messages.
+
+  [MS] drivedb.h updates:
+       - G.Skill FALCON II SSD (Indilinx)
+       - HP 250GB SATA disk VB0250EAVER
+       - SAMSUNG SpinPoint M5 HM160HC
+       - SAMSUNG SpinPoint MT2 HM100UI
+       - SAMSUNG HM100UX
+       - Hitachi Deskstar 5K3000 Series
+       - Seagate Barracuda Green (Adv. Format)
+       - Seagate Barracuda XT 3TB variant
+       - Western Digital RE4 Serial ATA family
+       - Western Digital Caviar Green WD20EACS
+       - Western Digital Caviar Black family, SATA 3.0 variants
+       - QUANTUM FIREBALLlct20 10
+       - QUANTUM FIREBALLP AS60.0
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add more OCZ SF-1200 and SF-1500 based drives
+
+       Thanks to Sudhir Verman from OCZ Technology for providing this info.
+
+  [CF] drivedb.h USB updates:
+       - Seagate Expansion External (0x0bc2:0x3300) (Debian bug 621411)
+       - ASMedia USB 3.0 (0x174c:0x55aa) (unsupported)
+
+  [CF] smartctl.8.in: Clarify '-t vendor,N' (ticket #169).
+       Update Intel info (ticket #168).
+
+  [CF] drivedb.h update:
+       - Intel 320 Series SSDs (ticket #168)
+
+  [CF] smartctl: Always print sector size in '-i' output (ticket #166).
+
+  [CF] os_linux.cpp: Shorten version string.
+
+  [CF] smartctl: Add option '-f brief' to select new attribute output
+       format.  This format includes additional attribute flags
+       (ticket #109) and fits in 80 columns (ticket #158).
+       This format is now the default for '-x'.
+
+  [CF] smartd: Log changes of offline data collection status if
+       '-l selftest' is specified.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add ADATA S599 64GB,
+         OWC Mercury Extreme Pro
+       - Kingston branded X25-V SSDs (ticket #156)
+       - Transcend SATA Solid State Drive: Truncate attribute name
+
+  [CF] drivedb.h USB updates:
+       - LaCie (0x059f:0x1029) (ticket #153)
+       - WD My Book Office Edition (0x1058:0x1101)
+       - JMicron USB 3.0 (0x152d:0x0539)
+
+  [CF] drivedb.h USB update:
+       - Verbatim Pocket Hard Drive (0x18a5:0x0227) (ticket #159)
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS) (ticket #159)
+
+  [CF] Add support for ATA Long Logical Sectors (LLS) (ticket #159).
+
+  [DG] [SCSI] smartctl: (re-)use capacity formatting in utility.cpp
+
+  [CF] configure.in: Remove '-Wno-format' for MinGW.
+       Recent MinGW versions support MSVCRT printf format strings.
+
+  [CF] Print ATA disk capacity with SI prefix.
+       Add/move capacity formatting to utility.cpp
+
+  [CF] Add error messages if ATA pass-through does not return required
+       ATA output registers (for SMART RETURN STATUS, GET POWER MODE).
+       This prevents misleading 'SMART Status command failed' messages
+       (see ticket #155).
+
+  [CF] Fix WWN support check for older ATA-7 disks.
+
+  [DG] [SCSI] smartctl: add 'Logical Unit id' from the Device
+       Identification VPD page (0x83)
+
+  [DG] [SCSI] smartctl: add 'User Capacity' (disk size) in human
+       readable form
+
+  [CF] smartctl, smartd: Print World Wide Name (WWN) of ATA device.
+
+  [CF] smartctl: Print more specific error message if IDENTIFY DEVICE
+       failed (ticket #61).  Add check for empty IDENTIFY data.
+
+  [CF] Windows installer: Add help message box.
+
+  [CF] Windows installer: Request admin rights, select 'All Users'
+       section.  This fixes shortcut removal under Vista and later.
+       Add '/SO' option to select components for unattended install.
+       Patch was provided by József Fejes.
+
   [CF] Windows: Add update-smart-drivedb.nsi NSIS script to build
        drivedb.h update tool.
 
diff --git a/INSTALL b/INSTALL
index 316f3fed642224c09d0fa3585ce5f5d2762a1aee..2e457759c3742184cd8a6a6277cce4d924ec12bd 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
 Smartmontools installation instructions
 =======================================
 
-$Id: INSTALL 3205 2010-11-15 18:32:55Z chrfranke $
+$Id: INSTALL 3356 2011-06-06 18:37:53Z chrfranke $
 
 Please also see the smartmontools home page:
 http://smartmontools.sourceforge.net/
@@ -465,7 +465,8 @@ Cross-compile on Cygwin with old gcc-mingw 3.x:
   ./configure --build=$(./config.guess) \
               --host=i686-pc-mingw32 \
                CC='gcc-3 -mno-cygwin' \
-              CXX='g++-3 -mno-cygwin'
+              CXX='g++-3 -mno-cygwin' \
+              CXXFLAGS='-g -O2 -Wall -W -Wno-format'
 
 Cross-compile on Debian Linux with gcc-mingw32:
 
@@ -687,7 +688,8 @@ OPTIONS              DEFAULT                                      AFFECTS
                                                                   Contents of smartd executable;
                                                                   Contents of smartd/smartd.conf man pages;
                                                                   Directory for rc.d/init.d/smartd init script
---with-initscriptdir  ${sysconfdir}/init.d/rc.d                   Location of init scripts
+--with-initscriptdir           auto                               Location of init scripts
+--with-systemdsystemunitdir    auto                               Location of systemd service files
 --with-docdir         ${prefix}/share/doc/smartmontools           Location of the documentation
 --with-exampledir     ${docdir}/examplescripts                    Location of example scripts
 --enable-sample       --disable-sample                            Adds the string '.sample' to the names of the smartd.conf file and the smartd RC file
@@ -710,14 +712,50 @@ default for --with-docdir was
 This was changed to make it consistent with the default of the
 new --docdir option added in autoconf 2.60.
 
+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:
 --sbindir             /home/joe/sbin
+--docdir              /home/joe/share/doc/smartmontools
 --mandir              /home/joe/share/man
 --sysconfdir          /home/joe/etc
---with-initscriptdir  /home/joe/etc/init.d/rc.d
---with-docdir         /home/joe/doc/smartmontools
+--with-exampledir     /home/joe/share/doc/smartmontools/examplescripts
+--with-drivedbdir     /home/joe/share/smartmontools
+--with-initscriptdir         [see below]
+--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]
 
 This is useful for test installs in a harmless subdirectory somewhere.
 
@@ -745,7 +783,8 @@ Case 4:
 
 
 Here are the differences with and without --enable-sample, assuming
-no other options specified (see above for details)
+that initscript location is set and no other options specified 
+(see above for details)
 
 Case 1:
 --enable-sample provided
index 6661801eee3037e790f551ccfaa08d1fccf16d2e..eb1f7a5cf28c7822f6a851076965e95fef00ef4f 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 #
-# $Id: Makefile.am 3296 2011-03-16 22:17:51Z chrfranke $
+# $Id: Makefile.am 3338 2011-05-23 08:29:12Z samm2 $
 #
 
 @SET_MAKE@
@@ -315,12 +315,14 @@ uninstall-sysconfDATA:
        rm -f "$$f"
 
 EXTRA_DIST = \
+        autogen.sh \
         smartd.initd.in \
+        smartd.freebsd.initd.in \
         smartd.8.in \
         smartctl.8.in \
         smartd.conf.5.in \
         smartd.conf \
-        autogen.sh \
+        smartd.service.in \
         update-smart-drivedb.in \
         os_darwin/SMART.in \
         os_darwin/StartupParameters.plist \
@@ -334,22 +336,25 @@ EXTRA_DIST = \
         $(examples_DATA) \
         $(examples_SCRIPTS)
 
-CLEANFILES = smartd.conf.5      \
-             smartd.conf.4      \
-             smartd.8           \
-             smartd.1m          \
-             smartd.8.html      \
-             smartd.8.txt       \
-             smartctl.8         \
-             smartctl.1m        \
-             smartctl.8.html    \
-             smartctl.8.txt     \
-             smartd.conf.5.html \
-             smartd.conf.5.txt  \
-             smartd.initd       \
-             svnversion.h       \
-             update-smart-drivedb \
-             SMART
+CLEANFILES = \
+        smartd.conf.5 \
+        smartd.conf.4 \
+        smartd.8 \
+        smartd.1m \
+        smartd.8.html \
+        smartd.8.txt \
+        smartctl.8 \
+        smartctl.1m \
+        smartctl.8.html \
+        smartctl.8.txt \
+        smartd.conf.5.html \
+        smartd.conf.5.txt \
+        smartd.initd \
+        smartd.freebsd.initd \
+        smartd.service \
+        svnversion.h \
+        update-smart-drivedb \
+        SMART
 
 # 'make maintainer-clean' also removes files generated by './autogen.sh'
 MAINTAINERCLEANFILES = \
@@ -452,10 +457,10 @@ uninstall-initdDATA-darwin:
 
 else
 
-initd_DATA = smartd.initd
+initd_DATA = @initdfile@
 
-smartd.initd: $(srcdir)/smartd.initd.in Makefile
-       sed "s|/usr/local/sbin/|$(sbindir)/|g" $(srcdir)/smartd.initd.in > $@
+@initdfile@: $(srcdir)/@initdfile@.in Makefile
+       sed "s|/usr/local/sbin/|$(sbindir)/|g" $(srcdir)/@initdfile@.in > $@
 
 initd_install_name = smartd$(smartd_suffix)
 
@@ -464,7 +469,7 @@ initd_DATA_uninstall = uninstall-initdDATA-generic
 
 install-initdDATA-generic: $(initd_DATA)
        $(mkinstalldirs) $(DESTDIR)$(initddir)
-       $(INSTALL_SCRIPT) $(top_builddir)/smartd.initd $(DESTDIR)$(initddir)/smartd$(smartd_suffix)
+       $(INSTALL_SCRIPT) $(top_builddir)/@initdfile@ $(DESTDIR)$(initddir)/smartd$(smartd_suffix)
 
 
 uninstall-initdDATA-generic:
@@ -483,6 +488,15 @@ install-initdDATA : $(initd_DATA_install)
 
 uninstall-initdDATA: $(initd_DATA_uninstall)
 
+if INSTALL_SYSTEMDUNIT
+systemdsystemunit_DATA = smartd.service
+endif
+
+smartd.service: smartd.service.in Makefile
+       sed "s|/usr/local/sbin/smartd|$(sbindir)/smartd|g; \
+            s|/usr/local/etc/sysconfig/smartmontools|$(sysconfdir)/sysconfig/smartmontools|g" \
+       $(srcdir)/smartd.service.in > $@
+
 if ENABLE_CAPABILITIES
 MAN_CAPABILITIES = cat
 else
diff --git a/NEWS b/NEWS
index 4921cf04a21d39c8e9c4a85ee56727c5689d06f0..e589c0bc071dc79daa2660a51bd4112648438691 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,35 +1,47 @@
 smartmontools NEWS
 ------------------
-$Id: NEWS 3296 2011-03-16 22:17:51Z chrfranke $
+$Id: NEWS 3365 2011-06-09 18:47:31Z chrfranke $
 
 The most up-to-date version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
 
-Date <Not released yet, please try current SVN>
+Date 2011-06-09
 Summary: smartmontools release 5.41
 -----------------------------------------------------------
 - Failed self-tests outdated by a newer successful extended
   self-test are no longer reported as errors.
-- smartctl prints physical and logical sector sizes.
+- Support for ATA Long Logical/Physical Sectors (LLS/LPS).
 - 'smartctl --scan-open' can create a draft smartd.conf.
-- smartd logs identify information of each ATA device.
+- smartctl prints World Wide Name (WWN) of ATA device.
+- smartctl option '-f brief' to select new attribute output
+  format which includes more flags and fits in 80 columns.
+- smartd logs identify information and WWN of each ATA device.
 - smartd logs warning from drive database if present.
+- smartd logs changes of offline data collection status.
 - smartd directive '-l scterc,READTIME,WRITETIME'.
 - smartd preserves last scheduled selective self-tests span.
+- 'smartd.service' file for systemd.
+- configure option '--with-systemdsystemunitdir'
 - configure option '--with-exampledir'.
+- configure searches for init.d or rc.d directory.
 - 'make install' does no longer overwrite an existing
   smartd.conf file.
 - 'update-smart-drivedb' does no longer require GNU sed.
+- Many HDD, SSD and USB additions to drive database.
+- Linux USB autodetection: Enable '-d sat,16' for newer kernels.
 - Linux megaraid: Fix segfault on non-data SCSI commands.
 - Linux megaraid: Fix pass-through of non-data ATA commands.
 - FreeBSD: Use 'fetch' in 'update-smart-drivedb'.
 - OpenBSD: Use 'ftp' in 'update-smart-drivedb'.
 - OpenBSD: Workaround for shell bug.
 - OpenBSD: Fix DEVICESCAN for OpenBSD >= 4.8.
-- Windows: Experimental support for Intel Matrix RAID.
+- Windows: Experimental support for Intel ICHxR RAID.
 - Windows: DEVICESCAN includes USB devices.
 - Windows: Faster USB ID detection.
 - Windows: update-smart-drivedb tool.
+- Windows installer: Option '/SO component,...'.
+- Windows: Fix smartd warning email truncation on Win7.
+- Windows installer: Fix shortcut removal on Vista/Win7.
 - Windows: Add missing quotes in smartctl-run.bat and
   smartd-run.bat
 
index 90095b02bf8f68a6e3e7c5bb35c50e52c5a1f3cb..2799e5fc619b82fdc0700f78368aa1bb9e77f97c 100644 (file)
@@ -36,7 +36,7 @@
 #include "utility.h"
 #include "dev_ata_cmd_set.h" // for parsed_ata_device
 
-const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3288 2011-03-09 18:40:36Z chrfranke $"
+const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3345 2011-05-25 20:50:02Z chrfranke $"
                                  ATACMDS_H_CVSID;
 
 // Print ATA debug messages?
@@ -385,12 +385,19 @@ void swap8(char *location){
   return;
 }
 
-// Invalidate serial number and adjust checksum in IDENTIFY data
-static void invalidate_serno(ata_identify_device * id){
+// Invalidate serial number and WWN and adjust checksum in IDENTIFY data
+static void invalidate_serno(ata_identify_device * id)
+{
   unsigned char sum = 0;
-  for (unsigned i = 0; i < sizeof(id->serial_no); i++) {
+  unsigned i;
+  for (i = 0; i < sizeof(id->serial_no); i++) {
     sum += id->serial_no[i]; sum -= id->serial_no[i] = 'X';
   }
+  unsigned char * b = (unsigned char *)id;
+  for (i = 2*108; i < 2*112; i++) { // words108-111: WWN
+    sum += b[i]; sum -= b[i] = 0x00;
+  }
+
 #ifndef __NetBSD__
   bool must_swap = !!isbigendian();
   if (must_swap)
@@ -595,7 +602,6 @@ int smartcommandhandler(ata_device * device, smart_command_set command, int sele
         pout("Unrecognized command %d in smartcommandhandler()\n"
              "Please contact " PACKAGE_BUGREPORT "\n", command);
         device->set_err(ENOSYS);
-        errno = ENOSYS;
         return -1;
     }
 
@@ -615,8 +621,15 @@ int smartcommandhandler(ata_device * device, smart_command_set command, int sele
         retval = 0;
         break;
       case CHECK_POWER_MODE:
-        data[0] = out.out_regs.sector_count;
-        retval = 0;
+        if (out.out_regs.sector_count.is_set()) {
+          data[0] = out.out_regs.sector_count;
+          retval = 0;
+        }
+        else {
+          pout("CHECK POWER MODE: incomplete response, ATA output registers missing\n");
+          device->set_err(ENOSYS);
+          retval = -1;
+        }
         break;
       case STATUS_CHECK:
         // Cyl low and Cyl high unchanged means "Good SMART status"
@@ -637,13 +650,19 @@ int smartcommandhandler(ata_device * device, smart_command_set command, int sele
           if (ata_debugmode)
             pout("SMART STATUS RETURN: half unhealthy response sequence, "
                  "probable SAT/USB truncation\n");
-        } else {
+        }
+        else if (!out.out_regs.is_set()) {
+          pout("SMART STATUS RETURN: incomplete response, ATA output registers missing\n");
+          device->set_err(ENOSYS);
+          retval = -1;
+        }
+        else {
           // We haven't gotten output that makes sense; print out some debugging info
           pout("Error SMART Status command failed\n");
           pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE);
           pout("Register values returned from SMART Status command are:\n");
           print_regs(" ", out.out_regs);
-          errno = EIO;
+          device->set_err(EIO);
           retval = -1;
         }
         break;
@@ -673,42 +692,63 @@ int smartcommandhandler(ata_device * device, smart_command_set command, int sele
     }
   }
 
-  errno = device->get_errno(); // TODO: Callers should not call syserror()
   return retval;
 }
 
-// Get number of sectors from IDENTIFY sector. If the drive doesn't
-// support LBA addressing or has no user writable sectors
-// (eg, CDROM or DVD) then routine returns zero.
-uint64_t get_num_sectors(const ata_identify_device * drive)
+// Get capacity and sector sizes from IDENTIFY data
+void ata_get_size_info(const ata_identify_device * id, ata_size_info & sizes)
 {
-  unsigned short command_set_2  = drive->command_set_2;
-  unsigned short capabilities_0 = drive->words047_079[49-47];
-  unsigned short sects_16       = drive->words047_079[60-47];
-  unsigned short sects_32       = drive->words047_079[61-47];
-  unsigned short lba_16         = drive->words088_255[100-88];
-  unsigned short lba_32         = drive->words088_255[101-88];
-  unsigned short lba_48         = drive->words088_255[102-88];
-  unsigned short lba_64         = drive->words088_255[103-88];
+  sizes.sectors = sizes.capacity = 0;
+  sizes.log_sector_size = sizes.phy_sector_size = 0;
+  sizes.log_sector_offset = 0;
+
+  // Return if no LBA support
+  if (!(id->words047_079[49-47] & 0x0200))
+    return;
+
+  // Determine 28-bit LBA capacity
+  unsigned lba28 = (unsigned)id->words047_079[61-47] << 16
+                 | (unsigned)id->words047_079[60-47]      ;
+
+  // Determine 48-bit LBA capacity if supported
+  uint64_t lba48 = 0;
+  if ((id->command_set_2 & 0xc400) == 0x4400)
+    lba48 = (uint64_t)id->words088_255[103-88] << 48
+          | (uint64_t)id->words088_255[102-88] << 32
+          | (uint64_t)id->words088_255[101-88] << 16
+          | (uint64_t)id->words088_255[100-88]      ;
+
+  // Return if capacity unknown (ATAPI CD/DVD)
+  if (!(lba28 || lba48))
+    return;
 
-  // LBA support?
-  if (!(capabilities_0 & 0x0200))
-    return 0; // No
+  // Determine sector sizes
+  sizes.log_sector_size = sizes.phy_sector_size = 512;
 
-  // if drive supports LBA addressing, determine 32-bit LBA capacity
-  uint64_t lba32 = (unsigned int)sects_32 << 16 |
-                   (unsigned int)sects_16 << 0  ;
+  unsigned short word106 = id->words088_255[106-88];
+  if ((word106 & 0xc000) == 0x4000) {
+    // Long Logical/Physical Sectors (LLS/LPS) ?
+    if (word106 & 0x1000)
+      // Logical sector size is specified in 16-bit words
+      sizes.log_sector_size = sizes.phy_sector_size =
+        ((id->words088_255[118-88] << 16) | id->words088_255[117-88]) << 1;
 
-  uint64_t lba64 = 0;
-  // if drive supports 48-bit addressing, determine THAT capacity
-  if ((command_set_2 & 0xc000) == 0x4000 && (command_set_2 & 0x0400))
-      lba64 = (uint64_t)lba_64 << 48 |
-              (uint64_t)lba_48 << 32 |
-              (uint64_t)lba_32 << 16 |
-              (uint64_t)lba_16 << 0  ;
+    if (word106 & 0x2000)
+      // Physical sector size is multiple of logical sector size
+      sizes.phy_sector_size <<= (word106 & 0x0f);
 
-  // return the larger of the two possible capacities
-  return (lba32 > lba64 ? lba32 : lba64);
+    unsigned short word209 = id->words088_255[209-88];
+    if ((word209 & 0xc000) == 0x4000)
+      sizes.log_sector_offset = (word209 & 0x3fff) * sizes.log_sector_size;
+  }
+
+  // Some early 4KiB LLS disks (Samsung N3U-3) return bogus lba28 value
+  if (lba48 >= lba28 || (lba48 && sizes.log_sector_size > 512))
+    sizes.sectors = lba48;
+  else
+    sizes.sectors = lba28;
+
+  sizes.capacity = sizes.sectors * sizes.log_sector_size;
 }
 
 // This function computes the checksum of a single disk sector (512
@@ -798,9 +838,6 @@ int ataCheckPowerMode(ata_device * device) {
   return (int)result;
 }
 
-
-
-
 // Reads current Device Identity info (512 bytes) into buf.  Returns 0
 // if all OK.  Returns -1 if no ATA Device identity can be
 // established.  Returns >0 if Device is ATA Packet Device (not SMART
@@ -949,6 +986,28 @@ int ataVersionInfo(const char ** description, const ata_identify_device * drive,
     return i;
 }
 
+// Get World Wide Name (WWN) fields.
+// Return NAA field or -1 if WWN is unsupported.
+// Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008.
+// (WWN was introduced in ATA/ATAPI-7 and is mandatory since ATA8-ACS Revision 3b)
+int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & unique_id)
+{
+  // Don't use word 84 to be compatible with some older ATA-7 disks
+  unsigned short word087 = id->csf_default;
+  if ((word087 & 0xc100) != 0x4100)
+    return -1; // word not valid or WWN support bit 8 not set
+
+  unsigned short word108 = id->words088_255[108-88];
+  unsigned short word109 = id->words088_255[109-88];
+  unsigned short word110 = id->words088_255[110-88];
+  unsigned short word111 = id->words088_255[111-88];
+
+  oui = ((word108 & 0x0fff) << 12) | (word109 >> 4);
+  unique_id = ((uint64_t)(word109 & 0xf) << 32)
+            | (unsigned)((word110 << 16) | word111);
+  return (word108 >> 12);
+}
+
 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
 int ataSmartSupport(const ata_identify_device * drive)
 {
@@ -984,7 +1043,7 @@ int ataIsSmartEnabled(const ata_identify_device * drive)
 int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){
   
   if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){
-    syserror("Error SMART Values Read failed");
+    pout("Error SMART Values Read failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -1033,7 +1092,7 @@ int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
 
   // get data from device
   if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){
-    syserror("Error SMART Error Self-Test Log Read failed");
+    pout("Error SMART Error Self-Test Log Read failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -1173,7 +1232,7 @@ int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_t
   
   // get data from device
   if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){
-    syserror("Error SMART Read Selective Self-Test Log failed");
+    pout("Error SMART Read Selective Self-Test Log failed: %s\n", device->get_errmsg());
     return -1;
   }
    
@@ -1371,7 +1430,7 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
 
   // write new selective self-test log
   if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){
-    syserror("Error Write Selective Self-Test Log failed");
+    pout("Error Write Selective Self-Test Log failed: %s\n", device->get_errmsg());
     return -3;
   }
 
@@ -1418,7 +1477,7 @@ int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
   
   // get data from device
   if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){
-    syserror("Error SMART Error Log Read failed");
+    pout("Error SMART Error Log Read failed: %s\n", device->get_errmsg());
     return -1;
   }
   
@@ -1482,7 +1541,7 @@ int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt
   
   // get data from device
   if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){
-    syserror("Error SMART Thresholds Read failed");
+    pout("Error SMART Thresholds Read failed: %s\n", device->get_errmsg());
     return -1;
   }
   
@@ -1499,7 +1558,7 @@ int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt
 
 int ataEnableSmart (ata_device * device ){
   if (smartcommandhandler(device, ENABLE, 0, NULL)){
-    syserror("Error SMART Enable failed");
+    pout("Error SMART Enable failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1508,7 +1567,7 @@ int ataEnableSmart (ata_device * device ){
 int ataDisableSmart (ata_device * device ){
   
   if (smartcommandhandler(device, DISABLE, 0, NULL)){
-    syserror("Error SMART Disable failed");
+    pout("Error SMART Disable failed: %s\n", device->get_errmsg());
     return -1;
   }  
   return 0;
@@ -1516,7 +1575,7 @@ int ataDisableSmart (ata_device * device ){
 
 int ataEnableAutoSave(ata_device * device){
   if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){
-    syserror("Error SMART Enable Auto-save failed");
+    pout("Error SMART Enable Auto-save failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1525,7 +1584,7 @@ int ataEnableAutoSave(ata_device * device){
 int ataDisableAutoSave(ata_device * device){
   
   if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){
-    syserror("Error SMART Disable Auto-save failed");
+    pout("Error SMART Disable Auto-save failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1539,7 +1598,7 @@ int ataEnableAutoOffline (ata_device * device){
   
   /* timer hard coded to 4 hours */  
   if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){
-    syserror("Error SMART Enable Automatic Offline failed");
+    pout("Error SMART Enable Automatic Offline failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1550,7 +1609,7 @@ int ataEnableAutoOffline (ata_device * device){
 int ataDisableAutoOffline (ata_device * device){
   
   if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){
-    syserror("Error SMART Disable Automatic Offline failed");
+    pout("Error SMART Disable Automatic Offline failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1582,7 +1641,7 @@ int ataSmartTest(ata_device * device, int testtype, const ata_selective_selftest
                  const ata_smart_values * sv, uint64_t num_sectors)
 {
   char cmdmsg[128]; const char *type, *captive;
-  int errornum, cap, retval, select=0;
+  int cap, retval, select=0;
 
   // Boolean, if set, says test is captive
   cap=testtype & CAPTIVE_MASK;
@@ -1634,14 +1693,11 @@ int ataSmartTest(ata_device * device, int testtype, const ata_selective_selftest
   }
   
   // Now send the command to test
-  errornum=smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL);
-  
-  if (errornum && !(cap && errno==EIO)){
-    char errormsg[128];
-    sprintf(errormsg,"Command \"%s\" failed",cmdmsg); 
-    syserror(errormsg);
-    pout("\n");
-    return -1;
+  if (smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL)) {
+    if (!(cap && device->get_errno() == EIO)) {
+      pout("Command \"%s\" failed: %s\n", cmdmsg, device->get_errmsg());
+      return -1;
+    }
   }
   
   // Since the command succeeded, tell user
@@ -1907,9 +1963,14 @@ std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
   // Get 48 bit or 64 bit raw value
   uint64_t rawvalue = ata_get_attr_raw_value(attr, defs);
 
-  // Get 16 bit words
-  // TODO: rebuild raw[6] from rawvalue
-  const unsigned char * raw = attr.raw;
+  // Split into bytes and words
+  unsigned char raw[6];
+  raw[0] = (unsigned char) rawvalue;
+  raw[1] = (unsigned char)(rawvalue >>  8);
+  raw[2] = (unsigned char)(rawvalue >> 16);
+  raw[3] = (unsigned char)(rawvalue >> 24);
+  raw[4] = (unsigned char)(rawvalue >> 32);
+  raw[5] = (unsigned char)(rawvalue >> 40);
   unsigned word[3];
   word[0] = raw[0] | (raw[1] << 8);
   word[1] = raw[2] | (raw[3] << 8);
@@ -2258,7 +2319,7 @@ int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
   // read SCT status via SMART log 0xe0
   memset(sts, 0, sizeof(*sts));
   if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){
-    syserror("Error Read SCT Status failed");
+    pout("Error Read SCT Status failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -2313,14 +2374,14 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
 
   // write command via SMART log page 0xe0
   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
-    syserror("Error Write SCT Data Table command failed");
+    pout("Error Write SCT Data Table command failed: %s\n", device->get_errmsg());
     return -1;
   }
 
   // read SCT data via SMART log page 0xe1
   memset(tmh, 0, sizeof(*tmh));
   if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){
-    syserror("Error Read SCT Data Table failed");
+    pout("Error Read SCT Data Table failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -2384,7 +2445,7 @@ int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persisten
 
   // write command via SMART log page 0xe0
   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
-    syserror("Error Write SCT Feature Control Command failed");
+    pout("Error Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
     return -1;
   }
 
index 7730e943f56803485ea4295e53b932fa5cdc18ce..2dccbb5142ae568050df181ecc7feab7d7733287 100644 (file)
--- a/atacmds.h
+++ b/atacmds.h
@@ -3,8 +3,8 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2008-9 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
 #ifndef ATACMDS_H_
 #define ATACMDS_H_
 
-#define ATACMDS_H_CVSID "$Id: atacmds.h 3288 2011-03-09 18:40:36Z chrfranke $"
+#define ATACMDS_H_CVSID "$Id: atacmds.h 3316 2011-04-19 19:34:57Z chrfranke $"
 
 #include "dev_interface.h" // ata_device
 
@@ -196,8 +196,9 @@ ASSERT_SIZEOF_STRUCT(ata_smart_attribute, 12);
 // 5: Selfpereserving bit
 #define ATTRIBUTE_FLAGS_SELFPRESERVING(x) (x & 0x20)
 
+// 6-15: Reserved for future use
+#define ATTRIBUTE_FLAGS_OTHER(x) ((x) & 0xffc0)
 
-// Last ten bits are reserved for future use
 
 /* ata_smart_values is format of the read drive Attribute command */
 /* see Table 34 of T13/1321D Rev 1 spec (Device SMART data structure) for *some* info */
@@ -779,6 +780,10 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
 // supports. Returns -1 if Version command is not supported
 int ataVersionInfo(const char ** description, const ata_identify_device * drive, unsigned short * minor);
 
+// Get World Wide Name (WWN) fields.
+// Return NAA field or -1 if WWN is unsupported.
+int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & unique_id);
+
 // If SMART supported, this is guaranteed to return 1 if SMART is enabled, else 0.
 int ataDoesSmartWork(ata_device * device);
 
@@ -934,8 +939,17 @@ int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
 int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
                              unsigned char fix_firmwarebug);
 
-// Get number of sectors from IDENTIFY sector.
-uint64_t get_num_sectors(const ata_identify_device * drive);
+// Get capacity and sector sizes from IDENTIFY data
+struct ata_size_info
+{
+  uint64_t sectors;
+  uint64_t capacity;
+  unsigned log_sector_size;
+  unsigned phy_sector_size;
+  unsigned log_sector_offset;
+};
+
+void ata_get_size_info(const ata_identify_device * id, ata_size_info & sizes);
 
 // Convenience function for formatting strings from ata_identify_device.
 void ata_format_id_string(char * out, const unsigned char * in, int n);
index 4c3ae28479390f99782800dfa5b2e9772ceb6bd2..32cb4712650ced173dc4fe37ba76f43e33ad3d0f 100644 (file)
@@ -30,9 +30,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif // #ifdef HAVE_LOCALE_H
 
 #include "int64.h"
 #include "atacmdnames.h"
@@ -43,7 +40,7 @@
 #include "utility.h"
 #include "knowndrives.h"
 
-const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3288 2011-03-09 18:40:36Z chrfranke $"
+const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3357 2011-06-06 18:56:55Z chrfranke $"
                                   ATAPRINT_H_CVSID;
 
 
@@ -168,11 +165,12 @@ static const char * construct_st_er_desc(
     print_lba=1;
     print_sector=SC;
     break;
-  case 0x25:  /* READ DMA EXT */
+  case 0x25:  // READ DMA EXT
   case 0x26:  // READ DMA QUEUED EXT
   case 0xC7:  // READ DMA QUEUED
-  case 0xC8:  /* READ DMA */
-  case 0xC9:
+  case 0xC8:  // READ DMA (with retries)
+  case 0xC9:  // READ DMA (without retries, obsolete since ATA-5)
+  case 0x60:  // READ FPDMA QUEUED (NCQ)
     error_flag[7] = icrc;
     error_flag[6] = unc;
     error_flag[5] = mc;
@@ -297,13 +295,14 @@ static const char * construct_st_er_desc(
       break;
     }
     break;
-  case 0xCA:  /* WRITE DMA */
-  case 0xCB:
+  case 0xCA:  // WRITE DMA (with retries)
+  case 0xCB:  // WRITE DMA (without retries, obsolete since ATA-5)
   case 0x35:  // WRITE DMA EXT
   case 0x3D:  // WRITE DMA FUA EXT
   case 0xCC:  // WRITE DMA QUEUED
   case 0x36:  // WRITE DMA QUEUED EXT
   case 0x3E:  // WRITE DMA QUEUED FUA EXT
+  case 0x61:  // WRITE FPDMA QUEUED (NCQ)
     error_flag[7] = icrc;
     error_flag[6] = wp;
     error_flag[5] = mc;
@@ -419,78 +418,8 @@ static inline const char * construct_st_er_desc(char * s,
     (const ata_smart_errorlog_error_struct *)0, &data->error);
 }
 
-
-// This returns the capacity of a disk drive and also prints this into
-// a string, using comma separators to make it easier to read.  If the
-// drive doesn't support LBA addressing or has no user writable
-// sectors (eg, CDROM or DVD) then routine returns zero.
-static uint64_t determine_capacity(const ata_identify_device * drive, char * pstring)
-{
-  // get correct character to use as thousands separator
-  const char *separator = ",";
-#ifdef HAVE_LOCALE_H
-  struct lconv *currentlocale=NULL;
-  setlocale (LC_ALL, "");
-  currentlocale=localeconv();
-  if (*(currentlocale->thousands_sep))
-    separator=(char *)currentlocale->thousands_sep;
-#endif // #ifdef HAVE_LOCALE_H
-
-  // get #sectors and turn into bytes
-  uint64_t capacity = get_num_sectors(drive) * 512;
-  uint64_t retval = capacity;
-
-  // print with locale-specific separators (default is comma)
-  int started=0, k=1000000000;
-  uint64_t power_of_ten = k;
-  power_of_ten *= k;
-  
-  for (k=0; k<7; k++) {
-    uint64_t threedigits = capacity/power_of_ten;
-    capacity -= threedigits*power_of_ten;
-    if (started)
-      // we have already printed some digits
-      pstring += sprintf(pstring, "%s%03"PRIu64, separator, threedigits);
-    else if (threedigits || k==6) {
-      // these are the first digits that we are printing
-      pstring += sprintf(pstring, "%"PRIu64, threedigits);
-      started = 1;
-    }
-    if (k!=6)
-      power_of_ten /= 1000;
-  }
-  
-  return retval;
-}
-
-// Get sector sizes and offset.
-// Return physical sector size if valid else return 0.
-static unsigned determine_sector_sizes(const ata_identify_device * id,
-  unsigned & log_sector_size, unsigned & log_sector_offset)
-{
-  unsigned short word106 = id->words088_255[106-88];
-  if ((word106 & 0xc000) != 0x4000)
-    return 0; // word not valid
-
-  log_sector_size = 512;
-  if (word106 & 0x1000)
-    // logical sector size is specified in 16-bit words
-    log_sector_size = ((id->words088_255[118-88] << 16) | id->words088_255[117-88]) << 1;
-
-  unsigned phy_sector_size = log_sector_size;
-  if (word106 & 0x2000)
-    // physical sector size is multiple of logical sector size
-    phy_sector_size <<= (word106 & 0x0f);
-
-  unsigned short word209 = id->words088_255[209-88];
-  log_sector_offset = 0;
-  if ((word209 & 0xc000) == 0x4000)
-    log_sector_offset = (word209 & 0x3fff) * log_sector_size;
-
-  return phy_sector_size;
-}
-
 static void print_drive_info(const ata_identify_device * drive,
+                             const ata_size_info & sizes,
                              const drive_settings * dbentry)
 {
   // format drive information (with byte swapping as needed)
@@ -504,27 +433,33 @@ static void print_drive_info(const ata_identify_device * drive,
     pout("Model Family:     %s\n", dbentry->modelfamily);
 
   pout("Device Model:     %s\n", infofound(model));
-  if (!dont_print_serial_number)
+  if (!dont_print_serial_number) {
     pout("Serial Number:    %s\n", infofound(serial));
+
+    unsigned oui = 0; uint64_t unique_id = 0;
+    int naa = ata_get_wwn(drive, oui, unique_id);
+    if (naa >= 0)
+      pout("LU WWN Device Id: %x %06x %09"PRIx64"\n", naa, oui, unique_id);
+  }
   pout("Firmware Version: %s\n", infofound(firmware));
 
-  char capacity[64];
-  if (determine_capacity(drive, capacity))
-    pout("User Capacity:    %s bytes\n", capacity);
-
-  // Print sector sizes.
-  // Don't print if drive reports the default values.
-  // Some from 4KiB sector drives report 512 bytes in IDENTIFY word 106
-  // (e.g. Samsung HD204UI).
-  unsigned log_sector_size = 0, log_sector_offset = 0;
-  unsigned phy_sector_size = determine_sector_sizes(drive, log_sector_size,
-    log_sector_offset);
-  if (phy_sector_size && !(phy_sector_size == 512 && log_sector_size == 512)) {
-    pout("Sector Sizes:     %u bytes physical, %u bytes logical",
-         phy_sector_size, log_sector_size);
-    if (log_sector_offset)
-      pout(" (offset %u bytes)", log_sector_offset);
-    pout("\n");
+  if (sizes.capacity) {
+    // Print capacity
+    char num[64], cap[32];
+    pout("User Capacity:    %s bytes [%s]\n",
+      format_with_thousands_sep(num, sizeof(num), sizes.capacity),
+      format_capacity(cap, sizeof(cap), sizes.capacity));
+
+    // Print sector sizes.
+    if (sizes.phy_sector_size == sizes.log_sector_size)
+      pout("Sector Size:      %u bytes logical/physical\n", sizes.log_sector_size);
+    else {
+      pout("Sector Sizes:     %u bytes logical, %u bytes physical",
+         sizes.log_sector_size, sizes.phy_sector_size);
+      if (sizes.log_sector_offset)
+        pout(" (offset %u bytes)", sizes.log_sector_offset);
+      pout("\n");
+    }
   }
 
   // See if drive is recognized
@@ -851,7 +786,7 @@ static int find_failed_attr(const ata_smart_values * data,
 static void PrintSmartAttribWithThres(const ata_smart_values * data,
                                       const ata_smart_thresholds_pvt * thresholds,
                                       const ata_vendor_attr_defs & defs,
-                                      int onlyfailed)
+                                      int onlyfailed, unsigned char format)
 {
   bool needheader = true;
 
@@ -878,7 +813,10 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data,
         pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber);
         pout("Vendor Specific SMART Attributes with Thresholds:\n");
       }
-      pout("ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE\n");
+      if (format == 0)
+        pout("ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE\n");
+      else
+        pout("ID# ATTRIBUTE_NAME          FLAGS    VALUE WORST THRESH FAIL RAW_VALUE\n");
       needheader = false;
     }
 
@@ -899,17 +837,47 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data,
 
     // Print line for each valid attribute
     std::string attrname = ata_get_smart_attr_name(attr.id, defs);
-    pout("%3d %-24s0x%04x   %-3s   %-3s   %-3s    %-10s%-9s%-12s%s\n",
-         attr.id, attrname.c_str(), attr.flags,
-         valstr.c_str(), worstr.c_str(), threstr.c_str(),
-         (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags)? "Pre-fail" : "Old_age"),
-         (ATTRIBUTE_FLAGS_ONLINE(attr.flags)? "Always" : "Offline"),
-         (state == ATTRSTATE_FAILED_NOW  ? "FAILING_NOW" :
-          state == ATTRSTATE_FAILED_PAST ? "In_the_past" :
-                                           "    -"        ),
-         ata_format_attr_raw_value(attr, defs).c_str());
-  }
-  if (!needheader) pout("\n");
+    std::string rawstr = ata_format_attr_raw_value(attr, defs);
+
+    if (format == 0)
+      pout("%3d %-24s0x%04x   %-3s   %-3s   %-3s    %-10s%-9s%-12s%s\n",
+           attr.id, attrname.c_str(), attr.flags,
+           valstr.c_str(), worstr.c_str(), threstr.c_str(),
+           (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) ? "Pre-fail" : "Old_age"),
+           (ATTRIBUTE_FLAGS_ONLINE(attr.flags)     ? "Always"   : "Offline"),
+           (state == ATTRSTATE_FAILED_NOW  ? "FAILING_NOW" :
+            state == ATTRSTATE_FAILED_PAST ? "In_the_past"
+                                           : "    -"        ) ,
+            rawstr.c_str());
+    else
+      pout("%3d %-24s%c%c%c%c%c%c%c  %-3s   %-3s   %-3s    %-5s%s\n",
+           attr.id, attrname.c_str(),
+           (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags)     ? 'P' : '-'),
+           (ATTRIBUTE_FLAGS_ONLINE(attr.flags)         ? 'O' : '-'),
+           (ATTRIBUTE_FLAGS_PERFORMANCE(attr.flags)    ? 'S' : '-'),
+           (ATTRIBUTE_FLAGS_ERRORRATE(attr.flags)      ? 'R' : '-'),
+           (ATTRIBUTE_FLAGS_EVENTCOUNT(attr.flags)     ? 'C' : '-'),
+           (ATTRIBUTE_FLAGS_SELFPRESERVING(attr.flags) ? 'K' : '-'),
+           (ATTRIBUTE_FLAGS_OTHER(attr.flags)          ? '+' : ' '),
+           valstr.c_str(), worstr.c_str(), threstr.c_str(),
+           (state == ATTRSTATE_FAILED_NOW  ? "NOW"  :
+            state == ATTRSTATE_FAILED_PAST ? "Past"
+                                           : "-"     ),
+            rawstr.c_str());
+
+  }
+
+  if (!needheader) {
+    if (!onlyfailed && format == 1)
+      pout("%28s||||||_ K auto-keep\n"
+           "%28s|||||__ C event count\n"
+           "%28s||||___ R error rate\n"
+           "%28s|||____ S speed/performance\n"
+           "%28s||_____ O updated online\n"
+           "%28s|______ P prefailure warning\n",
+           "", "", "", "", "", "");
+    pout("\n");
+  }
 }
 
 // Print SMART related SCT capabilities
@@ -1786,7 +1754,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     int powermode = ataCheckPowerMode(device);
     switch (powermode) {
       case -1:
-        if (errno == ENOSYS) {
+        if (device->get_errno() == ENOSYS) {
           pout("CHECK POWER MODE not implemented, ignoring -n option\n"); break;
         }
         powername = "SLEEP";   powerlimit = 2;
@@ -1881,9 +1849,15 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   // Start by getting Drive ID information.  We need this, to know if SMART is supported.
   int returnval = 0;
   ata_identify_device drive; memset(&drive, 0, sizeof(drive));
+  device->clear_err();
   int retid = ata_read_identity(device, &drive, options.fix_swapped_id);
   if (retid < 0) {
-    pout("Smartctl: Device Read Identity Failed (not an ATA/ATAPI device)\n\n");
+    pout("Smartctl: Device Read Identity Failed: %s\n\n",
+         (device->get_errno() ? device->get_errmsg() : "Unknown error"));
+    failuretest(MANDATORY_CMD, returnval|=FAILID);
+  }
+  else if (!nonempty(&drive, sizeof(drive))) {
+    pout("Smartctl: Device Read Identity Failed: empty IDENTIFY data\n\n");
     failuretest(MANDATORY_CMD, returnval|=FAILID);
   }
 
@@ -1901,10 +1875,14 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     dbentry = lookup_drive_apply_presets(&drive, attribute_defs,
       fix_firmwarebug);
 
+  // Get capacity and sector sizes
+  ata_size_info sizes;
+  ata_get_size_info(&drive, sizes);
+
   // Print most drive identity information if requested
   if (options.drive_info) {
     pout("=== START OF INFORMATION SECTION ===\n");
-    print_drive_info(&drive, dbentry);
+    print_drive_info(&drive, sizes, dbentry);
   }
 
   // Check and print SMART support and state
@@ -2110,7 +2088,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         else {
           print_on();
           pout("Please note the following marginal Attributes:\n");
-          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2);
+          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2, options.output_format);
         } 
         returnval|=FAILAGE;
       }
@@ -2131,7 +2109,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         else {
           print_on();
           pout("Failed Attributes:\n");
-          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1);
+          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1, options.output_format);
         }
       }
       else
@@ -2164,7 +2142,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         else {
           print_on();
           pout("Failed Attributes:\n");
-          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1);
+          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1, options.output_format);
         }
       }
       else {
@@ -2176,7 +2154,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
           else {
             print_on();
             pout("Please note the following marginal Attributes:\n");
-            PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2);
+            PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2, options.output_format);
           } 
           returnval|=FAILAGE;
         }
@@ -2198,7 +2176,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   if (smart_val_ok && options.smart_vendor_attrib) {
     print_on();
     PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs,
-                              (printing_is_switchable ? 2 : 0));
+                              (printing_is_switchable ? 2 : 0), options.output_format);
     print_off();
   }
 
@@ -2576,7 +2554,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   // Now do the test.  Note ataSmartTest prints its own error/success
   // messages
   if (ataSmartTest(device, options.smart_selftest_type, options.smart_selective_args,
-                   &smartval, get_num_sectors(&drive)                                ))
+                   &smartval, sizes.sectors                                          ))
     failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
   else {  
     // Tell user how long test will take to complete.  This is tricky
index ce93477a487d8862f5fd9f74dd1563a911e2c74e..00e6a433bdd89cff916a5c771449ce0149d7fd0a 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef ATAPRINT_H_
 #define ATAPRINT_H_
 
-#define ATAPRINT_H_CVSID "$Id: ataprint.h 3196 2010-10-28 21:31:49Z chrfranke $\n"
+#define ATAPRINT_H_CVSID "$Id: ataprint.h 3316 2011-04-19 19:34:57Z chrfranke $\n"
 
 #include <vector>
 
@@ -77,6 +77,7 @@ struct ata_print_options
   unsigned sct_temp_int;
   bool sct_temp_int_pers;
 
+  unsigned char output_format; // 0=old, 1=brief
   unsigned char fix_firmwarebug; // FIX_*, see atacmds.h
   bool fix_swapped_id; // Fix swapped ID strings returned by some buggy drivers
 
@@ -108,6 +109,7 @@ struct ata_print_options
       smart_auto_save_disable(false), smart_auto_save_enable(false),
       smart_selftest_type(-1),
       sct_temp_int(0), sct_temp_int_pers(false),
+      output_format(0),
       fix_firmwarebug(FIX_NOTSPECIFIED),
       fix_swapped_id(false),
       ignore_presets(false),
index b9d5e7c18db1f1b15bde28030bcc65ec4c680a64..368a0763e3812d287ead073eecd4df4ff7b9535a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# $Id: configure.in 3296 2011-03-16 22:17:51Z chrfranke $
+# $Id: configure.in 3365 2011-06-09 18:47:31Z chrfranke $
 #
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.50)
@@ -7,9 +7,9 @@ AC_INIT(smartmontools, 5.41, smartmontools-support@lists.sourceforge.net)
 AC_CONFIG_SRCDIR(smartctl.cpp)
 
 smartmontools_configure_date=`date -u +'%Y-%m-%d %T %Z'`
-smartmontools_cvs_tag=`echo '$Id: configure.in 3296 2011-03-16 22:17:51Z chrfranke $'`
-smartmontools_release_date=2010-10-16
-smartmontools_release_time="16:34:38 UTC"
+smartmontools_cvs_tag=`echo '$Id: configure.in 3365 2011-06-09 18:47:31Z chrfranke $'`
+smartmontools_release_date=2011-06-09
+smartmontools_release_time="18:46:32 UTC"
 
 AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args",            [smartmontools Configure Arguments])
 AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_DATE, "$smartmontools_configure_date", [smartmontools Configure Date])
@@ -29,6 +29,7 @@ dnl Checks for programs.
 AC_PROG_CXX
 AM_PROG_AS
 AC_PROG_INSTALL
+PKG_PROG_PKG_CONFIG
 
 AC_ARG_VAR(WINDMC, [Windows message compiler command])
 AC_ARG_VAR(WINDRES, [Windows resource compiler command])
@@ -164,11 +165,62 @@ 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)
+   test -n "$PKG_CONFIG" && systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd`
+   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(initscriptdir,
-  [AC_HELP_STRING([--with-initscriptdir=DIR],[Location of init scripts [SYSCONFDIR/rc.d/init.d]])],
-  [initddir="$withval"],[initddir='${sysconfdir}/rc.d/init.d'])
+  [AC_HELP_STRING([--with-initscriptdir@<:@=DIR|auto|yes|no@:>@], [Location of init scripts [auto]])],
+  [], [with_initscriptdir=auto])
+
+AC_MSG_CHECKING(which init (rc) directory to use)
+initddir=""
+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:-not found}])
+
+case "$with_initscriptdir" in
+  auto) test -n "$systemdsystemunitdir" && initddir= ;;
+  yes)
+   if test -z "$initddir"; then
+     AC_MSG_ERROR([Location of init scripts not found])
+   fi ;;
+  no) initddir= ;;
+  *) initddir="$with_initscriptdir" ;;
+esac
+
 AC_SUBST(initddir)
-AM_CONDITIONAL(INSTALL_INITSCRIPT, [test "$with_initscriptdir" != "no"])
+AM_CONDITIONAL(INSTALL_INITSCRIPT, [test -n "$initddir"])
+
+# use different init script templates for different OS
+case "${host}" in
+  *-*-freebsd*)
+    initdfile="smartd.freebsd.initd"
+    ;;
+  *)
+    initdfile="smartd.initd"
+    ;;
+esac
+AC_SUBST(initdfile)
 
 AC_ARG_WITH(docdir,
   [AC_HELP_STRING([--with-docdir=DIR],[Location of documentation [DATADIR/doc/smartmontools]])],
@@ -248,8 +300,7 @@ fi
 
 AC_ARG_WITH(libcap-ng,
   [AC_HELP_STRING([--with-libcap-ng@<:@=auto|yes|no@:>@],[Add Libcap-ng support to smartd [auto]])],
-  [with_libcap_ng="$withval"],
-  [with_libcap_ng=auto])
+  [], [with_libcap_ng=auto])
 
 use_libcap_ng=no
 if test "$with_libcap_ng" != "no"; then
@@ -394,11 +445,6 @@ if test "$GXX" = "yes"; then
   if test -z "`echo "$CXXFLAGS " | grep "\-W " 2> /dev/null`" ; then
       CXXFLAGS="$CXXFLAGS -W"
   fi
-  case "${host}" in
-    *-*-mingw*)
-      # MinGW uses MSVCRT.DLL which uses printf format "%I64d" and not "%lld" for int64_t
-      CXXFLAGS="$CXXFLAGS -Wno-format";;
-  esac
 
 else
  dnl We are NOT using gcc, so enable host-specific compiler flags
@@ -477,7 +523,14 @@ case "$host_os" in
     fi
     echo "local drive database:   `eval eval eval echo $sysconfdir`/smart_drivedb.h" >&AS_MESSAGE_FD
     echo "smartd config file:     `eval eval eval echo $sysconfdir`/smartd.conf${smartd_suffix}" >&AS_MESSAGE_FD
-    echo "smartd initd script:    `eval eval eval echo $initddir`/smartd${smartd_suffix}" >&AS_MESSAGE_FD
+    if test -n "$initddir"; then
+      echo "smartd initd script:    `eval eval eval echo $initddir`/smartd${smartd_suffix}" >&AS_MESSAGE_FD
+    elif test -z "$systemdsystemunitdir"; then
+      echo "smartd initd script:    [[disabled]]" >&AS_MESSAGE_FD
+    fi
+    if test -n "$systemdsystemunitdir"; then
+      echo "smartd systemd file:    `eval eval eval echo $systemdsystemunitdir`/smartd.service" >&AS_MESSAGE_FD
+    fi
     if test -n "$savestates"; then
       echo "smartd save files:      `eval eval eval echo $savestates`MODEL-SERIAL.TYPE.state" >&AS_MESSAGE_FD
     else
index 1b4ace5e7aaffb2cbbd763dec088b04f06c01c7e..bc0e76ff9e14cafce88390b9a7d526adba89e178 100644 (file)
--- a/drivedb.h
+++ b/drivedb.h
@@ -75,7 +75,7 @@
 /*
 const drive_settings builtin_knowndrives[] = {
  */
-  { "$Id: drivedb.h 3290 2011-03-09 20:40:36Z chrfranke $",
+  { "$Id: drivedb.h 3364 2011-06-08 21:26:23Z manfred99 $",
     "-", "-",
     "This is a dummy entry to hold the SVN-Id of drivedb.h",
     ""
@@ -84,34 +84,40 @@ const drive_settings builtin_knowndrives[] = {
     "APPLE SSD SM128",
     "", "", ""
   },
-  { "Apple SSD TS*", // Toshiba?
-      // tested with APPLE SSD TS064C/CJAA0201
-    "APPLE SSD TS.*",
-    "", "",
-    "-v 10,raw48,Unknown_Attribute "
-    "-v 240,raw48,Unknown_Attribute"
-  },
   { "Asus-Phison SSD",
     "ASUS-PHISON SSD",
     "", "", ""
   },
-  { "Crucial RealSSD C300 Series", // tested with C300-CTFDDAC128MAG/0002
+  { "Crucial RealSSD C300", // Marvell 88SS9174 BJP2, tested with C300-CTFDDAC128MAG/0002
     "C300-CTFDDA[AC](064|128|256)MAG",
     "", "",
-    "-v 189,raw48,Unknown_Attribute "
-    "-v 202,raw48,Unknown_Attribute "
-    "-v 206,raw48,Unknown_Attribute"
+    "-v 170,raw48,Grown_Failing_Block_Ct "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+    "-v 173,raw48,Wear_Levelling_Count "
+    "-v 174,raw48,Unexpect_Power_Loss_Ct "
+    "-v 181,raw48,Non4k_Aligned_Access "
+    "-v 183,raw48,SATA_Iface_Downshift "
+    "-v 189,raw48,Factory_Bad_Block_Ct "
+    "-v 202,raw48,Perc_Rated_Life_Used "
+    "-v 206,raw48,Write_Error_Rate"
   },
   { "SandForce Driven SSDs",
     "SandForce 1st Ed\\.|" // Demo Drive, tested with firmware 320A13F0
-    "ADATA SSD S599 ...GB|" // tested with ADATA SSD S599 256GB/3.1.0
+    "ADATA SSD S599 .?..GB|" // tested with ADATA SSD S599 256GB/3.1.0, 64GB/3.4.6
     "Corsair CSSD-F(40|60|80|120|160|240)GBP?2.*|" // Corsair Force, tested with
       // Corsair CSSD-F40GB2/1.1
     "FTM(06|12|24|48)CT25H|" // Supertalent TeraDrive CT, tested with
       // FTM24CT25H/STTMP2P1
-    "OCZ[ -](AGILITY2|VERTEX2(-PRO)?|VERTEX-LE)( .*)?|" // tested with
-      // OCZ-VERTEX2/1.11, OCZ-VERTEX2 3.5/1.11
+    "OCZ[ -](AGILITY2([ -]EX)?|COLOSSUS2|ONYX2|VERTEX2|VERTEX-LE)( [123]\\..*)?|" // SF-1200,
+      // tested with OCZ-VERTEX2/1.11, OCZ-VERTEX2 3.5/1.11
+    "OCZ[ -](VELO|VERTEX2[ -](EX|PRO))( [123]\\..*)?|" // SF-1500, tested with
       // OCZ VERTEX2-PRO/1.10 (Bogus thresholds for attribute 232 and 235)
+    "OCZ-VERTEX3|"  // SF-2200, tested with OCZ-VERTEX3/2.02
+    "(APOC|DENC|DENEVA|FTNC|GFGC|MANG|MMOC|NIMC|TMSC).*|" // other OCZ SF-1200,
+      // tested with DENCSTE251M11-0120/1.33, DENEVA PCI-E/1.33
+    "(DENR|DRSAK|EC188|NIMR|PSIR|TRSAK).*|" // other OCZ SF-1500
+    "OWC Mercury Extreme Pro SSD|" // tested with firmware 360A13F0
     "UGB(88P|99S)GC...H[BF].", // Unigen, tested with
       // UGB88PGC100HF2/MP Rev2, UGB99SGC100HB3/RC Rev3
     "", "",
@@ -151,8 +157,10 @@ const drive_settings builtin_knowndrives[] = {
     "OCZ[ -](AGILITY|ONYX|VERTEX( 1199|-TURBO)?)|" // tested with
       // OCZ-ONYX/1.6, OCZ-VERTEX 1199/00.P97, OCZ-VERTEX/1.30, OCZ VERTEX-TURBO/1.5
     "Patriot[ -]Torqx.*|"
-    "STT_FT[MD](28|32|56|64)GX25H|" // Super Talent Ultradrive, tested with STT_FTM64GX25H/1916
-    "TS(18|25)M(64|128)MLC(16|32|64|128|256|512)GSSD", // ASAX Leopard Hunt II, tested with TS25M64MLC64GSSD/0.1
+    "STT_FT[MD](28|32|56|64)GX25H|" // Super Talent Ultradrive GX, tested with STT_FTM64GX25H/1916
+    "TS(18|25)M(64|128)MLC(16|32|64|128|256|512)GSSD|" // ASAX Leopard Hunt II, tested with TS25M64MLC64GSSD/0.1
+    "FM-25S2I-(64|128)GBFII|" // G.Skill FALCON II, tested with FM-25S2I-64GBFII
+    "TS(60|120)GSSD25D-M", // Transcend Ultra SSD (SATA II), see also Ticket #80
     "", "",
     "-v 1,raw64 " // Raw_Read_Error_Rate
     "-v 9,raw64 " // Power_On_Hours
@@ -242,31 +250,129 @@ const drive_settings builtin_knowndrives[] = {
     "-v 227,raw48,Workld_Host_Reads_Perc "
     "-v 228,raw48,Workload_Minutes"
   },
-  { "Kingston SSDNow V Series", // tested with KINGSTON SNV425S264GB/C091126a
-    "KINGSTON SNV425S2(64|128)GB",
+  { "Intel 320 Series SSDs",
+    "INTEL SSDSA[12]CW(040|080|120|160|300|600)G3",
+    "", "",
+  //"-v 3,raw48,Spin_Up_Time "
+  //"-v 4,raw48,Start_Stop_Count "
+  //"-v 5,raw48,Reallocated_Sector_Ct "
+  //"-v 9,raw48,Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 170,raw48,Reserve_Block_Count "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+  //"-v 184,raw48,End-to-End_Error "
+  //"-v 187,raw48,Reported_Uncorrect "
+    "-v 192,raw48,Unsafe_Shutdown_Count "
+    "-v 225,raw48,Host_Writes_32MiB "
+    "-v 226,raw48,Workld_Media_Wear_Indic " // Timed Workload Media Wear Indicator (percent*1024)
+    "-v 227,raw48,Workld_Host_Reads_Perc "  // Timed Workload Host Reads Percentage
+    "-v 228,raw48,Workload_Minutes " // 226,227,228 can be reset by 'smartctl -t vendor,0x40'
+  //"-v 232,raw48,Available_Reservd_Space "
+  //"-v 233,raw48,Media_Wearout_Indicator "
+    "-v 241,raw48,Host_Writes_32MiB "
+    "-v 242,raw48,Host_Reads_32MiB"
+  },
+  { "Intel 510 Series SSDs",
+    "INTEL SSDSC2MH(120|250)A2",
+    "", "",
+  //"-v 3,raw48,Spin_Up_Time "
+  //"-v 4,raw48,Start_Stop_Count "
+  //"-v 5,raw48,Reallocated_Sector_Ct "
+  //"-v 9,raw48,Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 192,raw48,Unsafe_Shutdown_Count "
+    "-v 225,raw48,Host_Writes_32MiB "
+  //"-v 232,raw48,Available_Reservd_Space "
+  //"-v 233,raw48,Media_Wearout_Indicator"
+  },
+  { "Kingston branded X25-V SSDs", // fixed firmware
+    "KINGSTON SSDNow 40GB",
+    "2CV102(J[89A-Z]|[K-Z].)", // >= "2CV102J8"
+    "",
+    "-v 192,raw48,Unsafe_Shutdown_Count "
+    "-v 225,raw48,Host_Writes_32MiB "
+    "-v 226,raw48,Workld_Media_Wear_Indic "
+    "-v 227,raw48,Workld_Host_Reads_Perc "
+    "-v 228,raw48,Workload_Minutes"
+  },
+  { "Kingston branded X25-V SSDs", // buggy or unknown firmware
+    "KINGSTON SSDNow 40GB",
+    "",
+    "This drive may require a firmware update to\n"
+    "fix possible drive hangs when reading SMART self-test log.\n"
+    "To update Kingston branded drives, a modified Intel update\n"
+    "tool must be used. Search for \"kingston 40gb firmware\".",
+    "-v 192,raw48,Unsafe_Shutdown_Count "
+    "-v 225,raw48,Host_Writes_32MiB "
+    "-v 226,raw48,Workld_Media_Wear_Indic "
+    "-v 227,raw48,Workld_Host_Reads_Perc "
+    "-v 228,raw48,Workload_Minutes"
+  },
+  { "JMicron based SSDs", // JMicron JMF60x
+    "Kingston SSDNow V Series [0-9]*GB|" // tested with Kingston SSDNow V Series 64GB/B090522a
+    "TS(2|4|8|16|32|64|128|192)GSSD25S?-(M|S)", // Transcend IDE and SATA, tested with TS32GSSD25-M/V090331
+    "[BV].*", // other Transcend SSD versions will be catched by subsequent entry
+    "",
+  //"-v 9,raw48,Power_On_Hours " // raw value always 0?
+  //"-v 12,raw48,Power_Cycle_Count "
+  //"-v 194,tempminmax,Temperature_Celsius " // raw value always 0?
+    "-v 229,hex64:w012345r,Halt_System/Flash_ID " // Halt, Flash[7]
+    "-v 232,hex64:w012345r,Firmware_Version_Info " // "YYMMDD", #Channels, #Banks
+    "-v 233,hex48:w01234,ECC_Fail_Record " // Fail number, Row[3], Channel, Bank
+    "-v 234,raw24/raw24:w01234,Avg/Max_Erase_Ct "
+    "-v 235,raw24/raw24:w01z23,Good/Sys_Block_Ct"
+    //  1.....................................40 chars limit for smartmontools <= r3343
+  },
+  { "JMicron based SSDs", // JMicron JMF61x
+    "KINGSTON SNV425S2(64|128)GB|"  // SSDNow V Series (2. Generation, JMF618),
+                                    // tested with KINGSTON SNV425S264GB/C091126a
+    "KINGSTON SS100S2(8|16)G|"  // SSDNow S100 Series, tested with KINGSTON SS100S28G/D100309a
+    "KINGSTON SVP100S2B?(64|96|128|256|512)G|"  // SSDNow V+100 Series,
+                                                // tested with KINGSTON SVP100S296G/CJR10202
+    "TOSHIBA THNS128GG4BBAA|"  // Toshiba / Super Talent UltraDrive DX,
+                               // tested with Toshiba 128GB 2.5" SSD (built in MacBooks)
+    "APPLE SSD TS.*|"  // Toshiba?, tested with APPLE SSD TS064C/CJAA0201
+    "ADATA S596 Turbo|"  // tested with ADATA S596 Turbo 256GB SATA SSD (JMicron JMF616)
+    "TS(8|16|32|64|128|192|256|512)GSSD25S-(MD?|S)", // Transcend SATA (JMF612), tested with TS256GSSD25S-M/101028
     "", "",
     "-v 3,raw48,Unknown_Attribute "
     "-v 7,raw48,Unknown_Attribute "
     "-v 8,raw48,Unknown_Attribute "
+  //"-v 9,raw48,Power_On_Hours "
     "-v 10,raw48,Unknown_Attribute "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 168,raw48,SATA_Phy_Error_Count "
+    "-v 170,raw16,Bad_Block_Count "
+    "-v 173,raw16,Erase_Count "
+    "-v 175,raw48,Bad_Cluster_Table_Count "
+    "-v 192,raw48,Unexpect_Power_Loss_Ct "
     "-v 240,raw48,Unknown_Attribute"
   },
-  { "Transcend IDE Solid State Drive",
-    "TS(8|16|32|64|128)GSSD25-(M|S)",
-    "", "", ""
-  },
-  { "Transcend SATA Solid State Drive",
-    "TS(8|16|32|64|128|192)GSSD25S-(M|S)",
+  { "Samsung based SSDs",
+    "SAMSUNG SSD PM800 .*GB|"  // SAMSUNG PM800 SSDs, tested with SAMSUNG SSD PM800 TH 64GB/VBM25D1Q
+    "SAMSUNG SSD PM810 .*GB|"  // SAMSUNG PM810 (470 series) SSDs, tested with SAMSUNG SSD PM810 2.5" 128GB/AXM06D1Q
+    "SAMSUNG 470 Series SSD",  // SAMSUNG 470 Series SSD, tested with SAMSUNG 470 Series SSD 64GB/AXM09B1Q
     "", "",
-    "-v 229,hex64,Halt_System_ID "
-    "-v 232,hex64,Firmware_Version_information "
-    "-v 233,hex64,ECC_Fail_Record "
-    "-v 234,raw24/raw24,Erase_Count_Avg/Max "
-    "-v 235,raw24/raw24,Block_Count_Good/System"
-  },
-  { "Transcend Ultra Series Solid State Drive (SATA II)",
-    "TS(60|120)GSSD25D-M",
-    "", "", ""
+  //"-v 9,raw48,Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+  //"-v 175,raw48,Program_Fail_Count_Chip "
+  //"-v 176,raw48,Erase_Fail_Count_Chip "
+  //"-v 177,raw48,Wear_Leveling_Count Wear "
+  //"-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip "
+  //"-v 179,raw48,Used_Rsvd_Blk_Cnt_Tot "
+  //"-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot "
+  //"-v 181,raw48,Program_Fail_Cnt_Total "
+  //"-v 182,raw48,Erase_Fail_Count_Total "
+  //"-v 183,raw48,Runtime_Bad_Block "
+    "-v 187,raw48,Uncorrectable_Error_Cnt "
+  //"-v 190,raw48,Temperature_Exceed_Cnt "  // seems to be some sort of temperature value for 470 Series?
+  //"-v 194,raw48,Airflow_Temperature "
+    "-v 195,raw48,ECC_Rate "
+  //"-v 198,raw48,Offline_Uncorrectable "
+    "-v 199,raw48,CRC_Error_Count "
+    "-v 201,raw48,Supercap_Status "
+    "-v 202,raw48,Exception_Mode_Status"
   },
   { "Transcend CompactFlash Cards", // tested with TRANSCEND/20080820, TS4GCF133/20100709
     "TRANSCEND|TS4GCF133",
@@ -286,12 +392,16 @@ const drive_settings builtin_knowndrives[] = {
     "MM0500EANCR",
     "", "", ""
   },
-  { "IBM Deskstar 60GXP series",  // ER60A46A firmware
+  { "HP 250GB SATA disk VB0250EAVER",
+    "VB0250EAVER",
+    "", "", ""
+  },
+  { "IBM Deskstar 60GXP",  // ER60A46A firmware
     "(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
     "ER60A46A",
     "", ""
   },
-  { "IBM Deskstar 60GXP series",  // All other firmware
+  { "IBM Deskstar 60GXP",  // All other firmware
     "(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
     "",
     "IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n"
@@ -299,12 +409,12 @@ const drive_settings builtin_knowndrives[] = {
     "http://www.ibm.com/pc/support/site.wss/MIGR-42215.html",
     ""
   },
-  { "IBM Deskstar 40GV & 75GXP series (A5AA/A6AA firmware)",
+  { "IBM Deskstar 40GV & 75GXP (A5AA/A6AA firmware)",
     "(IBM-)?DTLA-30[57]0[123467][05].*",
     "T[WX][123468AG][OF]A[56]AA",
     "", ""
   },
-  { "IBM Deskstar 40GV & 75GXP series (all other firmware)",
+  { "IBM Deskstar 40GV & 75GXP (all other firmware)",
     "(IBM-)?DTLA-30[57]0[123467][05].*",
     "",
     "IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n"
@@ -322,25 +432,25 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHG series",
+  { "Fujitsu MHG",
     "FUJITSU MHG2...ATU?.*",
     "",
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHH series",
+  { "Fujitsu MHH",
     "FUJITSU MHH2...ATU?.*",
     "",
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHJ series",
+  { "Fujitsu MHJ",
     "FUJITSU MHJ2...ATU?.*",
     "",
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHK series",
+  { "Fujitsu MHK",
     "FUJITSU MHK2...ATU?.*",
     "",
     "",
@@ -360,7 +470,7 @@ const drive_settings builtin_knowndrives[] = {
       "checksum error bug.",
     "-v 9,seconds"
   },
-  { "Fujitsu MHN series",
+  { "Fujitsu MHN",
     "FUJITSU MHN2...AT",
     "",
     "",
@@ -379,7 +489,7 @@ const drive_settings builtin_knowndrives[] = {
     "-v 9,seconds -v 192,emergencyretractcyclect "
     "-v 198,offlinescanuncsectorct -v 200,writeerrorcount"
   },
-  { "Fujitsu MHSxxxxAT family",
+  { "Fujitsu MHS AT",
     "FUJITSU MHS20[6432]0AT(  .)?",
     "",
     "",
@@ -393,60 +503,60 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHU series",
+  { "Fujitsu MHU",
     "FUJITSU MHU2...ATU?.*",
     "",
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHV series",
+  { "Fujitsu MHV",
     "FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*",
     "",
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MPA..MPG series",
+  { "Fujitsu MPA..MPG",
     "FUJITSU MP[A-G]3...A[HTEV]U?.*",
     "",
     "",
     "-v 9,seconds"
   },
-  { "Fujitsu MHY2 BH series",
+  { "Fujitsu MHY BH",
     "FUJITSU MHY2(04|06|08|10|12|16|20|25)0BH.*",
     "", "",
     "-v 240,raw48,Transfer_Error_Rate"
   },
-  { "Fujitsu MHW2 AC", // tested with FUJITSU MHW2060AC/00900004
+  { "Fujitsu MHW AC", // tested with FUJITSU MHW2060AC/00900004
     "FUJITSU MHW20(40|60)AC",
     "", "", ""
   },
-  { "Fujitsu MHW2 BH series",
+  { "Fujitsu MHW BH",
     "FUJITSU MHW2(04|06|08|10|12|16)0BH.*",
     "", "", ""
   },
-  { "Fujitsu MHW2 BJ series",
+  { "Fujitsu MHW BJ",
     "FUJITSU MHW2(08|12|16)0BJ.*",
     "", "", ""
   },
-  { "Fujitsu MHZ2 BH series",
+  { "Fujitsu MHZ BH",
     "FUJITSU MHZ2(04|08|12|16|20|25|32)0BH.*",
     "", "", ""
   },
-  { "Fujitsu MHZ2 BJ series",
+  { "Fujitsu MHZ BJ",
     "FUJITSU MHZ2(08|12|16|20|25|32)0BJ.*",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Fujitsu MHZ2 BS series",
+  { "Fujitsu MHZ BS",
     "FUJITSU MHZ2(12|25)0BS.*",
     "", "", ""
   },
-  { "Fujitsu MHZ2 BK series",
+  { "Fujitsu MHZ BK",
     "FUJITSU MHZ2(08|12|16|25)0BK.*",
     "", "", ""
   },
-  { "Fujitsu MJA2 BH series",
+  { "Fujitsu MJA BH",
     "FUJITSU MJA2(08|12|16|25|32|40|50)0BH.*",
     "", "", ""
   },
@@ -490,7 +600,7 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG SV0322A",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint V80 series", // tested with SV1604N/TR100-23
+  { "SAMSUNG SpinPoint V80", // tested with SV1604N/TR100-23
     "SAMSUNG SV(0211|0401|0612|0802|1203|1604)N",
     "",
     "",
@@ -514,23 +624,23 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,halfminutes -F samsung"
   },
-  { "SAMSUNG SpinPoint F1 DT series", // tested with HD103UJ/1AA01113
+  { "SAMSUNG SpinPoint F1 DT", // tested with HD103UJ/1AA01113
     "SAMSUNG HD(083G|16[12]G|25[12]H|32[12]H|50[12]I|642J|75[23]L|10[23]U)J",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint F1 RE series", // tested with HE103UJ/1AA01113
+  { "SAMSUNG SpinPoint F1 RE", // tested with HE103UJ/1AA01113
     "SAMSUNG HE(252H|322H|502I|642J|753L|103U)J",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint F2 EG series", // tested with HD154UI/1AG01118
+  { "SAMSUNG SpinPoint F2 EG", // tested with HD154UI/1AG01118
     "SAMSUNG HD(502H|10[23]S|15[34]U)I",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint F3 series", // tested with HD502HJ/1AJ100E4
+  { "SAMSUNG SpinPoint F3", // tested with HD502HJ/1AJ100E4
     "SAMSUNG HD(502H|754J|103S)J",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint F3 EG series", // tested with HD503HI/1AJ100E4, HD153WI/1AN10002
+  { "SAMSUNG SpinPoint F3 EG", // tested with HD503HI/1AJ100E4, HD153WI/1AN10002
     "SAMSUNG HD(253G|(324|503)H|754J|105S|(153|203)W)I",
     "", "", ""
   },
@@ -546,11 +656,11 @@ const drive_settings builtin_knowndrives[] = {
     "http://sourceforge.net/apps/trac/smartmontools/wiki/SamsungF4EGBadBlocks",
     ""
   },
-  { "SAMSUNG SpinPoint S250 series", // tested with HD200HJ/KF100-06
+  { "SAMSUNG SpinPoint S250", // tested with HD200HJ/KF100-06
     "SAMSUNG HD(162|200|250)HJ",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint T133 series", // tested with HD300LJ/ZT100-12, HD400LJ/ZZ100-14, HD401LJ/ZZ100-15
+  { "SAMSUNG SpinPoint T133", // tested with HD300LJ/ZT100-12, HD400LJ/ZZ100-14, HD401LJ/ZZ100-15
     "SAMSUNG HD(250KD|(30[01]|320|40[01])L[DJ])",
     "", "", ""
   },
@@ -559,41 +669,41 @@ const drive_settings builtin_knowndrives[] = {
     "", "",
     "-v 197,increasing" // at least HD501LJ/CR100-11
   },
-  { "SAMSUNG SpinPoint P120 series", // VF100-37 firmware, tested with SP2514N/VF100-37
+  { "SAMSUNG SpinPoint P120", // VF100-37 firmware, tested with SP2514N/VF100-37
     "SAMSUNG SP(16[01]3|2[05][01]4)[CN]",
     "VF100-37",
     "",
     "-F samsung3"
   },
-  { "SAMSUNG SpinPoint P120 series", // other firmware, tested with SP2504C/VT100-33
+  { "SAMSUNG SpinPoint P120", // other firmware, tested with SP2504C/VT100-33
     "SAMSUNG SP(16[01]3|2[05][01]4)[CN]",
     "",
     "May need -F samsung3 enabled; see manual for details.",
     ""
   },
-  { "SAMSUNG SpinPoint P80 SD series", // tested with HD160JJ/ZM100-33
+  { "SAMSUNG SpinPoint P80 SD", // tested with HD160JJ/ZM100-33
     "SAMSUNG HD(080H|120I|160J)J",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint P80 series", // BH100-35 firmware, tested with SP0842N/BH100-35
+  { "SAMSUNG SpinPoint P80", // BH100-35 firmware, tested with SP0842N/BH100-35
     "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
     "BH100-35",
     "",
     "-F samsung3"
   },
-  { "SAMSUNG SpinPoint P80 series", // firmware *-35 or later
+  { "SAMSUNG SpinPoint P80", // firmware *-35 or later
     "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
     ".*-3[5-9]",
     "May need -F samsung3 enabled; see manual for details.",
     ""
   },
-  { "SAMSUNG SpinPoint P80 series", // firmware *-25...34, tested with SP1614C/SW100-25 and -34
+  { "SAMSUNG SpinPoint P80", // firmware *-25...34, tested with SP1614C/SW100-25 and -34
     "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
     ".*-(2[5-9]|3[0-4])",
     "",
     "-v 9,halfminutes -v 198,increasing"
   },
-  { "SAMSUNG SpinPoint P80 series", // firmware *-23...24, tested with
+  { "SAMSUNG SpinPoint P80", // firmware *-23...24, tested with
     // SP0802N/TK100-23,
     // SP1213N/TL100-23,
     // SP1604N/TM100-23 and -24
@@ -602,27 +712,27 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,halfminutes -F samsung2"
   },
-  { "SAMSUNG SpinPoint P80 series", // unknown firmware
+  { "SAMSUNG SpinPoint P80", // unknown firmware
     "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
     "",
     "May need -F samsung2 or -F samsung3 enabled; see manual for details.",
     ""
   },
-  { "SAMSUNG SpinPoint M40/60/80 series", // tested with HM160JI/AD100-16
+  { "SAMSUNG SpinPoint M40/60/80", // tested with HM160JI/AD100-16
     "SAMSUNG HM(0[468]0H|1[026]0J)[CI]",
     "",
     "",
     "-v 9,halfminutes"
   },
-  { "SAMSUNG SpinPoint M5 series", // tested with HM160HI/HH100-12
-    "SAMSUNG HM((061|080)G|(121|160)H|250J)I",
+  { "SAMSUNG SpinPoint M5", // tested with HM160HI/HH100-12
+    "SAMSUNG HM(((061|080)G|(121|160)H|250J)I|160HC)",
     "", "", ""
   },
   { "SAMSUNG SpinPoint M6", // tested with HM320JI/2SS00_01 M6
     "SAMSUNG HM(251J|320[HJ]|[45]00L)I",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint M7 series", // tested with HM500JI/2AC101C4
+  { "SAMSUNG SpinPoint M7", // tested with HM500JI/2AC101C4
     "SAMSUNG HM(250H|320I|[45]00J)I",
     "", "", ""
   },
@@ -630,18 +740,22 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HM(161G|(251|321)H|501I|641J)I",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint M series", // tested with MP0402H/UC100-11
+  { "SAMSUNG SpinPoint MT2", // tested with HM100UI/2AM10001
+    "SAMSUNG HM100UI",
+    "", "", ""
+  },
+  { "SAMSUNG HM100UX (S2 Portable)", // tested with HM100UX/2AM10001
+    "SAMSUNG HM100UX",
+    "", "", ""
+  },
+  { "SAMSUNG SpinPoint M", // tested with MP0402H/UC100-11
     "SAMSUNG MP0(302|402|603|804)H",
     "",
     "",
     "-v 9,halfminutes"
   },
-  { "SAMSUNG PM800 SSDs", // tested with SAMSUNG SSD PM800 TH 64GB/VBM25D1Q
-    "SAMSUNG SSD PM800 .*GB",
-    "", "", ""
-  },
-  { "SAMSUNG PM810 (470 series) SSDs", // tested with SAMSUNG SSD PM810 2.5" 128GB/AXM06D1Q
-    "SAMSUNG SSD PM810 .*GB",
+  { "SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS)", // tested with HS25YJZ/3AU10-01
+    "SAMSUNG HS(122H|2[05]YJ)Z",
     "", "", ""
   },
 /*
@@ -667,63 +781,63 @@ const drive_settings builtin_knowndrives[] = {
     ""
   },
 */
-  { "Maxtor Fireball 541DX family",
+  { "Maxtor Fireball 541DX",
     "Maxtor 2B0(0[468]|1[05]|20)H1",
     "",
     "",
     "-v 9,minutes -v 194,unknown"
   },
-  { "Maxtor Fireball 3 family",
+  { "Maxtor Fireball 3",
     "Maxtor 2F0[234]0[JL]0",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 1280 ATA family",  // no self-test log, ATA2-Fast
+  { "Maxtor DiamondMax 1280 ATA",  // no self-test log, ATA2-Fast
     "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 2160 Ultra ATA family",
+  { "Maxtor DiamondMax 2160 Ultra ATA",
     "Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 2880 Ultra ATA family",
+  { "Maxtor DiamondMax 2880 Ultra ATA",
     "Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 3400 Ultra ATA family",
+  { "Maxtor DiamondMax 3400 Ultra ATA",
     "Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax D540X-4G family",
+  { "Maxtor DiamondMax D540X-4G",
     "Maxtor 4G(120J6|160J[68])",
     "",
     "",
     "-v 9,minutes -v 194,unknown"
   },
-  { "Maxtor DiamondMax D540X-4K family",
+  { "Maxtor DiamondMax D540X-4K",
     "MAXTOR 4K(020H1|040H2|060H3|080H4)",
     "", "", ""
   },
-  { "Maxtor DiamondMax Plus D740X family",
+  { "Maxtor DiamondMax Plus D740X",
     "MAXTOR 6L0(20[JL]1|40[JL]2|60[JL]3|80[JL]4)",
     "", "", ""
   },
-  { "Maxtor DiamondMax Plus 5120 Ultra ATA 33 family",
+  { "Maxtor DiamondMax Plus 5120 Ultra ATA 33",
     "Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax Plus 6800 Ultra ATA 66 family",
+  { "Maxtor DiamondMax Plus 6800 Ultra ATA 66",
     "Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)",
     "",
     "",
@@ -735,119 +849,119 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,minutes -v 194,unknown"
   },
-  { "Maxtor DiamondMax 16 family",
+  { "Maxtor DiamondMax 16",
     "Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 4320 Ultra ATA family",
+  { "Maxtor DiamondMax 4320 Ultra ATA",
     "Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 17 VL family",
+  { "Maxtor DiamondMax 17 VL",
     "Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 20 VL family",
+  { "Maxtor DiamondMax 20 VL",
     "Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax VL 30 family",  // U: ATA66, H: ATA100
+  { "Maxtor DiamondMax VL 30",  // U: ATA66, H: ATA100
     "Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 36 family",
+  { "Maxtor DiamondMax 36",
     "Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 40 ATA 66 series",
+  { "Maxtor DiamondMax 40 ATA 66",
     "Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax Plus 40 series (Ultra ATA 66 and Ultra ATA 100)",
+  { "Maxtor DiamondMax Plus 40 (Ultra ATA 66 and Ultra ATA 100)",
     "Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 40 VL Ultra ATA 100 series",
+  { "Maxtor DiamondMax 40 VL Ultra ATA 100",
     "Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax Plus 45 Ulta ATA 100 family",
+  { "Maxtor DiamondMax Plus 45 Ulta ATA 100",
     "Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 60 ATA 66 family",
+  { "Maxtor DiamondMax 60 ATA 66",
     "Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 60 ATA 100 family",
+  { "Maxtor DiamondMax 60 ATA 100",
     "Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax Plus 60 family",
+  { "Maxtor DiamondMax Plus 60",
     "Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 80 family",
+  { "Maxtor DiamondMax 80",
     "Maxtor (98196H8|96147H6)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 536DX family",
+  { "Maxtor DiamondMax 536DX",
     "Maxtor 4W(100H6|080H6|060H4|040H3|030H2)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax Plus 8 family",
+  { "Maxtor DiamondMax Plus 8",
     "Maxtor 6(E0[234]|K04)0L0",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 10 family (ATA/133 and SATA/150)",
+  { "Maxtor DiamondMax 10 (ATA/133 and SATA/150)",
     "Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 10 family (SATA/300)",
+  { "Maxtor DiamondMax 10 (SATA/300)",
     "Maxtor 6V(080E|160E|200E|250F|300F|320F)0",
     "", "", ""
   },
-  { "Maxtor DiamondMax Plus 9 family",
+  { "Maxtor DiamondMax Plus 9",
     "Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor DiamondMax 11 family",
+  { "Maxtor DiamondMax 11",
     "Maxtor 6H[45]00[FR]0",
     "", "", ""
   },
@@ -903,23 +1017,23 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,minutes"
   },
-  { "Maxtor MaXLine II family",
+  { "Maxtor MaXLine II",
     "Maxtor [45]A(25|30|32)0[JN]0",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor MaXLine III family (ATA/133 and SATA/150)",
+  { "Maxtor MaXLine III (ATA/133 and SATA/150)",
     "Maxtor 7L(25|30)0[SR]0",
     "",
     "",
     "-v 9,minutes"
   },
-  { "Maxtor MaXLine III family (SATA/300)",
+  { "Maxtor MaXLine III (SATA/300)",
     "Maxtor 7V(25|30)0F0",
     "", "", ""
   },
-  { "Maxtor MaXLine Pro 500 family",  // There is also a 7H500R0 model, but I
+  { "Maxtor MaXLine Pro 500",  // There is also a 7H500R0 model, but I
     "Maxtor 7H500F0",               // haven't added it because I suspect
     "",                               // it might need vendoropts_9_minutes
     "", ""                            // and nobody has submitted a report yet
@@ -930,7 +1044,7 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,minutes -v 193,loadunload"
   },
-  { "HITACHI Travelstar DK23XX/DK23XXB series",
+  { "HITACHI Travelstar DK23XX/DK23XXB",
     "HITACHI_DK23..-..B?",
     "",
     "",
@@ -948,21 +1062,21 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,minutes -v 193,loadunload"
   },
-  { "Hitachi Travelstar C4K60 family",  // 1.8" slim drive
+  { "Hitachi Travelstar C4K60",  // 1.8" slim drive
     "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00",
     "",
     "",
     "-v 9,minutes -v 193,loadunload"
   },
-  { "IBM Travelstar 4GT family",
+  { "IBM Travelstar 4GT",
     "IBM-DTCA-2(324|409)0",
     "", "", ""
   },
-  { "IBM Travelstar 6GN family",
+  { "IBM Travelstar 6GN",
     "IBM-DBCA-20(324|486|648)0",
     "", "", ""
   },
-  { "IBM Travelstar 25GS, 18GT, and 12GN family",
+  { "IBM Travelstar 25GS, 18GT, and 12GN",
     "IBM-DARA-2(25|18|15|12|09|06)000",
     "", "", ""
   },
@@ -974,27 +1088,27 @@ const drive_settings builtin_knowndrives[] = {
     "IBM-DTNA-2(180|216)0",
     "", "", ""
   },
-  { "IBM Travelstar 48GH, 30GN, and 15GN family",
+  { "IBM Travelstar 48GH, 30GN, and 15GN",
     "(IBM-|Hitachi )?IC25(T048ATDA05|N0(30|20|15|12|10|07|06|05)ATDA04)-.",
     "", "", ""
   },
-  { "IBM Travelstar 32GH, 30GT, and 20GN family",
+  { "IBM Travelstar 32GH, 30GT, and 20GN",
     "IBM-DJSA-2(32|30|20|10|05)",
     "", "", ""
   },
-  { "IBM Travelstar 4GN family",
+  { "IBM Travelstar 4GN",
     "IBM-DKLA-2(216|324|432)0",
     "", "", ""
   },
-  { "IBM/Hitachi Travelstar 60GH and 40GN family",
+  { "IBM/Hitachi Travelstar 60GH and 40GN",
     "(IBM-|Hitachi )?IC25(T060ATC[SX]05|N0[4321]0ATC[SX]04)-.",
     "", "", ""
   },
-  { "IBM/Hitachi Travelstar 40GNX family",
+  { "IBM/Hitachi Travelstar 40GNX",
     "(IBM-|Hitachi )?IC25N0[42]0ATC[SX]05-.",
     "", "", ""
   },
-  { "Hitachi Travelstar 80GN family",
+  { "Hitachi Travelstar 80GN",
     "(Hitachi )?IC25N0[23468]0ATMR04-.",
     "", "", ""
   },
@@ -1071,26 +1185,30 @@ const drive_settings builtin_knowndrives[] = {
     "(Hitachi )?HT[ES]7250(12|16|25|32|50)A9A36[45]",
     "", "", ""
   },
-  { "IBM Deskstar 14GXP and 16GP series",
+  { "IBM Deskstar 14GXP and 16GP",
     "IBM-DTTA-3(7101|7129|7144|5032|5043|5064|5084|5101|5129|5168)0",
     "", "", ""
   },
-  { "IBM Deskstar 25GP and 22GXP family",
+  { "IBM Deskstar 25GP and 22GXP",
     "IBM-DJNA-3(5(101|152|203|250)|7(091|135|180|220))0",
     "", "", ""
   },
-  { "IBM Deskstar 37GP and 34GXP family",
+  { "IBM Deskstar 37GP and 34GXP",
     "IBM-DPTA-3(5(375|300|225|150)|7(342|273|205|136))0",
     "", "", ""
   },
-  { "IBM/Hitachi Deskstar 120GXP family",
+  { "IBM/Hitachi Deskstar 120GXP",
     "(IBM-)?IC35L((020|040|060|080|120)AVVA|0[24]0AVVN)07-[01]",
     "", "", ""
   },
-  { "IBM/Hitachi Deskstar GXP-180 family",
+  { "IBM/Hitachi Deskstar GXP-180",
     "(IBM-)?IC35L(030|060|090|120|180)AVV207-[01]",
     "", "", ""
   },
+  { "Hitachi Deskstar 5K3000",
+    "(Hitachi )?HDS5C30(15|20|30)ALA63[02].*",
+    "", "", ""
+  },
   { "Hitachi Deskstar 7K80",
     "(Hitachi )?HDS7280([48]0PLAT20|(40)?PLA320|80PLA380).*",
     "", "", ""
@@ -1155,35 +1273,35 @@ const drive_settings builtin_knowndrives[] = {
     "(Hitachi )?HUA7220((50|10)C|20A)LA33[01]",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD series (10-20 GB)",
+  { "Toshiba 2.5\" HDD (10-20 GB)",
     "TOSHIBA MK(101[67]GAP|15[67]GAP|20(1[678]GAP|(18|23)GAS))",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD series (30-60 GB)",
+  { "Toshiba 2.5\" HDD (30-60 GB)",
     "TOSHIBA MK((6034|4032)GSX|(6034|4032)GAX|(6026|4026|4019|3019)GAXB?|(6025|6021|4025|4021|4018|3025|3021|3018)GAS|(4036|3029)GACE?|(4018|3017)GAP)",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD series (80 GB and above)",
+  { "Toshiba 2.5\" HDD (80 GB and above)",
     "TOSHIBA MK(80(25GAS|26GAX|32GAX|32GSX)|10(31GAS|32GAX)|12(33GAS|34G[AS]X)|2035GSS)",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..52GSX series",
+  { "Toshiba 2.5\" HDD MK..52GSX",
     "TOSHIBA MK(80|12|16|25|32)52GSX",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..59GSXP series", // Adv. Format
+  { "Toshiba 2.5\" HDD MK..59GSXP (Adv. Format)", // Adv. Format
     "TOSHIBA MK(32|50|64|75)59GSXP?",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..59GSM series", // Adv. Format
+  { "Toshiba 2.5\" HDD MK..59GSM (Adv. Format)", // Adv. Format
     "TOSHIBA MK(75|10)59GSM",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..65GSX series", // tested with TOSHIBA MK5065GSX/GJ003A
+  { "Toshiba 2.5\" HDD MK..65GSX", // tested with TOSHIBA MK5065GSX/GJ003A
     "TOSHIBA MK(16|25|32|50|64)65GSX",
     "", "", ""
   },
-  { "Toshiba 1.8\" HDD series",
+  { "Toshiba 1.8\" HDD",
     "TOSHIBA MK[23468]00[4-9]GA[HL]",
     "", "", ""
   },
@@ -1199,67 +1317,67 @@ const drive_settings builtin_knowndrives[] = {
     "TOS MK[34]019GAXB SUN[34]0G",
     "", "", ""
   },
-  { "Seagate Momentus family",
+  { "Seagate Momentus",
     "ST9(20|28|40|48)11A",
     "", "", ""
   },
-  { "Seagate Momentus 42 family",
+  { "Seagate Momentus 42",
     "ST9(2014|3015|4019)A",
     "", "", ""
   },
-  { "Seagate Momentus 4200.2 series",
+  { "Seagate Momentus 4200.2",
     "ST9(100822|808210|60821|50212|402113|30219)A",
     "", "", ""
   },
-  { "Seagate Momentus 5400.2 series",
+  { "Seagate Momentus 5400.2",
     "ST9(808211|60822|408114|308110|120821|10082[34]|8823|6812|4813|3811)AS?",
     "", "", ""
   },
-  { "Seagate Momentus 5400.3 series",
+  { "Seagate Momentus 5400.3",
     "ST9(4081[45]|6081[35]|8081[15]|100828|120822|160821)AS?",
     "", "", ""
   },
-  { "Seagate Momentus 5400.3 ED series",
+  { "Seagate Momentus 5400.3 ED",
     "ST9(4081[45]|6081[35]|8081[15]|100828|120822|160821)AB",
     "", "", ""
   },
-  { "Seagate Momentus 5400.4 series",
+  { "Seagate Momentus 5400.4",
     "ST9(120817|(160|200|250)827)AS",
     "", "", ""
   },
-  { "Seagate Momentus 5400.5 series",
+  { "Seagate Momentus 5400.5",
     "ST9((80|120|160)310|(250|320)320)AS",
     "", "", ""
   },
-  { "Seagate Momentus 5400.6 series",
+  { "Seagate Momentus 5400.6",
     "ST9(80313|160(301|314)|(12|25)0315|250317|(320|500)325|500327|640320)ASG?",
     "", "", ""
   },
-  { "Seagate Momentus 5400 PSD series", // Hybrid drives
+  { "Seagate Momentus 5400 PSD", // Hybrid drives
     "ST9(808212|(120|160)8220)AS",
     "", "", ""
   },
-  { "Seagate Momentus 7200.1 series",
+  { "Seagate Momentus 7200.1",
     "ST9(10021|80825|6023|4015)AS?",
     "", "", ""
   },
-  { "Seagate Momentus 7200.2 series",
+  { "Seagate Momentus 7200.2",
     "ST9(80813|100821|120823|160823|200420)ASG?",
     "", "", ""
   },
-  { "Seagate Momentus 7200.3 series",
+  { "Seagate Momentus 7200.3",
     "ST9((80|120|160)411|(250|320)421)ASG?",
     "", "", ""
   },
-  { "Seagate Momentus 7200.4 series",
+  { "Seagate Momentus 7200.4",
     "ST9(160412|250410|320423|500420)ASG?",
     "", "", ""
   },
-  { "Seagate Momentus 7200 FDE.2 series",
+  { "Seagate Momentus 7200 FDE.2",
     "ST9((160413|25041[12]|320426|50042[12])AS|(16041[489]|2504[16]4|32042[67]|500426)ASG)",
     "", "", ""
   },
-  { "Seagate Momentus XT series", // tested with ST95005620AS/SD22
+  { "Seagate Momentus XT", // tested with ST95005620AS/SD22
     "ST9(2505610|3205620|5005620)AS",
     "", "", ""
   },
@@ -1271,55 +1389,55 @@ const drive_settings builtin_knowndrives[] = {
     "ST3(2110|3221|4321|6531|8641)A",
     "", "", ""
   },
-  { "Seagate U Series X family",
+  { "Seagate U Series X",
     "ST3(10014A(CE)?|20014A)",
     "", "", ""
   },
-  { "Seagate U8 family",
+  { "Seagate U8",
     "ST3(4313|6811|8410|13021|17221)A",
     "", "", ""
   },
-  { "Seagate U7 family",
+  { "Seagate U7",
     "ST3(30012|40012|60012|80022|120020)A",
     "", "", ""
   },
-  { "Seagate U Series 6 family",
+  { "Seagate U Series 6",
     "ST3(8002|6002|4081|3061|2041)0A",
     "", "", ""
   },
-  { "Seagate U Series 5 family",
+  { "Seagate U Series 5",
     "ST3(40823|30621|20413|15311|10211)A",
     "", "", ""
   },
-  { "Seagate U4 family",
+  { "Seagate U4",
     "ST3(2112|4311|6421|8421)A",
     "", "", ""
   },
-  { "Seagate U8 family",
+  { "Seagate U8",
     "ST3(8410|4313|17221|13021)A",
     "", "", ""
   },
-  { "Seagate U10 family",
+  { "Seagate U10",
     "ST3(20423|15323|10212)A",
     "", "", ""
   },
-  { "Seagate Barracuda ATA family",
+  { "Seagate Barracuda ATA",
     "ST3(2804|2724|2043|1362|1022|681)0A",
     "", "", ""
   },
-  { "Seagate Barracuda ATA II family",
+  { "Seagate Barracuda ATA II",
     "ST3(3063|2042|1532|1021)0A",
     "", "", ""
   },
-  { "Seagate Barracuda ATA III family",
+  { "Seagate Barracuda ATA III",
     "ST3(40824|30620|20414|15310|10215)A",
     "", "", ""
   },
-  { "Seagate Barracuda ATA IV family",
+  { "Seagate Barracuda ATA IV",
     "ST3(20011|30011|40016|60021|80021)A",
     "", "", ""
   },
-  { "Seagate Barracuda ATA V family",
+  { "Seagate Barracuda ATA V",
     "ST3(12002(3A|4A|9A|3AS)|800(23A|15A|23AS)|60(015A|210A)|40017A)",
     "", "", ""
   },
@@ -1327,38 +1445,38 @@ const drive_settings builtin_knowndrives[] = {
     "ST340015A",
     "", "", ""
   },
-  { "Seagate Barracuda 7200.7 and 7200.7 Plus family",
+  { "Seagate Barracuda 7200.7 and 7200.7 Plus",
     "ST3(200021A|200822AS?|16002[13]AS?|12002[26]AS?|1[26]082[78]AS|8001[13]AS?|8081[79]AS|60014A|40111AS|40014AS?)",
     "", "", ""
   },
-  { "Seagate Barracuda 7200.8 family",
+  { "Seagate Barracuda 7200.8",
     "ST3(400[68]32|300[68]31|250[68]23|200826)AS?",
     "", "", ""
   },
-  { "Seagate Barracuda 7200.9 family",
+  { "Seagate Barracuda 7200.9",
     "ST3(402111?|80[28]110?|120[28]1[0134]|160[28]1[012]|200827|250[68]24|300[68]22|(320|400)[68]33|500[68](32|41))AS?.*",
     "", "", ""
   },
-  { "Seagate Barracuda 7200.10 family",
+  { "Seagate Barracuda 7200.10",
     "ST3((80|160)[28]15|200820|250[34]10|(250|300|320|400)[68]20|360320|500[68]30|750[68]40)AS?",
     "", "", ""
   },
-  { "Seagate Barracuda 7200.11 family", // unaffected firmware
+  { "Seagate Barracuda 7200.11", // unaffected firmware
     "ST3(160813|320[68]13|500[368]20|640[36]23|640[35]30|750[36]30|1000(333|[36]40)|1500341)AS?",
     "CC.?.?", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957
     "", ""
   },
-  { "Seagate Barracuda 7200.11 family", // fixed firmware
+  { "Seagate Barracuda 7200.11", // fixed firmware
     "ST3(500[368]20|750[36]30|1000340)AS?",
     "SD1A", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207951
     "", ""
   },
-  { "Seagate Barracuda 7200.11 family", // fixed firmware
+  { "Seagate Barracuda 7200.11", // fixed firmware
     "ST3(160813|320[68]13|640[36]23|1000333|1500341)AS?",
     "SD[12]B", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957
     "", ""
   },
-  { "Seagate Barracuda 7200.11 family", // buggy firmware
+  { "Seagate Barracuda 7200.11", // buggy firmware
     "ST3(500[368]20|640[35]30|750[36]30|1000340)AS?",
     "(AD14|SD1[5-9]|SD81)",
     "There are known problems with these drives,\n"
@@ -1368,7 +1486,7 @@ const drive_settings builtin_knowndrives[] = {
     "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207951",
     ""
   },
-  { "Seagate Barracuda 7200.11 family", // unknown firmware
+  { "Seagate Barracuda 7200.11", // unknown firmware
     "ST3(160813|320[68]13|500[368]20|640[36]23|640[35]30|750[36]30|1000(333|[36]40)|1500341)AS?",
     "",
     "There are known problems with these drives,\n"
@@ -1378,7 +1496,7 @@ const drive_settings builtin_knowndrives[] = {
     "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957",
     ""
   },
-  { "Seagate Barracuda 7200.12 family",
+  { "Seagate Barracuda 7200.12",
     "ST3(160318|25031[18]|320418|50041[08]|750(518|52[38])|100052[38])AS",
     "", "", ""
   },
@@ -1404,8 +1522,12 @@ const drive_settings builtin_knowndrives[] = {
     "ST3(500412|1000520|1500541|2000542)AS",
     "", "", ""
   },
+  { "Seagate Barracuda Green (Adv. Format)",
+    "ST(1000DL002|(15|20)00DL003)-.*",
+    "", "", ""
+  },
   { "Seagate Barracuda XT",
-    "ST32000641AS",
+    "ST(32000641|33000651)AS",
     "", "", ""
   },
   { "Seagate Constellation (SATA)", // tested with ST9500530NS/SN03
@@ -1416,11 +1538,11 @@ const drive_settings builtin_knowndrives[] = {
     "ST3(50051|100052|200064)4NS",
     "", "", ""
   },
-  { "Seagate Pipeline HD 5900.1 family",
+  { "Seagate Pipeline HD 5900.1",
     "ST3(160310|320[34]10|500(321|422))CS",
     "", "", ""
   },
-  { "Seagate Pipeline HD 5900.2 family", // tested with ST31000322CS/SC13
+  { "Seagate Pipeline HD 5900.2", // tested with ST31000322CS/SC13
     "ST3(160316|250[34]12|320(311|413)|500(312|414)|1000(322|424))CS",
     "", "", ""
   },
@@ -1432,15 +1554,15 @@ const drive_settings builtin_knowndrives[] = {
     "ST3(1724|1303|1023|842|431)2A",
     "", "", ""
   },
-  { "Seagate NL35 family",
+  { "Seagate NL35",
     "ST3(250623|250823|400632|400832|250824|250624|400633|400833|500641|500841)NS",
     "", "", ""
   },
-  { "Seagate SV35.2 Series",
+  { "Seagate SV35.2",
     "ST3(160815|250820|320620|500630|750640)(A|S)V",
     "", "", ""
   },
-  { "Seagate DB35.3 Series",
+  { "Seagate DB35.3",
     "ST3(750640SCE|((80|160)215|(250|320|400)820|500830|750840)(A|S)CE)",
     "", "", ""
   },
@@ -1453,7 +1575,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD([2468]00E|1[26]00A)B-.*",
     "", "", ""
   },
-  { "Western Digital Caviar family",
+  { "Western Digital Caviar",
   /* Western Digital drives with this comment all appear to use Attribute 9 in
    * a  non-standard manner.  These entries may need to be updated when it
    * is understood exactly how Attribute 9 should be interpreted.
@@ -1462,7 +1584,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(2|3|4|6|8|10|12|16|18|20|25)00BB-.*",
     "", "", ""
   },
-  { "Western Digital Caviar WDxxxAB series",
+  { "Western Digital Caviar WDxxxAB",
   /* Western Digital drives with this comment all appear to use Attribute 9 in
    * a  non-standard manner.  These entries may need to be updated when it
    * is understood exactly how Attribute 9 should be interpreted.
@@ -1471,7 +1593,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(3|4|6|8|25)00AB-.*",
     "", "", ""
   },
-  { "Western Digital Caviar WDxxxAA series",
+  { "Western Digital Caviar WDxxxAA",
   /* Western Digital drives with this comment all appear to use Attribute 9 in
    * a  non-standard manner.  These entries may need to be updated when it
    * is understood exactly how Attribute 9 should be interpreted.
@@ -1480,7 +1602,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD...?AA(-.*)?",
     "", "", ""
   },
-  { "Western Digital Caviar WDxxxBA series",
+  { "Western Digital Caviar WDxxxBA",
   /* Western Digital drives with this comment all appear to use Attribute 9 in
    * a  non-standard manner.  These entries may need to be updated when it
    * is understood exactly how Attribute 9 should be interpreted.
@@ -1489,11 +1611,11 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD...BA",
     "", "", ""
   },
-  { "Western Digital Caviar AC series", // add only 5400rpm/7200rpm (ata33 and faster)
+  { "Western Digital Caviar AC", // add only 5400rpm/7200rpm (ata33 and faster)
     "WDC AC((116|121|125|225|132|232)|([1-4][4-9][0-9])|([1-4][0-9][0-9][0-9]))00[A-Z]?.*",
     "", "", ""
   },
-  { "Western Digital Caviar SE family",
+  { "Western Digital Caviar SE",
   /* Western Digital drives with this comment all appear to use Attribute 9 in
    * a  non-standard manner.  These entries may need to be updated when it
    * is understood exactly how Attribute 9 should be interpreted.
@@ -1503,89 +1625,101 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(4|6|8|10|12|16|18|20|25|30|32|40|50)00(JB|PB)-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Blue EIDE family",  // WD Caviar SE EIDE family
+  { "Western Digital Caviar Blue EIDE",  // WD Caviar SE EIDE
     /* not completely accurate: at least also WD800JB, WD(4|8|20|25)00BB sold as Caviar Blue */
     "WDC WD(16|25|32|40|50)00AAJB-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Blue EIDE family",  // WD Caviar SE16 EIDE family
+  { "Western Digital Caviar Blue EIDE",  // WD Caviar SE16 EIDE
     "WDC WD(25|32|40|50)00AAKB-.*",
     "", "", ""
   },
-  { "Western Digital RE EIDE family",
+  { "Western Digital RE EIDE",
     "WDC WD(12|16|25|32)00SB-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Serial ATA family",
+  { "Western Digital Caviar Serial ATA",
     "WDC WD(4|8|20|32)00BD-.*",
     "", "", ""
   },
-  { "Western Digital Caviar SE Serial ATA family",
+  { "Western Digital Caviar SE Serial ATA",
     "WDC WD(4|8|12|16|20|25|32|40)00(JD|KD|PD)-.*",
     "", "", ""
   },
-  { "Western Digital Caviar SE Serial ATA family",
+  { "Western Digital Caviar SE Serial ATA",
     "WDC WD(8|12|16|20|25|30|32|40|50)00JS-.*",
     "", "", ""
   },
-  { "Western Digital Caviar SE16 Serial ATA family",
+  { "Western Digital Caviar SE16 Serial ATA",
     "WDC WD(16|20|25|32|40|50|75)00KS-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Blue Serial ATA family",  // WD Caviar SE Serial ATA family
+  { "Western Digital Caviar Blue Serial ATA",  // WD Caviar SE Serial ATA
     /* not completely accurate: at least also WD800BD, (4|8)00JD sold as Caviar Blue */
     "WDC WD((8|12|16|25|32)00AABS|(8|12|16|25|32|40|50)00AAJS)-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Blue Serial ATA family",  // WD Caviar SE16 Serial ATA family
+  { "Western Digital Caviar Blue Serial ATA",  // WD Caviar SE16 Serial ATA
     "WDC WD((16|20|25|32|40|50|64|75)00AAKS|10EALS)-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Blue Serial ATA family",  // SATA 3.0 variants
+  { "Western Digital Caviar Blue Serial ATA",  // SATA 3.0 variants
     "WDC WD((25|32|50)00AAKX|7500AALX|10EALX)-.*",
     "", "", ""
   },
-  { "Western Digital RE Serial ATA family",
+  { "Western Digital RE Serial ATA",
     "WDC WD(12|16|25|32)00(SD|YD|YS)-.*",
     "", "", ""
   },
-  { "Western Digital RE2 Serial ATA family",
+  { "Western Digital RE2 Serial ATA",
     "WDC WD((40|50|75)00(YR|YS|AYYS)|(16|32|40|50)0[01]ABYS)-.*",
     "", "", ""
   },
-  { "Western Digital RE2-GP family",
+  { "Western Digital RE2-GP",
     "WDC WD(5000AB|7500AY|1000FY)PS-.*",
     "", "", ""
   },
-  { "Western Digital RE3 Serial ATA family",
+  { "Western Digital RE3 Serial ATA",
     "WDC WD((25|32|50)02A|(75|10)02F)BYS-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Green family",
+  { "Western Digital RE4 Serial ATA",
+    "WDC WD((((25|50)03A|1003F)BYX)|((15|20)03FYYS))-.*",
+    "", "", ""
+  },
+  { "Western Digital Caviar Green",
     "WDC WD((50|64|75)00AA(C|V)S|(50|64|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Green (Adv. Format) family",
-    "WDC WD((64|75|80)00AA|(10|15|20)EA|(25|30)EZ)RS-.*",
+  { "Western Digital Caviar Green (Adv. Format)",
+    "WDC WD(((64|75|80)00AA|(10|15|20)EA|(25|30)EZ)R|20EAC)S-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Black family",
+  { "Western Digital Caviar Black",
     "WDC WD((500|640|750)1AAL|1001FA[EL]|2001FAS)S-.*",
     "", "", ""
   },
-  { "Western Digital AV ATA family", // tested with WDC WD3200AVJB-63J5A0/01.03E01
+  { "Western Digital Caviar Black",  // SATA 3.0 variants
+    "WDC WD(5002AAL|(64|75)02AAE|(10|15|20)02FAE)X-.*",
+    "", "", ""
+  },
+  { "Western Digital AV ATA", // tested with WDC WD3200AVJB-63J5A0/01.03E01
     "WDC WD(8|16|25|32|50)00AV[BJ]B-.*",
     "", "", ""
   },
-  { "Western Digital AV SATA family",
+  { "Western Digital AV SATA",
     "WDC WD(16|25|32)00AVJS-.*",
     "", "", ""
   },
-  { "Western Digital AV-GP family",
+  { "Western Digital AV-GP",
     "WDC WD((16|25|32|50|64|75)00AVVS|(50|75)00AVCS|10EVVS|(10|20)EVCS|(10|15|20)EVDS)-.*",
     "", "", ""
   },
-  { "Western Digital Raptor family",
+  { "Western Digital AV-25",
+    "WDC WD((16|25|32|50)00BUD|5000BUC)T-.*",
+    "", "", ""
+  },
+  { "Western Digital Raptor",
     "WDC WD((360|740|800)GD|(360|740|800|1500)ADF[DS])-.*",
     "", "", ""
   },
@@ -1593,11 +1727,11 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD1500AHFD-.*",
     "", "", ""
   },
-  { "Western Digital VelociRaptor family",
+  { "Western Digital VelociRaptor",
     "WDC WD(((800H|(1500|3000)[BH]|1600H|3000G)LFS)|((4500|6000)[BH]LHX))-.*",
     "", "", ""
   },
-  { "Western Digital Scorpio EIDE family",
+  { "Western Digital Scorpio EIDE",
     "WDC WD(4|6|8|10|12|16)00(UE|VE)-.*",
     "", "", ""
   },
@@ -1605,15 +1739,19 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(4|6|8|10|12|16|25|32)00BEVE-.*",
     "", "", ""
   },
-  { "Western Digital Scorpio Serial ATA family",
+  { "Western Digital Scorpio Serial ATA",
     "WDC WD(4|6|8|10|12|16|25)00BEAS-.*",
     "", "", ""
   },
-  { "Western Digital Scorpio Blue Serial ATA family",
+  { "Western Digital Scorpio Blue Serial ATA",
     "WDC WD((4|6|8|10|12|16|25)00BEVS|(8|12|16|25|32|40|50|64)00BEVT|7500KEVT|10TEVT)-.*",
     "", "", ""
   },
-  { "Western Digital Scorpio Black Serial ATA family",
+  { "Western Digital Scorpio Blue Serial ATA (Adv. Format)",
+    "WDC WD((16|25|32|50|64|75)00BPVT|10TPVT)-.*",
+    "", "", ""
+  },
+  { "Western Digital Scorpio Black Serial ATA",
     "WDC WD(8|12|16|25|32)00B[EJ]KT-.*",
     "", "", ""
   },
@@ -1630,51 +1768,51 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(3200BMVV|5000BMVW)-.*",
     "", "", ""
   },
-  { "Quantum Bigfoot series", // tested with TS10.0A/A21.0G00, TS12.7A/A21.0F00
+  { "Quantum Bigfoot", // tested with TS10.0A/A21.0G00, TS12.7A/A21.0F00
     "QUANTUM BIGFOOT TS(10\\.0|12\\.7)A",
     "", "", ""
   },
-  { "Quantum Fireball lct15 series",
+  { "Quantum Fireball lct15",
     "QUANTUM FIREBALLlct15 ([123]0|22)",
     "", "", ""
   },
-  { "Quantum Fireball lct20 series",
-    "QUANTUM FIREBALLlct20 [234]0",
+  { "Quantum Fireball lct20",
+    "QUANTUM FIREBALLlct20 [1234]0",
     "", "", ""
   },
-  { "Quantum Fireball CX series",
+  { "Quantum Fireball CX",
     "QUANTUM FIREBALL CX10.2A",
     "", "", ""
   },
-  { "Quantum Fireball CR series",
+  { "Quantum Fireball CR",
     "QUANTUM FIREBALL CR(4.3|6.4|8.4|13.0)A",
     "", "", ""
   },
-  { "Quantum Fireball EX series",
+  { "Quantum Fireball EX",
     "QUANTUM FIREBALL EX(3.2|6.4)A",
     "", "", ""
   },
-  { "Quantum Fireball ST series",
+  { "Quantum Fireball ST",
     "QUANTUM FIREBALL ST(3.2|4.3|4300)A",
     "", "", ""
   },
-  { "Quantum Fireball SE series",
+  { "Quantum Fireball SE",
     "QUANTUM FIREBALL SE4.3A",
     "", "", ""
   },
-  { "Quantum Fireball Plus LM series",
+  { "Quantum Fireball Plus LM",
     "QUANTUM FIREBALLP LM(10.2|15|20.[45]|30)",
     "", "", ""
   },
-  { "Quantum Fireball Plus AS series",
-    "QUANTUM FIREBALLP AS(10.2|20.5|30.0|40.0)",
+  { "Quantum Fireball Plus AS",
+    "QUANTUM FIREBALLP AS(10.2|20.5|30.0|40.0|60.0)",
     "", "", ""
   },
-  { "Quantum Fireball Plus KX series",
+  { "Quantum Fireball Plus KX",
     "QUANTUM FIREBALLP KX27.3",
     "", "", ""
   },
-  { "Quantum Fireball Plus KA series",
+  { "Quantum Fireball Plus KA",
     "QUANTUM FIREBALLP KA(9|10).1",
     "", "", ""
   },
@@ -1738,6 +1876,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbjmicron"
   },
+  { "USB: Samsung S1 Portable; JMicron",
+    "0x04e8:0x2f03",
+    "",
+    "",
+    "-d usbjmicron"
+  },
   { "USB: Samsung Story Station; ",
     "0x04e8:0x5f06",
     "",
@@ -1831,12 +1975,30 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbjmicron,x"
   },
+  { "USB: LaCie Little Disk USB2; JMicron",
+    "0x059f:0x1021",
+    "",
+    "",
+    "-d usbjmicron"
+  },
+  { "USB: LaCie hard disk; ",
+    "0x059f:0x1029",
+    "", // 0x0100
+    "",
+    "-d sat"
+  },
   { "USB: Lacie rikiki; JMicron",
     "0x059f:0x102a",
     "",
     "",
     "-d usbjmicron,x"
   },
+  { "USB: LaCie rikiki USB 3.0; ",
+    "0x059f:0x1049",
+    "",
+    "",
+    "-d sat"
+  },
   // In-System Design
   { "USB: ; In-System/Cypress ISD-300A1",
     "0x05ab:0x0060",
@@ -1903,13 +2065,20 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbsunplus"
   },
+  // Oxford Semiconductor, Ltd
+  { "USB: ; Oxford OXU921DS",
+    "0x0928:0x0002",
+    "",
+    "",
+    "" // unsupported
+  },
   { "USB: Toshiba PX1396E-3T01; Sunplus", // similar to Dura Micro 501
     "0x0930:0x0b09",
     "",
     "",
     "-d usbsunplus"
   },
-  { "USB: Toshiba Stor.E Steel series; Sunplus",
+  { "USB: Toshiba Stor.E Steel; Sunplus",
     "0x0930:0x0b11",
     "",
     "",
@@ -1946,13 +2115,25 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
-  { "USB: Seagate FreeAgent Go Flex; ",
+  { "USB: Seagate Expansion External; ", // 2TB
+    "0x0bc2:0x3300",
+    "",
+    "",
+    "-d sat"
+  },
+  { "USB: Seagate FreeAgent GoFlex USB 2.0; ",
     "0x0bc2:0x5021",
     "",
     "",
     "-d sat"
   },
-  { "USB: Seagate FreeAgent Go Flex Desk USB 3.0; ",
+  { "USB: Seagate FreeAgent GoFlex USB 3.0; ",
+    "0x0bc2:0x5031",
+    "",
+    "",
+    "-d sat,12"
+  },
+  { "USB: Seagate FreeAgent GoFlex Desk USB 3.0; ",
     "0x0bc2:0x50a1",
     "",
     "",
@@ -1966,6 +2147,12 @@ const drive_settings builtin_knowndrives[] = {
     "-d usbsunplus"
   },
   // Maxtor
+  { "USB: Maxtor OneTouch 200GB; ",
+    "0x0d49:0x7010",
+    "",
+    "",
+    "" // unsupported
+  },
   { "USB: Maxtor OneTouch; ",
     "0x0d49:0x7300",
     "", // 0x0121
@@ -1996,6 +2183,13 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  // Cowon Systems, Inc.
+  { "USB: Cowon iAudio X5; ",
+    "0x0e21:0x0510",
+    "",
+    "",
+    "-d usbcypress"
+  },
   // iRiver
   { "USB: iRiver iHP-120/140 MP3 Player; Cypress",
     "0x1006:0x3002",
@@ -2076,6 +2270,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: WD My Book Office Edition; ", // 1TB
+    "0x1058:0x1101",
+    "", // 0x0165
+    "",
+    "-d sat"
+  },
   { "USB: WD My Book; ",
     "0x1058:0x1102",
     "", // 0x1028
@@ -2134,6 +2334,12 @@ const drive_settings builtin_knowndrives[] = {
     "-d usbcypress"
   },
   // JMicron
+  { "USB: ; JMicron USB 3.0",
+    "0x152d:0x0539",
+    "", // 0x0100
+    "",
+    "-d usbjmicron"
+  },
   { "USB: ; JMicron ", // USB->SATA->4xSATA (port multiplier)
     "0x152d:0x0551",
     "", // 0x0100
@@ -2201,6 +2407,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: ; ASMedia USB 3.0", // BYTECC T-200U3
+    "0x174c:0x55aa",
+    "",
+    "",
+    "" // unsupported
+  },
   // LucidPort
   { "USB: RaidSonic ICY BOX IB-110StU3-B; LucidPORT USB300",
     "0x1759:0x500[02]",
@@ -2221,6 +2433,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbsunplus"
   },
+  { "USB: Verbatim Pocket Hard Drive; JMicron", // SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS)
+    "0x18a5:0x0227",
+    "",
+    "",
+    "-d usbjmicron" // "-d usbjmicron,x" does not work
+  },
   // Silicon Image
   { "USB: Vantec NST-400MX-SR; Silicon Image 5744",
     "0x1a4a:0x1670",
index 1f2e73470de6889b53fcc4ef6a200315861a1bb4..cad0be217c3177b08de2dba613b3237edab0adc2 100644 (file)
@@ -34,7 +34,7 @@
 
 #include <stdexcept>
 
-const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 3289 2011-03-09 19:52:04Z chrfranke $"
+const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 3343 2011-05-25 20:18:17Z chrfranke $"
                                      KNOWNDRIVES_H_CVSID;
 
 #define MODEL_STRING_LENGTH                         40
@@ -214,8 +214,8 @@ static bool parse_db_presets(const char * presets, ata_vendor_attr_defs * defs,
     i += strspn(presets+i, " \t");
     if (!presets[i])
       break;
-    char opt, arg[40+1+13]; int len = -1;
-    if (!(sscanf(presets+i, "-%c %40[^ ]%n", &opt, arg, &len) >= 2 && len > 0))
+    char opt, arg[80+1+13]; int len = -1;
+    if (!(sscanf(presets+i, "-%c %80[^ ]%n", &opt, arg, &len) >= 2 && len > 0))
       return false;
     if (opt == 'v' && defs) {
       // Parse "-v N,format[,name]"
index 1a11c2977ad6b8839d31c314b3c3921ecaa5abbb..a974aaf9f2a6596e073c60e1bdfd0afb49ac262a 100644 (file)
@@ -74,7 +74,7 @@
 #define PATHINQ_SETTINGS_SIZE   128
 #endif
 
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3264 2011-02-21 15:52:04Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3335 2011-05-21 17:32:16Z samm2 $" \
 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 #define NO_RETURN 0
@@ -1267,6 +1267,8 @@ bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
   ccb.cdm.match_buf_len = bufsize;
   // TODO: Use local buffer instead of malloc() if possible
   ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
+  bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure
+  
   if (ccb.cdm.matches == NULL) {
     close(fd);
     throw std::bad_alloc();
@@ -1477,7 +1479,9 @@ bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
     ata_device * atadev = get_ata_device(atanames[i], type);
     if (atadev)
       devlist.push_back(atadev);
+    free(atanames[i]);
   }
+  if(numata) free(atanames);
 
   for (i = 0; i < (int)scsinames.size(); i++) {
     if(!*type) { // try USB autodetection if no type specified
@@ -1635,7 +1639,7 @@ smart_device * freebsd_smart_interface::autodetect_smart_device(const char * nam
   struct cam_device *cam_dev;
   union ccb ccb;
   int bus=-1;
-  int i;
+  int i,c;
   int len;
 
   // if dev_name null, or string length zero
@@ -1649,9 +1653,13 @@ smart_device * freebsd_smart_interface::autodetect_smart_device(const char * nam
     // check ATA/ATAPI devices
     for (i = 0; i < numata; i++) {
       if(!strcmp(atanames[i],name)) {
+        for (c = i; c < numata; c++) free(atanames[c]);
+        free(atanames);
         return new freebsd_ata_device(this, name, "");
       }
+      else free(atanames[i]);
     }
+    if(numata) free(atanames);
   }
   else {
     if (numata < 0)
index 0dfea39a83847d115b20059305ea3e899b5b032d..c46b756f63dcb65f12f881c070ddaaa3534596c7 100644 (file)
@@ -89,7 +89,7 @@
 
 #define ARGUSED(x) ((void)(x))
 
-const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3293 2011-03-09 21:55:15Z chrfranke $"
+const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3317 2011-04-19 19:42:54Z chrfranke $"
   OS_LINUX_H_CVSID;
 
 
@@ -2827,8 +2827,10 @@ private:
 std::string linux_smart_interface::get_os_version_str()
 {
   struct utsname u;
-  return strprintf("%s-%s", SMARTMONTOOLS_BUILD_HOST,
-    (!uname(&u) ? u.release : "?"));
+  if (!uname(&u))
+    return strprintf("%s-linux-%s", u.machine, u.release);
+  else
+    return SMARTMONTOOLS_BUILD_HOST;
 }
 
 std::string linux_smart_interface::get_app_examples(const char * appname)
index 1989af1de0854a451e965b368db28d34375dc045..06ae4b5522eaa26266fcd31684e0c431d2b5787d 100644 (file)
@@ -85,7 +85,7 @@
 #define SELECT_WIN_32_64(x32, x64) (x64)
 #endif
 
-const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3292 2011-03-09 21:12:03Z chrfranke $";
+const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3358 2011-06-06 19:04:20Z chrfranke $";
 
 // Disable Win9x/ME specific code if no longer supported by compiler.
 #ifdef _WIN64
@@ -380,6 +380,7 @@ private:
   bool m_usr_options; // options set by user?
   bool m_admin; // open with admin access?
   bool m_id_is_cached; // ata_identify_is_cached() return value.
+  bool m_is_3ware; // AMCC/3ware controller detected?
   int m_drive, m_port;
   int m_smartver_state;
 };
@@ -2116,6 +2117,9 @@ static int get_identify_from_device_property(HANDLE hdevice, ata_identify_device
   if (data.desc.ProductIdOffset) {
     while (i > 1 && model[i-2] == ' ') // Keep last blank from VendorId
       i--;
+    // Ignore VendorId "ATA"
+    if (i <= 4 && !strncmp(model, "ATA", 3) && (i == 3 || model[3] == ' '))
+      i = 0;
     for (unsigned j = 0; i < sizeof(model)-1 && data.raw[data.desc.ProductIdOffset+j]; i++, j++)
       model[i] = data.raw[data.desc.ProductIdOffset+j];
   }
@@ -2407,6 +2411,7 @@ win_ata_device::win_ata_device(smart_interface * intf, const char * dev_name, co
   m_usr_options(false),
   m_admin(false),
   m_id_is_cached(false),
+  m_is_3ware(false),
   m_drive(0),
   m_port(-1),
   m_smartver_state(0)
@@ -2532,13 +2537,16 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
   // Win9X/ME: Get drive map
   // RAID: Get port map
   GETVERSIONINPARAMS_EX vers_ex;
-  int devmap = smart_get_version(h, (port >= 0 ? &vers_ex : 0));
+  int devmap = smart_get_version(h, &vers_ex);
+
+  // 3ware RAID if vendor id present
+  m_is_3ware = (vers_ex.wIdentifier == SMART_VENDOR_3WARE);
 
   unsigned long portmap = 0;
   if (port >= 0 && devmap >= 0) {
     // 3ware RAID: check vendor id
-    if (vers_ex.wIdentifier != SMART_VENDOR_3WARE) {
-      pout("SMART_GET_VERSION returns unknown Identifier = %04x\n"
+    if (!m_is_3ware) {
+      pout("SMART_GET_VERSION returns unknown Identifier = 0x%04x\n"
            "This is no 3ware 9000 controller or driver has no SMART support.\n",
            vers_ex.wIdentifier);
       devmap = -1;
@@ -2643,6 +2651,12 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
   )
     return false;
 
+  // 3ware RAID: SMART DISABLE without port number disables SMART functions
+  if (   m_is_3ware && m_port < 0
+      && in.in_regs.command == ATA_SMART_CMD
+      && in.in_regs.features == ATA_SMART_DISABLE)
+    return set_err(ENOSYS, "SMART DISABLE requires 3ware port number");
+
   // Determine ioctl functions valid for this ATA cmd
   const char * valid_options = 0;
 
@@ -2821,7 +2835,8 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
         }
         if (!m_smartver_state) {
           assert(m_port == -1);
-          if (smart_get_version(get_fh()) < 0) {
+          GETVERSIONINPARAMS_EX vers_ex;
+          if (smart_get_version(get_fh(), &vers_ex) < 0) {
             if (!failuretest_permissive) {
               m_smartver_state = 2;
               rc = -1; errno = ENOSYS;
@@ -2829,6 +2844,11 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
             }
             failuretest_permissive--;
           }
+          else  {
+            // 3ware RAID if vendor id present
+            m_is_3ware = (vers_ex.wIdentifier == SMART_VENDOR_3WARE);
+          }
+
           m_smartver_state = 1;
         }
         rc = smart_ioctl(get_fh(), m_drive, &regs, data, datasize, m_port);
@@ -4038,6 +4058,10 @@ bool win_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
     memcpy(iop->sensep, sb.ucSenseBuf, slen);
     iop->resp_sense_len = slen;
     if (report) {
+      if (report > 1) {
+        pout("  >>> Sense buffer, len=%d:\n", slen);
+        dStrHex(iop->sensep, slen , 1);
+      }
       if ((iop->sensep[0] & 0x7f) > 0x71)
         pout("  status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
              iop->scsi_status, iop->sensep[1] & 0xf,
index 85ff8163ca955bd2345d6ff57606832898681dc1..74c02f23ddf5368308f99af69ad9ec8eeed2294d 100644 (file)
@@ -13,7 +13,7 @@
 ; 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 3296 2011-03-16 22:17:51Z chrfranke $
+; $Id: installer.nsi 3298 2011-03-22 18:36:44Z chrfranke $
 ;
 
 
@@ -46,6 +46,14 @@ Var UBCDDIR
 
 LicenseData "${INPDIR}\doc\COPYING.txt"
 
+!include "FileFunc.nsh"
+!include "Sections.nsh"
+
+!insertmacro GetParameters
+!insertmacro GetOptions
+
+RequestExecutionLevel admin
+
 ;--------------------------------------------------------------------
 ; Pages
 
@@ -187,6 +195,8 @@ Section "Start Menu Shortcuts" MENU_SECTION
 
   SectionIn 1
 
+  SetShellVarContext all
+
   CreateDirectory "$SMPROGRAMS\smartmontools"
 
   ; smartctl
@@ -311,7 +321,7 @@ SectionGroup "Add smartctl to drive menu"
   DeleteRegKey HKCR "Drive\shell\smartctl5"
 !macroend
 
-  Section "Remove existing entries first"
+  Section "Remove existing entries first" DRIVE_REMOVE_SECTION
     SectionIn 3
     !insertmacro DriveMenuRemove
   SectionEnd
@@ -450,6 +460,7 @@ Section "Uninstall"
   Delete "$INSTDIR\uninst-smartmontools.exe"
 
   ; Remove shortcuts
+  SetShellVarContext all
   Delete "$SMPROGRAMS\smartmontools\*.*"
   Delete "$SMPROGRAMS\smartmontools\Documentation\*.*"
   Delete "$SMPROGRAMS\smartmontools\smartctl Examples\*.*"
@@ -499,6 +510,59 @@ Function .onInit
   IfFileExists "$WINDIR\system32\cmd.exe" +2 0
     SectionSetText ${PATH_SECTION} ""
 
+  Call ParseCmdLine
+FunctionEnd
+
+; Command line parsing
+!macro CheckCmdLineOption name section
+  StrCpy $allopts "$allopts,${name}"
+  Push ",$opts,"
+  Push ",${name},"
+  Call StrStr
+  Pop $0
+  StrCmp $0 "" 0 sel_${name}
+  !insertmacro UnselectSection ${section}
+  Goto done_${name}
+sel_${name}:
+  !insertmacro SelectSection ${section}
+  StrCpy $nomatch ""
+done_${name}:
+!macroend
+
+Function ParseCmdLine
+  ; get /SO option
+  Var /global opts
+  ${GetParameters} $R0
+  ${GetOptions} $R0 "/SO" $opts
+  IfErrors 0 +2
+    Return
+  Var /global allopts
+  StrCpy $allopts ""
+  Var /global nomatch
+  StrCpy $nomatch "t"
+  ; turn sections on or off
+  !insertmacro CheckCmdLineOption "smartctl" ${SMARTCTL_SECTION}
+  !insertmacro CheckCmdLineOption "smartd" ${SMARTD_SECTION}
+  !insertmacro CheckCmdLineOption "smartctlnc" ${SMARTCTL_NC_SECTION}
+  !insertmacro CheckCmdLineOption "drivedb" ${DRIVEDB_SECTION}
+  !insertmacro CheckCmdLineOption "doc" ${DOC_SECTION}
+  !insertmacro CheckCmdLineOption "uninst" ${UNINST_SECTION}
+  !insertmacro CheckCmdLineOption "menu" ${MENU_SECTION}
+  !insertmacro CheckCmdLineOption "path" ${PATH_SECTION}
+  !insertmacro CheckCmdLineOption "driveremove" ${DRIVE_REMOVE_SECTION}
+  !insertmacro CheckCmdLineOption "drive0" ${DRIVE_0_SECTION}
+  !insertmacro CheckCmdLineOption "drive1" ${DRIVE_1_SECTION}
+  !insertmacro CheckCmdLineOption "drive2" ${DRIVE_2_SECTION}
+  !insertmacro CheckCmdLineOption "drive3" ${DRIVE_3_SECTION}
+  !insertmacro CheckCmdLineOption "drive4" ${DRIVE_4_SECTION}
+  !insertmacro CheckCmdLineOption "drive5" ${DRIVE_5_SECTION}
+  !insertmacro CheckCmdLineOption "ubcd" ${UBCD_SECTION}
+  StrCmp $opts "-" done
+  StrCmp $nomatch "" done
+    StrCpy $0 "$allopts,-" "" 1
+    MessageBox MB_OK "Usage: smartmontools-VERSION.win32-setup [/S] [/SO component,...] [/D=INSTDIR]$\n$\ncomponents:$\n  $0"
+    Abort
+done:
 FunctionEnd
 
 ; Directory page callbacks
index fb4d33272e24b4d526edf1274d1f4449d5cdd592..30a935641f4a46e196a046e3bd12a1bb95114534 100644 (file)
@@ -49,7 +49,7 @@
 #include "dev_interface.h"
 #include "utility.h"
 
-const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 3258 2011-02-14 22:31:01Z manfred99 $"
+const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 3302 2011-03-25 23:04:36Z dpgilbert $"
   SCSICMDS_H_CVSID;
 
 // Print SCSI debug messages?
@@ -146,7 +146,7 @@ const char * scsi_get_opcode_name(UINT8 opcode)
     struct scsi_opcode_name * onp;
 
     if (opcode >= 0xc0)
-       return vendor_specific;
+        return vendor_specific;
     for (k = 0; k < len; ++k) {
         onp = &opcode_name_arr[k];
         if (opcode == onp->opcode)
@@ -252,6 +252,159 @@ const char * scsiErrString(int scsiErr)
     }
 }
 
+/* Iterates to next designation descriptor in the device identification
+ * VPD page. The 'initial_desig_desc' should point to start of first
+ * descriptor with 'page_len' being the number of valid bytes in that
+ * and following descriptors. To start, 'off' should point to a negative
+ * value, thereafter it should point to the value yielded by the previous
+ * call. If 0 returned then 'initial_desig_desc + *off' should be a valid
+ * descriptor; returns -1 if normal end condition and -2 for an abnormal
+ * termination. Matches association, designator_type and/or code_set when
+ * any of those values are greater than or equal to zero. */
+int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
+                        int page_len, int * off, int m_assoc,
+                        int m_desig_type, int m_code_set)
+{
+    const unsigned char * ucp;
+    int k, c_set, assoc, desig_type;
+
+    for (k = *off, ucp = initial_desig_desc ; (k + 3) < page_len; ) {
+        k = (k < 0) ? 0 : (k + ucp[k + 3] + 4);
+        if ((k + 4) > page_len)
+            break;
+        c_set = (ucp[k] & 0xf);
+        if ((m_code_set >= 0) && (m_code_set != c_set))
+            continue;
+        assoc = ((ucp[k + 1] >> 4) & 0x3);
+        if ((m_assoc >= 0) && (m_assoc != assoc))
+            continue;
+        desig_type = (ucp[k + 1] & 0xf);
+        if ((m_desig_type >= 0) && (m_desig_type != desig_type))
+            continue;
+        *off = k;
+        return 0;
+    }
+    return (k == page_len) ? -1 : -2;
+}
+
+/* Decode VPD page 0x83 logical unit designator into a string. If both
+ * numeric address and SCSI name string present, prefer the former.
+ * Returns 0 on success, -1 on error with error string in s. */
+int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
+                         int slen, int * transport)
+{
+    int m, c_set, assoc, desig_type, i_len, naa, off, u, have_scsi_ns;
+    const unsigned char * ucp;
+    const unsigned char * ip;
+    char * orig_s = s;
+
+    if (transport)
+       *transport = -1;
+    if (slen < 32) {
+       if (slen > 0)
+           s[0] = '\0';
+       return -1;
+    }
+    have_scsi_ns = 0;
+    s[0] = '\0';
+    off = -1;
+    while ((u = scsi_vpd_dev_id_iter(b, blen, &off, -1, -1, -1)) == 0) {
+        ucp = b + off;
+        i_len = ucp[3];
+        if ((off + i_len + 4) > blen) {
+           s += sprintf(s, "error: designator length");
+           return -1;
+        }
+        assoc = ((ucp[1] >> 4) & 0x3);
+       if (transport && assoc && (ucp[1] & 0x80) && (*transport < 0))
+           *transport = (ucp[0] >> 4) & 0xf;
+       if (0 != assoc)
+           continue;
+        ip = ucp + 4;
+        c_set = (ucp[0] & 0xf);
+        desig_type = (ucp[1] & 0xf);
+
+        switch (desig_type) {
+        case 0: /* vendor specific */
+        case 1: /* T10 vendor identification */
+            break;
+        case 2: /* EUI-64 based */
+            if ((8 != i_len) && (12 != i_len) && (16 != i_len)) {
+               s += sprintf(s, "error: EUI-64 length");
+               return -1;
+           }
+           if (have_scsi_ns)
+               s = orig_s;
+            s += sprintf(s, "0x");
+            for (m = 0; m < i_len; ++m)
+                s += sprintf(s, "%02x", (unsigned int)ip[m]);
+            break;
+        case 3: /* NAA */
+            if (1 != c_set) {
+               s += sprintf(s, "error: NAA bad code_set");
+               return -1;
+           }
+            naa = (ip[0] >> 4) & 0xff;
+            if ((naa < 2) || (naa > 6) || (4 == naa)) {
+               s += sprintf(s, "error: unexpected NAA");
+               return -1;
+            }
+           if (have_scsi_ns)
+               s = orig_s;
+            if (2 == naa) {             /* NAA IEEE Extended */
+                if (8 != i_len) {
+                   s += sprintf(s, "error: NAA 2 length");
+                   return -1;
+                }
+                s += sprintf(s, "0x");
+                for (m = 0; m < 8; ++m)
+                    s += sprintf(s, "%02x", (unsigned int)ip[m]);
+            } else if ((3 == naa ) || (5 == naa)) {
+                /* NAA=3 Locally assigned; NAA=5 IEEE Registered */
+                if (8 != i_len) {
+                   s += sprintf(s, "error: NAA 3 or 5 length");
+                   return -1;
+                }
+                s += sprintf(s, "0x");
+                for (m = 0; m < 8; ++m)
+                    s += sprintf(s, "%02x", (unsigned int)ip[m]);
+            } else if (6 == naa) {      /* NAA IEEE Registered extended */
+                if (16 != i_len) {
+                   s += sprintf(s, "error: NAA 6 length");
+                   return -1;
+                }
+                s += sprintf(s, "0x");
+                for (m = 0; m < 16; ++m)
+                    s += sprintf(s, "%02x", (unsigned int)ip[m]);
+            }
+            break;
+        case 4: /* Relative target port */
+        case 5: /* (primary) Target port group */
+        case 6: /* Logical unit group */
+        case 7: /* MD5 logical unit identifier */
+            break;
+        case 8: /* SCSI name string */
+            if (3 != c_set) {
+               s += sprintf(s, "error: SCSI name string");
+               return -1;
+            }
+            /* does %s print out UTF-8 ok?? */
+           if (orig_s == s) {
+                s += sprintf(s, "%s", (const char *)ip);
+               ++have_scsi_ns;
+           }
+            break;
+        default: /* reserved */
+            break;
+        }
+    }
+    if (-2 == u) {
+        s += sprintf(s, "error: bad structure");
+       return -1;
+    }
+    return 0;
+}
+
 /* Sends LOG SENSE command. Returns 0 if ok, 1 if device NOT READY, 2 if
    command not supported, 3 if field (within command) not supported or
    returns negated errno.  SPC-3 sections 6.6 and 7.2 (rec 22a).
@@ -847,6 +1000,117 @@ int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_
     return scsiSimpleSenseFilter(&sinfo);
 }
 
+/* READ CAPACITY (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
+ * command not supported, 3 if field in command not supported or returns
+ * negated errno. SBC-3 section 5.15 (rev 26) */
+int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap,
+                       unsigned int * lb_sizep)
+{
+    int res;
+    struct scsi_cmnd_io io_hdr;
+    struct scsi_sense_disect sinfo;
+    UINT8 cdb[10];
+    UINT8 sense[32];
+    UINT8 resp[8];
+
+    memset(&io_hdr, 0, sizeof(io_hdr));
+    memset(cdb, 0, sizeof(cdb));
+    memset(resp, 0, sizeof(resp));
+    io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
+    io_hdr.dxfer_len = sizeof(resp);
+    io_hdr.dxferp = resp;
+    cdb[0] = READ_CAPACITY_10;
+    io_hdr.cmnd = cdb;
+    io_hdr.cmnd_len = sizeof(cdb);
+    io_hdr.sensep = sense;
+    io_hdr.max_sense_len = sizeof(sense);
+    io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
+
+    if (!device->scsi_pass_through(&io_hdr))
+      return -device->get_errno();
+    scsi_do_sense_disect(&io_hdr, &sinfo);
+    res = scsiSimpleSenseFilter(&sinfo);
+    if (res)
+        return res;
+    if (last_lbap)
+        *last_lbap = (resp[0] << 24) | (resp[1] << 16) | (resp[2] << 8) |
+                     resp[3];
+    if (lb_sizep)
+        *lb_sizep = (resp[4] << 24) | (resp[5] << 16) | (resp[6] << 8) |
+                    resp[7];
+    return 0;
+}
+
+/* READ CAPACITY (16) command. The bufLen argument should be 32. Returns 0
+ * if ok, 1 if NOT READY, 2 if command not supported, 3 if field in command
+ * not supported or returns negated errno. SBC-3 section 5.16 (rev 26) */
+int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen)
+{
+    struct scsi_cmnd_io io_hdr;
+    struct scsi_sense_disect sinfo;
+    UINT8 cdb[16];
+    UINT8 sense[32];
+
+    memset(&io_hdr, 0, sizeof(io_hdr));
+    memset(cdb, 0, sizeof(cdb));
+    io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
+    io_hdr.dxfer_len = bufLen;
+    io_hdr.dxferp = pBuf;
+    cdb[0] = READ_CAPACITY_16;
+    cdb[1] = SAI_READ_CAPACITY_16;
+    cdb[10] = (bufLen >> 24) & 0xff;
+    cdb[11] = (bufLen >> 16) & 0xff;
+    cdb[12] = (bufLen >> 8) & 0xff;
+    cdb[13] = bufLen & 0xff;
+    io_hdr.cmnd = cdb;
+    io_hdr.cmnd_len = sizeof(cdb);
+    io_hdr.sensep = sense;
+    io_hdr.max_sense_len = sizeof(sense);
+    io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
+
+    if (!device->scsi_pass_through(&io_hdr))
+      return -device->get_errno();
+    scsi_do_sense_disect(&io_hdr, &sinfo);
+    return scsiSimpleSenseFilter(&sinfo);
+}
+
+/* Return number of bytes of storage in 'device' or 0 if error. If
+ * successful and lb_sizep is not NULL then the logical block size
+ * in bytes is written to the location pointed to by lb_sizep. */
+uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep)
+{
+    unsigned int last_lba, lb_size;
+    int k, res;
+    uint64_t ret_val = 0;
+    UINT8 rc16resp[32];
+
+    res = scsiReadCapacity10(device, &last_lba, &lb_size);
+    if (res) {
+       if (scsi_debugmode)
+           pout("scsiGetSize: READ CAPACITY(10) failed, res=%d\n", res);
+       return ret_val;
+    }
+    if (0xffffffff == last_lba) {
+       res = scsiReadCapacity16(device, rc16resp, sizeof(rc16resp));
+        if (res) {
+           if (scsi_debugmode)
+               pout("scsiGetSize: READ CAPACITY(16) failed, res=%d\n", res);
+           return ret_val;
+       }
+       for (k = 0; k < 8; ++k) {
+           if (k > 0)
+                ret_val <<= 8;
+            ret_val |= rc16resp[k + 0];
+        }
+    } else
+       ret_val = last_lba;
+    if (lb_sizep)
+       *lb_sizep = lb_size;
+    ++ret_val; /* last_lba is origin 0 so need to bump to get number of */
+    return ret_val * lb_size;
+}
+
+
 /* Offset into mode sense (6 or 10 byte) response that actual mode page
  * starts at (relative to resp[0]). Returns -1 if problem */
 int scsiModePageOffset(const UINT8 * resp, int len, int modese_len)
index 4ba1a3b073c0473017cd799c58407cc9ca302a04..56b146495772aaad6ee01f67b5a67a96e246c085 100644 (file)
@@ -32,7 +32,7 @@
 #ifndef SCSICMDS_H_
 #define SCSICMDS_H_
 
-#define SCSICMDS_H_CVSID "$Id: scsicmds.h 3258 2011-02-14 22:31:01Z manfred99 $\n"
+#define SCSICMDS_H_CVSID "$Id: scsicmds.h 3302 2011-03-25 23:04:36Z dpgilbert $\n"
 
 #include <stdio.h>
 #include <stdlib.h>
 #define READ_CAPACITY_10  0x25
 #endif
 #ifndef READ_CAPACITY_16
-#define READ_CAPACITY_16  0x9e /* service action 0x10 */
+#define READ_CAPACITY_16  0x9e
+#endif
+#ifndef SAI_READ_CAPACITY_16    /* service action for READ_CAPACITY_16 */
+#define SAI_READ_CAPACITY_16  0x10
 #endif
 
 #ifndef SAT_ATA_PASSTHROUGH_12
@@ -305,6 +308,14 @@ int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo);
 
 const char * scsiErrString(int scsiErr);
 
+int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
+                         int page_len, int * off, int m_assoc,
+                         int m_desig_type, int m_code_set);
+
+int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
+                          int slen, int * transport);
+
+
 /* STANDARD SCSI Commands  */
 int scsiTestUnitReady(scsi_device * device);
 
@@ -340,6 +351,14 @@ int scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBu
 int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format,
                      UINT8 *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);
+
+uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep);
+
+
 /* SMART specific commands */
 int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage, UINT8 *asc,
                 UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp);
@@ -362,8 +381,8 @@ int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current);
 int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len);
 int scsiFetchTransportProtocol(scsi_device * device, int modese_len);
 
-/* T10 Standard IE Additional Sense Code strings taken from t10.org */
 
+/* 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);
 
index f10d0ebe858f1bf588bababa2c5bc1fe599e6733..d65674ab423a252cf9c2c94ece785a44605a62c2 100644 (file)
@@ -42,7 +42,7 @@
 
 #define GBUF_SIZE 65535
 
-const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 3256 2011-02-08 22:13:41Z chrfranke $"
+const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 3307 2011-03-31 14:54:58Z dpgilbert $"
                                  SCSIPRINT_H_CVSID;
 
 
@@ -1311,15 +1311,13 @@ static const char * transport_proto_arr[] = {
 /* Returns 0 on success, 1 on general error and 2 for early, clean exit */
 static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)
 {
-    char manufacturer[9];
-    char product[17];
-    char revision[5];
     char timedatetz[DATEANDEPOCHLEN];
     struct scsi_iec_mode_page iec;
-    int err, iec_err, len, req_len, avail_len, val;
+    int err, iec_err, len, req_len, avail_len;
     int is_tape = 0;
     int peri_dt = 0;
-    int returnval=0;
+    int returnval = 0;
+    int transport = -1;
         
     memset(gBuf, 0, 96);
     req_len = 36;
@@ -1350,19 +1348,15 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
         print_off();
         return 1;
     }
-    memset(manufacturer, 0, sizeof(manufacturer));
-    strncpy(manufacturer, (char *)&gBuf[8], 8);
-    memset(product, 0, sizeof(product));
-    strncpy(product, (char *)&gBuf[16], 16);
-        
-    memset(revision, 0, sizeof(revision));
-    strncpy(revision, (char *)&gBuf[32], 4);
-    if (all && (0 != strncmp(manufacturer, "ATA", 3)))
-        pout("Device: %s %s Version: %s\n", manufacturer, product, revision);
+    if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) {
+        pout("Vendor:               %.8s\n", (char *)&gBuf[8]);
+       pout("Product:              %.16s\n", (char *)&gBuf[16]);
+       if (gBuf[32] >= ' ')
+           pout("Revision:             %.4s\n", (char *)&gBuf[32]);
+    }
 
     if (!*device->get_req_type()/*no type requested*/ &&
-               (0 == strncmp(manufacturer, "ATA", 3))) {
+               (0 == strncmp((char *)&gBuf[8], "ATA", 3))) {
         pout("\nProbable ATA device behind a SAT layer\n"
              "Try an additional '-d ata' or '-d sat' argument.\n");
         return 2;
@@ -1370,6 +1364,20 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
     if (! all)
         return 0;
 
+    unsigned int lb_size;
+    char cap_str[64];
+    char si_str[64];
+    char lb_str[16];
+    uint64_t capacity = scsiGetSize(device, &lb_size);
+
+    if (capacity) {
+        format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);
+        format_capacity(si_str, sizeof(si_str), capacity);
+        pout("User Capacity:        %s bytes [%s]\n", cap_str, si_str);
+        snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);
+        pout("Logical block size:   %s bytes\n", lb_str);
+    }
+
     /* Do this here to try and detect badly conforming devices (some USB
        keys) that will lock up on a InquiryVpd or log sense or ... */
     if ((iec_err = scsiFetchIECmpage(device, &iec, modese_len))) {
@@ -1383,15 +1391,27 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
     } else
         modese_len = iec.modese_len;
 
-    if (!dont_print_serial_number) {
-        if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) {
-            /* should use VPD page 0x83 and fall back to this page (0x80)
-             * if 0x83 not supported. NAA requires a lot of decoding code */
+    if (! dont_print_serial_number) {
+       if (0 == (err = scsiInquiryVpd(device, 0x83, gBuf, 200))) {
+           char s[256];
+
             len = gBuf[3];
-            gBuf[4 + len] = '\0';
-            pout("Serial number: %s\n", &gBuf[4]);
+           scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);
+           if (strlen(s) > 0)
+                pout("Logical Unit id:      %s\n", s);
+        } else if (scsi_debugmode > 0) {
+            print_on();
+            if (SIMPLE_ERR_BAD_RESP == err)
+                pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
+            else
+                pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
+            print_off();
         }
-        else if (scsi_debugmode > 0) {
+       if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) {
+            len = gBuf[3];
+            gBuf[4 + len] = '\0';
+            pout("Serial number:        %s\n", &gBuf[4]);
+        } else if (scsi_debugmode > 0) {
             print_on();
             if (SIMPLE_ERR_BAD_RESP == err)
                 pout("Vital Product Data (VPD) bit ignored in INQUIRY\n");
@@ -1404,18 +1424,19 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
     // print SCSI peripheral device type
     if (peri_dt < (int)(sizeof(peripheral_dt_arr) / 
                         sizeof(peripheral_dt_arr[0])))
-        pout("Device type: %s\n", peripheral_dt_arr[peri_dt]);
+        pout("Device type:          %s\n", peripheral_dt_arr[peri_dt]);
     else
-        pout("Device type: <%d>\n", peri_dt);
+        pout("Device type:          <%d>\n", peri_dt);
 
     // See if transport protocol is known
-    val = scsiFetchTransportProtocol(device, modese_len);
-    if ((val >= 0) && (val <= 0xf))
-        pout("Transport protocol: %s\n", transport_proto_arr[val]);
+    if (transport < 0)
+        transport = scsiFetchTransportProtocol(device, modese_len);
+    if ((transport >= 0) && (transport <= 0xf))
+        pout("Transport protocol:   %s\n", transport_proto_arr[transport]);
 
     // print current time and date and timezone
     dateandtimezone(timedatetz);
-    pout("Local Time is: %s\n", timedatetz);
+    pout("Local Time is:        %s\n", timedatetz);
 
     if ((SCSI_PT_SEQUENTIAL_ACCESS == *peripheral_type) ||
         (SCSI_PT_MEDIUM_CHANGER == *peripheral_type))
index 10ae9e7ea4ccb352abb1f7ddeced08114719a957..093d16dc978422a25f0b8c45ed6f56260b5ad922 100644 (file)
@@ -1,7 +1,7 @@
 .ig
  Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
- $Id: smartctl.8.in 3283 2011-03-04 20:13:57Z chrfranke $
+ $Id: smartctl.8.in 3320 2011-04-30 20:44:55Z chrfranke $
  
  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
@@ -189,8 +189,8 @@ and the SMART options which require support for 48-bit ATA commands.
 Prints all SMART and non-SMART information about the device. For ATA
 devices this is equivalent to
 .nf
-\'\-H \-i \-c \-A \-l xerror,error \-l xselftest,selftest \-l selective
-\-l directory \-l scttemp \-l scterc \-l sataphy\'.
+\'\-H \-i \-c \-A \-f brief \-l xerror,error \-l xselftest,selftest
+\-l selective \-l directory \-l scttemp \-l scterc \-l sataphy\'.
 .fi
 and for SCSI, this is equivalent to
 .nf
@@ -817,6 +817,18 @@ and start\-stop cycle counter log pages. Certain vendor specific
 attributes are listed if recognised. The attributes are output in a
 relatively free format (compared with ATA disk attributes).
 .TP
+.B \-f FORMAT, \-\-format=FORMAT
+[ATA only] Selects the output format of the attributes to one of:
+
+.I old
+\- Old smartctl format. This is the default unless the \'\-x\' option is
+specified.
+
+.I brief
+\- New format which fits into 80 colums (except in some rare cases).
+This format also decodes four additional attribute flags.
+This is the default if the '\-x\' option is specified.
+.TP
 .B \-l TYPE, \-\-log=TYPE
 Prints either the SMART Error Log, the SMART Self\-Test Log, the SMART
 Selective Self\-Test Log [ATA only], the Log Directory [ATA only], or
@@ -1608,16 +1620,20 @@ This command also clears the temperature history table. See
 .I vendor,N
 \- [ATA only] issues the ATA command SMART EXECUTE OFF-LINE IMMEDIATE
 with subcommand N in LBA LOW register. The subcommand is specified as
-a hex value in the range 0x00 to 0xff. Subcommands 0x40-0x7f and
+a hex value in the range 0x00 to 0xff.  Subcommands 0x40-0x7e and
 0x90-0xff are reserved for vendor specific use, see table 61 of
-T13/1699-D Revision 6a (ATA8-ACS).
+T13/1699-D Revision 6a (ATA8-ACS).  Note that the subcommands
+0x00-0x04,0x7f,0x81-0x84 are supported by other smartctl options
+(e.g. 0x01: \'\-t short\', 0x7f: \'\-X\', 0x82: \'\-C \-t long\').
 
 \fBWARNING: Only run subcommands documented by the vendor of the
 device.\fP
 
-Example for Intel X18\-M/X25\-M G2 SSDs only: The subcommand 0x40
-(\'\-t vendor,0x40\') clears the timed workload related SMART
-attributes (226, 227, 228).
+Example for Intel (X18\-M/X25\-M G2 and 320 Series) SSDs only:
+The subcommand 0x40 (\'\-t vendor,0x40\') clears the timed workload
+related SMART attributes (226, 227, 228).  Note that the raw values of
+these attributes are held at 65535 (0xffff) until the workload timer
+reaches 60 minutes.
 .TP
 .B \-C, \-\-captive
 [ATA] Runs self\-tests in captive mode.  This has no effect with \'\-t
@@ -1939,4 +1955,4 @@ Links to these and other documents may be found on the Links page of the
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartctl.8.in 3283 2011-03-04 20:13:57Z chrfranke $
+$Id: smartctl.8.in 3320 2011-04-30 20:44:55Z chrfranke $
index c12120a2626bf77005e46a30387eaa9ca8a5a92b..57e8cbc80f64ea97c226069a70e8a8ea67967dfa 100644 (file)
@@ -55,7 +55,7 @@
 #include "smartctl.h"
 #include "utility.h"
 
-const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 3283 2011-03-04 20:13:57Z chrfranke $"
+const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 3316 2011-04-19 19:34:57Z chrfranke $"
   CONFIG_H_CVSID SMARTCTL_H_CVSID;
 
 // Globals to control printing
@@ -126,8 +126,10 @@ static void Usage()
 "        Show device SMART health status\n\n"
 "  -c, --capabilities                                                  (ATA)\n"
 "        Show device SMART capabilities\n\n"
-"  -A, --attributes                                                         \n"
+"  -A, --attributes\n"
 "        Show device SMART vendor-specific Attributes and values\n\n"
+"  -f FORMAT, --format=FORMAT                                          (ATA)\n"
+"        Set output format for attributes to one of: old, brief\n\n"
 "  -l TYPE, --log=TYPE\n"
 "        Show device log. TYPE: error, selftest, selective, directory[,g|s],\n"
 "                               background, sasphy[,reset], sataphy[,reset],\n"
@@ -201,6 +203,8 @@ static std::string getvalidarglist(char opt)
     return "none, samsung, samsung2, samsung3, swapid";
   case 'n':
     return "never, sleep, standby, idle";
+  case 'f':
+    return "old, brief";
   case 'v':
   default:
     return "";
@@ -241,7 +245,7 @@ static const char * parse_options(int argc, char** argv,
                            scsi_print_options & scsiopts)
 {
   // 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:";
+  const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:";
   // Please update getvalidarglist() if you edit longopts
   enum { opt_scan = 1000, opt_scan_open = 1001 };
   struct option longopts[] = {
@@ -273,6 +277,7 @@ static const char * parse_options(int argc, char** argv,
     { "firmwarebug",     required_argument, 0, 'F' },
     { "nocheck",         required_argument, 0, 'n' },
     { "drivedb",         required_argument, 0, 'B' },
+    { "format",          required_argument, 0, 'f' },
     { "scan",            no_argument,       0, opt_scan      },
     { "scan-open",       no_argument,       0, opt_scan_open },
     { 0,                 0,                 0, 0   }
@@ -284,6 +289,7 @@ static const char * parse_options(int argc, char** argv,
 
   const char * type = 0; // set to -d optarg
   bool no_defaultdb = false; // set true on '-B FILE'
+  bool output_format_set = false; // set true on '-f FORMAT'
   int scan = 0; // set by --scan, --scan-open
   bool badarg = false, captive = false;
   int testcnt = 0; // number of self-tests requested
@@ -558,6 +564,8 @@ static const char * parse_options(int argc, char** argv,
       ataopts.sataphy = true;
       scsiopts.smart_background_log = true;
       scsiopts.sasphy = true;
+      if (!output_format_set)
+        ataopts.output_format = 1; // '-f brief'
       break;
     case 'v':
       // parse vendor-specific definitions of attributes
@@ -697,6 +705,16 @@ static const char * parse_options(int argc, char** argv,
       else
         badarg = true;
       break;
+    case 'f':
+      output_format_set = true;
+      if (!strcmp(optarg,"old")) {
+        ataopts.output_format = 0;
+      } else if (!strcmp(optarg,"brief")) {
+        ataopts.output_format = 1;
+      } else {
+        badarg = true;
+      }
+      break;
     case 'B':
       {
         const char * path = optarg;
index 0ab6de736c68c322cb5cebe3e61d8a5e87ba6119..f4c0cf0cfb900e8d3dfd3c5ca186f05a0cc7993b 100644 (file)
@@ -125,7 +125,7 @@ extern "C" int getdomainname(char *, int); // no declaration in header files!
 
 #define ARGUSED(x) ((void)(x))
 
-const char * smartd_cpp_cvsid = "$Id: smartd.cpp 3288 2011-03-09 18:40:36Z chrfranke $"
+const char * smartd_cpp_cvsid = "$Id: smartd.cpp 3349 2011-05-27 21:46:31Z chrfranke $"
   CONFIG_H_CVSID;
 
 // smartd exit codes
@@ -1194,22 +1194,22 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
       newadd = address.c_str();
     }
 
-#ifdef _MSC_VER
-    _set_printf_count_output(1); // "%n" disabled by default
-#endif
     // Message for mail [0...] and messagebox [boxmsgoffs...]
     snprintf(stdinbuf, sizeof(stdinbuf),
              "This email was generated by the smartd daemon running on:\n\n"
              "   host name: %s\n"
              "  DNS domain: %s\n"
 //           "  NIS domain: %s\n"
-             "\n%n"
+             "\n",
+             hostname, /*domainname, */ nisdomain);
+    boxmsgoffs = strlen(stdinbuf);
+    snprintf(stdinbuf+boxmsgoffs, sizeof(stdinbuf)-boxmsgoffs,
              "The following warning/error was logged by the smartd daemon:\n\n"
              "%s\n\n"
              "For details see the event log or log file of smartd.\n\n"
              "%s%s%s"
              "\n",
-             hostname, /*domainname, */ nisdomain, &boxmsgoffs, message, further, original, additional);
+             message, further, original, additional);
   }
   else
     snprintf(command, sizeof(command), "%s", executable);
@@ -1658,6 +1658,29 @@ static int SelfTestErrorCount(ata_device * device, const char * name,
 #define SELFTEST_ERRORCOUNT(x) (x & 0xff)
 #define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff)
 
+// Log offline data collection status
+static void log_offline_data_coll_status(const char * name, unsigned char status)
+{
+  const char * msg;
+  switch (status & 0x7f) {
+    case 0x00: msg = "was never started"; break;
+    case 0x02: msg = "was completed without error"; break;
+    case 0x03: msg = (status == 0x03 ? "is in progress" : 0); break;
+    case 0x04: msg = "was suspended by an interrupting command from host"; break;
+    case 0x05: msg = "was aborted by an interrupting command from host"; break;
+    case 0x06: msg = "was aborted by the device with a fatal error"; break;
+    default:   msg = 0;
+  }
+
+  if (msg)
+    PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
+             "Device: %s, offline data collection %s%s\n", name, msg,
+             ((status & 0x80) ? " (auto:on)" : ""));
+  else
+    PrintOut(LOG_INFO, "Device: %s, unknown offline data collection status 0x%02x\n",
+             name, status);
+}
+
 // Log self-test execution status
 static void log_self_test_exec_status(const char * name, unsigned char status)
 {
@@ -1758,9 +1781,21 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
   ata_format_id_string(model, drive.model, sizeof(model)-1);
   ata_format_id_string(serial, drive.serial_no, sizeof(serial)-1);
   ata_format_id_string(firmware, drive.fw_rev, sizeof(firmware)-1);
-  state.num_sectors = get_num_sectors(&drive);
-  PrintOut(LOG_INFO, "Device: %s, %s, S/N:%s, FW:%s, %"PRIu64" sectors\n", name,
-           model, serial, firmware, state.num_sectors);
+
+  ata_size_info sizes;
+  ata_get_size_info(&drive, sizes);
+  state.num_sectors = sizes.sectors;
+
+  char wwn[30]; wwn[0] = 0;
+  unsigned oui = 0; uint64_t unique_id = 0;
+  int naa = ata_get_wwn(&drive, oui, unique_id);
+  if (naa >= 0)
+    snprintf(wwn, sizeof(wwn), "WWN:%x-%06x-%09"PRIx64", ", naa, oui, unique_id);
+
+  char cap[32];
+  PrintOut(LOG_INFO, "Device: %s, %s, S/N:%s, %sFW:%s, %s\n", name,
+           model, serial, wwn, firmware,
+           format_capacity(cap, sizeof(cap), sizes.capacity, "."));
 
   // Show if device in database, and use preset vendor attribute
   // options unless user has requested otherwise.
@@ -2777,7 +2812,8 @@ static void check_attribute(const dev_config & cfg, dev_state & state,
 }
 
 
-static int ATACheckDevice(const dev_config & cfg, dev_state & state, ata_device * atadev, bool allow_selftests)
+static int ATACheckDevice(const dev_config & cfg, dev_state & state, ata_device * atadev,
+                          bool firstpass, bool allow_selftests)
 {
   const char * name = cfg.name.c_str();
 
@@ -2922,9 +2958,14 @@ static int ATACheckDevice(const dev_config & cfg, dev_state & state, ata_device
         }
 
         if (cfg.selftest) {
-          // Log changes of self-test execution status
+          // Log changes of offline data collection and self-test execution status
+          if (   curval.offline_data_collection_status
+                 != state.smartval.offline_data_collection_status
+              || (firstpass && (debugmode || (curval.offline_data_collection_status & 0x7d))))
+            log_offline_data_coll_status(name, curval.offline_data_collection_status);
+
           if (   curval.self_test_exec_status != state.smartval.self_test_exec_status
-              || (!allow_selftests && curval.self_test_exec_status != 0x00)          )
+              || (firstpass && (debugmode || curval.self_test_exec_status != 0x00)))
             log_self_test_exec_status(name, curval.self_test_exec_status);
         }
 
@@ -3049,14 +3090,14 @@ static int SCSICheckDevice(const dev_config & cfg, dev_state & state, scsi_devic
 
 // Checks the SMART status of all ATA and SCSI devices
 static void CheckDevicesOnce(const dev_config_vector & configs, dev_state_vector & states,
-                             smart_device_list & devices, bool allow_selftests)
+                             smart_device_list & devices, bool firstpass, bool allow_selftests)
 {
   for (unsigned i = 0; i < configs.size(); i++) {
     const dev_config & cfg = configs.at(i);
     dev_state & state = states.at(i);
     smart_device * dev = devices.at(i);
     if (dev->is_ata())
-      ATACheckDevice(cfg, state, dev->to_ata(), allow_selftests);
+      ATACheckDevice(cfg, state, dev->to_ata(), firstpass, allow_selftests);
     else if (dev->is_scsi())
       SCSICheckDevice(cfg, state, dev->to_scsi(), allow_selftests);
   }
@@ -4578,7 +4619,7 @@ static int main_worker(int argc, char **argv)
 
     // check all devices once,
     // self tests are not started in first pass unless '-q onecheck' is specified
-    CheckDevicesOnce(configs, states, devices, (!firstpass || quit==3));
+    CheckDevicesOnce(configs, states, devices, firstpass, (!firstpass || quit==3));
 
      // Write state files
     if (!state_path_prefix.empty())
diff --git a/smartd.freebsd.initd.in b/smartd.freebsd.initd.in
new file mode 100644 (file)
index 0000000..04399de
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+# $FreeBSD: ports/sysutils/smartmontools/files/smartd.in,v 1.2 2010/03/27 00:15:05 dougb Exp $
+
+# PROVIDE: smartd
+# REQUIRE: DAEMON
+# BEFORE: LOGIN
+# KEYWORD: shutdown nojail
+
+# Define these smartd_* variables in one of these files:
+#       /etc/rc.conf
+#       /etc/rc.conf.local
+#       /etc/rc.conf.d/smartd
+#
+# DO NOT CHANGE THESE DEFAULT VALUES HERE
+#
+smartd_enable="${smartd_enable-NO}"
+smartd_pidfile="/var/run/smartd.pid"
+
+. /etc/rc.subr
+
+name="smartd"
+rcvar=`set_rcvar`
+command="/usr/local/sbin/smartd"
+extra_commands="reload report"
+reload_cmd="smartd_reload"
+report_cmd="smartd_report"
+
+smartd_reload()
+{
+    rc_pid=$(check_pidfile $pidfile $command)
+    if [ -z "$rc_pid" ]; then
+        [ -n "$rc_fast" ] && return 0
+        _run_rc_notrunning
+        return 1
+    fi
+    echo 'Reloading smartd.'
+    kill -HUP $rc_pid
+}
+
+smartd_report()
+{
+    rc_pid=$(check_pidfile $pidfile $command)
+    if [ -z "$rc_pid" ]; then
+        [ -n "$rc_fast" ] && return 0
+        _run_rc_notrunning
+        return 1
+    fi
+    echo 'Checking SMART devices now.'
+    kill -USR1 $rc_pid
+}
+
+load_rc_config $name
+
+: ${smartd_config="/usr/local/etc/smartd.conf"}
+: ${smartd_flags="-c ${smartd_config}"}
+
+pidfile="${smartd_pidfile}"
+required_files="${smartd_config}"
+
+case "${smartd_flags}" in
+*-p\ *)
+        echo "ERROR: \$smartd_flags includes -p option." \
+                "Please use \$smartd_pidfile instead."
+        exit 1
+        ;;
+*)
+        smartd_flags="-p ${pidfile} ${smartd_flags}"
+        ;;
+esac
+
+run_rc_command "$1"
old mode 100755 (executable)
new mode 100644 (file)
index 3050f19..7e0fe60
@@ -2,7 +2,7 @@
 
 # smartmontools init file for smartd
 # Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-# $Id: smartd.initd.in 3003 2009-12-19 18:47:47Z chrfranke $
+# $Id: smartd.initd.in 3360 2011-06-06 19:25:36Z chrfranke $
 
 # For RedHat and cousins:
 # chkconfig: 2345 40 40
 # For SuSE and cousins
 ### BEGIN INIT INFO
 # Provides:                   smartd
-# Required-Start:             $syslog
-# X-UnitedLinux-Should-Start: $sendmail
-# Should-Start:               $sendmail
-# Required-Stop:              $syslog
-# X-UnitedLinux-Should-Stop:
+# Required-Start:             $syslog $remote_fs
+# Should-Start:               sendmail
+# Required-Stop:              $syslog $remote_fs
+# Should-Stop:                sendmail
 # Default-Start:              2 3 5
 # Default-Stop:
 # Short-Description:          Monitors disk and tape health via S.M.A.R.T.
@@ -52,237 +51,370 @@ report_unsupported () {
 
 # Red Hat or Yellow Dog or Mandrake
 if [ -f /etc/redhat-release -o -f /etc/yellowdog-release -o -f /etc/mandrake-release -o -f /etc/whitebox-release -o -f /etc/trustix-release -o -f /etc/tinysofa-release ] ; then
-    
-# Source function library
+
+    # Source function library
     . /etc/rc.d/init.d/functions
 
-# Source configuration file.  This should define the shell variable smartd_opts
+    # Source configuration file.  This should define the shell variable smartd_opts
     [ -r /etc/sysconfig/smartmontools ] && . /etc/sysconfig/smartmontools
-    
+
     RETVAL=0
-    
+
     prog=smartd
-    
+    pidfile=/var/lock/subsys/smartd
+    config=/etc/smartd.conf
+
+    start()
+    {
+       [ $UID -eq 0 ] || exit 4
+       [ -x $SMARTD_BIN ] || exit 5
+       [ -f $config ] || exit 6
+       echo -n $"Starting $prog: "
+       daemon $SMARTD_BIN $smartd_opts
+       RETVAL=$?
+       echo
+       [ $RETVAL = 0 ] && touch $pidfile
+       return $RETVAL
+    }
+
+    stop()
+    {
+       [ $UID -eq 0 ] || exit 4
+       echo -n $"Shutting down $prog: "
+       killproc $SMARTD_BIN
+       RETVAL=$?
+       echo
+       rm -f $pidfile
+       return $RETVAL
+    }
+
+    reload()
+    {
+       echo -n $"Reloading $prog daemon configuration: "
+       killproc $SMARTD_BIN -HUP
+       RETVAL=$?
+       echo
+       return $RETVAL
+    }
+
+    report()
+    {
+       echo -n $"Checking SMART devices now: "
+       killproc $SMARTD_BIN -USR1
+       RETVAL=$?
+       echo
+       return $RETVAL
+    }
+
     case "$1" in
        start)
-           echo -n $"Starting $prog: "
-           daemon $SMARTD_BIN $smartd_opts
-           touch /var/lock/subsys/smartd
-           echo
-           ;;
+               start
+               ;;
        stop)
-           echo -n $"Shutting down $prog: "
-           killproc $SMARTD_BIN
-           rm -f /var/lock/subsys/smartd
-           echo
-           ;;
+               stop
+               ;;
        reload)
-            echo -n $"Reloading $prog daemon configuration: "
-           killproc $SMARTD_BIN -HUP
-           RETVAL=$?
-           echo
-           ;;
+               reload
+               ;;
        report)
-           echo -n $"Checking SMART devices now: "
-           killproc $SMARTD_BIN -USR1
-           RETVAL=$?
-           echo
-            ;;
+               report
+               ;;
        restart)
-           $0 stop
-           $0 start
-           ;;
+               stop
+               start
+               ;;
+       condrestart|try-restart)
+               if [ -f $pidfile ]; then
+                       stop
+                       start
+               fi
+               ;;
+       force-reload)
+               reload || (stop; start)
+               ;;
        status)
-           status $prog
-           ;;
+               status $prog
+               RETVAL=$?
+               ;;
        *)
-           echo $"Usage: $0 {start|stop|reload|report|restart|status}"
-           RETVAL=1
+               echo $"Usage: $0 {start|stop|restart|status|condrestart|try-restart|reload|force-reload|report}"
+               RETVAL=2
+               [ "$1" = 'usage' ] && RETVAL=0
     esac
-    
     exit $RETVAL
 
 # Slackware
 elif [ -f /etc/slackware-version ] ; then
-    
-# Source configuration file.  This should define the shell variable smartd_opts.
-# Email smartmontools-support@lists.sourceforge.net if there is a better choice
-# of path for Slackware.
+
+    # Source configuration file.  This should define the shell variable smartd_opts.
+    # Email smartmontools-support@lists.sourceforge.net if there is a better choice
+    # of path for Slackware.
 
     [ -r /etc/sysconfig/smartmontools ] && . /etc/sysconfig/smartmontools
 
+    RETVAL=0
     case "$1" in
        start)
            echo -n "Starting smartd: "
            $SMARTD_BIN $smartd_opts
+           RETVAL=$?
            echo
            ;;
        stop)
            echo -n "Shutting down smartd: "
            killall $SMARTD_BIN
+           RETVAL=$?
            echo
            ;;
        restart)
            $0 stop
            sleep 1
            $0 start
+           RETVAL=$?
+           ;;
+       try-restart)
+           if pidof $SMARTD_BIN >/dev/null; then
+               $0 restart
+               RETVAL=$?
+           fi
+           ;;
+       force-reload)
+           $0 reload || $0 restart
+           RETVAL=$?
+           ;;
+       reload)
+           echo -n "Reloading smartd configuration: "
+           killall -s HUP $SMARTD_BIN
+           RETVAL=$?
+           echo
+           ;;
+       report)
+           echo -n "Checking SMART devices now: "
+           killall -s USR1 $SMARTD_BIN
+           RETVAL=$?
+           echo
+           ;;
+       status)
+           if pidof $SMARTD_BIN >/dev/null; then
+               echo "$SMARTD_BIN is running."
+           else
+               echo "$SMARTD_BIN is not running."
+               RETVAL=1
+           fi
            ;;
        *)
-           echo "Usage: smartd {start|stop|restart}"
-           exit 1
+           echo "Usage: $0 {start|stop|restart|try-restart|force-reload|reload|report|status}"
+           RETVAL=1
     esac
-    
-    exit 0
-    
+    exit $RETVAL
+
 # SuSE
 elif [ -f /etc/SuSE-release ] ; then
     test -x $SMARTD_BIN || exit 5
-    
+
     # Existence of config file is optional
     SMARTD_CONFIG=/etc/smartd.conf
 
-# source configuration file. This should set the shell variable smartd_opts
-    [ -r /etc/default/smartmontools ] && . /etc/default/smartmontools
+    # source configuration file.
+    [ -r /etc/sysconfig/smartmontools ] && . /etc/sysconfig/smartmontools
+    smartd_opts=
+    if test -n "$SMARTD_CHECK_INTERVAL" -a "$SMARTD_CHECK_INTERVAL" != 1800 ; then
+       smartd_opts=" -i $SMARTD_CHECK_INTERVAL"
+    fi
+    if test -n "$SMARTD_LOG_FACILITY" -a "$SMARTD_LOG_FACILITY" != "daemon" ; then
+       smartd_opts="$smartd_opts -l $SMARTD_LOG_FACILITY"
+    fi
+    if test -n "$SMARTD_DRIVEDB" ; then
+       smartd_opts="$smartd_opts -B $SMARTD_DRIVEDB"
+    fi
 
-   # Shell functions sourced from /etc/rc.status:
-   #      rc_check         check and set local and overall rc status
-   #      rc_status        check and set local and overall rc status
-   #      rc_status -v     ditto but be verbose in local rc status
-   #      rc_status -v -r  ditto and clear the local rc status
-   #      rc_failed        set local and overall rc status to failed
-   #      rc_reset         clear local rc status (overall remains)
-   #      rc_exit          exit appropriate to overall rc status
+    # Shell functions sourced from /etc/rc.status:
+    #      rc_check         check and set local and overall rc status
+    #      rc_status        check and set local and overall rc status
+    #      rc_status -v     be verbose in local rc status and clear it afterwards
+    #      rc_status -v -r  ditto and clear both the local and overall rc status
+    #      rc_status -s     display "skipped" and exit with status 3
+    #      rc_status -u     display "unused" and exit with status 3
+    #      rc_failed        set local and overall rc status to failed
+    #      rc_failed <num>  set local and overall rc status to <num>
+    #      rc_reset         clear both the local and overall rc status
+    #      rc_exit          exit appropriate to overall rc status
+    #      rc_active        checks whether a service is activated by symlinks
     . /etc/rc.status
-    
-   # First reset status of this service
+
+    # Reset status of this service
     rc_reset
-    
-   # Return values acc. to LSB for all commands but status:
-   # 0 - success
-   # 1 - misc error
-   # 2 - invalid or excess args
-   # 3 - unimplemented feature (e.g. reload)
-   # 4 - insufficient privilege
-   # 5 - program not installed
-   # 6 - program not configured
-   #
-   # Note that starting an already running service, stopping
-   # or restarting a not-running service as well as the restart
-   # with force-reload (in case signalling is not supported) are
-   # considered a success.
+
+    # Return values acc. to LSB for all commands but status:
+    # 0       - success
+    # 1       - generic or unspecified error
+    # 2       - invalid or excess argument(s)
+    # 3       - unimplemented feature (e.g. "reload")
+    # 4       - user had insufficient privileges
+    # 5       - program is not installed
+    # 6       - program is not configured
+    # 7       - program is not running
+    # 8--199  - reserved (8--99 LSB, 100--149 distrib, 150--199 appl)
+    #
+    # Note that starting an already running service, stopping
+    # or restarting a not-running service as well as the restart
+    # with force-reload (in case signaling is not supported) are
+    # considered a success.
+
     case "$1" in
        start)
            echo -n "Starting smartd "
-            ## Start daemon with startproc(8). If this fails
-            ## the echo return value is set appropriate.
-           
-            # startproc should return 0, even if service is
-            # already running to match LSB spec.
-            startproc $SMARTD_BIN $smartd_opts
-           
-            # Remember status and be verbose
-            rc_status -v
+           ## Start daemon with startproc(8). If this fails
+           ## the return value is set appropriately by startproc.
+
+           # We don't use startproc - we need to check for return code 17.
+           if ! /sbin/checkproc $SMARTD_BIN ; then
+               $SMARTD_BIN $smartd_opts
+               # Remember status and be verbose
+               if test $? -ne 17 ; then
+                   rc_status -v
+               else
+                   rc_status -u
+               fi
+           else
+               rc_reset
+               rc_status -v
+           fi
            ;;
        stop)
            echo -n "Shutting down smartd "
-            killproc -TERM $SMARTD_BIN
-           
-            # Remember status and be verbose
-            rc_status -v
+           /sbin/killproc -TERM $SMARTD_BIN
+           # Remember status and be verbose
+           rc_status -v
            ;;
-    try-restart|condrestart)
+       try-restart)
            ## Do a restart only if the service was active before.
            ## Note: try-restart is now part of LSB (as of 1.9).
-           ## RH has a similar command named condrestart.
-           if test "$1" = "condrestart"; then
-                   echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
-           fi
            $0 status
            if test $? = 0; then
-                   $0 restart 
-           else 
-                   rc_reset    # Not running is not a failure.
+               $0 restart
+           else
+               rc_reset        # Not running is not a failure.
            fi
            # Remember status and be quiet
            rc_status
            ;;
-    restart | force-reload)
+       restart)
            $0 stop
            $0 start
+           # Remember status and be quiet
+           rc_status
            ;;
-    reload)
-       ## Like force-reload, but if daemon does not support
-       ## signaling, do nothing (!)
-           rc_failed 3
+       force-reload|reload)
+           echo -n "Reload service smartd "
+           /sbin/killproc -HUP $SMARTD_BIN
            rc_status -v
            ;;
-    status)
-            echo -n "Checking for service smartd "
-            ## Check status with checkproc(8), if process is running
-            ## checkproc will return with exit status 0.
-           
-            # Status has a slightly different for the status command:
-            # 0 - service running
-            # 1 - service dead, but /var/run/  pid  file exists
-            # 2 - service dead, but /var/lock/ lock file exists
-            # 3 - service not running
-           
-            # NOTE: checkproc returns LSB compliant status values.
-            checkproc $SMARTD_BIN
-            rc_status -v
-            ;;
-        probe)
+       report)
+           ## Checking SMART devices now (smartd specific function)
+           echo -n "Checking SMART devices now "
+           /sbin/killproc -USR1 $SMARTD_BIN
+           rc_status -v
+           ;;
+       status)
+           echo -n "Checking for service smartd "
+           ## Check status with checkproc(8), if process is running
+           ## checkproc will return with exit status 0.
+
+           # Return value is slightly different for the status command:
+           # 0 - service up and running
+           # 1 - service dead, but /var/run/  pid  file exists
+           # 2 - service dead, but /var/lock/ lock file exists
+           # 3 - service not running (unused)
+           # 4 - service status unknown :-(
+           # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
+
+           # NOTE: checkproc returns LSB compliant status values.
+           /sbin/checkproc $SMARTD_BIN
+           rc_status -v
+           ;;
+       probe)
            ## Optional: Probe for the necessity of a reload, print out the
            ## argument to this init script which is required for a reload.
-           ## Note: probe is not (yet) part of LSB (as of 1.2)
+           ## Note: probe is not (yet) part of LSB (as of 1.9)
 
            test $SMARTD_CONFIG -nt /var/run/smartd.pid && echo reload
            ;;
        *)
-           echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
+           echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|report|probe}"
            exit 1
-           ;;
     esac
-    
     rc_exit
 
 # Debian case
 elif [ -f /etc/debian_version ] ; then
-        PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-       SMARTDPID=/var/run/smartd.pid
-       [ -x $SMARTD_BIN ] || exit 0
-       RET=0
+    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+    SMARTDPID=/var/run/smartd.pid
+    [ -x $SMARTD_BIN ] || exit 0
+    RET=0
+
+    # source configuration file
+    [ -r /etc/default/rcS ] && . /etc/default/rcS
+    [ -r /etc/default/smartmontools ] && . /etc/default/smartmontools
 
-# source configuration file
-       [ -r /etc/default/smartmontools ] && . /etc/default/smartmontools
+    smartd_opts="--pidfile $SMARTDPID $smartd_opts"
 
-       smartd_opts="--pidfile $SMARTDPID $smartd_opts"
-       
-       case "$1" in
+    case "$1" in
        start)
                echo -n "Starting S.M.A.R.T. daemon: smartd"
                if start-stop-daemon --start --quiet --pidfile $SMARTDPID \
-               --exec $SMARTD_BIN -- $smartd_opts; then 
-                       echo "."
+                       --exec $SMARTD_BIN -- $smartd_opts; then
+                       echo "."
                else
-                       echo " (failed)"
+                       echo " (failed)"
                        RET=1
-               fi
-       ;;
+               fi
+               ;;
        stop)
                echo -n "Stopping S.M.A.R.T. daemon: smartd"
                start-stop-daemon --stop --quiet --oknodo --pidfile $SMARTDPID
                echo "."
-       ;;
-       restart|force-reload)
-                       $0 stop
-               $0 start
-               ;;
-       *)
-               echo "Usage: /etc/init.d/smartmontools {start|stop|restart|force-reload}"
+               ;;
+       restart)
+               $0 stop
+               $0 start
+               ;;
+       force-reload)
+               $0 reload || $0 restart
+               ;;
+       reload)
+               echo -n "Reload S.M.A.R.T. daemon: smartd"
+               if start-stop-daemon --stop --quiet --signal 1 \
+                       --pidfile $SMARTDPID; then
+                       echo "."
+               else
+                       echo " (failed)"
+                       RET=1
+               fi
+               ;;
+       report)
+               echo -n "Checking SMART devices now"
+               if start-stop-daemon --stop --quiet --signal 10 \
+                       --pidfile $SMARTDPID; then
+                       echo "."
+               else
+                       echo " (failed)"
+                       RET=1
+               fi
+               ;;
+       status)
+               if pidof $SMARTD_BIN >/dev/null; then
+                       echo "$SMARTD_BIN is running."
+               else
+                       echo "$SMARTD_BIN is not running."
+                       RET=1
+               fi
+               ;;
+       *)
+               echo "Usage: $0 {start|stop|restart|force-reload|reload|report|status}"
                exit 1
-       esac
-       exit $RET
+    esac
+    exit $RET
 
 elif [ -f /etc/gentoo-release ] ; then
     report_unsupported "Gentoo"
@@ -296,30 +428,30 @@ elif [ -f /etc/environment.corel ] ; then
 # PLEASE ADD OTHER LINUX DISTRIBUTIONS JUST BEFORE THIS LINE, USING elif
 
 elif uname -a | grep FreeBSD > /dev/null 2>&1 ; then
-# following is replaced by port install
+    # following is replaced by port install
     PREFIX=@@PREFIX@@
-    
-# Updated to try both the RCNG version of things from 5.x, or fallback to
-# oldfashioned rc.conf
 
-    if [ -r /etc/rc.subr ]; then 
-# This is RC-NG, pick up our values
+    # Updated to try both the RCNG version of things from 5.x, or fallback to
+    # oldfashioned rc.conf
+
+    if [ -r /etc/rc.subr ]; then
+       # This is RC-NG, pick up our values
        . /etc/rc.subr
-        name="smartd"
-       rcvar="smartd_enable" 
-        command="$SMARTD_BIN"
+       name="smartd"
+       rcvar="smartd_enable"
+       command="$SMARTD_BIN"
        load_rc_config $name
     elif [ -r /etc/defaults/rc.conf ]; then
-# Not a 5.x system, try the default location for variables
+       # Not a 5.x system, try the default location for variables
        . /etc/defaults/rc.conf
        source_rc_confs
     elif [ -r /etc/rc.conf ]; then
-# Worst case, fallback to system config file
+       # Worst case, fallback to system config file
        . /etc/rc.conf
     fi
 
-    if [ -r /etc/rc.subr ]; then 
-# Use new functionality from RC-NG
+    if [ -r /etc/rc.subr ]; then
+       # Use new functionality from RC-NG
        run_rc_command "$1"
     else
        PID_FILE=/var/run/smartd.pid
@@ -337,23 +469,29 @@ elif uname -a | grep FreeBSD > /dev/null 2>&1 ; then
                sleep 1
                $0 start
                ;;
+           reload)
+               kill -s HUP `cat $PID_FILE`
+               ;;
+           report)
+               kill -s USR1 `cat $PID_FILE`
+               ;;
            *)
-               echo "Usage: smartd {start|stop|restart}"
+               echo "Usage: $0 {start|stop|restart|reload|report}"
                exit 1
        esac
-       
        exit 0
     fi
+
 elif uname -a | grep SunOS > /dev/null 2>&1 ; then
-    
-# Source configuration file.  This should define the shell variable smartd_opts.
-# Email smartmontools-support@lists.sourceforge.net if there is a better choice
-# of path for Solaris
+
+    # Source configuration file.  This should define the shell variable smartd_opts.
+    # Email smartmontools-support@lists.sourceforge.net if there is a better choice
+    # of path for Solaris
 
     [ -r /etc/default/smartmontools ] && . /etc/default/smartmontools
 
     PID_FILE=/var/run/smartd.pid
-    
+
     case "$1" in
        start)
            $SMARTD_BIN -p $PID_FILE $smartd_opts
@@ -368,17 +506,22 @@ elif uname -a | grep SunOS > /dev/null 2>&1 ; then
            sleep 1
            $0 start
            ;;
+       reload)
+           kill -s HUP `cat $PID_FILE`
+           ;;
+       report)
+           kill -s USR1 `cat $PID_FILE`
+           ;;
        *)
-           echo "Usage: smartd {start|stop|restart}"
+           echo "Usage: $0 {start|stop|restart|reload|report}"
            exit 1
     esac
-    
     exit 0
 
 # Cygwin
 elif uname | grep -i CYGWIN > /dev/null 2>&1 ; then
 
-# The following settings may be changed by the configuration file below
+    # The following settings may be changed by the configuration file below
     # Service Name (must be unique)
     smartd_svcname=smartd
     # Service display name
@@ -390,9 +533,9 @@ Analysis and Reporting Technology System (S.M.A.R.T.) \
 built into ATA and SCSI Hard Drives. \
 http://smartmontools.sourceforge.net/"
 
-# Source configuration file.  This should define the shell variable smartd_opts.
-# Email smartmontools-support@lists.sourceforge.net if there is a better choice
-# of path for Cygwin
+    # Source configuration file.  This should define the shell variable smartd_opts.
+    # Email smartmontools-support@lists.sourceforge.net if there is a better choice
+    # of path for Cygwin
 
     [ -r /etc/sysconfig/smartmontools ] && . /etc/sysconfig/smartmontools
 
@@ -504,7 +647,7 @@ else
 fi
 
 # One should NEVER arrive here, except for a badly written case above,
-# that fails to exit.  
+# that fails to exit.
 echo "SOMETHING IS WRONG WITH THE SMARTD STARTUP SCRIPT"
 echo "PLEASE CONTACT smartmontools-support@lists.sourceforge.net"
 exit 1
diff --git a/smartd.service.in b/smartd.service.in
new file mode 100644 (file)
index 0000000..94930ee
--- /dev/null
@@ -0,0 +1,10 @@
+[Unit]
+Description=Self Monitoring and Reporting Technology (SMART) Daemon
+After=syslog.target
+
+[Service]
+EnvironmentFile=/usr/local/etc/sysconfig/smartmontools
+ExecStart=/usr/local/sbin/smartd -n $smartd_opts
+
+[Install]
+WantedBy=multi-user.target
index 62e5845522d7371c5d01e59180b1b134c71d7a39..9d37aab5e134b9f52d047308c3a5385fe147be95 100644 (file)
 // BOTH SCSI AND ATA DEVICES, AND THAT MAY BE USED IN SMARTD,
 // SMARTCTL, OR BOTH.
 
+#include "config.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <ctype.h>
-#include <syslog.h>
 #include <stdarg.h>
 #include <sys/stat.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
 #ifdef _WIN32
 #include <mbstring.h> // _mbsinc()
 #endif
 
 #include <stdexcept>
 
-#include "config.h"
 #include "svnversion.h"
 #include "int64.h"
 #include "utility.h"
@@ -50,7 +53,7 @@
 #include "atacmds.h"
 #include "dev_interface.h"
 
-const char * utility_cpp_cvsid = "$Id: utility.cpp 3285 2011-03-04 22:08:49Z chrfranke $"
+const char * utility_cpp_cvsid = "$Id: utility.cpp 3305 2011-03-30 21:32:05Z chrfranke $"
                                  UTILITY_H_CVSID INT64_H_CVSID;
 
 const char * packet_types[] = {
@@ -727,6 +730,80 @@ void MsecToText(unsigned int msec, char *txt){
   return;
 }
 
+// Format integer with thousands separator
+const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
+                                       const char * thousands_sep /* = 0 */)
+{
+  if (!thousands_sep) {
+    thousands_sep = ",";
+#ifdef HAVE_LOCALE_H
+    setlocale(LC_ALL, "");
+    const struct lconv * currentlocale = localeconv();
+    if (*(currentlocale->thousands_sep))
+      thousands_sep = currentlocale->thousands_sep;
+#endif
+  }
+
+  char num[64];
+  snprintf(num, sizeof(num), "%"PRIu64, val);
+  int numlen = strlen(num);
+
+  int i = 0, j = 0;
+  do
+    str[j++] = num[i++];
+  while (i < numlen && (numlen - i) % 3 != 0 && j < strsize-1);
+  str[j] = 0;
+
+  while (i < numlen && j < strsize-1) {
+    j += snprintf(str+j, strsize-j, "%s%.3s", thousands_sep, num+i);
+    i += 3;
+  }
+
+  return str;
+}
+
+// Format capacity with SI prefixes
+const char * format_capacity(char * str, int strsize, uint64_t val,
+                             const char * decimal_point /* = 0 */)
+{
+  if (!decimal_point) {
+    decimal_point = ".";
+#ifdef HAVE_LOCALE_H
+    setlocale(LC_ALL, "");
+    const struct lconv * currentlocale = localeconv();
+    if (*(currentlocale->decimal_point))
+      decimal_point = currentlocale->decimal_point;
+#endif
+  }
+
+  const unsigned factor = 1000; // 1024 for KiB,MiB,...
+  static const char prefixes[] = " KMGTP";
+
+  // Find d with val in [d, d*factor)
+  unsigned i = 0;
+  uint64_t d = 1;
+  for (uint64_t d2 = d * factor; val >= d2; d2 *= factor) {
+    d = d2;
+    if (++i >= sizeof(prefixes)-2)
+      break;
+  }
+
+  // Print 3 digits
+  uint64_t n = val / d;
+  if (i == 0)
+    snprintf(str, strsize, "%u B", (unsigned)n);
+  else if (n >= 100) // "123 xB"
+    snprintf(str, strsize, "%"PRIu64" %cB", n, prefixes[i]);
+  else if (n >= 10)  // "12.3 xB"
+    snprintf(str, strsize, "%"PRIu64"%s%u %cB", n, decimal_point,
+        (unsigned)(((val % d) * 10) / d), prefixes[i]);
+  else               // "1.23 xB"
+    snprintf(str, strsize, "%"PRIu64"%s%02u %cB", n, decimal_point,
+        (unsigned)(((val % d) * 100) / d), prefixes[i]);
+
+  return str;
+}
+
 // return (v)sprintf() formatted std::string
 
 std::string vstrprintf(const char * fmt, va_list ap)
index f2d081ffc022751ca6a69fbd10b9c8c8ec6b267c..e9dfb352cc879ac912bdd3ed8d765b35432355de 100644 (file)
--- a/utility.h
+++ b/utility.h
@@ -26,7 +26,7 @@
 #ifndef UTILITY_H_
 #define UTILITY_H_
 
-#define UTILITY_H_CVSID "$Id: utility.h 3285 2011-03-04 22:08:49Z chrfranke $"
+#define UTILITY_H_CVSID "$Id: utility.h 3305 2011-03-30 21:32:05Z chrfranke $"
 
 #include <time.h>
 #include <sys/types.h> // for regex.h (according to POSIX)
@@ -173,6 +173,14 @@ void FixGlibcTimeZoneBug();
 // convert time in msec to a text string
 void MsecToText(unsigned int msec, char *txt);
 
+// Format integer with thousands separator
+const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
+                                       const char * thousands_sep = 0);
+
+// Format capacity with SI prefixes
+const char * format_capacity(char * str, int strsize, uint64_t val,
+                             const char * decimal_point = 0);
+
 // Wrapper class for a raw data buffer
 class raw_buffer
 {