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 #include <kiconloader.h>
42 #define INFO_CPU_AVAILABLE
43 #define INFO_CPU "/proc/cpuinfo"
45 #define INFO_IRQ_AVAILABLE
46 #define INFO_IRQ "/proc/interrupts"
48 #define INFO_DMA_AVAILABLE
49 #define INFO_DMA "/proc/dma"
51 #define INFO_PCI_AVAILABLE
52 #define INFO_PCI "/proc/pci"
54 #define INFO_IOPORTS_AVAILABLE
55 #define INFO_IOPORTS "/proc/ioports"
57 #define INFO_SOUND_AVAILABLE
58 #define INFO_DEV_SNDSTAT "/dev/sndstat"
59 #define INFO_SOUND "/proc/sound"
60 #define INFO_ASOUND "/proc/asound/oss/sndstat"
61 #define INFO_ASOUND09 "/proc/asound/sndstat"
63 #define INFO_DEVICES_AVAILABLE
64 #define INFO_DEVICES "/proc/devices"
65 #define INFO_MISC "/proc/misc"
67 #define INFO_SCSI_AVAILABLE
68 #define INFO_SCSI "/proc/scsi/scsi"
70 #define INFO_PARTITIONS_AVAILABLE
71 #define INFO_PARTITIONS "/proc/partitions"
72 #define INFO_MOUNTED_PARTITIONS "/etc/mtab" /* on Linux... */
74 #define INFO_XSERVER_AVAILABLE
77 #define MAXCOLUMNWIDTH 600
79 bool GetInfo_ReadfromFile(Q3ListView
* lbox
, const char *FileName
,
80 const QChar
& splitChar
,
81 Q3ListViewItem
* lastitem
= 0,
82 Q3ListViewItem
** newlastitem
= 0)
91 if (!file
.open(QIODevice::ReadOnly
)) {
92 /* *GetInfo_ErrorString =
93 i18n("You do not have read-access to the file %1.\nPlease ask your system administrator for advice.")
98 QTextStream
stream(&file
);
101 while (!stream
.atEnd()) {
103 line
= stream
.readLine();
104 if (!line
.isEmpty()) {
105 if (!splitChar
.isNull()) {
106 int pos
= line
.indexOf(splitChar
);
107 s1
= line
.left(pos
-1).trimmed();
108 s2
= line
.mid(pos
+1).trimmed();
113 lastitem
= new Q3ListViewItem(lbox
, lastitem
, s1
, s2
);
119 *newlastitem
= lastitem
;
127 bool GetInfo_CPU(Q3ListView
* lBox
)
129 lBox
->addColumn(i18n("Information"));
130 lBox
->addColumn(i18n("Value"));
131 return GetInfo_ReadfromFile(lBox
, INFO_CPU
, ':');
135 bool GetInfo_IRQ(Q3ListView
* lBox
)
137 lBox
->setFont(KGlobalSettings::fixedFont());
138 return GetInfo_ReadfromFile(lBox
, INFO_IRQ
, 0);
141 bool GetInfo_DMA(Q3ListView
* lBox
)
143 QFile
file(INFO_DMA
);
145 lBox
->addColumn(i18n("DMA-Channel"));
146 lBox
->addColumn(i18n("Used By"));
148 if (file
.exists() && file
.open(QIODevice::ReadOnly
)) {
149 QTextStream
stream(&file
);
151 Q3ListViewItem
*child
=0L;
153 while (!stream
.atEnd()) {
154 line
= stream
.readLine();
155 if (!line
.isEmpty()) {
156 QRegExp
rx("^\\s*(\\S+)\\s*:\\s*(\\S+)");
157 if (-1 != rx
.indexIn(line
)) {
158 child
= new Q3ListViewItem(lBox
,child
,rx
.cap(1),rx
.cap(2));
170 bool GetInfo_PCI(Q3ListView
* lBox
)
173 sorting_allowed
= false; /* no sorting by user */
175 /* ry to get the output of the lspci package first */
176 if ((num
= GetInfo_ReadfromPipe(lBox
, "lspci -v", true)) ||
177 (num
= GetInfo_ReadfromPipe(lBox
, "/sbin/lspci -v", true)) ||
178 (num
= GetInfo_ReadfromPipe(lBox
, "/usr/sbin/lspci -v", true)) ||
179 (num
= GetInfo_ReadfromPipe(lBox
, "/usr/local/sbin/lspci -v", true)) ||
180 (num
= GetInfo_ReadfromPipe(lBox
, "/usr/bin/lspci -v", true)))
183 /* if lspci failed, read the contents of /proc/pci */
184 return GetInfo_ReadfromFile(lBox
, INFO_PCI
, 0);
187 bool GetInfo_IO_Ports(Q3ListView
* lBox
)
189 lBox
->addColumn(i18n("I/O-Range"));
190 lBox
->addColumn(i18n("Used By"));
191 return GetInfo_ReadfromFile(lBox
, INFO_IOPORTS
, ':');
194 bool GetInfo_Sound(Q3ListView
* lBox
)
196 sorting_allowed
= false; /* no sorting by user */
197 if (GetInfo_ReadfromFile(lBox
, INFO_DEV_SNDSTAT
, 0))
199 else if (GetInfo_ReadfromFile(lBox
, INFO_SOUND
, 0))
201 else if (GetInfo_ReadfromFile(lBox
, INFO_ASOUND
, 0))
204 return GetInfo_ReadfromFile(lBox
, INFO_ASOUND09
, 0);
207 bool GetInfo_Devices(Q3ListView
* lBox
)
210 Q3ListViewItem
*misc
=0L;
212 lBox
->setRootIsDecorated(true);
213 lBox
->addColumn(i18n("Devices"));
214 lBox
->addColumn(i18n("Major Number"));
215 lBox
->addColumn(i18n("Minor Number"));
217 file
.setFileName(INFO_DEVICES
);
218 if (file
.exists() && file
.open(QIODevice::ReadOnly
)) {
219 QTextStream
stream(&file
);
221 Q3ListViewItem
*parent
=0L, *child
=0L;
223 while (!stream
.atEnd()) {
224 line
= stream
.readLine();
225 if (!line
.isEmpty()) {
226 if (-1 != line
.indexOf("character device",0,Qt::CaseInsensitive
)) {
227 parent
= new Q3ListViewItem(lBox
,parent
,i18n("Character Devices"));
228 parent
->setPixmap(0,SmallIcon("chardevice"));
229 parent
->setOpen(true);
230 } else if (-1 != line
.indexOf("block device",0,Qt::CaseInsensitive
)) {
231 parent
= new Q3ListViewItem(lBox
,parent
,i18n("Block Devices"));
232 parent
->setPixmap(0,SmallIcon("blockdevice"));
233 parent
->setOpen(true);
235 QRegExp
rx("^\\s*(\\S+)\\s+(\\S+)");
236 if (-1 != rx
.indexIn(line
)) {
238 child
= new Q3ListViewItem(parent
,child
,rx
.cap(2),rx
.cap(1));
240 child
= new Q3ListViewItem(lBox
,parent
,rx
.cap(2),rx
.cap(1));
242 if (rx
.cap(2)=="misc") {
254 file
.setFileName(INFO_MISC
);
255 if (misc
&& file
.exists() && file
.open(QIODevice::ReadOnly
)) {
256 QTextStream
stream(&file
);
258 Q3ListViewItem
*child
=0L;
260 misc
->setText(0,i18n("Miscellaneous Devices"));
261 misc
->setPixmap(0,SmallIcon("memory"));
264 while (!stream
.atEnd()) {
265 line
= stream
.readLine();
266 if (!line
.isEmpty()) {
267 QRegExp
rx("^\\s*(\\S+)\\s+(\\S+)");
268 if (-1 != rx
.indexIn(line
)) {
269 child
= new Q3ListViewItem(misc
,child
,rx
.cap(2),"10",rx
.cap(1));
279 bool GetInfo_SCSI(Q3ListView
* lBox
)
281 return GetInfo_ReadfromFile(lBox
, INFO_SCSI
, 0);
284 static void cleanPassword(QString
& str
)
287 QString
passwd("password=");
291 index
= str
.indexOf(passwd
, index
, Qt::CaseInsensitive
);
293 index
+= passwd
.length();
294 while (index
< (int) str
.length() &&
295 str
[index
] != ' ' && str
[index
] != ',')
301 #ifndef INFO_PARTITIONS_FULL_INFO
303 bool GetInfo_Partitions(Q3ListView
* lBox
)
305 return GetInfo_ReadfromFile(lBox
, INFO_PARTITIONS
, 0);
308 #else /* INFO_PARTITIONS_FULL_INFO */
310 // Some Ideas taken from garbazo from his source in info_fbsd.cpp
313 #if ( defined(HAVE_LINUX_RAW_H) || defined(HAVE_SYS_RAW_H) ) && defined(HAVE_SYS_IOCTL_H) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
314 #include <sys/ioctl.h>
317 #if defined(HAVE_SYS_RAW_H)
319 #elif defined(HAVE_LINUX_RAW_H)
320 #include <linux/raw.h>
324 * get raw device bindings and information
326 void Get_LinuxRawDevices(Q3ListView
*lbox
)
329 int new_raw_devs
= 1;
330 struct raw_config_request rq
;
332 QString
MB(i18n("MB")); /* "MB" = "Mega-Byte" */
334 /* try to open the raw device control file */
335 f
= open("/dev/rawctl", O_RDWR
);
337 f
= open("/dev/raw", O_RDWR
);
343 for (i
=1; i
<256; i
++) {
345 if (ioctl(f
, RAW_GETBIND
, &rq
))
347 if (!rq
.block_major
) /* unbound ? */
349 unsigned int minor
= rq
.block_minor
;
351 switch ((int)rq
.block_major
) {
354 case 3: first_letter
= 'a';
356 devname
= QString("/dev/hd%1%2")
357 .arg(QChar(first_letter
+ minor
/64))
360 case 22:first_letter
= 'c'; goto set_ide_name
;
361 case 33:first_letter
= 'e'; goto set_ide_name
;
362 case 34:first_letter
= 'g'; goto set_ide_name
;
363 case 56:first_letter
= 'i'; goto set_ide_name
;
364 case 57:first_letter
= 'k'; goto set_ide_name
;
365 case 88:first_letter
= 'm'; goto set_ide_name
;
366 case 89:first_letter
= 'o'; goto set_ide_name
;
367 case 90:first_letter
= 'q'; goto set_ide_name
;
368 case 91:first_letter
= 's'; goto set_ide_name
;
371 case 8: first_letter
= 'a';
373 devname
= QString("/dev/sd%1%2")
374 .arg(QChar(first_letter
+ minor
/16))
377 case 65:first_letter
= 'q'; goto set_scsi_name
;
379 /* Compaq /dev/cciss devices */
380 case 104: case 105: case 106:
381 case 107: case 108: case 109:
382 devname
= QString("/dev/cciss/c%1d%2")
383 .arg((int)rq
.block_major
-104)
387 /* Compaq Intelligent Drive Array (ida) */
388 case 72: case 73: case 74: case 75:
389 case 76: case 77: case 78: case 79:
390 devname
= QString("/dev/ida/c%1d%2")
391 .arg((int)rq
.block_major
-72)
395 default: devname
= QString("%1/%2")
396 .arg((int)rq
.block_major
)
401 /* TODO: get device size */
404 new Q3ListViewItem(lbox
, devname
,
405 QString(new_raw_devs
? "/dev/raw/raw%1" : "/dev/raw%1").arg(i
),
406 "raw", size
, " ", "");
411 #define Get_LinuxRawDevices(x) /* nothing */
414 bool GetInfo_Partitions(Q3ListView
* lbox
)
417 QString Title
[NUMCOLS
];
418 QStringList Mounted_Partitions
;
423 struct fstab
*fstab_ent
;
424 # define FS_NAME fstab_ent->fs_spec // device-name
425 # define FS_FILE fstab_ent->fs_file // mount-point
426 # define FS_TYPE fstab_ent->fs_vfstype // fs-type
427 # define FS_MNTOPS fstab_ent->fs_mntops // mount-options
429 struct mntent
*mnt_ent
;
431 # define FS_NAME mnt_ent->mnt_fsname // device-name
432 # define FS_FILE mnt_ent->mnt_dir // mount-point
433 # define FS_TYPE mnt_ent->mnt_type // fs-type
434 # define FS_MNTOPS mnt_ent->mnt_opts // mount-options
438 quint64 total
, avail
;
439 QString str
, mountopts
;
440 QString
MB(i18n("MB")); /* "MB" = "Mega-Byte" */
444 if (setfsent() == 0) /* Try to open fstab */
447 if (!(fp
= setmntent("/etc/fstab", "r")))
451 /* read the list of already mounted file-systems.. */
452 QFile
*file
= new QFile(INFO_MOUNTED_PARTITIONS
);
453 if (file
->open(QIODevice::ReadOnly
)) {
455 while (file
->readLine(buf
, sizeof( buf
)) > 0) {
456 str
= QString::fromLocal8Bit(buf
);
458 int p
= str
.indexOf(' '); /* find first space. */
460 str
.remove(p
, 1024); /* erase all chars including space. */
461 Mounted_Partitions
.append(str
);
468 /* create the header-tables */
469 MB
= QString(" ") + MB
;
470 Title
[0] = i18n("Device");
471 Title
[1] = i18n("Mount Point");
472 Title
[2] = i18n("FS Type");
473 Title
[3] = i18n("Total Size");
474 Title
[4] = i18n("Free Size");
475 Title
[5] = i18n("Mount Options");
477 for (n
= 0; n
< NUMCOLS
; ++n
)
478 lbox
->addColumn(Title
[n
]);
480 /* loop through all partitions... */
482 while ((fstab_ent
= getfsent()) != NULL
)
484 while ((mnt_ent
= getmntent(fp
)) != NULL
)
487 total
= avail
= 0; /* initialize size.. */
488 found_in_List
= (Mounted_Partitions
.contains(FS_NAME
) > 0);
489 if (found_in_List
&& statfs(FS_FILE
, &sfs
) == 0) {
490 total
= ((quint64
) sfs
.f_blocks
) * sfs
.f_bsize
;
491 avail
= (getuid()? sfs
.f_bavail
: sfs
.f_bfree
)
492 * ((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
);
503 new Q3ListViewItem(lbox
, QString(FS_NAME
) + " ",
504 QString(FS_FILE
) + " ",
505 QString(FS_TYPE
) + " ",
506 Value((int) (((total
/ 1024) + 512) / 1024),
508 Value((int) (((avail
/ 1024) + 512) / 1024),
511 new Q3ListViewItem(lbox
, QString(FS_NAME
), QString(FS_FILE
),
512 QString(FS_TYPE
), " ", " ", mountopts
);
516 endfsent(); /* close fstab.. */
518 endmntent(fp
); /* close fstab.. */
521 /* get raw device entires if available... */
522 Get_LinuxRawDevices(lbox
);
524 sorting_allowed
= true; /* sorting by user allowed ! */
529 #endif /* INFO_PARTITIONS_FULL_INFO */
534 bool GetInfo_XServer_and_Video(Q3ListView
* lBox
)
536 return GetInfo_XServer_Generic(lBox
);