📄 smartctl.cpp
字号:
// don't scan remainder of disk after doing selected segments con->scanafterselect=1; } else if (!strncmp(optarg,"pending,",strlen("pending,"))) { // parse number of minutes that test should be pending int i; char *tailptr=NULL; errno=0; i=(int)strtol(optarg+strlen("pending,"), &tailptr, 10); if (errno || *tailptr != '\0') { sprintf(extraerror, "Option -t pending,N requires N to be a non-negative integer\n"); badarg = TRUE; } else if (i<0 || i>65535) { sprintf(extraerror, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i); badarg = TRUE; } else { con->pendingtime=i+1; } } else if (!strncmp(optarg,"select",strlen("select"))) { // parse range of LBAs to test uint64_t start, stop; int mode; if (split_selective_arg(optarg, &start, &stop, &mode)) { sprintf(extraerror, "Option -t select,M-N must have non-negative integer M and N\n"); badarg = TRUE; } else { if (con->smartselectivenumspans >= 5 || start > stop) { if (start > stop) { sprintf(extraerror, "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n", start, stop, optarg); } else { sprintf(extraerror,"ERROR: No more than five selective self-test spans may be" " defined\n"); } badarg = TRUE; } con->smartselectivespan[con->smartselectivenumspans][0] = start; con->smartselectivespan[con->smartselectivenumspans][1] = stop; con->smartselectivemode[con->smartselectivenumspans] = mode; con->smartselectivenumspans++; con->testcase = SELECTIVE_SELF_TEST; } } else if (!strncmp(optarg, "scttempint,", sizeof("scstempint,")-1)) { unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg); if (!( sscanf(optarg,"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1 && 0 < interval && interval <= 0xffff && (n1 == len || n2 == len))) { strcpy(extraerror, "Option -t scttempint,N[,p] must have positive integer N\n"); badarg = TRUE; } con->scttempint = interval; con->scttempintp = (n2 == len); } else { badarg = TRUE; } break; case 'C': captive = TRUE; break; case 'X': con->smartselftestabort = TRUE; con->testcase = ABORT_SELF_TEST; break; case 'n': // skip disk check if in low-power mode if (!strcmp(optarg, "never")) con->powermode = 1; // do not skip, but print mode else if (!strcmp(optarg, "sleep")) con->powermode = 2; else if (!strcmp(optarg, "standby")) con->powermode = 3; else if (!strcmp(optarg, "idle")) con->powermode = 4; else badarg = TRUE; break; case 'h': con->dont_print=FALSE; printslogan(); Usage(); EXIT(0); break; case '?': default: con->dont_print=FALSE; printslogan();#ifdef HAVE_GETOPT_LONG // Point arg to the argument in which this option was found. arg = argv[optind-1]; // Check whether the option is a long option that doesn't map to -h. if (arg[1] == '-' && optchar != 'h') { // Iff optopt holds a valid option then argument must be missing. if (optopt && (strchr(shortopts, optopt) != NULL)) { pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2); printvalidarglistmessage(optopt); } else pout("=======> UNRECOGNIZED OPTION: %s\n",arg+2); if (extraerror[0]) pout("=======> %s", extraerror); UsageSummary(); EXIT(FAILCMD); }#endif if (optopt) { // Iff optopt holds a valid option then argument must be // missing. Note (BA) this logic seems to fail using Solaris // getopt! if (strchr(shortopts, optopt) != NULL) { pout("=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt); printvalidarglistmessage(optopt); } else pout("=======> UNRECOGNIZED OPTION: %c\n",optopt); if (extraerror[0]) pout("=======> %s", extraerror); UsageSummary(); EXIT(FAILCMD); } Usage(); EXIT(0); } // closes switch statement to process command-line options // Check to see if option had an unrecognized or incorrect argument. if (badarg) { printslogan(); // It would be nice to print the actual option name given by the user // here, but we just print the short form. Please fix this if you know // a clean way to do it. pout("=======> INVALID ARGUMENT TO -%c: %s\n", optchar, optarg); printvalidarglistmessage(optchar); if (extraerror[0]) pout("=======> %s", extraerror); UsageSummary(); EXIT(FAILCMD); } } // At this point we have processed all command-line options. If the // print output is switchable, then start with the print output // turned off if (con->printing_switchable) con->dont_print=TRUE; // error message if user has asked for more than one test if (1<(con->smartexeoffimmediate+con->smartshortselftest+con->smartextendselftest+ con->smartshortcapselftest+con->smartextendcapselftest+con->smartselftestabort + (con->smartselectivenumspans>0?1:0))){ con->dont_print=FALSE; printslogan(); pout("\nERROR: smartctl can only run a single test type (or abort) at a time.\n"); UsageSummary(); EXIT(FAILCMD); } // error message if user has set selective self-test options without // asking for a selective self-test if ((con->pendingtime || con->scanafterselect) && !con->smartselectivenumspans){ con->dont_print=FALSE; printslogan(); if (con->pendingtime) pout("\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n"); else pout("\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n"); UsageSummary(); EXIT(FAILCMD); } // If captive option was used, change test type if appropriate. if (captive && con->smartshortselftest) { con->smartshortselftest = FALSE; con->smartshortcapselftest = TRUE; con->testcase = SHORT_CAPTIVE_SELF_TEST; } else if (captive && con->smartextendselftest) { con->smartextendselftest = FALSE; con->smartextendcapselftest = TRUE; con->testcase = EXTEND_CAPTIVE_SELF_TEST; } else if (captive && con->smartconveyanceselftest) { con->smartconveyanceselftest = FALSE; con->smartconveyancecapselftest = TRUE; con->testcase = CONVEYANCE_CAPTIVE_SELF_TEST; } else if (captive && con->smartselectiveselftest) { con->smartselectiveselftest = FALSE; con->smartselectivecapselftest = TRUE; con->testcase = SELECTIVE_CAPTIVE_SELF_TEST; } // From here on, normal operations... printslogan(); // Warn if the user has provided no device name if (argc-optind<1){ pout("ERROR: smartctl requires a device name as the final command-line argument.\n\n"); UsageSummary(); EXIT(FAILCMD); } // Warn if the user has provided more than one device name if (argc-optind>1){ int i; pout("ERROR: smartctl takes ONE device name as the final command-line argument.\n"); pout("You have provided %d device names:\n",argc-optind); for (i=0; i<argc-optind; i++) pout("%s\n",argv[optind+i]); UsageSummary(); EXIT(FAILCMD); } }// Printing function (controlled by global con->dont_print) // [From GLIBC Manual: Since the prototype doesn't specify types for// optional arguments, in a call to a variadic function the default// argument promotions are performed on the optional argument// values. This means the objects of type char or short int (whether// signed or not) are promoted to either int or unsigned int, as// appropriate.]void pout(const char *fmt, ...){ va_list ap; // initialize variable argument list va_start(ap,fmt); if (con->dont_print){ va_end(ap); return; } // print out vprintf(fmt,ap); va_end(ap); fflush(stdout); return;}// This function is used by utility.cpp to report LOG_CRIT errors.// The smartctl version prints to stdout instead of syslog().void PrintOut(int priority, const char *fmt, ...) { va_list ap; // avoid warning message about unused variable from gcc -W: just // change value of local copy. priority=0; va_start(ap,fmt); vprintf(fmt,ap); va_end(ap); return;}/* Main Program */int main (int argc, char **argv){ int fd,retval=0; char *device; smartmonctrl control; char *mode=NULL; // define control block for external functions con=&control; // Part input arguments ParseOpts(argc,argv); device = argv[argc-1]; // Device name "-": Parse "smartctl -r ataioctl,2 ..." output if (!strcmp(device,"-")) { if (con->controller_type != CONTROLLER_UNKNOWN) { pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n"); UsageSummary(); return FAILCMD; } con->controller_type = CONTROLLER_PARSEDEV; } // If use has specified 3ware controller, determine which interface if (con->controller_type == CONTROLLER_3WARE) { con->controller_type=guess_device_type(device); if (con->controller_type!=CONTROLLER_3WARE_9000_CHAR && con->controller_type!=CONTROLLER_3WARE_678K_CHAR) con->controller_type = CONTROLLER_3WARE_678K; } if (con->controller_type == CONTROLLER_UNKNOWN) con->controller_type=guess_device_type(device); if (con->controller_type == CONTROLLER_UNKNOWN) { pout("Smartctl: please specify device type with the -d option.\n"); UsageSummary(); return FAILCMD; } // set up mode for open() call. SCSI case is: switch (con->controller_type) { case CONTROLLER_SCSI: case CONTROLLER_SAT: mode="SCSI"; break; case CONTROLLER_3WARE_9000_CHAR: mode="ATA_3WARE_9000"; break; case CONTROLLER_3WARE_678K_CHAR: mode="ATA_3WARE_678K"; break; case CONTROLLER_CCISS: mode="CCISS"; break; default: mode="ATA"; break; } // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the // scsi generic device can be used (needs write permission for MODE // SELECT command) plus O_NONBLOCK to stop open hanging if media not // present (e.g. with st). Opening is retried O_RDONLY if read-only // media prevents opening O_RDWR (it cannot happen for scsi generic // devices, but it can for the others). if (con->controller_type != CONTROLLER_PARSEDEV) fd = deviceopen(device, mode); else fd = parsedev_open(device); if (fd<0) { char errmsg[256]; snprintf(errmsg,256,"Smartctl open device: %s failed",argv[argc-1]); errmsg[255]='\0'; syserror(errmsg); return FAILDEV; } // now call appropriate ATA or SCSI routine switch (con->controller_type) { case CONTROLLER_UNKNOWN: // we should never fall into this branch! pout("Smartctl: please specify device type with the -d option.\n"); UsageSummary(); retval = FAILCMD; break; case CONTROLLER_SCSI: retval = scsiPrintMain(fd); if ((0 == retval) && (CONTROLLER_SAT == con->controller_type)) retval = ataPrintMain(fd); break; case CONTROLLER_CCISS: // route the cciss command through scsiPrintMain. // cciss pass-throughs will separeate from the SCSI data-path. retval = scsiPrintMain(fd); break; default: retval = ataPrintMain(fd); break; } if (con->controller_type != CONTROLLER_PARSEDEV) deviceclose(fd); else parsedev_close(fd); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -