Error storing extended attributes in mounted disk


I found an odd behaviour in GLib: I get the list of mounted drives with VolumeMonitor.get_mounts(), and then I store some extended attributes (“metadata::nautilus-icon-position”) using set_attributes_from_info(). It works fine, except if my user isn’t the one who mounted the disk. I mean: if userA, from its Gnome Shell session, mounts an external disk, exit session, and userB enters session, the disk remains mounted but for userA. In this case, get_mounts() return the disk, but set_attributes_from_info() fails with an exception.

Since the metadata is stored at $HOME/.local/share/gvfs-metadata, I presume that there should be no error, but that metadata should be stored locally for that user… Or am I getting it wrong?


Yes, this should work. The volume monitors should return only mounts for which you have access rights and the metadata database is stored in your home directory. Can you please be more specific on how this can be reproduced? How is the disk mounted (do you really have access rights)? What error is returned? Don’t you see something relevant in journalctl output (i.e. warnings from gvfsd-metadata)? Is this reproducible also overgio set (e.g. gio set [path] metadata::nautilus-icon-position 0,0)?

Yes, it is also reproducible. But here is a simple test to check what I mean: just mount from gnome shell an external drive from one user, exit the session, enter with other user, and run this piece of code. It will try to store metadata in each externally mounted drive, but with the one mounted by the other user, it will fail.

#!/usr/bin/env gjs

const Gio =;
const GLib =;

function getMounts() {
    var mounts = Gio.VolumeMonitor.get().get_mounts();

    let result = [];
    for (let mount of mounts) {
        let is_drive = (mount.get_drive() != null) || (mount.get_volume() != null);
        if (is_drive) {
    return result;

for (let drive of getMounts()) {
    print(`Writting metadata for ${drive.get_uri()}`);
    let info = new Gio.FileInfo();
    info.set_attribute_string('metadata::test-info-in-volume', `set-string-sucessful`);
    drive.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null);

Maybe I have to filter the list of mounted drives?

If I simply mount some disk, which doesn’t have corresponding fstab entry, it is mounted under /run/user/USER/ and your script doesn’t see that mount at all. If I change the mount path using the custom fstab entry, then the mount is handled by your script successfully, regardless of the user who mounted it. So I am still missing something to reproduce your issue :thinking:

Mmm… but how are you mounting it? I just connect the drive while inside the Gnome Shell session of the other user, and the system automounts it at /media/$USER/uuid-of-the-partition…

The full process that I do is:

  • enter from GDM into UserA
  • plug the external drive (the drive is automagically mounted at /media/UserA/xxxxxxxxxxxxxxx)
  • exit session (no, I don’t “change user”, I close the current session), without unmounting the drive
  • enter from GDM into UserB
  • run the script
  • Profit!

So I have tried again and closed the session instead of just switching the user, but still can’t reproduce. But is it really automatically mounted under /media/$USER/ in your case (without some custom fstab entry)? What is your distribution? It should be mounted under the runtime dir (i.e. /run/media/$USER) and then the mount is not visible by volume monitors…

Just note that we should somehow ensure that the disk is umounted when closing the session, but that’s another story.

What exception, or error do you see? Does gio info works for such location? Can you please share corresponding entry from mount output?

I use Debian SID (linux 5.9.0, Gnome shell 3.38.1). There is no specific FSTAB entry.

This is the output of my code (blank lines removed):

raster@debian:~$ LANG=en_US ./test_drives.js 
Writting metadata for file:///media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251
(gjs:15920): Gjs-CRITICAL **: 16:26:00.209: JS ERROR: Gio.IOErrorEnum: Error setting file metadata: Permission denied
(gjs:15920): Gjs-CRITICAL **: 16:26:00.209: Script ./test_drives.js threw an exception

mount returns this line for that disk:

/dev/sda1 on /media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251 type ext4 (rw,nosuid,nodev,relatime,uhelper=udisks2)

gio info returns this:

raster@debian:~$ LANG=en_US gio info /media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251
display name: 6c75349d-eefb-41a9-8e19-594e09302251
edit name: 6c75349d-eefb-41a9-8e19-594e09302251
name: 6c75349d-eefb-41a9-8e19-594e09302251
uri: file:///media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251
local path: /media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251
unix mount: /dev/sda1 /media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251 ext4 rw,nosuid,nodev,relatime,uhelper=udisks2
  standard::name: 6c75349d-eefb-41a9-8e19-594e09302251
  standard::display-name: 6c75349d-eefb-41a9-8e19-594e09302251
  standard::edit-name: 6c75349d-eefb-41a9-8e19-594e09302251
  standard::copy-name: 6c75349d-eefb-41a9-8e19-594e09302251
  standard::icon: application-octet-stream, application-x-generic, application-octet-stream-symbolic, application-x-generic-symbolic
  standard::content-type: application/octet-stream
  standard::fast-content-type: application/octet-stream
  standard::symbolic-icon: application-octet-stream-symbolic, application-x-generic-symbolic, application-octet-stream, application-x-generic

but an ‘ls -l /media/iotpartners’ returns ‘ls: cannot open directory ‘/media/iotpartners’: Permission denied’

‘ls -ld /media/iotpartners’ returns ‘drwxr-x—+ 3 root root 4096 oct 22 12:15 /media/iotpartners/’, and the plus symbol, AFAIK, is related with ACLs.

(of course, all this done from the other user)

Thanks for the feedback. I haven’t known that Debian-based distributions use /media instead of /run/media in this case, but you are right, more info can be found on Ok, I think I have enough info now. The error came from because of lstat failure. I will take a look next week…

1 Like

It is totally expected that Permission denied is returned in this case. You don’t have permissions for /media/iotpartners folder, so you can’t store the attributes for files inside this folder…

However, there is some weird bug that gio info doesn’t fail with Permission denied error in this case:

Also GVfsUdisks2VolumeMonitor needs obviously some work to not show such mounts at all. Can you please provide the corresponding udisksctl dump output for this mount? I wonder if it has HintSystem, or HintIgnore set to true, or not…

Just a doubt: the “metadata::” attributes are stored in a database in the $HOME folder, so unless the library specifically checks the permissions of the file, it should not return an error when writing them… Or did I misunderstood it?

This is the dump:

    Configuration:              []
    CryptoBackingDevice:        '/'
    Device:                     /dev/sda
    DeviceNumber:               2048
    Drive:                      '/org/freedesktop/UDisks2/drives/TOSHIBA_External_USB_3_2e0_20190608012699F'
    HintAuto:                   true
    HintIgnore:                 false
    HintPartitionable:          true
    HintSystem:                 false
    Id:                         by-id-usb-TOSHIBA_External_USB_3.0_20190608012699F-0:0
    MDRaid:                     '/'
    MDRaidMember:               '/'
    PreferredDevice:            /dev/sda
    ReadOnly:                   false
    Size:                       1000204883968
    Symlinks:                   /dev/disk/by-id/usb-TOSHIBA_External_USB_3.0_20190608012699F-0:0
    Partitions:         /org/freedesktop/UDisks2/block_devices/sda1
    Type:               dos

    Configuration:              []
    CryptoBackingDevice:        '/'
    Device:                     /dev/sda1
    DeviceNumber:               2049
    Drive:                      '/org/freedesktop/UDisks2/drives/TOSHIBA_External_USB_3_2e0_20190608012699F'
    HintAuto:                   true
    HintIgnore:                 false
    HintPartitionable:          true
    HintSystem:                 false
    Id:                         by-id-usb-TOSHIBA_External_USB_3.0_20190608012699F-0:0-part1
    IdType:                     ext4
    IdUUID:                     6c75349d-eefb-41a9-8e19-594e09302251
    IdUsage:                    filesystem
    IdVersion:                  1.0
    MDRaid:                     '/'
    MDRaidMember:               '/'
    PreferredDevice:            /dev/sda1
    ReadOnly:                   false
    Size:                       900183621632
    Symlinks:                   /dev/disk/by-id/usb-TOSHIBA_External_USB_3.0_20190608012699F-0:0-part1
    UserspaceMountOptions:      uhelper=udisks2
    MountPoints:        /media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251
    Size:               900183621632
    Flags:              128
    IsContained:        false
    IsContainer:        false
    Number:             1
    Offset:             1048576
    Size:               900183621632
    Table:              '/org/freedesktop/UDisks2/block_devices/sda'
    Type:               0x83
    UUID:               12b88f52-01

    Configuration:              []
    CryptoBackingDevice:        '/'
    Device:                     /dev/sda2
    DeviceNumber:               2050
    Drive:                      '/org/freedesktop/UDisks2/drives/TOSHIBA_External_USB_3_2e0_20190608012699F'
    HintAuto:                   true
    HintIgnore:                 false
    HintPartitionable:          true
    HintSystem:                 false
    Id:                         by-id-usb-TOSHIBA_External_USB_3.0_20190608012699F-0:0-part2
    IdType:                     swap
    IdUUID:                     b11c99dd-906d-4b0f-b683-a0ffe971c7fe
    IdUsage:                    other
    IdVersion:                  1
    MDRaid:                     '/'
    MDRaidMember:               '/'
    PreferredDevice:            /dev/sda2
    ReadOnly:                   false
    Size:                       100019470336
    Symlinks:                   /dev/disk/by-id/usb-TOSHIBA_External_USB_3.0_20190608012699F-0:0-part2
    Flags:              0
    IsContained:        false
    IsContainer:        false
    Number:             2
    Offset:             900184670208
    Size:               100019470336
    Table:              '/org/freedesktop/UDisks2/block_devices/sda'
    Type:               0x82
    UUID:               12b88f52-02
    Active:             false

    CanPowerOff:                true
    Configuration:              {}
    ConnectionBus:              usb
    Ejectable:                  false
    Id:                         TOSHIBA-External-USB-3.0-20190608012699F
    MediaAvailable:             true
    MediaChangeDetected:        true
    MediaRemovable:             false
    Model:                      External USB 3.0
    Optical:                    false
    OpticalBlank:               false
    OpticalNumAudioTracks:      0
    OpticalNumDataTracks:       0
    OpticalNumSessions:         0
    OpticalNumTracks:           0
    Removable:                  true
    Revision:                   5438
    RotationRate:               -1
    Seat:                       seat0
    Serial:                     20190608012699F
    SiblingId:                  /sys/devices/pci0000:00/0000:00:08.1/0000:04:00.3/usb2/2-2/2-2:1.0
    Size:                       1000204883968
    SortKey:                    01hotplug/1603815661957053
    TimeDetected:               1603815661957053
    TimeMediaDetected:          1603815661957053
    Vendor:                     TOSHIBA

(you can forget the swap partition. I’m not using it).

Given the fact that the database is stored under the home directory, it is possible to store metadata for read-only locations, but not for inaccessible locations as in this case. Your user doesn’t have permission to access this path and thus it is unknown whether the path exists at all (stat /media/iotpartners/6c75349d-eefb-41a9-8e19-594e09302251 and ls /media/iotpartners fail), so storing metadata for such locations don’t make sense…

1 Like

Ok, so it is the code in the library the one that checks if the path is accessible.



This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.