smartctl.cpp 9.17 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
extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5; 
40
const char* CVSid6="$Id: smartctl.cpp,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n"
41
"\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ;
42

ballen4705's avatar
ballen4705 committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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;
63
unsigned char smart009minutes         = FALSE;
64
int           testcase                = -1;
ballen4705's avatar
ballen4705 committed
65
66
67
68
69
70
71
72


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



void Usage ( void){
73
  printf( "Usage: smartctl -[options] [device]\n\n");
ballen4705's avatar
ballen4705 committed
74
  printf( "Read Only Options:\n");
75
76
77
78
79
80
81
82
83
84
85
  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
86
87
  printf( "\n");
  printf( "Enable/Disable Options:\n");
88
89
90
91
92
93
  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
94
95
  printf( "\n");
  printf( "Test Options:\n");
96
97
98
99
100
  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 );
101
  printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n",                 SMARTSELFTESTABORT );
ballen4705's avatar
ballen4705 committed
102
103
104
  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");
105
106
  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
107
108
109

}

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

119
/*      Takes command options and sets features to be run */	
ballen4705's avatar
ballen4705 committed
120
void ParseOpts (int argc, char** argv){
121
122
123
  int optchar;
  extern char *optarg;
  extern int optopt, optind, opterr;
ballen4705's avatar
ballen4705 committed
124
  
125
126
  opterr=1;
  while (-1 != (optchar = getopt(argc, argv, opts))) {
ballen4705's avatar
ballen4705 committed
127
    switch (optchar){
128
129
130
    case SMART009MINUTES:
      smart009minutes=TRUE;
      break;
ballen4705's avatar
ballen4705 committed
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
179
    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;
180
      testcase=OFFLINE_FULL_SCAN;
ballen4705's avatar
ballen4705 committed
181
182
183
      break;
    case SMARTSHORTSELFTEST :
      smartshortselftest = TRUE;
184
      testcase=SHORT_SELF_TEST;
ballen4705's avatar
ballen4705 committed
185
186
187
      break;
    case SMARTEXTENDSELFTEST :
      smartextendselftest = TRUE;
188
      testcase=EXTEND_SELF_TEST;
ballen4705's avatar
ballen4705 committed
189
190
191
      break;
    case SMARTSHORTCAPSELFTEST:
      smartshortcapselftest = TRUE;
192
      testcase=SHORT_CAPTIVE_SELF_TEST;
ballen4705's avatar
ballen4705 committed
193
194
195
      break;
    case SMARTEXTENDCAPSELFTEST:
      smartextendcapselftest = TRUE;
196
      testcase=EXTEND_CAPTIVE_SELF_TEST;
ballen4705's avatar
ballen4705 committed
197
198
199
      break;
    case SMARTSELFTESTABORT:
      smartselftestabort = TRUE;
200
      testcase=ABORT_SELF_TEST;
ballen4705's avatar
ballen4705 committed
201
202
203
      break;
    default:
      Usage();
204
      exit(FAILCMD);	
ballen4705's avatar
ballen4705 committed
205
206
207
208
    }
    
    if ( (smartexeoffimmediate + smartshortselftest +
	  smartextendselftest + smartshortcapselftest +
209
	  smartextendcapselftest +smartselftestabort ) > 1){
ballen4705's avatar
ballen4705 committed
210
      Usage();
211
      printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
212
      exit(FAILCMD);
ballen4705's avatar
ballen4705 committed
213
214
215
216
217
218
219
    }
  }
}

/* Main Program */

int main (int argc, char **argv){
220
  int fd,retval=0;
ballen4705's avatar
ballen4705 committed
221
222
  char *device;
  
223
  printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
224
  printf("Home page of smartctl is %s\n",PROJECTHOME);
225
  
ballen4705's avatar
ballen4705 committed
226
  // Part input arguments
227
  ParseOpts(argc,argv);
ballen4705's avatar
ballen4705 committed
228
229
230
  
  // Print Copyright/License info if needed
  if (printcopyleft){
231
    printf("\nsmartctl comes with ABSOLUTELY NO WARRANTY. This\n");
ballen4705's avatar
ballen4705 committed
232
233
    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");
234
    printf("See http://www.gnu.org for further details.\n\n");
235
    printf("CVS version IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6);
236
    if (argc==2)
237
238
239
      return 0;
  }
  
ballen4705's avatar
ballen4705 committed
240
  // Further argument checking
241
  if (argc != 3){
ballen4705's avatar
ballen4705 committed
242
    Usage();
243
    return FAILCMD;
ballen4705's avatar
ballen4705 committed
244
  }
245
  
246
  // open device - read-only mode is enough to issue needed commands
247
  fd = open(device=argv[2], O_RDONLY);
ballen4705's avatar
ballen4705 committed
248
  
249
250
251
  if (fd< 0) {
    perror ("Smartctl device open failed:");
    return FAILDEV;
ballen4705's avatar
ballen4705 committed
252
253
  }
  
254
255
  if (device[5] == 'h')
    retval=ataPrintMain(fd );
ballen4705's avatar
ballen4705 committed
256
257
  else if (device[5] == 's')
    scsiPrintMain (fd);
258
  else {
ballen4705's avatar
ballen4705 committed
259
    Usage();
260
261
262
263
    return FAILCMD;
  }

  return retval;
ballen4705's avatar
ballen4705 committed
264
}