smartmontools  SVN Rev 4335
Utility to control and monitor storage systems with "S.M.A.R.T."
os_darwin.cpp
Go to the documentation of this file.
1 /*
2  * os_darwin.cpp
3  *
4  * Home page of code is: http://www.smartmontools.org
5  *
6  * Copyright (C) 2004-8 Geoffrey Keating <geoffk@geoffk.org>
7  * Copyright (C) 2014 Alex Samorukov <samm@os2.kiev.ua>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with smartmontools. If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #include <stdbool.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <mach/mach.h>
23 #include <mach/mach_error.h>
24 #include <mach/mach_init.h>
25 #include <sys/utsname.h>
26 #include <IOKit/IOCFPlugIn.h>
27 #include <IOKit/IOKitLib.h>
28 #include <IOKit/IOReturn.h>
29 #include <IOKit/IOBSD.h>
30 #include <IOKit/storage/IOBlockStorageDevice.h>
31 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
32 #include <IOKit/storage/IOMedia.h>
33 #include <IOKit/storage/ata/IOATAStorageDefines.h>
34 #include <IOKit/storage/ata/ATASMARTLib.h>
35 #include <CoreFoundation/CoreFoundation.h>
36 
37  // No, I don't know why there isn't a header for this.
38 #define kIOATABlockStorageDeviceClass "IOATABlockStorageDevice"
39 
40 #include "config.h"
41 #include "int64.h"
42 #include "atacmds.h"
43 #include "scsicmds.h"
44 #include "utility.h"
45 #include "os_darwin.h"
46 #include "dev_interface.h"
47 
48 // Needed by '-V' option (CVS versioning) of smartd/smartctl
49 const char *os_darwin_cpp_cvsid="$Id: os_darwin.cpp 4214 2016-01-24 22:53:37Z samm2 $" \
51 
52 // examples for smartctl
53 static const char smartctl_examples[] =
54  "=================================================== SMARTCTL EXAMPLES =====\n\n"
55  " smartctl -a disk0 (Prints all SMART information)\n\n"
56  " smartctl -t long /dev/disk0 (Executes extended disk self-test)\n\n"
57 #ifdef HAVE_GETOPT_LONG
58  " smartctl --smart=on --saveauto=on /dev/rdisk0 (Enables SMART on first disk)\n\n"
59  " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/disk0\n"
60  " (Prints Self-Test & Attribute errors)\n\n"
61 #else
62  " smartctl -s on -S on /dev/rdisk0 (Enables SMART on first disk)\n\n"
63  " smartctl -A -l selftest -q errorsonly /dev/disk0\n"
64  " (Prints Self-Test & Attribute errors)\n\n"
65 #endif
66  " smartctl -a IOService:/MacRISC2PE/pci@f4000000/AppleMacRiscPCI/ata-6@D/AppleKauaiATA/ATADeviceNub@0/IOATABlockStorageDriver/IOATABlockStorageDevice\n"
67  " (You can use IOService: ...)\n\n"
68  " smartctl -c IODeviceTree:/pci@f4000000/ata-6@D/@0:0\n"
69  " (... Or IODeviceTree:)\n"
70  ;
71 
72 
73 // Information that we keep about each device.
74 
75 static struct {
76  io_object_t ioob;
77  IOCFPlugInInterface **plugin;
78  IOATASMARTInterface **smartIf;
79 } devices[20];
80 
81 const char * dev_darwin_cpp_cvsid = "$Id: os_darwin.cpp 4214 2016-01-24 22:53:37Z samm2 $"
83 
84 /////////////////////////////////////////////////////////////////////////////
85 
86 namespace os { // No need to publish anything, name provided for Doxygen
87 
88 /////////////////////////////////////////////////////////////////////////////
89 /// Implement shared open/close routines with old functions.
90 
92 : virtual public /*implements*/ smart_device
93 {
94 public:
95  explicit darwin_smart_device(const char * mode)
97  m_fd(-1), m_mode(mode) { }
98 
99  virtual ~darwin_smart_device() throw();
100 
101  virtual bool is_open() const;
102 
103  virtual bool open();
104 
105  virtual bool close();
106 
107 protected:
108  /// Return filedesc for derived classes.
109  int get_fd() const
110  { return m_fd; }
111 
112 
113 private:
114  int m_fd; ///< filedesc, -1 if not open.
115  const char * m_mode; ///< Mode string for deviceopen().
116 };
117 
118 
120 {
121  if (m_fd >= 0)
123 }
124 
126 {
127  return (m_fd >= 0);
128 }
129 
130 // Determine whether 'dev' is a SMART-capable device.
131 static bool is_smart_capable (io_object_t dev) {
132  CFTypeRef smartCapableKey;
133  CFDictionaryRef diskChars;
134 
135  // If the device has kIOPropertySMARTCapableKey, then it's capable,
136  // no matter what it looks like.
137  smartCapableKey = IORegistryEntryCreateCFProperty
138  (dev, CFSTR (kIOPropertySMARTCapableKey),
139  kCFAllocatorDefault, 0);
140  if (smartCapableKey)
141  {
142  CFRelease (smartCapableKey);
143  return true;
144  }
145 
146  // If it's an kIOATABlockStorageDeviceClass then we're successful
147  // only if its ATA features indicate it supports SMART.
148  if (IOObjectConformsTo (dev, kIOATABlockStorageDeviceClass)
149  && (diskChars = (CFDictionaryRef)IORegistryEntryCreateCFProperty
150  (dev, CFSTR (kIOPropertyDeviceCharacteristicsKey),
151  kCFAllocatorDefault, kNilOptions)) != NULL)
152  {
153  CFNumberRef diskFeatures = NULL;
154  UInt32 ataFeatures = 0;
155 
156  if (CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"),
157  (const void **)&diskFeatures))
158  CFNumberGetValue (diskFeatures, kCFNumberLongType,
159  &ataFeatures);
160  CFRelease (diskChars);
161  if (diskFeatures)
162  CFRelease (diskFeatures);
163 
164  return (ataFeatures & kIOATAFeatureSMART) != 0;
165  }
166  return false;
167 }
168 
170 {
171  // Acceptable device names are:
172  // /dev/disk*
173  // /dev/rdisk*
174  // disk*
175  // IOService:*
176  // IODeviceTree:*
177  size_t devnum;
178  const char *devname;
179  io_object_t disk;
180  const char *pathname = get_dev_name();
181  char *type = const_cast<char*>(m_mode);
182 
183  if (strcmp (type, "ATA") != 0)
184  {
185  set_err (EINVAL);
186  return false;
187  }
188 
189  // Find a free device number.
190  for (devnum = 0; devnum < sizeof (devices) / sizeof (devices[0]); devnum++)
191  if (! devices[devnum].ioob)
192  break;
193  if (devnum == sizeof (devices) / sizeof (devices[0]))
194  {
195  set_err (EMFILE);
196  return false;
197  }
198 
199  devname = NULL;
200  if (strncmp (pathname, "/dev/rdisk", 10) == 0)
201  devname = pathname + 6;
202  else if (strncmp (pathname, "/dev/disk", 9) == 0)
203  devname = pathname + 5;
204  else if (strncmp (pathname, "disk", 4) == 0)
205  // allow user to just say 'disk0'
206  devname = pathname;
207 
208  // Find the device.
209  if (devname)
210  {
211  CFMutableDictionaryRef matcher;
212  matcher = IOBSDNameMatching (kIOMasterPortDefault, 0, devname);
213  disk = IOServiceGetMatchingService (kIOMasterPortDefault, matcher);
214  }
215  else
216  {
217  disk = IORegistryEntryFromPath (kIOMasterPortDefault, pathname);
218  }
219 
220  if (! disk)
221  {
222  set_err(ENOENT);
223  return false;
224  }
225 
226  // Find a SMART-capable driver which is a parent of this device.
227  while (! is_smart_capable (disk))
228  {
229  IOReturn err;
230  io_object_t prevdisk = disk;
231 
232  // Find this device's parent and try again.
233  err = IORegistryEntryGetParentEntry (disk, kIOServicePlane, &disk);
234  if (err != kIOReturnSuccess || ! disk)
235  {
236  set_err(ENODEV);
237  IOObjectRelease (prevdisk);
238  return false;
239  }
240  }
241 
242  devices[devnum].ioob = disk;
243 
244  {
245  SInt32 dummy;
246 
247  devices[devnum].plugin = NULL;
248  devices[devnum].smartIf = NULL;
249 
250  // Create an interface to the ATA SMART library.
251  if (IOCreatePlugInInterfaceForService (disk,
252  kIOATASMARTUserClientTypeID,
253  kIOCFPlugInInterfaceID,
254  &devices[devnum].plugin,
255  &dummy) == kIOReturnSuccess)
256  (*devices[devnum].plugin)->QueryInterface
257  (devices[devnum].plugin,
258  CFUUIDGetUUIDBytes ( kIOATASMARTInterfaceID),
259  (void **)&devices[devnum].smartIf);
260  }
261 
262 
263  m_fd = devnum;
264  if (m_fd < 0) {
265  set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno);
266  return false;
267  }
268  return true;
269 }
270 
272 {
273  int fd = m_fd; m_fd = -1;
274  if (devices[fd].smartIf)
275  (*devices[fd].smartIf)->Release (devices[fd].smartIf);
276  if (devices[fd].plugin)
277  IODestroyPlugInInterface (devices[fd].plugin);
278  IOObjectRelease (devices[fd].ioob);
279  devices[fd].ioob = MACH_PORT_NULL;
280  return true;
281 }
282 
283 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
284 // smartd. Returns number N of devices, or -1 if out of
285 // memory. Allocates N+1 arrays: one of N pointers (devlist); the
286 // other N arrays each contain null-terminated character strings. In
287 // the case N==0, no arrays are allocated because the array of 0
288 // pointers has zero length, equivalent to calling malloc(0).
289 static int make_device_names (char*** devlist, const char* name) {
290  IOReturn err;
291  io_iterator_t i;
292  io_object_t device = MACH_PORT_NULL;
293  int result;
294  int index;
295 
296  // We treat all devices as ATA so long as they support SMARTLib.
297  if (strcmp (name, "ATA") != 0)
298  return 0;
299 
300  err = IOServiceGetMatchingServices
301  (kIOMasterPortDefault, IOServiceMatching (kIOBlockStorageDeviceClass), &i);
302  if (err != kIOReturnSuccess)
303  return -1;
304 
305  // Count the devices.
306  result = 0;
307  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
308  if (is_smart_capable (device))
309  result++;
310  IOObjectRelease (device);
311  }
312 
313  // Create an array of service names.
314  IOIteratorReset (i);
315  if (! result)
316  goto error;
317  *devlist = (char**)calloc (result, sizeof (char *));
318  index = 0;
319  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
320  if (is_smart_capable (device))
321  {
322  io_string_t devName;
323  IORegistryEntryGetPath(device, kIOServicePlane, devName);
324  (*devlist)[index] = strdup (devName);
325  if (! (*devlist)[index])
326  goto error;
327  index++;
328  }
329  IOObjectRelease (device);
330  }
331 
332  IOObjectRelease (i);
333  return result;
334 
335  error:
336  if (device != MACH_PORT_NULL)
337  IOObjectRelease (device);
338  IOObjectRelease (i);
339  if (*devlist)
340  {
341  for (index = 0; index < result; index++)
342  if ((*devlist)[index])
343  free ((*devlist)[index]);
344  free (*devlist);
345  }
346  if(!result) // no devs found
347  return 0;
348 
349  return -1;
350 }
351 
352 /////////////////////////////////////////////////////////////////////////////
353 /// Implement standard ATA support
354 
356 : public /*implements*/ ata_device,
357  public /*extends*/ darwin_smart_device
358 {
359 public:
360  darwin_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
361  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
362 
363 protected:
364  // virtual int ata_command_interface(smart_command_set command, int select, char * data);
365 };
366 
367 darwin_ata_device::darwin_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
368 : smart_device(intf, dev_name, "ata", req_type),
369  darwin_smart_device("ATA")
370 {
371 }
372 
374 {
375  if (!ata_cmd_is_ok(in,
376  true, // data_out_support
377  true, // multi_sector_support
378  false) // not supported by API
379  )
380  return false;
381 
382  int select = 0;
383  char * data = (char *)in.buffer;
384  int fd = get_fd();
385  IOATASMARTInterface **ifp = devices[fd].smartIf;
386  IOATASMARTInterface *smartIf;
387  IOReturn err;
388  int timeoutCount = 5;
389  int rc = 0;
390 
391  if (! ifp)
392  return -1;
393  smartIf = *ifp;
394  clear_err(); errno = 0;
395  do {
396  switch (in.in_regs.command) {
397  case ATA_IDENTIFY_DEVICE:
398  {
399  UInt32 dummy;
400  err = smartIf->GetATAIdentifyData (ifp, data, 512, &dummy);
401  if (err != kIOReturnSuccess && err != kIOReturnTimeout
402  && err != kIOReturnNotResponding)
403  printf ("identify failed: %#x\n", (unsigned) rc);
404  if (err == kIOReturnSuccess && isbigendian())
405  {
406  int i;
407  /* The system has already byte-swapped, undo it. */
408  for (i = 0; i < 256; i+=2)
409  swap2 (data + i);
410  }
411  }
412  break;
415  errno = ENOTSUP;
416  err = -1;
417  break;
418  case ATA_SMART_CMD:
419  switch (in.in_regs.features) {
421  err = smartIf->SMARTReadData (ifp, (ATASMARTData *)data);
422  break;
424  err = smartIf->SMARTReadDataThresholds (ifp,
425  (ATASMARTDataThresholds *)data);
426  break;
428  err = smartIf->SMARTReadLogAtAddress (ifp, in.in_regs.lba_low, data, 512 * in.in_regs.sector_count);
429  break;
431  err = smartIf->SMARTWriteLogAtAddress (ifp, in.in_regs.lba_low, data, 512 * in.in_regs.sector_count);
432  break;
433  case ATA_SMART_ENABLE:
434  case ATA_SMART_DISABLE:
435  err = smartIf->SMARTEnableDisableOperations (ifp, in.in_regs.features == ATA_SMART_ENABLE);
436  break;
437  case ATA_SMART_STATUS:
438  if (in.out_needed.lba_high) // statuscheck
439  {
440  Boolean is_failing;
441  err = smartIf->SMARTReturnStatus (ifp, &is_failing);
442  if (err == kIOReturnSuccess && is_failing) {
443  err = -1; // thresholds exceeded condition
444  out.out_regs.lba_high = 0x2c; out.out_regs.lba_mid = 0xf4;
445  }
446  else
447  out.out_regs.lba_high = 0xc2; out.out_regs.lba_mid = 0x4f;
448  break;
449  }
450  else err = 0;
451  break;
452  case ATA_SMART_AUTOSAVE:
453  err = smartIf->SMARTEnableDisableAutosave (ifp,
454  (in.in_regs.sector_count == 241 ? true : false));
455  break;
457  select = in.in_regs.lba_low;
458  if (select != SHORT_SELF_TEST && select != EXTEND_SELF_TEST)
459  {
460  errno = EINVAL;
461  return set_err(ENOSYS, "Unsupported SMART self-test mode");
462  }
463  err = smartIf->SMARTExecuteOffLineImmediate (ifp,
464  select == EXTEND_SELF_TEST);
465  break;
467  return set_err(ENOSYS, "SMART command not supported");
468  default:
469  return set_err(ENOSYS, "Unknown SMART command");
470  }
471  break;
472  default:
473  return set_err(ENOSYS, "Non-SMART commands not implemented");
474  }
475  } while ((err == kIOReturnTimeout || err == kIOReturnNotResponding)
476  && timeoutCount-- > 0);
477  if (err == kIOReturnExclusiveAccess)
478  errno = EBUSY;
479  rc = err == kIOReturnSuccess ? 0 : -1;
480  if (rc < 0) {
481  if (!get_errno())
482  set_err(errno);
483  return false;
484  }
485  return true;
486 }
487 
488 /////////////////////////////////////////////////////////////////////////////
489 /// Implement platform interface
490 
492 : public /*implements*/ smart_interface
493 {
494 public:
495  virtual std::string get_os_version_str();
496 
497  virtual std::string get_app_examples(const char * appname);
498 
499  virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
500  const char * pattern = 0);
501 
502 protected:
503  virtual ata_device * get_ata_device(const char * name, const char * type);
504 
505  virtual scsi_device * get_scsi_device(const char * name, const char * type);
506 
507  virtual smart_device * autodetect_smart_device(const char * name);
508 
509 };
510 
511 
512 //////////////////////////////////////////////////////////////////////
513 
515 {
516  // now we are just getting darwin runtime version, to get OSX version more things needs to be done, see
517  // http://stackoverflow.com/questions/11072804/how-do-i-determine-the-os-version-at-runtime-in-os-x-or-ios-without-using-gesta
518  struct utsname osname;
519  uname(&osname);
520  return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
521 }
522 
523 std::string darwin_smart_interface::get_app_examples(const char * appname)
524 {
525  if (!strcmp(appname, "smartctl"))
526  return smartctl_examples;
527  return ""; // ... so don't print again.
528 }
529 
530 ata_device * darwin_smart_interface::get_ata_device(const char * name, const char * type)
531 {
532  return new darwin_ata_device(this, name, type);
533 }
534 
536 {
537  return 0; // scsi devices are not supported [yet]
538 }
539 
540 
542 {
543  return new darwin_ata_device(this, name, "");
544 }
545 
546 static void free_devnames(char * * devnames, int numdevs)
547 {
548  for (int i = 0; i < numdevs; i++)
549  free(devnames[i]);
550  free(devnames);
551 }
552 
554  const char * type, const char * pattern /*= 0*/)
555 {
556  if (pattern) {
557  set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
558  return false;
559  }
560 
561  // Make namelists
562  char * * atanames = 0; int numata = 0;
563  if (!type || !strcmp(type, "ata")) {
564  numata = make_device_names(&atanames, "ATA");
565  if (numata < 0) {
566  set_err(ENOMEM);
567  return false;
568  }
569  }
570 
571  // Add to devlist
572  int i;
573  if (!type)
574  type="";
575  for (i = 0; i < numata; i++) {
576  ata_device * atadev = get_ata_device(atanames[i], type);
577  if (atadev)
578  devlist.push_back(atadev);
579  }
580  free_devnames(atanames, numata);
581  return true;
582 }
583 
584 } // namespace
585 
586 
587 /////////////////////////////////////////////////////////////////////////////
588 /// Initialize platform interface and register with smi()
589 
591 {
592  static os::darwin_smart_interface the_interface;
593  smart_interface::set(&the_interface);
594 }
virtual bool close()
Close device, return false on error.
Definition: os_darwin.cpp:271
virtual scsi_device * get_scsi_device(const char *name, const char *type)
Return standard SCSI device.
Definition: os_darwin.cpp:535
#define ATA_SMART_READ_LOG_SECTOR
Definition: atacmds.h:100
#define ATA_SMART_WRITE_LOG_SECTOR
Definition: atacmds.h:101
bool isbigendian()
Definition: utility.h:104
#define ATACMDS_H_CVSID
Definition: atacmds.h:28
ata_out_regs_flags out_needed
True if output register value needed.
virtual smart_device * autodetect_smart_device(const char *name)
Autodetect device if no device type specified.
Definition: os_darwin.cpp:541
int m_fd
filedesc, -1 if not open.
Definition: os_darwin.cpp:114
#define ATA_SMART_CMD
Definition: atacmds.h:75
int get_errno() const
Get last error number.
virtual ata_device * get_ata_device(const char *name, const char *type)
Return standard ATA device.
Definition: os_darwin.cpp:530
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)
ATA pass through.
Definition: os_darwin.cpp:373
virtual ~darwin_smart_device()
Definition: os_darwin.cpp:119
const char * m_mode
Mode string for deviceopen().
Definition: os_darwin.cpp:115
Implement platform interface.
Definition: os_darwin.cpp:491
virtual bool is_open() const
Return true if device is open.
Definition: os_darwin.cpp:125
static void free_devnames(char **devnames, int numdevs)
Definition: dev_legacy.cpp:276
#define ATA_SMART_DISABLE
Definition: atacmds.h:104
#define ATA_SMART_AUTOSAVE
Definition: atacmds.h:97
virtual bool scan_smart_devices(smart_device_list &devlist, const char *type, const char *pattern=0)
Fill 'devlist' with devices of some 'type' with device names specified by some optional 'pattern'...
Definition: os_darwin.cpp:553
#define EXTEND_SELF_TEST
Definition: atacmds.h:113
static bool is_smart_capable(io_object_t dev)
Definition: os_darwin.cpp:131
#define ENOTSUP
Definition: os_linux.cpp:100
void * buffer
Pointer to data buffer.
Implement standard ATA support.
Definition: os_darwin.cpp:355
void push_back(smart_device *dev)
#define ATA_IDENTIFY_DEVICE
Definition: atacmds.h:72
ata_register lba_mid
#define DEV_INTERFACE_H_CVSID
Definition: dev_interface.h:21
#define INT64_H_CVSID
Definition: int64.h:23
#define ATA_IDENTIFY_PACKET_DEVICE
Definition: atacmds.h:73
#define kIOATABlockStorageDeviceClass
Definition: os_darwin.cpp:38
#define SCSICMDS_H_CVSID
Definition: scsicmds.h:33
ata_in_regs_48bit in_regs
Input registers.
ata_out_regs_48bit out_regs
Output registers.
ptr_t data
Definition: megaraid.h:94
Implement shared open/close routines with old functions.
Definition: os_darwin.cpp:91
List of devices for DEVICESCAN.
virtual std::string get_os_version_str()
Return info string about build host and/or OS version.
Definition: os_darwin.cpp:514
#define ATA_CHECK_POWER_MODE
Definition: atacmds.h:71
static void init()
Initialize platform interface and register with smi().
Definition: dev_legacy.cpp:341
The platform interface abstraction.
IOATASMARTInterface ** smartIf
Definition: os_darwin.cpp:78
darwin_smart_device(const char *mode)
Definition: os_darwin.cpp:95
static void set(smart_interface *intf)
Set interface to use, must be called from init().
IOCFPlugInInterface ** plugin
Definition: os_darwin.cpp:77
static const char smartctl_examples[]
Definition: os_darwin.cpp:53
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
const char * os_darwin_cpp_cvsid
Definition: os_darwin.cpp:49
#define ATA_SMART_READ_VALUES
Definition: atacmds.h:95
ata_register lba_low
SCSI device access.
ata_register features
#define ATA_SMART_AUTO_OFFLINE
Definition: atacmds.h:108
#define OS_DARWIN_H_CVSID
Definition: os_darwin.h:27
#define kIOPropertySMARTCapableKey
Definition: os_darwin.h:32
bool ata_cmd_is_ok(const ata_cmd_in &in, bool data_out_support=false, bool multi_sector_support=false, bool ata_48bit_support=false)
Check command input parameters (old version).
io_object_t ioob
Definition: os_darwin.cpp:76
static int make_device_names(char ***devlist, const char *name)
Definition: os_darwin.cpp:289
#define ATA_SMART_READ_THRESHOLDS
Definition: atacmds.h:96
Base class for all devices.
Definition: dev_interface.h:39
static struct @40 devices[20]
ATA device access.
ata_register sector_count
#define SHORT_SELF_TEST
Definition: atacmds.h:112
const char * dev_darwin_cpp_cvsid
Definition: os_darwin.cpp:81
#define ATA_SMART_IMMEDIATE_OFFLINE
Definition: atacmds.h:99
virtual std::string get_app_examples(const char *appname)
Return example string for program 'appname'.
Definition: os_darwin.cpp:523
virtual bool open()
Open device, return false on error.
Definition: os_darwin.cpp:169
ata_register command
ATA pass through input parameters.
#define ATA_SMART_ENABLE
Definition: atacmds.h:103
void swap2(char *location)
Definition: atacmds.cpp:314
darwin_ata_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_darwin.cpp:367
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:750
ata_register lba_high
void clear_err()
Clear last error info.
const char * get_dev_name() const
Get device (path)name.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
ATA pass through output parameters.
int get_fd() const
Return filedesc for derived classes.
Definition: os_darwin.cpp:109
#define UTILITY_H_CVSID
Definition: utility.h:28
#define ATA_SMART_STATUS
Definition: atacmds.h:105