Logo Search packages:      
Sourcecode: afflib version File versions  Download package

ident_linux.cpp

#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 */
    strcpy(path,dirname);
    strcat(path,filename);
    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));
      strcpy(sdname,filename+5);
      /* 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];
          strcpy(dirname,"/sys/bus/scsi/devices/");
          strcat(dirname,dp->d_name);

          char devname[MAXPATHLEN];
          strcpy(devname,dirname);
          strcat(devname,"/");
          strcat(devname,"/block");

          /* 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];
                strcpy(usbdir,dirname);
                strcat(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];
          sprintf(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
                strcat(capbuf,buf); // 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
}


#include <sys/vfs.h>
#define HAS_STATFS





Generated by  Doxygen 1.6.0   Back to index