diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 8195c379fcbcf294478f0b214787116e578530b0..ecf041116c0bda76435fe35ff24a1b0ce135ff5f 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.737 2008/09/27 17:04:36 chrfranke Exp $ +$Id: CHANGELOG,v 1.738 2008/09/29 19:13:49 chrfranke Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -40,6 +40,10 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] Add option '-d sat+TYPE' to use SAT with controllers which + require option '-d TYPE'. Should work with '-d sat+megaraid,N'. + As a side effect, '-d usbcypress+TYPE' is also supported. + [CF] Add parser to read drive database from a file. Add '-B' option to smartctl and smartd to specify database file name. File syntax is identical to the C/C++ syntax used to inialize the internal diff --git a/sm5/dev_interface.cpp b/sm5/dev_interface.cpp index 52a37ff168ded72de4ac2a39618ea2d8c93e1487..d16e8ab0477ec4e2206f7648b52985bfaa510712 100644 --- a/sm5/dev_interface.cpp +++ b/sm5/dev_interface.cpp @@ -25,7 +25,7 @@ #include <stdexcept> -const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp,v 1.3 2008/08/23 19:56:18 chrfranke Exp $" +const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp,v 1.4 2008/09/29 19:13:49 chrfranke Exp $" DEV_INTERFACE_H_CVSID; ///////////////////////////////////////////////////////////////////////////// @@ -224,18 +224,17 @@ const char * smart_interface::get_os_version_str() const char * smart_interface::get_valid_dev_types_str() { - static char buf[80+1]; - if (buf[0]) - return buf; + static std::string buf; + if (!buf.empty()) + return buf.c_str(); // default - strcpy(buf, "ata, scsi, sat[,N]"); + buf = "ata, scsi, sat[,N][+TYPE]"; // append custom const char * add = get_valid_custom_dev_types_str(); if (!add || !*add) - return buf; - strcat(buf, ", "); - strcat(buf, add); - return buf; + return buf.c_str(); + buf += ", "; buf += add; + return buf.c_str(); } const char * smart_interface::get_app_examples(const char * /*appname*/) @@ -294,9 +293,41 @@ smart_device * smart_interface::get_smart_device(const char * name, const char * dev = get_ata_device(name, type); else if (!strcmp(type, "scsi")) dev = get_scsi_device(name, type); - else if ( (!strncmp(type, "sat", 3) && (!type[3] || type[3] == ',')) - || (!strncmp(type, "usb", 3))) - dev = get_sat_device(name, type /*, 0*/); + + else if ( (!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3])) + || (!strncmp(type, "usb", 3)))) { + // Split "sat...+base..." -> ("sat...", "base...") + unsigned satlen = strcspn(type, "+"); + std::string sattype(type, satlen); + const char * basetype = (type[satlen] ? type+satlen+1 : ""); + // Recurse to allocate base device, default is standard SCSI + if (!*basetype) + basetype = "scsi"; + dev = get_smart_device(name, basetype); + if (!dev) { + set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg()); + return 0; + } + // Result must be SCSI + if (!dev->is_scsi()) { + delete dev; + set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype); + return 0; + } + // Attach SAT tunnel + try { + ata_device * satdev = get_sat_device(sattype.c_str(), dev->to_scsi()); + if (!satdev) { + delete dev; + return 0; + } + return satdev; + } + catch (...) { + delete dev; throw; + } + } + else { set_err(EINVAL, "Unknown device type '%s'", type); return 0; diff --git a/sm5/dev_interface.h b/sm5/dev_interface.h index d10fadc8e46be31ce4bb8548a590c7bfe4c593b9..35e7afd80eb69fb4476cbc9e3d0c80bf2306a050 100644 --- a/sm5/dev_interface.h +++ b/sm5/dev_interface.h @@ -18,7 +18,7 @@ #ifndef DEV_INTERFACE_H #define DEV_INTERFACE_H -#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h,v 1.6 2008/08/29 20:07:36 chrfranke Exp $\n" +#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h,v 1.7 2008/09/29 19:13:49 chrfranke Exp $\n" #include <stdarg.h> #include <string> @@ -674,7 +674,7 @@ protected: /// Return ATA->SCSI filter for SAT or USB. /// Override only if platform needs special handling. - virtual ata_device * get_sat_device(const char * name, const char * type, scsi_device * scsidev = 0); + virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev); //{ implemented in scsiata.cpp } public: diff --git a/sm5/scsiata.cpp b/sm5/scsiata.cpp index bff27d946b622a6caf88d43de2f212b5da049cca..c2590b9af09539e55de5250d52e23ab639903f24 100644 --- a/sm5/scsiata.cpp +++ b/sm5/scsiata.cpp @@ -50,7 +50,7 @@ #include "dev_ata_cmd_set.h" // ata_device_with_command_set #include "dev_tunnelled.h" // tunnelled_device<> -const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.18 2008/09/12 19:26:09 chrfranke Exp $" +const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.19 2008/09/29 19:13:49 chrfranke Exp $" CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID; /* for passing global control variables */ @@ -790,13 +790,8 @@ using namespace sat; // Return ATA->SCSI filter for SAT or USB. -ata_device * smart_interface::get_sat_device(const char * name, const char * type, scsi_device * scsidev /* = 0*/) +ata_device * smart_interface::get_sat_device(const char * type, scsi_device * scsidev) { - if (!scsidev) { - scsidev = get_scsi_device(name, "scsi"); - if (!scsidev) - return 0; - } if (!strncmp(type, "sat", 3)) { int ptlen = 0, n1 = -1, n2 = -1; if (!(((sscanf(type, "sat%n,%d%n", &n1, &ptlen, &n2) == 1 && n2 == (int)strlen(type)) || n1 == (int)strlen(type))