📄 smartd.c
字号:
/* * smartd.c * * 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. */#include <stdio.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <linux/hdreg.h>#include <syslog.h>#include "atacmds.h"#include "scsicmds.h"#include "smartd.h"int daemon_init(void){ pid_t pid; if ( (pid = fork()) < 0) return -1; else if (pid != 0) exit (0); setsid (); chdir("/"); umask(0); return(0);}/* void Usage (void) prints help information for command syntax */void Usage ( void){ printf( "smartd version %i.%i - S.M.A.R.T. Daemon\n", VERSION_MAJOR, VERSION_MINOR); printf( "useage: smartd -[opts] \n"); printf( "Read Only Commands:\n"); printf( "\t\t%c\t\tStart smartd in debug Mode\n",DEBUGMODE);} /* void ParseOpts ( chars *opts) Takes command options and sets features to be run */ void ParseOpts ( char *opts){ int i = 0; char options[255]; strcpy ( (char *) &options, opts); if ( options[0] != '-' ) { Usage(); exit (-1); } for (i = 1; options[i] != '\0'; i++ ) { switch (options[i]) { case DEBUGMODE : debugmode = TRUE; break; case EMAILNOTIFICATION: emailnotification = TRUE; break; default: Usage(); exit (-1); } }}void failurenotify ( char *message){}void atadevicescan ( atadevices_t *devices){ int i; int fd; struct hd_driveid drive; char device[] = "/dev/hda"; for(i = 0; i < MAXATADEVICES ; i++,device[7]++ ) { fd = 0; if (debugmode) printf("Reading Device %s\n", device); fd = open ( device , O_RDWR ); if ( fd >= 0) { if (ataReadHDIdentity ( fd, &drive) == 0 ) { if (ataSmartSupport (drive) ) { if (ataEnableSmart) { devices[numatadevices].fd = fd; strcpy((char *) &devices[numatadevices].devicename, (char*) &device); devices[numatadevices].drive = drive; if ( ataReadSmartValues ( fd, &devices[numatadevices].smartval) != 0 ) { syslog (LOG_INFO, "Device: %s, Read Smart Values Failed\n", device); } if ( ataReadSmartThresholds ( fd, &devices[numatadevices].smartthres) != 0 ) { syslog (LOG_INFO, "Device: %s, Read Smart Thresholds Failed\n", device); } if (debugmode) printf("%s Found and is SMART capable\n", devices[numatadevices].devicename); syslog (LOG_INFO, "Device: %s, Found and is SMART capable\n", device); devices[numatadevices].selftest = isSupportSelfTest(devices[numatadevices].smartval); numatadevices++; } } } } }}void scsidevicescan ( scsidevices_t *devices){ int i, fd, smartsupport; unsigned char tBuf[4096]; char device[] = "/dev/sda"; for(i = 0; i < MAXSCSIDEVICES ; i++,device[7]++ ) { fd = 0; if (debugmode) printf("Reading Device %s\n", device); fd = open ( device , O_RDWR ); if(debugmode) printf ("Device: %s, File Descriptor: %d \n", device, fd); if ( fd >= 0) { if ( testunitready (fd) == 0 ) { if (modesense ( fd, 0x1c, (UINT8 *) &tBuf) != 0) { if(debugmode) printf ("Device: %s, Failed read of ModePage 1C \n", device); } else { if ( scsiSmartSupport( fd, (UINT8 *) &smartsupport) == 0) { if (!(smartsupport & DEXCPT_ENABLE)) { devices[numscsidevices].fd = fd; strcpy((char *) &devices[numscsidevices].devicename, (char*) &device); if (debugmode) printf("%s Found and is SMART capable\n", devices[numscsidevices].devicename); syslog (LOG_INFO, "Device: %s, Found and is SMART capable\n", device); if (logsense ( fd , SUPPORT_LOG_PAGES, (UINT8 *) &tBuf) == 0) { for ( i = 4; i < tBuf[3] + LOGPAGEHDRSIZE ; i++) { switch ( tBuf[i]) { case TEMPERATURE_PAGE: devices[numscsidevices].TempPageSupported = 1; break; case SMART_PAGE: devices[numscsidevices].SmartPageSupported = 1; break; default: break; } } } numscsidevices++; } } } } }}}void ataCompareSmartValues ( atadevices_t *device, struct ata_smart_values b ){ int i; for ( i =0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { if( device->smartval.vendor_attributes[i].id & b.vendor_attributes[i].id & (device->smartval.vendor_attributes[i].current != b.vendor_attributes[i].current)) { syslog (LOG_INFO, "Device: %s, S.M.A.R.T. Attribute: %i Changed %i\n", device->devicename, device->smartval.vendor_attributes[i].id, (device->smartval.vendor_attributes[i].current - b.vendor_attributes[i].current)); } } }int ataCheckDevice( atadevices_t *drive){ struct ata_smart_values tempsmartval; struct ata_smart_thresholds tempsmartthres; if ( ataReadSmartValues ( drive->fd, &tempsmartval) != 0 ) { syslog (LOG_INFO, "%s:Failed to read smart values\n", drive->devicename); } if ( ataReadSmartThresholds ( drive->fd, &tempsmartthres) != 0 ) { syslog (LOG_INFO, "%s:Failed to read smart thresholds\n", drive->devicename); } if (ataCheckSmart( tempsmartval, tempsmartthres)) { if(debugmode) printf ("Device: %s, Failed attribute: %i\n", drive->devicename, ataCheckSmart( tempsmartval, tempsmartthres)); else syslog (LOG_CRIT, "Device: %s, Failed attribute: %i\n", drive->devicename, ataCheckSmart( tempsmartval, tempsmartthres)); } if(debugmode) printf ("Device: %s, S.M.A.R.T. Failure attribute: %i\n", drive->devicename, ataCheckSmart( tempsmartval, tempsmartthres)); ataCompareSmartValues (drive , tempsmartval); /* Copy the values back to the structure */ drive->smartval = tempsmartval; drive->smartthres = tempsmartthres; return 0;}int scsiCheckDevice( scsidevices_t *drive){ UINT8 returnvalue; UINT8 currenttemp; UINT8 triptemp; currenttemp = triptemp = 0; if ( scsiCheckSmart( drive->fd, drive->SmartPageSupported, &returnvalue, ¤ttemp, &triptemp ) != 0) { syslog (LOG_INFO, "%s:Failed to read smart values\n", drive->devicename); } if ( returnvalue ) { if(debugmode) printf ("Device: %s, S.M.A.R.T. Failure: (%02x) %s\n", drive->devicename, returnvalue, scsiSmartGetSenseCode( returnvalue) ); else syslog (LOG_CRIT, "Device: %s, S.M.A.R.T. Failure: (%02x) %s\n", drive->devicename, returnvalue, scsiSmartGetSenseCode( returnvalue) ); } else { if(debugmode) printf ("Device: %s, Okay attribute: %d\n", drive->devicename, returnvalue); } if ( currenttemp ) { if ( (currenttemp != drive->Temperature) && ( drive->Temperature) ) syslog (LOG_INFO, "Device: %s, Temperature changed %d degrees to %d degress since last reading\n", drive->devicename, (int) (currenttemp - drive->Temperature), (unsigned int) currenttemp ); drive->Temperature = currenttemp; } return 0;}void CheckDevices ( atadevices_t *atadevices, scsidevices_t *scsidevices){ int i; while (1) { for (i = 0; i < numatadevices;i++) { if ( ataCheckDevice ( &atadevices[i]) != 0 ) { exit (-1); /* never reached */ } } for (i = 0; i < numscsidevices;i++) { if ( scsiCheckDevice ( &scsidevices[i]) != 0 ) { exit (-1); /* never reached */ } } sleep ( checktime ); }}/* Main Program */int main (int argv, char **argc){ atadevices_t atadevices[MAXATADEVICES], *atadevicesptr; scsidevices_t scsidevices[MAXSCSIDEVICES], *scsidevicesptr; numatadevices=0; numscsidevices=0; scsidevicesptr = scsidevices; atadevicesptr = atadevices; if ( *(argc+1) != NULL) ParseOpts ( *(argc+1)); syslog (LOG_INFO, "smartd started\n"); if (!debugmode) { daemon_init(); } /* fork into indepentant process */ atadevicescan (atadevicesptr); scsidevicescan (scsidevicesptr); CheckDevices ( atadevicesptr, scsidevicesptr); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -