📄 ident.cpp
字号:
#include "config.h"#include "afflib.h" #include "afflib_i.h" // grab the internal versions#include "aimage.h"#include "imager.h"#ifdef HAVE_SYS_VFS_H#include <sys/vfs.h>#endif#include "ident.h"void ident::init(){ filename = 0; opened = 0; memset(&scsi,0,sizeof(scsi)); memset(&ata,0,sizeof(ata)); memset(¶ms,0,sizeof(params));}ident::ident(int fd_){ init(); fd = fd_;}ident::ident(const char *fn){ init(); filename = strdup(fn);}ident::~ident(){ if(opened) close(fd); if(filename) free(filename); if(params.manufacturer) free(params.manufacturer); if(params.model) free(params.model); if(params.sn) free(params.sn); if(params.firmware) free(params.firmware); if(params.human) free(params.human);}/* is_scsi: * If we were given a filename, check to see if this is a scsi device and, * if it is, set all of the various values. */char *ident::append(char *base,char *add){ if(base==0){ base = (char *)malloc(1); base[0] = 0; return base; } base = (char *)realloc(base,strlen(base)+strlen(add)+4); strcat(base,add); return base;}#ifdef linux#include "ident.h"#include <stdio.h>#include <regex.h>#include <sys/param.h>#include <sys/mount.h>/* getvalue * Looks for a name in a line in a buf and, if found, * make a copy of the text and return a pointer to it. */char *getvalue(char *name,char *buf){ while(buf[0] && isspace(buf[0])) buf++; // advance buf to end of spaces char *pos = strstr(buf,name); if(pos==0) return 0; /* The string was found */ char *cc = pos + strlen(name); // skip past to the end of the string while(*cc && isspace(*cc)) cc++; // scan to end of spaces char *ret = strdup(cc); // got the return string char *dd = index(ret,'\n'); // can we find a \n? if(dd) *dd = '\000'; // yes; clear it return ret;}/* getfile: * Look for the contents of a file and, if found, read the first line and * return it in a newly-allocated buffer. */#include <dirent.h>char *getfileline(const char *dirname,const char *filename){ char path[MAXPATHLEN]; /* Build the pathname we are supposed to get */ strlcpy(path,dirname,sizeof(path)); strlcat(path,filename,sizeof(path)); FILE *f = fopen(path,"r"); if(f){ char *buf = (char *)calloc(1,1024); if(fgets(buf,1023,f)){ char *cc = rindex(buf,'\n'); if(cc) *cc = '\000'; // remove trailing \n } fclose(f); if(buf[0]) return buf; // if we got something, return it free(buf); } return 0;}int ident::get_params(){ /* Is this a regular file? If so, just return */ struct stat so; if(stat(filename,&so)==0){ if(so.st_mode & S_IFMT){ errno = ENODEV; return 1; } } /* Check to see if infile is a USB device. If so, print things about it. * If the Linux /sys file system is installed, then /sys/bus/scsi/devices/.../block * are symlinks to the actual devices. * These have the same name as the /dev/<name>, minus the partition. */ if(strncmp(filename,"/dev/",5)==0){ char *cc; char sdname[MAXPATHLEN]; memset(sdname,0,sizeof(sdname)); strlcpy(sdname,filename+5,sizeof(sdname)); /* If a partition name was provided, eliminate it */ for(cc=sdname;*cc;cc++){ if(isdigit(*cc)){ *cc = '\000'; break; } } /* Look to see if this is a USB device*/ DIR *dir = opendir("/sys/bus/scsi/devices/"); struct dirent *dp; while((dp = readdir(dir))!=0){ if(dp->d_name[0]=='.') continue; // skip the dot names char dirname[MAXPATHLEN]; strlcpy(dirname,"/sys/bus/scsi/devices/",sizeof(dirname)); strlcat(dirname,dp->d_name,sizeof(dirname)); char devname[MAXPATHLEN]; strlcpy(devname,dirname,sizeof(devname)); strlcat(devname,"/",sizeof(devname)); strlcat(devname,"/block",sizeof(devname)); /* If this is a link, then stat it */ char path[MAXPATHLEN]; memset(path,0,sizeof(path)); if(readlink(devname,path,sizeof(path))>0){ cc = rindex(path,'/'); // find the end of the link if(cc && strcmp(cc+1,sdname)==0){ /* Found it! * Now, it turns out that dirname is also a symbolic link. * Use it to find the directory where the USB information is stored. */ char usbdir[MAXPATHLEN]; strlcpy(usbdir,dirname,sizeof(usbdir)); strlcat(usbdir,"/../../../../",sizeof(usbdir)); params.manufacturer = getfileline(usbdir,"manufacturer"); params.model = getfileline(usbdir,"product"); params.sn = getfileline(usbdir,"serial"); params.firmware = getfileline(usbdir,"version"); return 0; // we have successfully identified the device } } } /* Fall back to a regular hard drive */ if(access(filename,R_OK)==0){ char capbuf[65536]; char buf[256]; if(af_hasmeta(filename)) return -1; snprintf(buf,sizeof(buf),"hdparm -I %s",filename); capbuf[0] = 0; FILE *f = popen(buf,"r"); while(!feof(f)){ if(fgets(buf,sizeof(buf),f)){ buf[sizeof(buf)-1] = 0; // make sure it is null-terminated strlcat(capbuf,buf,sizeof(capbuf)); // append to the buffer /* Now check for each of the lines */ params.model = getvalue("Model Number:",buf); params.sn = getvalue("Serial Number:",buf); params.firmware = getvalue("Firmware Revision:",buf); char *b; if( (b = getvalue("cylinders",buf)) != 0){ params.cylinders = atoi(b); free(b); } if( (b = getvalue("heads",buf)) != 0){ params.heads = atoi(b); free(b); } if( (b = getvalue("sectors/track",buf)) != 0){ params.sectors_per_track = atoi(b); free(b); } } } pclose(f); params.human = strdup(capbuf); return 0; } } errno = ENODEV; return -1; // can't figure it out}#endif#ifdef __FreeBSD__#include "ident.h"#include <stdio.h>#include <regex.h>#include <sys/param.h>#include <sys/mount.h>int ident::get_params(){ return -1;}#endif#ifdef __APPLE__#include "ident.h"#include <stdio.h>#include <regex.h>#include <sys/param.h>#include <sys/mount.h>int ident::get_params(){ return -1;}#endif#ifdef UNIX#include "ident.h"#include <stdio.h>#include <regex.h>#ifndef IDENT_IS_SCSIbool ident::is_scsi(){ return false;}#endif#ifndef IDENT_IS_ATAbool ident::is_ata(){ return false;}#endifchar *pat="([0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:""[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f])";int in_path(const char *cmd){ char *path = strdup(getenv("PATH")); char *pathi = path; char *check; char *last = 0; while((check = strtok_r(pathi,":",&last))!=0){ char buf[MAXPATHLEN+1]; strlcpy(buf,check,sizeof(buf)); strlcat(buf,"/",sizeof(buf)); strlcat(buf,cmd,sizeof(buf)); if(access(buf,R_OK)==0){ free(path); return 1; } pathi= 0; } free(path); return 0;}char *ident::mac_addresses(){ char *buf = append(0,0); if(!in_path("ifconfig")) return buf; // no ifconfig command FILE *f = popen("ifconfig","r"); if(!f) return buf; regex_t r; if(regcomp(&r,pat,REG_EXTENDED|REG_ICASE)) err(1,"regcomp"); while(!feof(f)){ char line[1024]; regmatch_t pm[2]; memset(pm,0,sizeof(pm)); if(fgets(line,sizeof(line),f)){ if(regexec(&r,line,2,pm,0)==0){ char mac[64]; memset(mac,0,sizeof(mac)); strncpy(mac,line+pm[1].rm_so,pm[1].rm_eo-pm[1].rm_so); buf = append(buf,mac); buf = append(buf,"\n"); } } } pclose(f); return buf;}/* Return the results of dmesg */char *ident::dmesg(){ char *buf = append(0,0); FILE *f = popen("dmesg 2>/dev/null","r"); if(!f) return buf; while(!feof(f)){ char line[1024]; if(fgets(line,sizeof(line),f)){ buf = append(buf,line); } } pclose(f); return buf;}#endif#ifdef HAVE_FSTATFS/* ident-specific things for FreeBSD */long long ident::freebytes(){ if(!opened){ fd = open(filename,O_RDONLY,0666); // need file opened for this if(fd>0){ opened = true; } } if(opened){ struct statfs sbuf; if(fstatfs(fd,&sbuf)==0){ return (long long)sbuf.f_bavail * (long long)sbuf.f_bsize; } } return -1;}#elselong long ident::freebytes(){ return 0; // eventually, call "df"}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -