Logo Search packages:      
Sourcecode: kdebase-kde4 version File versions  Download package

info_solaris.cpp

/*
 *  info_solaris.cpp
 *
 *  Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
 */

#include "config-infocenter.h"

#include <stdio.h>
#include <stdlib.h>
#include <sys/mnttab.h>
#include <kstat.h>
#include <sys/types.h>
#include <sys/statvfs.h>
#include <time.h>

#ifdef HAVE_LIBDEVINFO_H
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/mkdev.h>
#include <sys/stat.h>
#include <devid.h>
#include <libdevinfo.h>
#endif /* HAVE_LIBDEVINFO_H */

#define INFO_CPU_AVAILABLE
#define INFO_IRQ_AVAILABLE
#define INFO_DMA_AVAILABLE
#define INFO_PCI_AVAILABLE
#define INFO_IOPORTS_AVAILABLE
#define INFO_SOUND_AVAILABLE
#define INFO_DEVICES_AVAILABLE
#define INFO_SCSI_AVAILABLE
#define INFO_PARTITIONS_AVAILABLE
#define INFO_XSERVER_AVAILABLE


bool GetInfo_CPU( Q3ListView *lBox ) {

      kstat_ctl_t *kctl;
      kstat_t           *ksp;
      kstat_named_t     *kdata;
      char        cputype[16],
                  fputype[16];
      char        *timetxt;
      char        *ptr;
      uint32_t    i, ncpus;
      unsigned long     state_begin;
      QString           state;
      QString           mhz;
      QString           inst;

      /*
       *  get a kstat handle first and update the user's kstat chain
       */
      if( (kctl = kstat_open()) == NULL ) {
            return false;
      }
      while( kstat_chain_update( kctl ) != 0 )
            ;

      /*
       *  get the # of CPUs
       */
      if( (ksp = kstat_lookup( kctl, "unix", 0, "system_misc" )) == NULL ) {
            return false;
      }
      if( kstat_read( kctl, ksp, NULL ) == -1 ) {
            return false;
      }
      kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ncpus" );
      if( kdata != NULL ) {
            ncpus = kdata->value.ui32;
      } else {
            ncpus = 0;
      }

      lBox->addColumn( i18n( "Instance" ));
      lBox->addColumn( i18n( "CPU Type" ));
      lBox->addColumn( i18n( "FPU Type" ));
      lBox->addColumn( i18n( "MHz" ));
      lBox->addColumn( i18n( "State" ));

      /*
       *  get the per-processor info
       */
      for( i = 0; i < ncpus; i++ ) {

            if( (ksp = kstat_lookup( kctl, "cpu_info", i, NULL )) == NULL ){
                  return false;
            }

            if( kstat_read( kctl, ksp, NULL ) == -1 ) {
                  return false;
            }

            inst.setNum( i );
            kdata = (kstat_named_t *) kstat_data_lookup( ksp, "cpu_type" );
            if( kdata != NULL ) {
                  strcpy( cputype, kdata->value.c );
            } else {
                  sprintf( cputype, "???" );
            }
            kdata = (kstat_named_t *) kstat_data_lookup( ksp, "fpu_type" );
            if( kdata != NULL ) {
                  strcpy( fputype, kdata->value.c );
            } else {
                  sprintf( fputype, "???" );
            }
            kdata = (kstat_named_t *) kstat_data_lookup( ksp, "clock_MHz" );
            if( kdata != NULL ) {
                  mhz.setNum( kdata->value.ul );
            } else {
                  mhz.setNum( 0 );
            }
            kdata = (kstat_named_t *) kstat_data_lookup( ksp, "state" );
            if( kdata != NULL ) {
                  state = QString( kdata->value.c );
            } else {
                  state = "???";
            }
            kdata = (kstat_named_t *) kstat_data_lookup( ksp, "state_begin" );
            if( kdata != NULL ) {
                  state_begin = kdata->value.i32;
                  if( (timetxt = ctime( (time_t *) &state_begin )) != NULL ) {
                        ptr = strrchr( timetxt, '\n' );
                        *ptr = '\0';
                        state += " since " + QString( timetxt );
                  }
            }

            new Q3ListViewItem( lBox, inst, cputype, fputype, mhz, state );
      }

      // sorting_allowed = true;
      lBox->setSorting( 0 );

      return true;
}

bool GetInfo_IRQ( Q3ListView * ) {
      return false;
}

bool GetInfo_DMA( Q3ListView * ) {
      return false;
}

bool GetInfo_PCI( Q3ListView * ) {
      return false;
}

bool GetInfo_IO_Ports( Q3ListView * ) {
      return false;
}

bool GetInfo_Sound( Q3ListView * ) {
      return false;
}

bool GetInfo_SCSI( Q3ListView * ) {
      return false;
}

bool GetInfo_Partitions( Q3ListView *lBox ) {

      FILE        *mnttab;
      struct mnttab     mnt;
      struct statvfs    statbuf;
      fsblkcnt_t  tmp;
      QString           total;
      QString           avail;
      time_t            mnttime;
      char        *timetxt;
      char        *ptr;

      if( (mnttab = fopen( MNTTAB, "r" )) == NULL ) {
            return false;
      }

      /*
       *  set up column headers
       */
      lBox->addColumn( i18n( "Device" ));
      lBox->addColumn( i18n( "Mount Point" ));
      lBox->addColumn( i18n( "FS Type" ));
      lBox->addColumn( i18n( "Total Size" ));
      // XXX: FIXME: how do I set column alignment correctly?
      lBox->setColumnAlignment( 3, 2 );
      lBox->addColumn( i18n( "Free Size" ));
      // XXX: FIXME: how do I set column alignment correctly?
      lBox->setColumnAlignment( 4, 2 );
      lBox->addColumn( i18n( "Mount Time" ));
      lBox->addColumn( i18n( "Mount Options" ));

      /*
       *  get info about mounted file systems
       */
      rewind( mnttab );
      while( getmntent( mnttab, &mnt ) == 0 ) {
            /*
             *  skip fstype "nfs" and "autofs" for two reasons:
             *    o if the mountpoint is visible, the fs is not
             *      necessarily available (autofs option "-nobrowse")
             *      and we don't want to mount every remote fs just
             *      to get its size, do we?
             *    o the name "Partitions" for this statistics implies
             *      "local file systems only"
             */
            if( (strcmp( mnt.mnt_fstype, "nfs" ) == 0)
                        || (strcmp( mnt.mnt_fstype, "autofs" ) == 0) )
                  continue;
            if( statvfs( mnt.mnt_mountp, &statbuf ) == 0 ) {
                  if( statbuf.f_blocks > 0 ) {
                        /*
                         *  produce output in KB, MB, or GB for
                         *  readability -- unfortunately, this
                         *  breaks sorting for these columns...
                         */
                        tmp = statbuf.f_blocks
                              * (statbuf.f_frsize / 1024);
                        if( tmp > 9999 ) {
                              tmp /= 1024;
                              if( tmp > 9999 ) {
                                    tmp /= 1024;
                                    total.setNum( tmp );
                                    total += " G";
                              } else {
                                    total.setNum( tmp );
                                    total += " M";
                              }
                        } else {
                              total.setNum( tmp );
                              total += " K";
                        }
//                      avail.setNum( statbuf.f_bavail );
//                      avail += " K";
                        tmp = statbuf.f_bavail
                              * (statbuf.f_frsize / 1024);
                        if( tmp > 9999 ) {
                              tmp /= 1024;
                              if( tmp > 9999 ) {
                                    tmp /= 1024;
                                    avail.setNum( tmp );
                                    avail += " G";
                              } else {
                                    avail.setNum( tmp );
                                    avail += " M";
                              }
                        } else {
                              avail.setNum( tmp );
                              avail += " K";
                        }
                  } else {
                        total = "-";
                        avail = "-";
                  }
            } else {
                  total = "???";
                  avail = "???";
            }
            /*
             *  ctime() adds a '\n' which we have to remove
             *  so that we get a one-line output for the Q3ListViewItem
             */
            mnttime = (time_t) atol( mnt.mnt_time );
            if( (timetxt = ctime( &mnttime )) != NULL ) {
                  ptr = strrchr( timetxt, '\n' );
                  *ptr = '\0';
            }

            new Q3ListViewItem(
                  lBox,
                  mnt.mnt_special,
                  mnt.mnt_mountp,
                  mnt.mnt_fstype,
                  total,
                  avail,
                  QString( timetxt ),
                  mnt.mnt_mntopts
            );
      }
      fclose( mnttab );

      lBox->setSorting( 0 );
      // sorting_allowed = true;

      return true;
}

bool GetInfo_XServer_and_Video( Q3ListView *lBox ) {
      return GetInfo_XServer_Generic( lBox );
}

#ifdef HAVE_LIBDEVINFO_H
/*
 *  get Solaris' device configuration data through libdevinfo(3)
 *  and display it in a prtconf(1M) style tree
 *
 *  NOTE: though the devinfo library seems to be present on earlier
 *        Solaris releases, this interface is documented to be available
 *        since Solaris 7 (libdevinfo.h is missing on pre-Solaris 7 systems)
 *
 *  documentation for libdevinfo(3) including code samples on which
 *  this implementation is based on is available at
 *    http://soldc.sun.com/developer/support/driver/wps/libdevinfo/
 */

/*
 *  we start with various helper routines for GetInfo_Devices()
 */

/*
 *  mktree() -- break up the device path and place its components
 *          into the tree widget
 */
Q3ListViewItem *mktree( Q3ListViewItem *top, const char *path ) {

      Q3ListViewItem    *parent,
                  *previous,
                  *result;
      char        *str = strdup( path ),
                  *token;

      /*
       *  start at "/"
       */
      parent = top;
      result = (*top).firstChild();
      previous = (*top).firstChild();

      token = strtok( str, "/" );
      while( token != NULL ) {
            /*
             *  find insert pos:
             *  try to match the node at the current level
             *
             *  NOTE: this implementation assumes that there are
             *        no two nodes with identical names at the
             *        same level of the device tree
             */
            while( result != NULL ) {
                  if( strcmp( token, (*result).text( 0 ).toLatin1()) == 0 )
                        break;
                  previous = result;
                  result = (*result).nextSibling();
            }
            if( result == NULL ) {
                  /*
                   *  we haven't found the node, create a new one
                   */
                  result = new Q3ListViewItem( parent,
                              previous,
                              token );
            } else {
                  /*
                   *  we've found the node
                   */
                  parent = result;
                  previous = NULL;
                  if( (*result).firstChild() == NULL ) {
                        /*
                         *  create new node during next iteration
                         */
                        result->setExpandable( true );
                        result->setOpen( false );
                  } else {
                        /*
                         *  follow the child path
                         */
                        result = (*result).firstChild();
                  }
            }
            token = strtok( NULL, "/" );
      }
      free( str );

      return( result );
}

/*
 *  prop_type_str()  -- return the property type as a string
 */
char *prop_type_str( di_prop_t prop ) {

      switch( di_prop_type( prop )) {
            case DI_PROP_TYPE_UNDEF_IT:
                  return( "undefined" );
            case DI_PROP_TYPE_BOOLEAN:
                  return( "BOOL" );
            case DI_PROP_TYPE_INT:
                  return( "INT" );
            case DI_PROP_TYPE_STRING:
                  return( "STRING" );
            case DI_PROP_TYPE_BYTE:
                  return( "BYTE" );
            default:
                  return( "unknown" );
      }
}

/*
 *  prop_type_guess() -- guess the property type
 */
int prop_type_guess( uchar_t *data, int len ) {

      int   slen;
      int   guess;
      int   i, c;

      if( len < 0 )
            return( -1 );
      else if( len == 0 )
            return( DI_PROP_TYPE_BOOLEAN );

      slen = 0;
      guess = DI_PROP_TYPE_STRING;

      for( i = 0; i < len; i++ ) {
            c = (int) data[i];
            switch( c ) {
                  case 0:
                        if( i == (len - 1 ))
                              break;
                        if( slen == 0 )
                              guess = DI_PROP_TYPE_BYTE;
                        else
                              guess = slen = 0;
                        break;
                  default:
                        if( ! isprint( c ))
                              guess = DI_PROP_TYPE_BYTE;
                        else
                              slen++;
            }
            if( guess != DI_PROP_TYPE_STRING )
                  break;
      }

//    if( (guess == DI_PROP_TYPE_BYTE) && (len % sizeof( int ) == 0 ))
//          guess = DI_PROP_TYPE_INT;

      return( guess );
}

/*
 *  dump_minor_node()  --  examine a device minor node
 *                   this routine gets passed to di_walk_node()
 */
int dump_minor_node( di_node_t node, di_minor_t minor, void *arg ) {

      Q3ListViewItem    *item;
      QString           majmin;
      char        *type;
      dev_t       dev;

      item = new Q3ListViewItem( (Q3ListViewItem *) arg,
                  di_minor_name( minor ));
      item->setExpandable( true );
      item->setOpen( false );
      new Q3ListViewItem( item, i18n( "Spectype:" ),
            (di_minor_spectype( minor ) == S_IFCHR)
                  ? i18n( "character special" )
                  : i18n( "block special" ));
      type = di_minor_nodetype( minor );
      new Q3ListViewItem( item, i18n( "Nodetype:" ),
            (type == NULL) ? "NULL" : type );

      if( (dev = di_minor_devt( minor )) != DDI_DEV_T_NONE ) {
            majmin.sprintf( "%ld/%ld", major( dev ), minor( dev ));
            new Q3ListViewItem( item, i18n( "Major/Minor:" ), majmin );
      }

      if( di_minor_next( node, minor ) == DI_MINOR_NIL )
            return( DI_WALK_TERMINATE );
      else
            return( DI_WALK_CONTINUE );
}

/*
 *  propvalue() -- return the property value
 */
QString propvalue( di_prop_t prop ) {

      int   type;
      int   i, n;
      char  *strp;
      int   *intp;
      uchar_t     *bytep;
      QString     result;

      /*
       *  Since a lot of printable strings seem to be tagged as 'byte',
       *  we're going to guess, if the property is not STRING or INT
       *  The actual type is shown in the info tree, though.
       */
      type = di_prop_type( prop );
      if( (type != DI_PROP_TYPE_STRING) && (type != DI_PROP_TYPE_INT) ) {
            n = di_prop_bytes( prop, &bytep );
            type = prop_type_guess( bytep, n );
      }

      result = "";
      switch( type ) {
            case DI_PROP_TYPE_STRING:
                  if( (n = di_prop_strings( prop, &strp )) < 0 ) {
                        result = "(error)";
                  } else {
                        for( i = 0; i < n; i++ ) {
                              result += "\"";
                              result += strp;
                              result += "\" ";
                              strp += strlen( strp ) + 1;
                        }
                  }
                  break;
            case DI_PROP_TYPE_INT:
                  if( (n = di_prop_ints( prop, &intp )) < 0 ) {
                        result = "(error)";
                  } else {
                        for( i = 0; i < n; i++ ) {
                              QString tmp;
                              tmp.setNum( intp[i] );
                              result += tmp;
                              result += ' ';
                        }
                  }
                  break;
            case DI_PROP_TYPE_BOOLEAN:
                  /*
                   *  hmm, Sun's sample code handles the existence
                   *  of a boolean property as "true", whereas
                   *  prtconf(1M) obviously does not (Sol8, at least)
                   *  -- we're doing the same and handle "bool" as "byte"
                   */
            case DI_PROP_TYPE_BYTE:
                  if( (n = di_prop_bytes( prop, &bytep )) < 0 ) {
                        result = "(error)";
                  } else {
                        if( n == 0 ) {
                              result = i18n( "(no value)" );
                              break;
                        }
                        result = "0x";
                        for( i = 0; i < n; i++ ) {
                              QString tmp;
                              unsigned byte = (unsigned) bytep[i];
                              tmp.sprintf( "%2.2x", byte );
                              result += tmp;
                        }
                  }
                  break;
            default:
                  result = "???";
      }

      return( result );
}

/*
 *  dump_node() -- examine a device node and its children
 *             this routine gets passed to di_walk_node()
 */
int dump_node( di_node_t node, void *arg ) {

      Q3ListViewItem    *top = (Q3ListViewItem *) arg,
                  *parent,
                  *previous;
      char        *path;
      char        *drivername;
      char        *names;
      QString           compatnames;
      int         i, n;
      di_prop_t   prop;

      path = di_devfs_path( node );

      /*
       *  if this is the root node ("/"), initialize the tree
       */
      if( strlen( path ) == 1 ) {
            top->setText( 0, QString( di_binding_name( node )));
            top->setPixmap( 0, SmallIcon( "kcmdevices" ));
            top->setOpen( true );
            top->setSelectable( false );
            top->setExpandable( false );
      }

      /*
       *  place the node in the tree
       */
      parent = mktree( top, path );

      /*
       *  we have to handle the root node differently...
       */
      if( strlen( path ) > 1 ) {
            parent->setExpandable( true );
            parent->setOpen( false );
      } else {
            previous = parent;
            parent = top;
      }

      /*
       *  node name and physical device path
       */
      drivername = di_driver_name( node );
      previous = new Q3ListViewItem( parent,
            i18n( "Driver Name:" ),
            (drivername == NULL)
                  ? i18n( "(driver not attached)" )
                  : drivername );
      previous = new Q3ListViewItem( parent, previous,
            i18n( "Binding Name:" ), di_binding_name( node ));

      n = di_compatible_names( node, &names );
      if( n < 1 ) {
            compatnames = i18n( "(none)" );
      } else {
            for( i = 0; i < n; i++ ) {
                  compatnames += names;
                  compatnames += ' ';
                  names += strlen( names ) + 1;
            }
      }

      previous = new Q3ListViewItem( parent, previous,
            i18n( "Compatible Names:" ), compatnames );

      previous = new Q3ListViewItem( parent, previous,
            i18n( "Physical Path:" ), QString( path ));

      /*
       *  dump the node's property list (if any)
       */
      if( (prop = di_prop_next( node, DI_PROP_NIL )) != DI_PROP_NIL ) {
            previous = new Q3ListViewItem( parent, previous, i18n( "Properties" ));
            previous->setExpandable( true );
            previous->setOpen( false );
            do {
                  /*
                   *  property type & value
                   */
                  Q3ListViewItem    *tmp,
                              *prev;
                  tmp = new Q3ListViewItem( previous, di_prop_name( prop ));
                  tmp->setExpandable( true );
                  tmp->setOpen( false );
                  prev = new Q3ListViewItem( tmp, i18n( "Type:" ),
                        prop_type_str( prop ));
                  new Q3ListViewItem( tmp, prev, i18n( "Value:" ),
                        propvalue( prop ));
            } while( (prop = di_prop_next( node, prop )) != DI_PROP_NIL );
      }

      /*
       *  if there are minor nodes, expand the tree appropriately
       */
      if( di_minor_next( node, DI_MINOR_NIL ) != DI_MINOR_NIL ) {
            previous = new Q3ListViewItem( parent, previous, i18n( "Minor Nodes" ));
            previous->setExpandable( true );
            previous->setOpen( false );
            di_walk_minor( node, NULL, 0, previous, dump_minor_node );
      }

      return( DI_WALK_CONTINUE );
}

bool GetInfo_Devices( Q3ListView *lBox ) {

      Q3ListViewItem          *top;
      di_node_t         root_node;

      /*
       *  create a snapshot of the device tree
       */
      if( (root_node = di_init( "/", DINFOCPYALL )) == DI_NODE_NIL ) {
            return( false );
      }
      // XXX: might try to di_prom_init() here as well (if we're setgid sys)

      /*
       *  prepare the tree widget
       */
      lBox->addColumn( i18n( "Device Information" ));
      lBox->addColumn( i18n( "Value" ));

      top = new Q3ListViewItem( lBox );

      /*
       *  traverse the device tree
       */
      di_walk_node( root_node, DI_WALK_CLDFIRST, top, dump_node );

      di_fini( root_node );

      sorting_allowed = false;
      return true;
}

#else /* ! HAVE_LIBDEVINFO_H */
bool GetInfo_Devices( Q3ListView * ) {
      return false;
}
#endif /* ! HAVE_LIBDEVINFO_H */

Generated by  Doxygen 1.6.0   Back to index