directoryfile-permissionsvalaaptfile-listing

How can I read a folder owned by root with Vala?


I'm trying to read the path /var/cache/apt/archives with the following permissions:

drwxr-xr-x 3 root root 90112 ago 2 14:36 archives

And I got the following error:

ERROR: Error opening directory '/var/cache/apt/archives/partial': Permission denied

Can somebody give me a hand with this?

The source code is the following:

using Gtk;
using GLib;

private int64[] get_folder_data (File file, string space = "",     Cancellable? cancellable = null) throws Error
{
    FileEnumerator enumerator = file.enumerate_children (
    "standard::*",
    FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
    cancellable);

    int64 files = 0;
    int64 size  = 0;
    int64[] data = new int64[2];
    FileInfo info = null;

    while (cancellable.is_cancelled () == false && ((info = enumerator.next_file (cancellable)) != null)) {
        if (info.get_file_type () == FileType.DIRECTORY) {
            File subdir = file.resolve_relative_path (info.get_name ());
            get_folder_data (subdir, space + " ", cancellable);
        } else {
            files += 1;//Sum Files
            size  += info.get_size ();//Accumulates Size
        }
    }

    if (cancellable.is_cancelled ()) {
        throw new IOError.CANCELLED ("Operation was cancelled");
    }

    data[0] = files;
    data[1] = size;

    stdout.printf ("APT CACHE SIZE: %s\n", files.to_string());
    stdout.printf ("APT CACHE FILES: %s\n", size.to_string());

    return data;
}

public static int main (string[] args) {
    Gtk.init (ref args);

    File APT_CACHE_PATH = File.new_for_path ("/var/cache/apt/archives");
    try {
        get_folder_data (APT_CACHE_PATH, "", new Cancellable ());
    } catch (Error e) {
        stdout.printf ("ERROR: %s\n", e.message);    
    }
    Gtk.main ();
    return 0;
}

And the command I used for compile is the following:

valac --pkg gtk+-3.0 --pkg glib-2.0 --pkg gio-2.0 apt-cache.vala

Solution

  • If you run your app as a normal user, you have to exclude the "partial" dir, it has more restrictive permissions (0700):

    drwx------ 2 _apt root 4096 Jul 29 11:36 /var/cache/apt/archives/partial
    

    One way to exclude the partial dir is to just ignore any dir that is inaccessible:

    int64[] data = new int64[2];
    FileEnumerator enumerator = null;
    try {
        enumerator = file.enumerate_children (
            "standard::*",
            FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
            cancellable);
    }
    catch (IOError e) {
        stderr.printf ("WARNING: Unable to get size of dir '%s': %s\n", file.get_path (), e.message);
        data[0] = 0;
        data[1] = 0;
        return data;
    }
    

    In addition it might be a good idea to always explicitly ignore the partial folder.

    If you are planning to make your utility useful for the root user as well, you might even think of adding a command line option like "--include-partial-dir".

    Also the same thing can be done with simple bash commands which is much easier than writing your own program.

    du -sh /var/cache/apt/archives
    find /var/cache/apt/archives -type f | wc -l
    

    Note that du and find also warn about the inaccessible partial dir:

    $ du -sh /var/cache/apt/archives
    du: cannot read directory '/var/cache/apt/archives/partial': Permission denied
    4.6G    /var/cache/apt/archives
    
    $ find /var/cache/apt/archives -type f | wc -l
    find: '/var/cache/apt/archives/partial': Permission denied
    3732