Annotation of embedaddon/smartmontools/dev_legacy.cpp, revision 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>