3 Linux-specific Information about the Hardware.
5 (C) Copyright 1998-2001 by Helge Deller <deller@gmx.de>
8 - include Information about XFree86 and/or Accelerated X
9 (needs to change configure-script, to see, if Header-files are available !)
10 - maybe also include information about the video-framebuffer devices
11 - rewrite detection-routines (maybe not to use the /proc-fs)
12 - more & better sound-information
14 /dev/sndstat support added: 1998-12-08 Duncan Haldane (f.d.m.haldane@cwix.com)
22 #include <linux/kernel.h>
24 #include "config-infocenter.h"
26 #ifdef HAVE_FSTAB_H /* some Linux-versions don't have fstab.h */
28 # include <sys/statfs.h>
29 # define INFO_PARTITIONS_FULL_INFO /* show complete info */
30 #elif defined HAVE_MNTENT_H /* but maybe they have mntent.h ? */
33 # define INFO_PARTITIONS_FULL_INFO /* show complete info */
35 # undef INFO_PARTITIONS_FULL_INFO /* no partitions-info */
40 #endif //HAVE_PCIUTILS
43 #include <QHeaderView>
46 #include <kiconloader.h>
47 #include <kglobalsettings.h>
50 #define INFO_CPU "/proc/cpuinfo"
52 #define INFO_IRQ "/proc/interrupts"
53 #define INFO_DMA "/proc/dma"
55 #define INFO_PCI "/proc/pci"
57 #define INFO_IOPORTS "/proc/ioports"
59 #define INFO_DEV_SNDSTAT "/dev/sndstat"
60 #define INFO_SOUND "/proc/sound"
61 #define INFO_ASOUND "/proc/asound/oss/sndstat"
62 #define INFO_ASOUND09 "/proc/asound/sndstat"
64 #define INFO_DEVICES "/proc/devices"
65 #define INFO_MISC "/proc/misc"
67 #define INFO_SCSI "/proc/scsi/scsi"
69 #define INFO_PARTITIONS "/proc/partitions"
70 #define INFO_MOUNTED_PARTITIONS "/etc/mtab" /* on Linux... */
72 #define MAXCOLUMNWIDTH 600
74 bool GetInfo_ReadfromFile(QTreeWidget
* tree
, const char *FileName
, const QChar
& splitChar
) {
82 if (!file
.open(QIODevice::ReadOnly
)) {
85 QTextStream
stream(&file
);
87 QString line
= stream
.readLine();
89 while (!line
.isNull()) {
91 if (!line
.isEmpty()) {
92 if (!splitChar
.isNull()) {
93 int pos
= line
.indexOf(splitChar
);
94 s1
= line
.left(pos
-1).trimmed();
95 s2
= line
.mid(pos
+1).trimmed();
101 new QTreeWidgetItem(tree
, list
);
103 line
= stream
.readLine();
111 bool GetInfo_CPU(QTreeWidget
* tree
) {
113 headers
<< i18n("Information") << i18n("Value");
114 tree
->setHeaderLabels(headers
);
116 return GetInfo_ReadfromFile(tree
, INFO_CPU
, ':');
119 bool GetInfo_IRQ(QTreeWidget
* tree
) {
120 tree
->setFont(KGlobalSettings::fixedFont());
121 tree
->setHeaderHidden(true);
123 return GetInfo_ReadfromFile(tree
, INFO_IRQ
, 0);
126 bool GetInfo_DMA(QTreeWidget
* tree
) {
127 QFile
file(INFO_DMA
);
130 headers
<< i18n("DMA-Channel") << i18n("Used By");
131 tree
->setHeaderLabels(headers
);
133 if (file
.exists() && file
.open(QIODevice::ReadOnly
)) {
134 QTextStream
stream(&file
);
137 line
= stream
.readLine();
138 while (!line
.isNull()) {
139 if (!line
.isEmpty()) {
140 QRegExp
rx("^\\s*(\\S+)\\s*:\\s*(\\S+)");
141 if (-1 != rx
.indexIn(line
)) {
143 list
<< rx
.cap(1) << rx
.cap(2);
144 new QTreeWidgetItem(tree
, list
);
147 line
= stream
.readLine();
157 bool GetInfo_PCI(QTreeWidget
* tree
) {
161 if ( (num
= GetInfo_PCIUtils(tree
))) {
165 #endif //HAVE_PCIUTILS
166 tree
->setHeaderHidden(true);
167 tree
->setSortingEnabled(false);
169 /* try to get the output of the lspci package first */
170 if ((num
= GetInfo_ReadfromPipe(tree
, "lspci -v", true)) || (num
= GetInfo_ReadfromPipe(tree
, "/sbin/lspci -v", true)) || (num
= GetInfo_ReadfromPipe(tree
, "/usr/sbin/lspci -v", true)) || (num
= GetInfo_ReadfromPipe(tree
, "/usr/local/sbin/lspci -v", true)) || (num
= GetInfo_ReadfromPipe(tree
,
171 "/usr/bin/lspci -v", true)))
174 /* if lspci failed, read the contents of /proc/pci */
175 return GetInfo_ReadfromFile(tree
, INFO_PCI
, 0);
179 bool GetInfo_IO_Ports(QTreeWidget
* tree
) {
181 headers
<< i18n("I/O-Range") << i18n("Used By");
182 tree
->setHeaderLabels(headers
);
183 return GetInfo_ReadfromFile(tree
, INFO_IOPORTS
, ':');
186 bool GetInfo_Sound(QTreeWidget
* tree
) {
187 tree
->setSortingEnabled(false);
189 if (GetInfo_ReadfromFile(tree
, INFO_DEV_SNDSTAT
, 0))
191 else if (GetInfo_ReadfromFile(tree
, INFO_SOUND
, 0))
193 else if (GetInfo_ReadfromFile(tree
, INFO_ASOUND
, 0))
196 return GetInfo_ReadfromFile(tree
, INFO_ASOUND09
, 0);
199 bool GetInfo_Devices(QTreeWidget
* tree
) {
200 kDebug() << "Linux Info Devices" << endl
;
202 QTreeWidgetItem
*misc
=NULL
;
204 tree
->setRootIsDecorated(true);
206 headers
<< i18n("Devices") << i18n("Major Number") << i18n("Minor Number");
207 tree
->setHeaderLabels(headers
);
209 file
.setFileName(INFO_DEVICES
);
210 if (file
.exists() && file
.open(QIODevice::ReadOnly
)) {
211 QTextStream
stream(&file
);
212 QTreeWidgetItem
*parent
=0L, *child
=0L;
214 QString line
= stream
.readLine();
216 while (!line
.isNull()) {
217 if (!line
.isEmpty()) {
218 if (-1 != line
.indexOf("character device", 0, Qt::CaseInsensitive
)) {
220 list
<< i18n("Character Devices");
221 parent
= new QTreeWidgetItem(tree
, list
);
222 parent
->setIcon(0, SmallIcon("chardevice"));
223 parent
->setExpanded(true);
225 } else if (-1 != line
.indexOf("block device", 0, Qt::CaseInsensitive
)) {
227 list
<< i18n("Block Devices");
228 parent
= new QTreeWidgetItem(tree
, list
);
229 parent
->setIcon(0, SmallIcon("blockdevice"));
230 parent
->setExpanded(true);
233 QRegExp
rx("^\\s*(\\S+)\\s+(\\S+)");
234 if (-1 != rx
.indexIn(line
)) {
237 list
<< rx
.cap(2) << rx
.cap(1);
238 child
= new QTreeWidgetItem(parent
, list
);
241 list
<< rx
.cap(2) << rx
.cap(1);
242 child
= new QTreeWidgetItem(tree
, list
);
245 if (rx
.cap(2)=="misc") {
251 line
= stream
.readLine();
258 file
.setFileName(INFO_MISC
);
259 if (misc
&& file
.exists() && file
.open(QIODevice::ReadOnly
)) {
260 QTextStream
stream(&file
);
262 misc
->setText(0, i18n("Miscellaneous Devices"));
263 misc
->setIcon(0, SmallIcon("memory"));
264 misc
->setExpanded(true);
266 QString line
= stream
.readLine();
268 while (!line
.isNull()) {
269 if (!line
.isEmpty()) {
270 QRegExp
rx("^\\s*(\\S+)\\s+(\\S+)");
271 if (-1 != rx
.indexIn(line
)) {
273 list
<< rx
.cap(2) << "10" << rx
.cap(1);
274 new QTreeWidgetItem(misc
, list
);
277 line
= stream
.readLine();
285 bool GetInfo_SCSI(QTreeWidget
* tree
) {
286 return GetInfo_ReadfromFile(tree
, INFO_SCSI
, 0);
289 static void cleanPassword(QString
& str
) {
291 QString
passwd("password=");
294 index
= str
.indexOf(passwd
, index
, Qt::CaseInsensitive
);
296 index
+= passwd
.length();
297 while (index
< (int) str
.length() && str
[index
] != ' ' && str
[index
] != ',')
303 #ifndef INFO_PARTITIONS_FULL_INFO
305 bool GetInfo_Partitions(QTreeWidget
* tree
)
307 return GetInfo_ReadfromFile(tree
, INFO_PARTITIONS
, 0);
310 #else /* INFO_PARTITIONS_FULL_INFO */
312 // Some Ideas taken from garbazo from his source in info_fbsd.cpp
315 #if ( defined(HAVE_LINUX_RAW_H) || defined(HAVE_SYS_RAW_H) ) && defined(HAVE_SYS_IOCTL_H) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
316 #include <sys/ioctl.h>
319 #if defined(HAVE_SYS_RAW_H)
321 #elif defined(HAVE_LINUX_RAW_H)
322 #include <linux/raw.h>
326 * get raw device bindings and information
328 void Get_LinuxRawDevices(QTreeWidget
* tree
)
331 int new_raw_devs
= 1;
332 struct raw_config_request rq
;
334 QString
MB(i18n("MB")); /* "MB" = "Mega-Byte" */
336 /* try to open the raw device control file */
337 f
= open("/dev/rawctl", O_RDWR
);
339 f
= open("/dev/raw", O_RDWR
);
345 for (i
=1; i
<256; i
++) {
347 if (ioctl(f
, RAW_GETBIND
, &rq
))
349 if (!rq
.block_major
) /* unbound ? */
351 unsigned int minor
= rq
.block_minor
;
353 switch ((int)rq
.block_major
) {
356 case 3: first_letter
= 'a';
358 devname
= QString("/dev/hd%1%2")
359 .arg(QChar(first_letter
+ minor
/64))
362 case 22:first_letter
= 'c'; goto set_ide_name
;
363 case 33:first_letter
= 'e'; goto set_ide_name
;
364 case 34:first_letter
= 'g'; goto set_ide_name
;
365 case 56:first_letter
= 'i'; goto set_ide_name
;
366 case 57:first_letter
= 'k'; goto set_ide_name
;
367 case 88:first_letter
= 'm'; goto set_ide_name
;
368 case 89:first_letter
= 'o'; goto set_ide_name
;
369 case 90:first_letter
= 'q'; goto set_ide_name
;
370 case 91:first_letter
= 's'; goto set_ide_name
;
373 case 8: first_letter
= 'a';
375 devname
= QString("/dev/sd%1%2")
376 .arg(QChar(first_letter
+ minor
/16))
379 case 65:first_letter
= 'q'; goto set_scsi_name
;
381 /* Compaq /dev/cciss devices */
382 case 104: case 105: case 106:
383 case 107: case 108: case 109:
384 devname
= QString("/dev/cciss/c%1d%2")
385 .arg((int)rq
.block_major
-104)
389 /* Compaq Intelligent Drive Array (ida) */
390 case 72: case 73: case 74: case 75:
391 case 76: case 77: case 78: case 79:
392 devname
= QString("/dev/ida/c%1d%2")
393 .arg((int)rq
.block_major
-72)
397 default: devname
= QString("%1/%2")
398 .arg((int)rq
.block_major
)
403 /* TODO: get device size */
409 list
<< QString("/dev/raw/raw%1").arg(i
);
411 list
<< QString("/dev/raw%1").arg(i
);
413 list
<< "raw" << size
<< " " << "";
414 new QTreeWidgetItem(tree
, list
);
419 #define Get_LinuxRawDevices(x) /* nothing */
422 bool GetInfo_Partitions(QTreeWidget
* tree
) {
423 QStringList Mounted_Partitions
;
428 struct fstab
*fstab_ent
;
429 # define FS_NAME fstab_ent->fs_spec // device-name
430 # define FS_FILE fstab_ent->fs_file // mount-point
431 # define FS_TYPE fstab_ent->fs_vfstype // fs-type
432 # define FS_MNTOPS fstab_ent->fs_mntops // mount-options
434 struct mntent
*mnt_ent
;
436 # define FS_NAME mnt_ent->mnt_fsname // device-name
437 # define FS_FILE mnt_ent->mnt_dir // mount-point
438 # define FS_TYPE mnt_ent->mnt_type // fs-type
439 # define FS_MNTOPS mnt_ent->mnt_opts // mount-options
443 quint64 total
, avail
;
444 QString str
, mountopts
;
445 QString
MB(i18n("MB")); /* "MB" = "Mega-Byte" */
448 if (setfsent() == 0) /* Try to open fstab */
451 if (!(fp
= setmntent("/etc/fstab", "r")))
455 /* read the list of already mounted file-systems.. */
456 QFile
*file
= new QFile(INFO_MOUNTED_PARTITIONS
);
457 if (file
->open(QIODevice::ReadOnly
)) {
459 while (file
->readLine(buf
, sizeof(buf
)) > 0) {
460 str
= QString::fromLocal8Bit(buf
);
462 int p
= str
.indexOf(' '); /* find first space. */
464 str
.remove(p
, 1024); /* erase all chars including space. */
465 Mounted_Partitions
.append(str
);
472 /* create the header-tables */
473 MB
= QString(" ") + MB
;
476 headers
<< i18n("Device") << i18n("Mount Point") << i18n("FS Type") << i18n("Total Size") << i18n("Free Size") << i18n("Mount Options");
477 tree
->setHeaderLabels(headers
);
479 for (n
= 0; n
< 6; ++n
)
481 /* loop through all partitions... */
483 while ((fstab_ent
= getfsent()) != NULL
)
485 while ((mnt_ent
= getmntent(fp
)) != NULL
)
488 total
= avail
= 0; /* initialize size.. */
489 found_in_List
= (Mounted_Partitions
.contains(FS_NAME
) > 0);
490 if (found_in_List
&& statfs(FS_FILE
, &sfs
) == 0) {
491 total
= ((quint64
) sfs
.f_blocks
) * sfs
.f_bsize
;
492 avail
= (getuid() ? sfs
.f_bavail
: sfs
.f_bfree
) * ((quint64
) sfs
.f_bsize
);
495 if (stat(fstab_ent->fs_file,&st)!=0)
497 if (!S_ISDIR(st.st_mode))
500 mountopts
= FS_MNTOPS
;
501 cleanPassword(mountopts
);
504 list
<< QString(FS_NAME
) + " " << QString(FS_FILE
) + " " << QString(FS_TYPE
) + " " << Value((int) (((total
/ 1024) + 512) / 1024), 6) + MB
<< Value((int) (((avail
/ 1024) + 512) / 1024), 6) + MB
<< mountopts
;
506 new QTreeWidgetItem(tree
, list
);
509 list
<< QString(FS_NAME
) + " " << QString(FS_FILE
) + " " << QString(FS_TYPE
) + " " << " " << " " << mountopts
;
511 new QTreeWidgetItem(tree
, list
);
517 endfsent(); /* close fstab.. */
519 endmntent(fp
); /* close fstab.. */
522 /* get raw device entires if available... */
523 Get_LinuxRawDevices(tree
);
525 tree
->sortItems(1, Qt::AscendingOrder
);
529 #endif /* INFO_PARTITIONS_FULL_INFO */
531 bool GetInfo_XServer_and_Video(QTreeWidget
* tree
) {
532 return GetInfo_XServer_Generic(tree
);