LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How to get a list of physical drives in C++ (https://www.linuxquestions.org/questions/programming-9/how-to-get-a-list-of-physical-drives-in-c-538365/)

ManuPeng 03-17-2007 05:29 PM

How to get a list of physical drives in C++
 
Hi,

So here's my problem, I'm writing a small application in C++ using kdevelop, and for this application, I want to have some kind of a drop-down list listing the available drives on the system.

I'm more interested in CD/DVD drives to be exact, on windows, the drop-down list would look like this:
-D:/SUSE_10.2
-E:/MY_BACKUP

You get the picture... how do I get my program to fetch a list of the available mountpoints? I mean, I don't want to make a dumb system call out of the program like "cd /media" "ls", there has to be a better way, besides, I've heard only Suse mounts in /media, so it would be trouble with other distros...
I've found QDir::drives() but it only seems to work on Windows, the reference saying that one other system, only root "/" will be returned.

Any help is appreciated!

Manu

wjevans_7d1@yahoo.co 03-17-2007 07:00 PM

File /etc/fstab is a file which you should never write to, but can read. Try this:

Code:

cat /etc/fstab
man fstab

Hope this helps.

ManuPeng 03-18-2007 04:53 AM

Thanks for your answer,

I thought of that, but, and that's where it gets tricky, there are no mention of my optical drives in /etc/fstab. I guess it has to do with that hotplug feature, I only see the CD/DVD drive in konqueror (media:/). When OpenSuSE mounts CD/DVD drives, it adds a line in /etc/mtab and mounts them to /media, but there are exceptions, like it won't add the mtab entry, nor mount it to /media, if the CD/DVD is either an Audio CD or a movie DVD.
They'll still show up in konqueror (media:/) though, what the f...!?

You see, I'd like a solution that somewhat guarantees that I'll get a list of optical drives on any distro. There's got to be some sort of an API call to do that through KDE. System calls to the shell are kind of an ugly way to do this anyway.

Manu

wjevans_7d1@yahoo.co 03-18-2007 09:12 AM

This is beyond my area of familiarity. (I'm a command line kinda guy.)

Anyone else out there with an answer? Anyone? Beuller?

_john_i_ 03-18-2007 12:07 PM

If you are trying to find cd/dvd drives, you might be able to scan through the /sys/block directory. In there you will find subdirectories for each block device, and in those diretories you will find a file called "removable". If it is a cd/dvd, this file will contain "1".

you may be able to get even more specific exploring /sys a little further.

ManuPeng 03-18-2007 01:50 PM

Thanks guys for your answers, I thought for a second that I was on my own on this one :-)

Well, it seems that I will have to make a system call in the end. Don't get me wrong, I appreciate your answers, but I just can't believe there is no C++ class, or method to fetch a list of drives.
I mean, on Windows, there's this .NET API call, "System.IO.Directory.GetLogicalDrives" or something, I did it before and you get your list back.

I checked the source code of k3b for example, because of the drive selection dialog it has. The program is somehow capable of finding my optical drives and the vendor description.
Well, it didn't help me because it goes in all directions, ihheriting classes from classes of classes, and that's just too much for my modest C++ knowledge. Beside, I couldn't really tell what was doing what and couldn't find the code that realizes this particular feature.

I've been combing the kdevelop QT and KDE reference and I couldn't find anything, it's weird.

So let's say I go for it and use a system call, like in C++:

system("ls /sys/block");
and so on...

By the way, _john_i_, your solution works, I checked it out using the shell.

How do I get the result of the query? The system method only returns an int for SUCCESS or FAIL? Do I have the shell write the result in a temporary file to later parse it with my program? Now, that sounds ugly...

Manu
Ps: Any KDE C++ guru out here?

indienick 03-18-2007 02:06 PM

To write to a file, simply redirect the output:
Code:

/* To write/overwrite to sysblock.tmp */
system("cat /sys/block > sysblock.tmp");

/* To write/append to sysblock.tmp */
system("cat /sys/block >> sysblock.tmp");

:)

I wish I could help you out in the KDE/QT way of things, but that's an area I'm just starting to learn, myself.

Nick_Battle 03-19-2007 08:22 AM

You can read through the various system files mentioned here either using the C++ iostream library, or the KDE/Qt helper classes such as QFile - http://doc.trolltech.com/3.3/qfile.html. There is example code there too.

Using the system(3) call is very inefficient as it spawns another process to execute the command line in a shell.

I'm not sure why KDE doesn't include anything for this. It could in principle, but you need to distinguish between what pure C++ does (just a language with supporting libraries), what KDE does (a desktop environment, but not strictly Linux specific) and what the operating system provides (via the libc system calls and supporting system files). The KDE designers may have decided that it isn't KDE's place to provide disk device information(?)

HTH
-nick

ManuPeng 03-19-2007 02:17 PM

I totally agree with you that using the "system" call is plain inefficient. I mean, first the call to have the shell write the output of the command in a file, then a C++ method to parse the content of the output file, this all would work, but I will never allow my name to appear in the header of such code.
I mean, even in the 80's, it would have looked ridiculous :)

I have to be honest with all of you, I hate C++ from the bottom of my heart, this language just doesn't work well with my brain. I understand that some people feel confortable using it, but it brings me in such a rage every time I'm dealing with strings, you have no idea, I find myself screaming in pain every once in a while...

So I looked at other options today, modern languages that take the burden of C++ away. I can use C++ just fine, but it costs me 4 times the effort I need to do the same thing in C#, VB.NET, java, or even C (I know, not object oriented).
I wrote in a previous post about how easy it was using .NET to get such a list of drives, guess what, I did a small test program in C#, ran it on linux using mono, and here's my output:
Code:

/
/home
/windows/C
/windows/D
/windows/E
/media/SU1020.001
/media/disk

My CDs are in media, there you go, it's all I freaking wanted... 5mn of work...
I'll have a look into the limitations of that .NET option, I mean, displaying a list of drives isn't the only thing I want my program to do, but it's the base of it all.
Besides, I'll still have to parse /etc/fstab or /etc/mtab and /sys/block to make sure it's a CD (removable file contains "1"). Maybe a method of the System.IO.Directory namespace does it anyway.

Code:

// Collect a list of available drives
string[] drives = System.IO.Directory.GetLogicalDrives();

// Output the available drives
foreach (string str in drives)
{
        System.Console.WriteLine(str);
}

Still, thanks to all you, it's good to know there really is a linux community of people helping eachother.

Manu

_john_i_ 03-19-2007 03:18 PM

There's no need to resort to running shell commands for this. The /sys filesystem entities will appear to be just regular files to a program. You can use the libc api calls to list out the files in the directory and read them as normal files.

Do:
man opendir
man readdir
To see how to open and enumerate files in a directory.

Once you get the list of files, jsut open them to read the contents.

Nick_Battle 03-20-2007 03:32 AM

Quote:

Originally Posted by ManuPeng
So I looked at other options today, modern languages that take the burden of C++ away.
[snip]
I wrote in a previous post about how easy it was using .NET to get such a list of drives, guess what, I did a small test program in C#, ran it on linux using mono, and here's my output

OK. But my point was that you should distinguish between a language, its libraries, and the operating environment it's running under.

I don't want to start a language flame-war(!), but I think the problem you're having isn't with C++ itself, but with the KDE class libraries that you're using. The C# libraries (evidently) include the device support you need as standard. This could perfectly well be provided in KDE's C++ libraries, though as I mentioned, the KDE designers may not consider "disk drive support" as KDE's business (it's the operating system's business), whereas the C# designers do, probably because they have a Windows mindset where "disk drives" are much more visible to general applications (just a guess).

Small point. Doesn't help anyone, I know. I'll shut up :)

ManuPeng 03-20-2007 02:15 PM

Oh no, no programming flame-war, it wouldn't take anyone anywhere :)

You're right in what you say though, it could just be that KDE didn't consider the hardware device handling being its responsibility. As for my complaining about C++, it wasn't only related to this specific problem I'm having, it's just a general issue that I have with the language, which is why I wrote that it doesn't work well with my brain.

I hated C++ on Windows too, I just can't understand the whole MFC, ATL, and so on...
My main problem is that thing with the strings, I remember trying to use SQLite with C++, the TextBox on the Form would give me a System::String back, and SQLite wanted a C string, it took me 6 hours to figure out how to convert the string and finding the header file hosting that function. I was slowly thinking about just doing a for... loop for each character of the string and casting them one by one into a C string.

I saw today that I will have to wait for Mono .NET 2 to be able to use the DriveInfo class, it's being implemented as we speak. In the meantime, I can implement that whole shell solution that you all helped me put together.

Manu


All times are GMT -5. The time now is 07:56 PM.