LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Help with C code for detecting ext4 in VisParted (fork of GParted) (http://www.linuxquestions.org/questions/programming-9/help-with-c-code-for-detecting-ext4-in-visparted-fork-of-gparted-624924/)

Patrick Verner 03-01-2008 07:47 AM

Help with C code for detecting ext4 in VisParted (fork of GParted)
 
I'm having trouble detecting ext4 file systems in my fork of GParted called VisParted. It's the partitioning program for the Parted Magic distribution.

All I need to do is get it to detect the ext4 file system and full ext4 support in VisParted is done. The fix needs to be here around line 737:

http://partedmagic-svn.cvsdude.com/p...Parted_Core.cc

I'm not opposed to using external commands like blkid which detects ext4 flawlessly. I'm out of ideas and I'm even willing to pay to get this working.

osor 03-02-2008 04:30 PM

You have to read the superblock and look for features that are peculiar to ext4. The easiest way to do this is to do a bitwise and with ~EXT3_FEATURE_INCOMPAT_SUPP (you have to take into account endianness, or use the kernel macros which automatically account for it).

Or, you could use libblkid.

Patrick Verner 03-02-2008 05:57 PM

This is how Bart detected reiser4:

char buf[512] ;

ped_device_open( lp_device );

//reiser4
ped_geometry_read( & lp_partition ->geom, buf, 128, 1 ) ;
ped_device_close( lp_device );

if ( Glib::ustring( buf ) == "ReIsEr4" )
return VisParted::FS_REISER4 ;

This approach could work except parted thinks it's ext3 and therefore it returns "return VisParted::FS_EXT3". So it gets picked-up a few lines earlier as ext3. I can't find any obvious code that states it's ext4 like reiser4 does.

I could use blkid, but I've been pulling my hair out trying to get blkid to execute the proper device. When I usually do external commands I don't have these issues because I call device from the predefined menus and use commands like:

Utils::execute_command( "dumpe2fs -h " + partition .get_path() );

I can't get an external command like this to work mostly because I don't know exactly what's going on. Somebody with more experience could probably figure this out pretty easily.

osor 03-03-2008 12:31 PM

Quote:

Originally Posted by Patrick Verner (Post 3076085)
This approach could work except parted thinks it's ext3 and therefore it returns "return VisParted::FS_EXT3". So it gets picked-up a few lines earlier as ext3. I can't find any obvious code that states it's ext4 like reiser4 does.

Thatís because ext[2-4] all have the same magic numbers, whereas reiser3 and reiser4 have different magic numbers.
Quote:

Originally Posted by Patrick Verner (Post 3076085)
I could use blkid, but I've been pulling my hair out trying to get blkid to execute the proper device.

Well, what is the path to the partition? In your example, you use partition.get_path(), which wonít work in the function youíve given.

I havenít deeply looked at the code, but you can use libblkid as follows:
Code:

Index: src/VisParted_Core.cc
===================================================================
--- src/VisParted_Core.cc        (revision 26)
+++ src/VisParted_Core.cc        (working copy)
@@ -38,6 +38,8 @@
 #include "../include/reiser4.h"
 #include "../include/ufs.h"
 
+#include <blkid/blkid.h>
+
 #include <cerrno>
 #include <cstdio>
 #include <csignal>
@@ -733,7 +735,23 @@
        ped_device_close( lp_device );
       
        if ( Glib::ustring( buf ) == "ReIsEr4" )
-                return VisParted::FS_REISER4 ;               
+                return VisParted::FS_REISER4 ;
+
+        //ext4 through libblkid
+        blkid_cache cache;
+        blkid_dev dev;
+        VisParted::FILESYSTEM retval = 0;
+
+        if(blkid_get_cache(&cache, "/dev/null") == 0) { //use a dummy cache to make life easier
+                if((dev = blkid_get_dev(cache, partition.get_path(), BLKID_DEV_NORMAL)) != NULL) {
+                        if(blkid_dev_has_tag(dev, "TYPE", "ext4") || blkid_dev_has_tag(dev, "TYPE", "ext4dev"))
+                                retval = VisParted::FS_EXT4;
+                        blkid_free_dev(dev);
+                }
+                blkid_put_cache(cache);
+        }
+        if(retval)
+                return retval;
               
        //no filesystem found....
        temp = _( "Unable to detect filesystem! Possible reasons are:" ) ;
Index: src/Makefile.am
===================================================================
--- src/Makefile.am        (revision 26)
+++ src/Makefile.am        (working copy)
@@ -54,7 +54,7 @@
        ufs.cc                                \
        xfs.cc
       
-visparted_LDFLAGS = -lparted -lgthread-2.0
+visparted_LDFLAGS = -lparted -lgthread-2.0 -lblkid
 
 visparted_LDADD = $(GTKMM_LIBS)

It looks a little tacked-on (mostly since libblkid is a C library and you have to do your own allocations and deallocations), but it will work as long as partition.get_path() actually points to the path of the partition you want to investigate (which doesnít occur in your code). It will use a dummy cache so you donít have to keep verifying consistency.

Patrick Verner 03-03-2008 05:39 PM

Quote:

Well, what is the path to the partition? In your example, you use partition.get_path(), which wonít work in the function youíve given.
This is 99% of my problem. I can't figure out how to assign the device to blkid. I don't understand this "lp_partition" and "lp_device" stuff that's going on here. If I could come up with the device I could just run it through blkid as and external command or through libblkid.

I'm a project manager more than a programmer and the project donations in part are supposed to go to paying programmers to "add to" / "fix" VisParted. Man, I wish I knew this stuff as well as you guys do.

osor 03-03-2008 06:27 PM

Quote:

Originally Posted by Patrick Verner (Post 3077092)
This is 99% of my problem. I can't figure out how to assign the device to blkid. I don't understand this "lp_partition" and "lp_device" stuff that's going on here.

I see. I didnít know any of that stuff either (besides that which I read in your sourcecode). After looking at the libparted API, it seems you can get the path of a partition through the helper function ped_partition_get_path() (you need to free() the result). So
Code:

char *path;
path = ped_partition_get_path(lp_partition);
// use path here
free(path);

Btw, the most elegant fix to your problem as a whole would be to patch libparted (and if the patch is useful, submit it upstream) so that you can use consistent code from within VisParted, instead of hacking on something you might not understand. That way, the changes are kept local to what is actually affected, but you are free to distribute the patched version of libparted (or the patch itself) until upstream makes a new release with reiser4 and ext4 detection. A side effect is that you wonít have to remove the hackish code once upstream libparted gets around to the release.

Patrick Verner 03-03-2008 08:00 PM

Quote:

Btw, the most elegant fix to your problem as a whole would be to patch libparted
Over my head by miles.

I tried "ped_partition_get_path(lp_partition)" and I couldn't get that to work either. Most likely because I wasn't doing it right.

Probably the best solution would be to sit back and wait for parted to add the detection itself. I already have the ext3 code cloned for ext4 support and would work now if parted could detect ext4.

Oh, well...


All times are GMT -5. The time now is 09:33 PM.