My *nix world

How to patch a baobab

For those who were around Linux in the last years the Gnome utility called Disk Usage Analyzer (aka baobab) is not a secret anymore.

disk usage analyzer baobab open folder

source: http://www.marzocca.net/linux/baobab/figures/baobab_fullscan.png

It is a gnome-utils, which perhaps works perfectly with the Gnome desktop environment, but in Gentoo with Xfce4 however it seems to have an issue: whenever you right-click on a folder, in order to open it (with your default editor as defined in "MIME type editor"), it wouldn't open but instead will show an error message like this:

disk usage analyzer baobab open folder

click to zoom

If you dig into your baobab's sources you will find that the message comes from open_file_with_application function within baobab-utils.c source code.

One of the reasons I love Linux (especially Gentoo distro) is because I have access to the source code and I don't have to wait (forever) for a patch from the community instead I can patch the code myself right away.

open_file_with_application (GFile *file)
{
        GAppInfo *application;
        gchar *primary;
        GFileInfo *info;
        gchar *uri_scheme;
        const char *content;
        gboolean local = FALSE;

        info = g_file_query_info (file,
                                  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
                                  G_FILE_QUERY_INFO_NONE,
                                  NULL,
                                  NULL);
        if (!info) return;

        uri_scheme = g_file_get_uri_scheme (file);
        if (g_ascii_strcasecmp(uri_scheme,"quot;file"quot;) == 0)  local = TRUE;

        content = g_file_info_get_content_type (info);
        application = g_app_info_get_default_for_type (content, TRUE);

        if (!application) {
                        primary = g_strdup_printf (_("quot;Could not open folder "quot;%s"quot;"quot;),
                                                   g_file_get_basename (file));
                        message (primary,
                                 _("quot;There is no installed viewer capable "quot;
                                   "quot;of displaying the folder."quot;),
                                 GTK_MESSAGE_ERROR,
                                 baobab.window);
                        g_free (primary);
        }
        else {

The problem, in our case, starts with the line #21 (see my code snapshot above) because the function g_app_info_get_default_for_type is not capable of returning the right GAppInfo when it's not called from within Gnome desktop environment. This is neither a bug in baobab code or gnome-utils but a missing patch in Gentoo distro about the gnome-utils-2.32.0-r2 package. Maybe is not a missing patch in Gentoo but a problem that I have locally so I'm going to patch it.

In my dirty lazy patch I will use a function from xdg-utils library, which should be installed on all platforms where you have X Window System installed. The function we are going to use it's called xdg-open and its purpose is to "open a file or URL in the user's preferred application".

So, comment or remove the code between line 24-30 (like in my code snapshot above) and patch it with the following:

                gchar *uri_file=g_file_get_uri(file);
                primary=g_strdup_printf("quot;xdg-open "quot;%s"quot;"quot;,uri_file);
                system(primary);
                g_free(uri_file);

So after all this changes your function code should looks like this:

open_file_with_application (GFile *file)
{
        GAppInfo *application;
        gchar *primary;
        GFileInfo *info;
        gchar *uri_scheme;
        const char *content;
        gboolean local = FALSE;

        info = g_file_query_info (file,
                                  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
                                  G_FILE_QUERY_INFO_NONE,
                                  NULL,
                                  NULL);
        if (!info) return;

        uri_scheme = g_file_get_uri_scheme (file);
        if (g_ascii_strcasecmp(uri_scheme,"quot;file"quot;) == 0)  local = TRUE;

        content = g_file_info_get_content_type (info);
        application = g_app_info_get_default_for_type (content, TRUE);

        if (!application) {
                gchar *uri_file=g_file_get_uri(file);
                primary=g_strdup_printf("quot;xdg-open "quot;%s"quot;"quot;,uri_file);
                system(primary);
                g_free(uri_file);
                g_free (primary);
        }
        else {

Now, the question is: how do you install your new patch into Gentoo?

I found two different ways of achieving this: the patch-forever way and the patch-and-go way. In the permanent way we prepare the system to be able to merge our patch automatically even after a system update. In the volatile way we just prepare the system to merge manually our patch, but if you call emerge then the system will use the original not patched source code instead of the patched one.

The patch-forever way

This method supposed to create our own custom overlay for this package. Before doing that let's tell the emerge where is the root directory for our custom overlays: edit the /etc/make.conf and add a line like:

# a custom place where we create our custom overlays
PORTDIR_OVERLAY="${PORTDIR_OVERLAY} /usr/local/portage"
  1. Make sure the directory /usr/local/portage exists, and if not then create it.
  2. Create the folder structure for our custom overlay:
mkdir -p /usr/local/portage/gnome-extra/gnome-utils/files
# patch/a - is where we put the untouched original code
# patch/b - is where we save the changed source code
mkdir -p /usr/local/portage/gnome-extra/gnome-utils/patch/{a,b}/baobab/src
  1. Copy the original overlay file to our custom overlay directory:
cp /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild /usr/local/portage/gnome-extra/gnome-utils/

If the original overlay contains other patch files that you want also to apply, then copy them to your local overlay in the ./files directory:

cp -R /usr/portage/gnome-extra/gnome-utils/files/ /usr/local/portage/gnome-extra/gnome-utils/files/
  1. Create our the patch file starting from the "buggy" source code
    1. fetch and unpack the source code:
      1. ebuild gnome-utils-2.32.0-r2.ebuild manifest fetch unpack
    2. copy the buggy source code to our custom overlay directory structure:
      1. cp /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work/gnome-utils-2.32.0/baobab/src/baobab-utils.c patch/{a,b}/baobab/src/
    3. edit the patch/b/baobab/src/baobab-utils.c and change those lines (24-30) as indicated few paragraphs above, then save the changes
      1. nano patch/b/baobab/src/baobab-utils.c
    4. finally we create the real patch file by comparing the original with the changed file:
      1. git diff patch/a/baobab/src/baobab-utils.c patch/b/baobab/src/baobab-utils.c > files/baobab-utils-my_fix.patch
  1. Instruct our custom overlay file to take into consideration also our custom patch(es) created above. So we have to edit the gnome-utils-2.32.0-r2.ebuild file:
    1. make sure that you inherits also the eutils package by changing the inherit line (at the top of the file) like the one below:
      1. inherit gnome2 eutils autotools
    2. add the following function at the end of the file then save the changes and exit:
      1. src_unpack() {
        unpack ${A}
        cd "${S}"
        epatch "${FILESDIR}"/baobab-utils-my_fix.patch
        }
    3. Now make sure you communicate to ebuild that your ebuild overlay file has changed:
      1. ebuild gnome-utils-2.32.0-r2.ebuild digest manifest
  2. emerge the custom overlay that contains our patch:
    1. emerge -v gnome-utils

The patch-and-go way

For this we are going to use ebuild instead of emerge tool. It will help us to prepare the build environment, to fetch the baobab original source code, to unpack the source code into our build environment, to compile the source code, to install it int the build environment and finally to emerge it into Gentoo live system.

Run the following commands:

  1. ebuild /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild clean
  2. ebuild /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild fetch
* gnome-utils-2.32.0.tar.bz2 RMD160 SHA1 SHA256 size ... [ ok ]
* gnome-utils-2.32.0-icons.tar.xz RMD160 SHA1 SHA256 size ... [ ok ]
* checking ebuild checksums ... [ ok ]
* checking auxfile checksums ... [ ok ]
* checking miscfile checksums ... [ ok ]
  1. ebuild /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild unpack
 * gnome-utils-2.32.0.tar.bz2 RMD160 SHA1 SHA256 size  ...                                                                                                             [ ok ]
 * gnome-utils-2.32.0-icons.tar.xz RMD160 SHA1 SHA256 size  ...                                                                                                        [ ok ]
 * checking ebuild checksums  ...                                                                                                                                      [ ok ]
 * checking auxfile checksums  ...                                                                                                                                     [ ok ]
 * checking miscfile checksums  ...                                                                                                                                    [ ok ]
>>> Unpacking source...
>>> Unpacking gnome-utils-2.32.0.tar.bz2 to /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work
>>> Unpacking gnome-utils-2.32.0-icons.tar.xz to /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work
>>> Source unpacked in /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work

This is the moment when you should edit/patch the original code with the one I showed you above.

  1. nano /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work/gnome-utils-2.32.0/baobab/src/baobab-utils.c

If you have changed/saved your code then continue with the next steps to compile,install and merge the installation into the live Gentoo system folder.

  1. ebuild /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild compile
>> Existing ${T}/environment for 'gnome-utils-2.32.0-r2' will be sourced.
>>> Run 'clean' to start with a fresh environment.
>>> Checking gnome-utils-2.32.0-icons.tar.xz's mtime...
>>> Checking gnome-utils-2.32.0.tar.bz2's mtime...
>>> WORKDIR is up-to-date, keeping...
 * checking ebuild checksums  ...                                                                                                                                      [ ok ]
 * checking auxfile checksums  ...                                                                                                                                     [ ok ]
 * checking miscfile checksums  ...                                                                                                                                    [ ok ]
>>> It appears that 'pretend' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.pretended' to force pretend.
>>> It appears that 'setup' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.setuped' to force setup.
>>> It appears that 'unpack' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.unpacked' to force unpack.
>>> Preparing source in /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work/gnome-utils-2.32.0 ...
 * Applying gnome-utils-2.32.0-fix-uninitialized.patch ...                                                                                                                [ ok ]
 * Applying gnome-utils-2.32.0-new-icons.patch ...                                                                                                                        [ ok ]
 * Applying gnome-utils-2.32.0-new-icons2.patch ...                                                                                                                       [ ok ]
 * Running eautoreconf in '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work/gnome-utils-2.32.0' ...
 * Running glib-gettextize --copy --force ...                                                                                                                             [ ok ]
 * Running intltoolize --automake --copy --force ...                                                                                                                      [ ok ]
 * Skipping 'gtkdocize --copy' due gtkdocize not installed
 * Running gnome-doc-prepare --copy --force ...                                                                                                                           [ ok ]
 * Running libtoolize --install --copy --force --automake ...                                                                                                             [ ok ]
 * Running aclocal -I m4 ...                                                                                                                                              [ ok ]
 * Running autoconf ...                                                                                                                                                   [ ok ]
 * Running autoheader ...                                                                                                                                                 [ ok ]
 * Running automake --add-missing --copy ...                                                                                                                              [ ok ]
 * Running elibtoolize in: gnome-utils-2.32.0/
 *   Applying portage/1.2.0 patch ...
 *   Applying sed/1.5.6 patch ...
 *   Applying as-needed/2.2.6 patch ...
 * Fixing OMF Makefiles ...                                                                                                                                               [ ok ]
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/work/gnome-utils-2.32.0 ...
 * econf: updating gnome-utils-2.32.0/config.guess with /usr/share/gnuconfig/config.guess
 * econf: updating gnome-utils-2.32.0/config.sub with /usr/share/gnuconfig/config.sub
./configure --prefix=/usr --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --libdir=/usr/lib64 --disable-dependency-tracking --enable-debug=minimum --disable-ipv6 --disable-gdict-applet --disable-maintainer-flags --enable-zlib --disable-static --disable-schemas-install --disable-scrollkeeper --disable-gtk-doc --disable-scrollkeeper
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
.................................. and so on .................................
  1. ebuild /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild install
>>> Existing ${T}/environment for 'gnome-utils-2.32.0-r2' will be sourced.
>>> Run 'clean' to start with a fresh environment.
>>> Checking gnome-utils-2.32.0-icons.tar.xz's mtime...
>>> Checking gnome-utils-2.32.0.tar.bz2's mtime...
>>> WORKDIR is up-to-date, keeping...
 * checking ebuild checksums  ...                                                                                                                                      [ ok ]
 * checking auxfile checksums  ...                                                                                                                                     [ ok ]
 * checking miscfile checksums  ...                                                                                                                                    [ ok ]
>>> It appears that 'pretend' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.pretended' to force pretend.
>>> It appears that 'setup' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.setuped' to force setup.
>>> It appears that 'unpack' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.unpacked' to force unpack.
>>> It appears that 'prepare' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.prepared' to force prepare.
>>> It appears that 'configure' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.configured' to force configure.
>>> It appears that 'compile' has already executed for 'gnome-utils-2.32.0-r2'; skipping.
>>> Remove '/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/.compiled' to force compile.
>>> Test phase [not enabled]: gnome-extra/gnome-utils-2.32.0-r2

>>> Install gnome-utils-2.32.0-r2 into /var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/image/ category gnome-extra
make -j3 DESTDIR=/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/image/ 'scrollkeeper_localstate_dir=/var/tmp/portage/gnome-extra/gnome-utils-2.32.0-r2/image//var/lib/scrollkeeper ' install 
Making install in m4
Making install in po
Making install in libeggsmclient
.................................. and so on .................................
  1. ebuild /usr/portage/gnome-extra/gnome-utils/gnome-utils-2.32.0-r2.ebuild qmerge
>>> Existing ${T}/environment for 'gnome-utils-2.32.0-r2' will be sourced.
>>> Run 'clean' to start with a fresh environment.
 * checking ebuild checksums  ...                                                                                                                                      [ ok ]
 * checking auxfile checksums  ...                                                                                                                                     [ ok ]
 * checking miscfile checksums  ...                                                                                                                                    [ ok ]
 * checking 125 files for package collisions
>>> Merging gnome-extra/gnome-utils-2.32.0-r2 to /
--- /etc/
--- /etc/gconf/
--- /etc/gconf/schemas/
>>> /etc/gconf/schemas/gnome-dictionary.schemas
>>> /etc/gconf/schemas/gnome-system-log.schemas
.................................. and so on .................................

Whatever method you embraced, if everything went OK then your baobab should be already patched 😉

Now, if you think that this article was interesting don't forget to rate it. It shows me that you care and thus I will continue write about these things.

The following two tabs change content below.
How to patch a baobab

Eugen Mihailescu

Founder/programmer/one-man-show at Cubique Software
Always looking to learn more about *nix world, about the fundamental concepts of math, physics, electronics. I am also passionate about programming, database and systems administration. 16+ yrs experience in software development, designing enterprise systems, IT support and troubleshooting.
How to patch a baobab

Latest posts by Eugen Mihailescu (see all)

Leave a Reply

Your email address will not be published. Required fields are marked *