The discrepancy you’re seeing between running /usr/bin/gio mount -l
directly in the terminal and running it from your C/C++ program comes down to environment differences, even though both run under the same user.
Specifically, GIO and GVfs (GIO’s virtual filesystem layer) rely on certain environment variables and session services (like D-Bus and GVfs daemons) that are typically initialized when you run a full graphical login session. These include:
- A valid
DBUS_SESSION_BUS_ADDRESS
- Running
gvfsd
, gvfs-udisks2-volume-monitor
, and related daemons
- Environment variables like
XDG_RUNTIME_DIR
Why your C++ program doesn’t show drives
When you launch a process via execv()
in a minimal environment (like your C/C++ program), you’re not inheriting all the session environment variables, especially those that GIO depends on to interface with system and user volumes.
As a result, the subprocess may only be able to see GIO volumes that do not require full session context (like WebDAV mounts), while missing those that need deeper integration (e.g., physical drives).
This is why you’re seeing Drive(0)
missing — the GIO volume monitor backend for drives is not functioning fully in that environment.
How to fix it
To make your C++ program behave exactly like the shell does, you need to replicate the environment. Here are your options:
1. Pass the full environment using execve()
or execle()
instead of execv()
extern char **environ;
execve(GIO_ARGUMENTS[0], GIO_ARGUMENTS, environ);
This ensures the new process inherits the same environment as your parent (including DBUS_SESSION_BUS_ADDRESS
, which is critical).
2. Make sure the D-Bus session address is present
You can check this in your environment with:
echo $DBUS_SESSION_BUS_ADDRESS
If your program is missing this, you can manually fetch and set it (though it’s better to inherit the environment). To get the value dynamically:
export DBUS_SESSION_BUS_ADDRESS=$(cat /run/user/$(id -u)/bus)
Or in C/C++, setenv before calling execv()
:
setenv("DBUS_SESSION_BUS_ADDRESS", "...", 1);
3. Use GIO_USE_VFS=local
or unset it if it’s interfering
This env var can sometimes interfere with what backends GIO uses. Try explicitly unsetting it:
unsetenv("GIO_USE_VFS");
Or at least ensure it’s not overriding anything.
4. Call gio mount -l
directly in a shell using system()
for debugging
Try temporarily replacing your execv()
call with:
system("/usr/bin/gio mount -l");
If this version shows Drive(0)
, it’s a clear confirmation that the missing environment is the cause.
5. Consider using GLib APIs directly
If you’re trying to integrate with GIO programmatically, you might be better off using GLib’s GIO API (e.g., g_volume_monitor_get()
, g_volume_get_drive()
), but the same environment concerns apply.
Summary
You’re missing key environment variables (most likely DBUS_SESSION_BUS_ADDRESS
and related GIO session setup) in your execv()
-launched process. Use execve()
with inherited environ
or carefully set the needed variables manually. This will align the runtime environment with what your interactive shell provides, allowing GIO to detect and show all drives.