Annotation of embedaddon/smartmontools/dev_legacy.cpp, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * dev_legacy.cpp
                      3:  *
                      4:  * Home page of code is: http://smartmontools.sourceforge.net
                      5:  *
                      6:  * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 2, or (at your option)
                     11:  * any later version.
                     12:  *
                     13:  * You should have received a copy of the GNU General Public License
                     14:  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
                     15:  *
                     16:  */
                     17: 
                     18: #include "config.h"
                     19: #include "int64.h"
                     20: #include "utility.h"
                     21: #include "atacmds.h"
                     22: #include "scsicmds.h"
                     23: #include "dev_interface.h"
                     24: #include "dev_ata_cmd_set.h"
                     25: 
                     26: #include <errno.h>
                     27: 
                     28: const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 3263 2011-02-20 18:32:56Z chrfranke $"
                     29:   DEV_INTERFACE_H_CVSID;
                     30: 
                     31: /////////////////////////////////////////////////////////////////////////////
                     32: 
                     33: // Legacy interface declarations (now commented out globally):
                     34: 
                     35: // from utility.h:
                     36: int guess_device_type(const char * dev_name);
                     37: int make_device_names (char ***devlist, const char* name);
                     38: int deviceopen(const char *pathname, char *type);
                     39: int deviceclose(int fd);
                     40: 
                     41: // from atacmds.h:
                     42: int ata_command_interface(int device, smart_command_set command, int select, char *data);
                     43: 
                     44: // from scsicmds.h:
                     45: int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report);
                     46: 
                     47: // from smartctl.h:
                     48: void print_smartctl_examples();
                     49: 
                     50: /////////////////////////////////////////////////////////////////////////////
                     51: 
                     52: namespace os { // No need to publish anything, name provided for Doxygen
                     53: 
                     54: /////////////////////////////////////////////////////////////////////////////
                     55: /// Implement shared open/close routines with old functions.
                     56: 
                     57: class legacy_smart_device
                     58: : virtual public /*implements*/ smart_device
                     59: {
                     60: public:
                     61:   explicit legacy_smart_device(const char * mode)
                     62:     : smart_device(never_called),
                     63:       m_fd(-1), m_mode(mode) { }
                     64: 
                     65:   virtual ~legacy_smart_device() throw();
                     66: 
                     67:   virtual bool is_open() const;
                     68: 
                     69:   virtual bool open();
                     70: 
                     71:   virtual bool close();
                     72: 
                     73: protected:
                     74:   /// Return filedesc for derived classes.
                     75:   int get_fd() const
                     76:     { return m_fd; }
                     77: 
                     78: private:
                     79:   int m_fd; ///< filedesc, -1 if not open.
                     80:   const char * m_mode; ///< Mode string for deviceopen().
                     81: };
                     82: 
                     83: 
                     84: legacy_smart_device::~legacy_smart_device() throw()
                     85: {
                     86:   if (m_fd >= 0)
                     87:     ::deviceclose(m_fd);
                     88: }
                     89: 
                     90: bool legacy_smart_device::is_open() const
                     91: {
                     92:   return (m_fd >= 0);
                     93: }
                     94: 
                     95: bool legacy_smart_device::open()
                     96: {
                     97:   m_fd = ::deviceopen(get_dev_name(), const_cast<char*>(m_mode));
                     98:   if (m_fd < 0) {
                     99:     set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno);
                    100:     return false;
                    101:   }
                    102:   return true;
                    103: }
                    104: 
                    105: bool legacy_smart_device::close()
                    106: {
                    107:   int fd = m_fd; m_fd = -1;
                    108:   if (::deviceclose(fd) < 0) {
                    109:     set_err(errno);
                    110:     return false;
                    111:   }
                    112:   return true;
                    113: }
                    114: 
                    115: /////////////////////////////////////////////////////////////////////////////
                    116: /// Implement standard ATA support with old functions
                    117: 
                    118: class legacy_ata_device
                    119: : public /*implements*/ ata_device_with_command_set,
                    120:   public /*extends*/ legacy_smart_device
                    121: {
                    122: public:
                    123:   legacy_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
                    124: 
                    125: protected:
                    126:   virtual int ata_command_interface(smart_command_set command, int select, char * data);
                    127: };
                    128: 
                    129: legacy_ata_device::legacy_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
                    130: : smart_device(intf, dev_name, "ata", req_type),
                    131:   legacy_smart_device("ATA")
                    132: {
                    133: }
                    134: 
                    135: int legacy_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
                    136: {
                    137:   return ::ata_command_interface(get_fd(), command, select, data);
                    138: }
                    139: 
                    140: 
                    141: /////////////////////////////////////////////////////////////////////////////
                    142: /// Implement standard SCSI support with old functions
                    143: 
                    144: class legacy_scsi_device
                    145: : public /*implements*/ scsi_device,
                    146:   public /*extends*/ legacy_smart_device
                    147: {
                    148: public:
                    149:   legacy_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
                    150: 
                    151:   virtual smart_device * autodetect_open();
                    152: 
                    153:   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
                    154: };
                    155: 
                    156: legacy_scsi_device::legacy_scsi_device(smart_interface * intf,
                    157:   const char * dev_name, const char * req_type)
                    158: : smart_device(intf, dev_name, "scsi", req_type),
                    159:   legacy_smart_device("SCSI")
                    160: {
                    161: }
                    162: 
                    163: bool legacy_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
                    164: {
                    165:   int status = ::do_scsi_cmnd_io(get_fd(), iop, scsi_debugmode);
                    166:   if (status < 0) {
                    167:       set_err(-status);
                    168:       return false;
                    169:   }
                    170:   return true;
                    171: }
                    172: 
                    173: 
                    174: /////////////////////////////////////////////////////////////////////////////
                    175: /// SCSI open with autodetection support
                    176: 
                    177: smart_device * legacy_scsi_device::autodetect_open()
                    178: {
                    179:   // Open device
                    180:   if (!open())
                    181:     return this;
                    182: 
                    183:   // No Autodetection if device type was specified by user
                    184:   if (*get_req_type())
                    185:     return this;
                    186: 
                    187:   // The code below is based on smartd.cpp:SCSIFilterKnown()
                    188: 
                    189:   // Get INQUIRY
                    190:   unsigned char req_buff[64] = {0, };
                    191:   int req_len = 36;
                    192:   if (scsiStdInquiry(this, req_buff, req_len)) {
                    193:     // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
                    194:     // watch this spot ... other devices could lock up here
                    195:     req_len = 64;
                    196:     if (scsiStdInquiry(this, req_buff, req_len)) {
                    197:       // device doesn't like INQUIRY commands
                    198:       close();
                    199:       set_err(EIO, "INQUIRY failed");
                    200:       return this;
                    201:     }
                    202:   }
                    203: 
                    204:   int avail_len = req_buff[4] + 5;
                    205:   int len = (avail_len < req_len ? avail_len : req_len);
                    206:   if (len < 36)
                    207:     return this;
                    208: 
                    209:   // Use INQUIRY to detect type
                    210: 
                    211:   // SAT or USB ?
                    212:   {
                    213:     smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
                    214:     if (newdev)
                    215:       // NOTE: 'this' is now owned by '*newdev'
                    216:       return newdev;
                    217:   }
                    218: 
                    219:   // Nothing special found
                    220:   return this;
                    221: }
                    222: 
                    223: 
                    224: /////////////////////////////////////////////////////////////////////////////
                    225: /// Implement platform interface with old functions.
                    226: 
                    227: class legacy_smart_interface
                    228: : public /*implements*/ smart_interface
                    229: {
                    230: public:
                    231:   virtual std::string get_app_examples(const char * appname);
                    232: 
                    233:   virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
                    234:     const char * pattern = 0);
                    235: 
                    236: protected:
                    237:   virtual ata_device * get_ata_device(const char * name, const char * type);
                    238: 
                    239:   virtual scsi_device * get_scsi_device(const char * name, const char * type);
                    240: 
                    241:   virtual smart_device * autodetect_smart_device(const char * name);
                    242: };
                    243: 
                    244: 
                    245: //////////////////////////////////////////////////////////////////////
                    246: 
                    247: std::string legacy_smart_interface::get_app_examples(const char * appname)
                    248: {
                    249:   if (!strcmp(appname, "smartctl"))
                    250:     ::print_smartctl_examples(); // this prints to stdout ...
                    251:   return ""; // ... so don't print again.
                    252: }
                    253: 
                    254: ata_device * legacy_smart_interface::get_ata_device(const char * name, const char * type)
                    255: {
                    256:   return new legacy_ata_device(this, name, type);
                    257: }
                    258: 
                    259: scsi_device * legacy_smart_interface::get_scsi_device(const char * name, const char * type)
                    260: {
                    261:   return new legacy_scsi_device(this, name, type);
                    262: }
                    263: 
                    264: 
                    265: smart_device * legacy_smart_interface::autodetect_smart_device(const char * name)
                    266: {
                    267:   switch (::guess_device_type(name)) {
                    268:     case CONTROLLER_ATA : return new legacy_ata_device(this, name, "");
                    269:     case CONTROLLER_SCSI: return new legacy_scsi_device(this, name, "");
                    270:   }
                    271:   // TODO: Test autodetect device here
                    272:   return 0;
                    273: }
                    274: 
                    275: 
                    276: static void free_devnames(char * * devnames, int numdevs)
                    277: {
                    278:   static const char version[] = "$Id: dev_legacy.cpp 3263 2011-02-20 18:32:56Z chrfranke $";
                    279:   for (int i = 0; i < numdevs; i++)
                    280:     FreeNonZero(devnames[i], -1,__LINE__, version);
                    281:   FreeNonZero(devnames, (sizeof (char*) * numdevs),__LINE__, version);
                    282: }
                    283: 
                    284: bool legacy_smart_interface::scan_smart_devices(smart_device_list & devlist,
                    285:   const char * type, const char * pattern /*= 0*/)
                    286: {
                    287:   if (pattern) {
                    288:     set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
                    289:     return false;
                    290:   }
                    291: 
                    292:   // Make namelists
                    293:   char * * atanames = 0; int numata = 0;
                    294:   if (!type || !strcmp(type, "ata")) {
                    295:     numata = ::make_device_names(&atanames, "ATA");
                    296:     if (numata < 0) {
                    297:       set_err(ENOMEM);
                    298:       return false;
                    299:     }
                    300:   }
                    301: 
                    302:   char * * scsinames = 0; int numscsi = 0;
                    303:   if (!type || !strcmp(type, "scsi")) {
                    304:     numscsi = ::make_device_names(&scsinames, "SCSI");
                    305:     if (numscsi < 0) {
                    306:       free_devnames(atanames, numata);
                    307:       set_err(ENOMEM);
                    308:       return false;
                    309:     }
                    310:   }
                    311: 
                    312:   // Add to devlist
                    313:   int i;
                    314:   if (!type)
                    315:     type="";
                    316:   for (i = 0; i < numata; i++) {
                    317:     ata_device * atadev = get_ata_device(atanames[i], type);
                    318:     if (atadev)
                    319:       devlist.push_back(atadev);
                    320:   }
                    321:   free_devnames(atanames, numata);
                    322: 
                    323:   for (i = 0; i < numscsi; i++) {
                    324:     scsi_device * scsidev = get_scsi_device(scsinames[i], type);
                    325:     if (scsidev)
                    326:       devlist.push_back(scsidev);
                    327:   }
                    328:   free_devnames(scsinames, numscsi);
                    329:   return true;
                    330: }
                    331: 
                    332: } // namespace
                    333: 
                    334: 
                    335: /////////////////////////////////////////////////////////////////////////////
                    336: /// Initialize platform interface and register with smi()
                    337: 
                    338: void smart_interface::init()
                    339: {
                    340:   static os::legacy_smart_interface the_interface;
                    341:   smart_interface::set(&the_interface);
                    342: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>