⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_linux.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* *  os_linux.c * * Home page of code is: http://smartmontools.sourceforge.net * * Copyright (C) 2003-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> * Copyright (C) 2003-8 Doug Gilbert <dougg@torque.net> * *  Parts of this file are derived from code that was * *  Written By: Adam Radford <linux@3ware.com> *  Modifications By: Joel Jacobson <linux@3ware.com> *                   Arnaldo Carvalho de Melo <acme@conectiva.com.br> *                    Brad Strand <linux@3ware.com> * *  Copyright (C) 1999-2003 3ware Inc. * *  Kernel compatablity By:     Andre Hedrick <andre@suse.com> *  Non-Copyright (C) 2000      Andre Hedrick <andre@suse.com> * * Other ars of this file are derived from code that was * * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.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. * * 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/ * */// This file contains the linux-specific IOCTL parts of// smartmontools. It includes one interface routine for ATA devices,// one for SCSI devices, and one for ATA devices behind escalade// controllers.#include "config.h"#include <errno.h>#include <fcntl.h>#include <glob.h>#include <scsi/scsi_ioctl.h>#include <scsi/sg.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <unistd.h>#ifndef makedev // old versions of types.h do not include sysmacros.h#include <sys/sysmacros.h>#endif#include "int64.h"#include "atacmds.h"#include "extern.h"extern smartmonctrl * con;#include "os_linux.h"#include "scsicmds.h"#include "utility.h"#include "extern.h"#include "cciss.h"#ifndef ENOTSUP#define ENOTSUP ENOSYS#endiftypedef unsigned long long u8;#define ARGUSED(x) ((void)(x))static const char *filenameandversion="$Id: os_linux.cpp,v 1.100 2008/03/04 22:09:47 ballen4705 Exp $";const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.100 2008/03/04 22:09:47 ballen4705 Exp $" \ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_LINUX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;// to hold onto exit code for atexit routineextern int exitstatus;// global variable holding byte count of allocated memoryextern long long bytes;/* for passing global control variables */extern smartmonctrl *con;/* This function will setup and fix device nodes for a 3ware controller. */#define MAJOR_STRING_LENGTH 3#define DEVICE_STRING_LENGTH 32#define NODE_STRING_LENGTH 16int setup_3ware_nodes(char *nodename, char *driver_name) {  int              tw_major      = 0;  int              index         = 0;  char             majorstring[MAJOR_STRING_LENGTH+1];  char             device_name[DEVICE_STRING_LENGTH+1];  char             nodestring[NODE_STRING_LENGTH];  struct stat      stat_buf;  FILE             *file;  /* First try to open up /proc/devices */  if (!(file = fopen("/proc/devices", "r"))) {    pout("Error opening /proc/devices to check/create 3ware device nodes\n");    syserror("fopen");    return 0;  // don't fail here: user might not have /proc !  }  /* Attempt to get device major number */  while (EOF != fscanf(file, "%3s %32s", majorstring, device_name)) {    majorstring[MAJOR_STRING_LENGTH]='\0';    device_name[DEVICE_STRING_LENGTH]='\0';    if (!strncmp(device_name, nodename, DEVICE_STRING_LENGTH)) {      tw_major = atoi(majorstring);      break;    }  }  fclose(file);  /* See if we found a major device number */  if (!tw_major) {    pout("No major number for /dev/%s listed in /proc/devices. Is the %s driver loaded?\n", nodename, driver_name);    return 2;  }  /* Now check if nodes are correct */  for (index=0; index<16; index++) {    sprintf(nodestring, "/dev/%s%d", nodename, index);    /* Try to stat the node */    if ((stat(nodestring, &stat_buf))) {      /* Create a new node if it doesn't exist */      if (mknod(nodestring, S_IFCHR|0600, makedev(tw_major, index))) {        pout("problem creating 3ware device nodes %s", nodestring);        syserror("mknod");        return 3;      }    }    /* See if nodes major and minor numbers are correct */    if ((tw_major != (int)(major(stat_buf.st_rdev))) ||        (index    != (int)(minor(stat_buf.st_rdev))) ||        (!S_ISCHR(stat_buf.st_mode))) {      /* Delete the old node */      if (unlink(nodestring)) {        pout("problem unlinking stale 3ware device node %s", nodestring);        syserror("unlink");        return 4;      }      /* Make a new node */      if (mknod(nodestring, S_IFCHR|0600, makedev(tw_major, index))) {        pout("problem creating 3ware device nodes %s", nodestring);        syserror("mknod");        return 5;      }    }  }  return 0;}static char prev_scsi_dev[128];// equivalent to open(path, flags)int deviceopen(const char *pathname, char *type){  int fd;  if (0 == strcmp(type,"SCSI")) {    strncpy(prev_scsi_dev, pathname, sizeof(prev_scsi_dev) - 1);    fd = open(pathname, O_RDWR | O_NONBLOCK);    if (fd < 0 && errno == EROFS)      fd = open(pathname, O_RDONLY | O_NONBLOCK);    return fd;  } else if (0 == strcmp(type,"ATA")) {    // smartd re-opens SCSI devices with "type"==ATA for some reason.    // If that was a SCSI generic device (e.g. /dev/sg0) then the    // sg driver wants O_RDWR to allow through ATA PASS-THROUGH commands.    // The purpose of the next code line is to limit the scope of    // this change as a release is pending (and smartd needs a rewrite).    if (0 == strncmp(pathname, prev_scsi_dev, sizeof(prev_scsi_dev)))      return open(pathname, O_RDWR | O_NONBLOCK);    else      return open(pathname, O_RDONLY | O_NONBLOCK);  } else if (0 == strcmp(type,"ATA_3WARE_9000")) {    // the device nodes for this controller are dynamically assigned,    // so we need to check that they exist with the correct major    // numbers and if not, create them    if (setup_3ware_nodes("twa", "3w-9xxx")) {      if (!errno)        errno=ENXIO;      return -1;    }    return open(pathname, O_RDONLY | O_NONBLOCK);  }  else if (0 == strcmp(type,"ATA_3WARE_678K")) {    // the device nodes for this controller are dynamically assigned,    // so we need to check that they exist with the correct major    // numbers and if not, create them    if (setup_3ware_nodes("twe", "3w-xxxx")) {      if (!errno)        errno=ENXIO;      return -1;    }    return open(pathname, O_RDONLY | O_NONBLOCK);  }  else if(0 == strcmp(type, "CCISS")) {    // the device is a cciss smart array device.    return open(pathname, O_RDWR | O_NONBLOCK);  }  else    return -1;}// equivalent to close(file descriptor)int deviceclose(int fd){  return close(fd);}// print examples for smartctlvoid print_smartctl_examples(){  printf("=================================================== SMARTCTL EXAMPLES =====\n\n");#ifdef HAVE_GETOPT_LONG  printf(         "  smartctl --all /dev/hda                    (Prints all SMART information)\n\n"         "  smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n"         "                                              (Enables SMART on first disk)\n\n"         "  smartctl --test=long /dev/hda          (Executes extended disk self-test)\n\n"         "  smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n"         "                                      (Prints Self-Test & Attribute errors)\n"         "  smartctl --all --device=3ware,2 /dev/sda\n"         "  smartctl --all --device=3ware,2 /dev/twe0\n"         "  smartctl --all --device=3ware,2 /dev/twa0\n"         "          (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"         "  smartctl --all --device=hpt,1/1/3 /dev/sda\n"         "          (Prints all SMART info for the SATA disk attached to the 3rd PMPort\n"         "           of the 1st channel on the 1st HighPoint RAID controller)\n"         );#else  printf(         "  smartctl -a /dev/hda                       (Prints all SMART information)\n"         "  smartctl -s on -o on -S on /dev/hda         (Enables SMART on first disk)\n"         "  smartctl -t long /dev/hda              (Executes extended disk self-test)\n"         "  smartctl -A -l selftest -q errorsonly /dev/hda\n"         "                                      (Prints Self-Test & Attribute errors)\n"         "  smartctl -a -d 3ware,2 /dev/sda\n"         "  smartctl -a -d 3ware,2 /dev/twa0\n"         "  smartctl -a -d 3ware,2 /dev/twe0\n"         "          (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"         "  smartctl -a -d hpt,1/1/3 /dev/sda\n"         "          (Prints all SMART info for the SATA disk attached to the 3rd PMPort\n"         "           of the 1st channel on the 1st HighPoint RAID controller)\n"         );#endif  return;}// we are going to take advantage of the fact that Linux's devfs will only// have device entries for devices that exist.  So if we get the equivalent of// ls /dev/hd[a-t], we have all the ATA devices on the system//// If any errors occur, leave errno set as it was returned by the// system call, and return <0.int get_dev_names(char*** names, const char* pattern, const char* name, int max) {  int n = 0, retglob, i, lim;  char** mp;  glob_t globbuf;  memset(&globbuf, 0, sizeof(globbuf));  // in case of non-clean exit  *names=NULL;  // Use glob to look for any directory entries matching the pattern  if ((retglob=glob(pattern, GLOB_ERR, NULL, &globbuf))) {    //  glob failed: free memory and return    globfree(&globbuf);    if (retglob==GLOB_NOMATCH){      pout("glob(3) found no matches for pattern %s\n", pattern);      return 0;    }    if (retglob==GLOB_NOSPACE)      pout("glob(3) ran out of memory matching pattern %s\n", pattern);#ifdef GLOB_ABORTED // missing in old versions of glob.h    else if (retglob==GLOB_ABORTED)      pout("glob(3) aborted matching pattern %s\n", pattern);#endif    else      pout("Unexplained error in glob(3) of pattern %s\n", pattern);    return -1;  }  // did we find too many paths?  lim = ((int)globbuf.gl_pathc < max) ? (int)globbuf.gl_pathc : max;  if (lim < (int)globbuf.gl_pathc)    pout("glob(3) found %d > MAX=%d devices matching pattern %s: ignoring %d paths\n",         (int)globbuf.gl_pathc, max, pattern, (int)(globbuf.gl_pathc-max));  // allocate space for up to lim number of ATA devices  if (!(mp =  (char **)calloc(lim, sizeof(char*)))){    pout("Out of memory constructing scan device list\n");    return -1;  }  // now step through the list returned by glob.  If not a link, copy  // to list.  If it is a link, evaluate it and see if the path ends  // in "disc".  for (i=0; i<lim; i++){    int retlink;    // prepare a buffer for storing the link    char linkbuf[1024];    // see if path is a link    retlink=readlink(globbuf.gl_pathv[i], linkbuf, 1023);    // if not a link (or a strange link), keep it    if (retlink<=0 || retlink>1023)      mp[n++] = CustomStrDup(globbuf.gl_pathv[i], 1, __LINE__, filenameandversion);    else {      // or if it's a link that points to a disc, follow it      char *p;      linkbuf[retlink]='\0';      if ((p=strrchr(linkbuf,'/')) && !strcmp(p+1, "disc"))        // This is the branch of the code that gets followed if we are        // using devfs WITH traditional compatibility links. In this        // case, we add the traditional device name to the list that        // is returned.        mp[n++] = CustomStrDup(globbuf.gl_pathv[i], 1, __LINE__, filenameandversion);      else {        // This is the branch of the code that gets followed if we are        // using devfs WITHOUT traditional compatibility links.  In        // this case, we check that the link to the directory is of        // the correct type, and then append "disc" to it.        char tmpname[1024]={0};        const char * type = (strcmp(name,"ATA") ? "scsi" : "ide");        if (strstr(linkbuf, type)){          snprintf(tmpname, 1024, "%s/disc", globbuf.gl_pathv[i]);          mp[n++] = CustomStrDup(tmpname, 1, __LINE__, filenameandversion);        }      }    }  }  // free memory, track memory usage  globfree(&globbuf);  mp = static_cast<char **>(realloc(mp,n*(sizeof(char*))));  bytes += n*(sizeof(char*));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -