smartctl.cpp 9.08 KB
Newer Older
ballen4705's avatar
ballen4705 committed
1
2
3
/*
 * smartctl.c
 *
4
5
 * Home page of code is: http://smartmontools.sourceforge.net
 *
ballen4705's avatar
ballen4705 committed
6
 * Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
ballen4705's avatar
ballen4705 committed
7
8
9
10
11
12
13
14
15
16
 * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * You should have received a copy of the GNU General Public License
 * (for example COPYING); if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
ballen4705's avatar
ballen4705 committed
17
18
19
20
21
22
 *
 * This code was originally developed as a Senior Thesis by Michael Cornwell
 * at the Concurrent Systems Laboratory (now part of the Storage Systems
 * Research Center), Jack Baskin School of Engineering, University of
 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 *
ballen4705's avatar
ballen4705 committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 */


#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <string.h>
#include "smartctl.h"
#include "atacmds.h"
#include "ataprint.h"
#include "scsicmds.h"
#include "scsiprint.h"

39
40
41
extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5; 
const char* CVSid6="$Id: smartctl.cpp,v 1.12 2002/10/22 09:44:55 ballen4705 Exp $\n" CVSID1 CVSID2 CVSID4 CVSID5 CVSID6 ;

ballen4705's avatar
ballen4705 committed
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
unsigned char driveinfo               = FALSE;
unsigned char checksmart              = FALSE;
unsigned char smartvendorattrib       = FALSE;
unsigned char generalsmartvalues      = FALSE;
unsigned char smartselftestlog        = FALSE;
unsigned char smarterrorlog           = FALSE;
unsigned char smartdisable            = FALSE;
unsigned char smartenable             = FALSE;
unsigned char smartstatus             = FALSE;
unsigned char smartexeoffimmediate    = FALSE;
unsigned char smartshortselftest      = FALSE;
unsigned char smartextendselftest     = FALSE;
unsigned char smartshortcapselftest   = FALSE;
unsigned char smartextendcapselftest  = FALSE;
unsigned char smartselftestabort      = FALSE;
unsigned char smartautoofflineenable  = FALSE;
unsigned char smartautoofflinedisable = FALSE;
unsigned char smartautosaveenable     = FALSE;
unsigned char smartautosavedisable    = FALSE;
unsigned char printcopyleft           = FALSE;
62
unsigned char smart009minutes         = FALSE;
63
int           testcase                = -1;
ballen4705's avatar
ballen4705 committed
64
65
66
67
68
69
70
71


/*  void Usage (void) 
	prints help information for command syntax */



void Usage ( void){
72
  printf( "Usage: smartctl -[options] [device]\n\n");
ballen4705's avatar
ballen4705 committed
73
  printf( "Read Only Options:\n");
74
75
76
77
78
79
80
81
82
83
84
  printf( "\t\t%c\t\tShow version, copyright and license information\n", PRINTCOPYLEFT);
  printf( "\t\t%c\t\tShow all S.M.A.R.T. Information (ATA and SCSI)\n",  SMARTVERBOSEALL);
  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info      (ATA and SCSI)\n",  DRIVEINFO);
  printf( "\t\t%c\t\tShow S.M.A.R.T. Status          (ATA and SCSI)\n",  CHECKSMART);
  printf( "\t\t%c\t\tShow S.M.A.R.T. General Attributes  (ATA Only)\n",  GENERALSMARTVALUES);
  printf( "\t\t%c\t\tShow S.M.A.R.T. Vendor Attributes   (ATA Only)\n",  SMARTVENDORATTRIB);
  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log     (ATA Only\n",   SMARTERRORLOG);
  printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Self Test Log (ATA Only)\n",  SMARTSELFTESTLOG);
  printf( "\n");
  printf( "Vendor-specific Display Options:\n");
  printf( "\t\t%c\t\tRaw Attribute 009 is minutes        (ATA Only)\n",  SMART009MINUTES);
ballen4705's avatar
ballen4705 committed
85
86
  printf( "\n");
  printf( "Enable/Disable Options:\n");
87
88
89
90
91
92
  printf( "\t\t%c\t\tEnable  S.M.A.R.T. data collection    (ATA and SCSI)\n",SMARTENABLE);
  printf( "\t\t%c\t\tDisable S.M.A.R.T. data collection    (ATA and SCSI)\n",SMARTDISABLE);
  printf( "\t\t%c\t\tEnable  S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEENABLE);
  printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEDISABLE);
  printf( "\t\t%c\t\tEnable  S.M.A.R.T. Attribute Autosave     (ATA Only)\n",SMARTAUTOSAVEENABLE);
  printf( "\t\t%c\t\tDisable S.M.A.R.T. Attribute Autosave     (ATA Only)\n",SMARTAUTOSAVEDISABLE);
ballen4705's avatar
ballen4705 committed
93
94
  printf( "\n");
  printf( "Test Options:\n");
95
96
97
98
99
  printf( "\t\t%c\t\tExecute Off-line data collection (ATA Only)\n",          SMARTEXEOFFIMMEDIATE);
  printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n",                   SMARTSHORTSELFTEST );
  printf( "\t\t%c\t\tExecute Short Self Test (Captive Mode) (ATA Only)\n",    SMARTSHORTCAPSELFTEST );
  printf( "\t\t%c\t\tExecute Extended Self Test (ATA Only)\n",                SMARTEXTENDSELFTEST );
  printf( "\t\t%c\t\tExecute Extended Self Test (Captive Mode) (ATA Only)\n", SMARTEXTENDCAPSELFTEST );
100
  printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n",                 SMARTSELFTESTABORT );
ballen4705's avatar
ballen4705 committed
101
102
103
  printf( "Examples:\n");
  printf("\tsmartctl -etf /dev/hda   (Enables S.M.A.R.T. on first disk)\n");
  printf("\tsmartctl -a   /dev/hda   (Prints all S.M.A.R.T. information)\n");
104
105
  printf("\tsmartctl -X   /dev/hda   (Executes extended disk self-test)\n\n");
  printf("Please see the man pages or %s for further information.\n",PROJECTHOME);
ballen4705's avatar
ballen4705 committed
106
107
108

}

109
110
111
112
113
114
const char opts[] = { 
  DRIVEINFO, CHECKSMART, SMARTVERBOSEALL, SMARTVENDORATTRIB,
  GENERALSMARTVALUES, SMARTERRORLOG, SMARTSELFTESTLOG, SMARTDISABLE,
  SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE,
  SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST, 
  SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT,
115
  SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,'\0'
116
};
ballen4705's avatar
ballen4705 committed
117

118
/*      Takes command options and sets features to be run */	
ballen4705's avatar
ballen4705 committed
119
void ParseOpts (int argc, char** argv){
120
121
122
  int optchar;
  extern char *optarg;
  extern int optopt, optind, opterr;
ballen4705's avatar
ballen4705 committed
123
  
124
125
  opterr=1;
  while (-1 != (optchar = getopt(argc, argv, opts))) {
ballen4705's avatar
ballen4705 committed
126
    switch (optchar){
127
128
129
    case SMART009MINUTES:
      smart009minutes=TRUE;
      break;
ballen4705's avatar
ballen4705 committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    case PRINTCOPYLEFT :
      printcopyleft=TRUE;
      break;
    case DRIVEINFO :
      driveinfo  = TRUE;
      break;		
    case CHECKSMART :
      checksmart = TRUE;		
      break;
    case SMARTVERBOSEALL :
      driveinfo = TRUE;
      checksmart = TRUE;
      generalsmartvalues = TRUE;
      smartvendorattrib = TRUE;
      smarterrorlog = TRUE;
      smartselftestlog = TRUE;
      break;
    case SMARTVENDORATTRIB :
      smartvendorattrib = TRUE;
      break;
    case GENERALSMARTVALUES :
      generalsmartvalues = TRUE;
      break;
    case SMARTERRORLOG :
      smarterrorlog = TRUE;
      break;
    case SMARTSELFTESTLOG :
      smartselftestlog = TRUE;
      break;
    case SMARTDISABLE :
      smartdisable = TRUE;
      break;
    case SMARTENABLE :
      smartenable   = TRUE;
      break;
    case SMARTAUTOSAVEENABLE:
      smartautosaveenable = TRUE;
      break;
    case SMARTAUTOSAVEDISABLE:
      smartautosavedisable = TRUE;
      break;
    case SMARTAUTOOFFLINEENABLE: 
      smartautoofflineenable = TRUE;
      break;
    case SMARTAUTOOFFLINEDISABLE:
      smartautoofflinedisable = TRUE;
      break;
    case SMARTEXEOFFIMMEDIATE:
      smartexeoffimmediate = TRUE;
179
      testcase=OFFLINE_FULL_SCAN;
ballen4705's avatar
ballen4705 committed
180
181
182
      break;
    case SMARTSHORTSELFTEST :
      smartshortselftest = TRUE;
183
      testcase=SHORT_SELF_TEST;
ballen4705's avatar
ballen4705 committed
184
185
186
      break;
    case SMARTEXTENDSELFTEST :
      smartextendselftest = TRUE;
187
      testcase=EXTEND_SELF_TEST;
ballen4705's avatar
ballen4705 committed
188
189
190
      break;
    case SMARTSHORTCAPSELFTEST:
      smartshortcapselftest = TRUE;
191
      testcase=SHORT_CAPTIVE_SELF_TEST;
ballen4705's avatar
ballen4705 committed
192
193
194
      break;
    case SMARTEXTENDCAPSELFTEST:
      smartextendcapselftest = TRUE;
195
      testcase=EXTEND_CAPTIVE_SELF_TEST;
ballen4705's avatar
ballen4705 committed
196
197
198
      break;
    case SMARTSELFTESTABORT:
      smartselftestabort = TRUE;
199
      testcase=ABORT_SELF_TEST;
ballen4705's avatar
ballen4705 committed
200
201
202
203
204
205
206
207
      break;
    default:
      Usage();
      exit (-1);	
    }
    
    if ( (smartexeoffimmediate + smartshortselftest +
	  smartextendselftest + smartshortcapselftest +
208
	  smartextendcapselftest +smartselftestabort ) > 1){
ballen4705's avatar
ballen4705 committed
209
      Usage();
210
      printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
ballen4705's avatar
ballen4705 committed
211
212
213
214
215
216
217
218
219
220
221
      exit(-1);
    }
  }
}

/* Main Program */

int main (int argc, char **argv){
  int fd;
  char *device;
  
222
  printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
223
  printf("Home page of smartctl is %s\n",PROJECTHOME);
224
  
ballen4705's avatar
ballen4705 committed
225
226
227
228
229
  // Part input arguments
  ParseOpts (argc,argv);
  
  // Print Copyright/License info if needed
  if (printcopyleft){
230
    printf("\nsmartctl comes with ABSOLUTELY NO WARRANTY. This\n");
ballen4705's avatar
ballen4705 committed
231
232
    printf("is free software, and you are welcome to redistribute it\n");
    printf("under the terms of the GNU General Public License Version 2.\n");
233
    printf("See http://www.gnu.org for further details.\n\n");
234
    printf("CVS version IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6);
235
236
    if (argc==2)
      exit(0);
ballen4705's avatar
ballen4705 committed
237
238
239
240
241
242
243
244
 }

  // Further argument checking
  if ( argc != 3 ){
    Usage();
    exit (-1);
  }
    
245
246
  // open device - read-only mode is enough to issue needed commands
  fd = open ( device=argv[2], O_RDONLY );
ballen4705's avatar
ballen4705 committed
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  
  if ( fd < 0) {
    perror ( "Device open failed");
    exit(-1);
  }
  
  if ( device[5] == 'h')
    ataPrintMain (fd );
  else if (device[5] == 's')
    scsiPrintMain (fd);
  else 
    Usage();
  
  return 0;
}