]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - dev_legacy.cpp
Correct maintscript syntax
[mirror_smartmontools-debian.git] / dev_legacy.cpp
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 }