After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 432651 - Add a glib-ish xdg_user_dir_lookup
Add a glib-ish xdg_user_dir_lookup
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
unspecified
Other All
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2007-04-23 16:00 UTC by Bastien Nocera
Modified: 2009-06-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
[PATCH] Retrieve special directories (7.14 KB, patch)
2007-05-24 16:17 UTC, Emmanuele Bassi (:ebassi)
none Details | Review
[PATCH] Add configure check for Carbon (1.12 KB, patch)
2007-05-24 18:42 UTC, Emmanuele Bassi (:ebassi)
none Details | Review
[PATCH] Retrieve special folders via logical id. (8.59 KB, patch)
2007-05-24 18:42 UTC, Emmanuele Bassi (:ebassi)
needs-work Details | Review
[PATCH] Test and document the special directories patch (3.28 KB, patch)
2007-05-24 18:42 UTC, Emmanuele Bassi (:ebassi)
none Details | Review
Retrieve special folders via logical id (13.28 KB, patch)
2007-05-26 14:26 UTC, Emmanuele Bassi (:ebassi)
needs-work Details | Review
[PATCH] Retrieve special folders via logical id (16.37 KB, patch)
2007-06-02 13:11 UTC, Emmanuele Bassi (:ebassi)
needs-work Details | Review
alternative approach (11.92 KB, patch)
2007-06-04 01:13 UTC, Matthias Clasen
none Details | Review
Combined patch (15.54 KB, patch)
2007-06-04 14:45 UTC, Michael Natterer
none Details | Review

Description Bastien Nocera 2007-04-23 16:00:11 UTC
xdg-user-dirs allows to use defaults for some known directories.

See
http://freedesktop.org/wiki/Software_2fxdg_2duser_2ddirs

It would be nice if glib had a version of xdg_user_dir_lookup, so the applications don't need to cut'n'paste the code.

It would also be useful if this code could monitor ~/.config/user-dirs.dirs and /etc/xdg/user-dirs.defaults so that applications are told straight away about possible location changes.
Comment 1 Behdad Esfahbod 2007-04-23 16:13:59 UTC
Humm, dupe of bug 328679?
Comment 2 Bastien Nocera 2007-04-23 16:28:27 UTC
g_user_data_dir() and g_user_config_dir() would be useful to implement this piece of code, but the purpose of this bug is to look up default user directories for a specific type of data, ie.
xdg_user_dir_lookup ("VIDEO") would return ~/Movies
Comment 3 Rodrigo Moya 2007-05-09 14:50:27 UTC
Is anyone working on this? If not, I'll give it a try
Comment 4 Bastien Nocera 2007-05-09 14:55:00 UTC
I haven't looked into implementing this either.
Comment 5 Alexander Larsson 2007-05-10 07:37:15 UTC
Remember that there are two common use cases for this:
1) quick one-time lookup when the user initiated an operations.
This can basically read the config file at the time and rely on kernel caching to make it work mostly ok.
2) Tracking a specific directory during the display of something.
Say nautilus tracking the desktop directory. It looks this up a *lot*, and would like this to be cached, but still it wants some form of updates when the setting changes. Ideally using file notification, but a cache that rereads the config file on access if the last read was more than N seconds ago might do.
Comment 6 Michael Natterer 2007-05-14 16:43:00 UTC
We just added Win32 and Carbon versions of that functionality to GIMP.
It's tested on the platforms and works. So if this goes into GLib,
just take the code:

http://svn.gnome.org/viewcvs/gimp/trunk/libgimpbase/gimpenv.c?view=markup

(function gimp_user_directory())
Comment 7 Emmanuele Bassi (:ebassi) 2007-05-24 16:17:03 UTC
Created attachment 88740 [details] [review]
[PATCH] Retrieve special directories


This is a preliminary patch adding the g_get_user_special_dir() function.
This function returns the full path for "special" directories, depending
on the platform, using a logical ID. On G_OS_WIN, SHGetSpecialFolderLocation()
is used; on G_OS_UNIX, the user configuration file defined by the
xdg-user-dirs specification is parsed and the path is extracted from it,
resolving the $HOME variable if needed.
---
 glib/gutils.c    |  220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/gutils.h    |   15 ++++
 tests/testglib.c |    6 ++
 3 files changed, 241 insertions(+), 0 deletions(-)
Comment 8 Emmanuele Bassi (:ebassi) 2007-05-24 18:42:21 UTC
Created attachment 88755 [details] [review]
[PATCH] Add configure check for Carbon


This patch adds a configure-time check for the Carbon framework and adds
the LDFLAGS necessary. It also adds a conditional (OS_CARBON) for Makefile
templates and a define (HAVE_CARBON) for source files including "config.h".
---
 configure.in |   18 +++++++++++++++++-
 1 files changed, 17 insertions(+), 1 deletions(-)
Comment 9 Emmanuele Bassi (:ebassi) 2007-05-24 18:42:27 UTC
Created attachment 88756 [details] [review]
[PATCH] Retrieve special folders via logical id.


This adds the g_get_user_special_dir() function. This function returns the
full path for "special" directories, depending on the platform, using a
logical ID. On G_OS_WIN, SHGetSpecialFolderLocation() is used; on G_OS_UNIX,
the user configuration file defined by the xdg-user-dirs specification is
parsed and the path is extracted from it, resolving the $HOME variable if
needed; on OS X, Carbon is used to retrieve the special directories.

Each path found is cached the first time it's retrieved; the cache expires
after fifteen minutes, in case the user changed the location of the directory.
---
 glib/gutils.c |  299 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/gutils.h |   15 +++
 2 files changed, 314 insertions(+), 0 deletions(-)
Comment 10 Emmanuele Bassi (:ebassi) 2007-05-24 18:42:31 UTC
Created attachment 88757 [details] [review]
[PATCH] Test and document the special directories patch


Add a test for the newly added g_get_user_special_dir() function; export
the symbol; let gtk-doc pick up the inline documentation.
---
 docs/reference/glib/glib-sections.txt       |    2 ++
 docs/reference/glib/tmpl/main.sgml          |    3 +++
 docs/reference/glib/tmpl/misc_utils.sgml    |   24 ++++++++++++++++++++++++
 docs/reference/gobject/tmpl/gparamspec.sgml |    2 ++
 glib/glib.symbols                           |    1 +
 tests/testglib.c                            |    6 ++++++
 6 files changed, 38 insertions(+), 0 deletions(-)
Comment 11 Bastien Nocera 2007-05-24 18:49:02 UTC
(In reply to comment #9)
> Created an attachment (id=88756) [edit]
> [PATCH] Retrieve special folders via logical id.
<snip>
> Each path found is cached the first time it's retrieved; the cache expires
> after fifteen minutes, in case the user changed the location of the directory.

Why not check if it's actually changed by either using inotify, or checking the mtime the next time it's accessed?
Comment 12 Emmanuele Bassi (:ebassi) 2007-05-24 18:55:04 UTC
using inotify would add the dependency to glib *and* would only work on linux, while the xdg-user-dirs code is meant to work on every *nix, as far as I understand.

checking the mtime might be better, in this case.
Comment 13 Michael Natterer 2007-05-24 19:11:59 UTC
G_OS_UNIX is TRUE on OSX too, so the xdg code must only be built
if (!G_OS_WIN32 && !HAVE_CARBON)
Comment 14 Emmanuele Bassi (:ebassi) 2007-05-24 19:52:17 UTC
(In reply to comment #11)

> Why not check if it's actually changed by either using inotify, or checking the
> mtime the next time it's accessed?

on second thought: given that we choose to cache the results, we need a way to expire the cache in the win32 and xdg-user-dirs cases, as both platforms can change the location of the directory associated to the logical id. it's not known if the carbon platform can do that too. so having a common expiration code path makes sense.

if we decide not to cache the results, there is a penalty for the xdg-user-dirs platform, where we need to hit a file; if both carbon and win32 calls are not smart enough, it would also have a penalty on those platforms (hit the registry/whatever osx uses).

so having an expiration time for the cache seems a good compromise, for the time being.

(In reply to comment #13)
> G_OS_UNIX is TRUE on OSX too, so the xdg code must only be built
> if (!G_OS_WIN32 && !HAVE_CARBON)

thanks, fixed in my trunk, will attach a patch (with the full license for the xdg_user_dir_lookup() function too).
Comment 15 Emmanuele Bassi (:ebassi) 2007-05-26 14:26:49 UTC
Created attachment 88844 [details] [review]
Retrieve special folders via logical id

This adds the g_get_user_special_dir() function. This function returns the
full path for "special" directories, depending on the platform, using a
logical ID. On G_OS_WIN, SHGetSpecialFolderLocation() is used; on G_OS_UNIX,
the user configuration file defined by the xdg-user-dirs specification is
parsed and the path is extracted from it, resolving the $HOME variable if
needed; on OS X, Carbon is used to retrieve the special directories.
    
Each path found is cached the first time it's retrieved; the cache expires
after fifteen minutes, in case the user changed the location of the directory.

This iteration fixes some issues of g_get_user_special_dir():
* do not compile xdg_user_dir_lookup() on Carbon;
* add MIT license notice above xdg_user_dir_lookup();
* load the entire file and split it in lines, instead of iterating over it;
* resolve a bare "$HOME" to the user's home directory;
* remove trailing slashes.

 configure.in                             |   18 +
 docs/reference/glib/glib-sections.txt    |    2 
 docs/reference/glib/tmpl/misc_utils.sgml |   24 ++
 glib/glib.symbols                        |    1 
 glib/gutils.c                            |  326 +++++++++++++++++++++++++++++++
 glib/gutils.h                            |   15 +
 tests/testglib.c                         |    8 
 7 files changed, 393 insertions(+), 1 deletion(-)
Comment 16 Daniel Macks 2007-05-29 03:24:53 UTC
For OS X, could you please adjust the configure tests to distinguish between (or at least clarify the flag-names for) the platform itself vs the way you expect to locate the special folders on that platform? As it stands, they are mixed: approximately "presence of Carbon.h, therefore use its special-dir lookups instead of xdg's". My concern is for OS X users who want a self-consistent X11 world and therefore would like glib2 to use xdg. Maybe configure.in not gutils.c should have the logic to decide what back-end to use for g_get_user_special_dir() and pass it in as the value of a SPECIAL_DIR_SUPPORT config.h token? That way there could be a --use-xdg to force use of xdg_user_dir_lookup regardless of platform for those who really want it. Sounds like here, you're trying to second-guess potential platform-missupport in libxdg...if a lower-level lib is broken, then *they* should be get it fixed so it propagates correctly (and more importantly, consistently) into all who use that lib.
Comment 17 Matthias Clasen 2007-05-30 03:48:47 UTC
This should probably be part of the GUserDirectory docs:

+ * The #GUserDirectory enumeration can be extended at later date. Not every
+ * platform has a directory for every logical id in the #GUserDirectory
+ * enumeration.


Wrt to the caching, I'd prefer if we did the same thing we do e.g. for icon themes in gtk:

Compare the actual mtime of the file, and reload it if it changed, but not stat the file more often than some small constant. the icon theme code uses 5 seconds,
which may be a little short, but the 15 minutes you use here look a bit too long.
Comment 18 Emmanuele Bassi (:ebassi) 2007-06-02 13:10:24 UTC
(In reply to comment #17)
> This should probably be part of the GUserDirectory docs:
> 
> + * The #GUserDirectory enumeration can be extended at later date. Not every
> + * platform has a directory for every logical id in the #GUserDirectory
> + * enumeration.

done.

> Wrt to the caching, I'd prefer if we did the same thing we do e.g. for icon
> themes in gtk:
> 
> Compare the actual mtime of the file, and reload it if it changed, but not stat
> the file more often than some small constant. the icon theme code uses 5
> seconds,
> which may be a little short, but the 15 minutes you use here look a bit too
> long.

done this too. the cache if G_OS_UNIX && !HAVE_CARBON is expired if the mtime of the configuration file has changed, but stat() is invoked only if more than five seconds are passed since the last check; on the other platforms, the cache expires automatically after 15 minutes because we don't have notification of user changes.

Comment 19 Emmanuele Bassi (:ebassi) 2007-06-02 13:11:34 UTC
Created attachment 89234 [details] [review]
[PATCH] Retrieve special folders via logical id


This adds the g_get_user_special_dir() function. This function returns the
full path for "special" directories, depending on the platform, using a
logical ID. On G_OS_WIN, SHGetSpecialFolderLocation() is used; on G_OS_UNIX,
the user configuration file defined by the xdg-user-dirs specification is
parsed and the path is extracted from it, resolving the $HOME variable if
needed; on OS X, Carbon is used to retrieve the special directories.

Each path found is cached the first time it's retrieved. If using the XDG
user directories, the cache is expired when the configuration file mtime
changes (stat() on the configuration file is called only if 5 seconds are
elapsed since the last check). On the other platforms, where we don't have
any notification of user changes the cache is expired after 15 minutes.
---
 ChangeLog                                |   12 +
 configure.in                             |   18 ++-
 docs/reference/ChangeLog                 |    5 +
 docs/reference/glib/glib-sections.txt    |    2 +
 docs/reference/glib/tmpl/misc_utils.sgml |   24 ++
 glib/glib.symbols                        |    1 +
 glib/gutils.c                            |  369 ++++++++++++++++++++++++++++++
 glib/gutils.h                            |   37 +++
 tests/testglib.c                         |    8 +
 9 files changed, 475 insertions(+), 1 deletions(-)
Comment 20 Matthias Clasen 2007-06-03 00:21:07 UTC
I don't see where maybe_expire_xdg_user_dirs updates g_user_special_dirs_mtime ?
Also, don't you want to keep two times around 
1) the mtime of user-dirs.dirs
2) the time you last stat'ed that file 
?
Comment 21 Emmanuele Bassi (:ebassi) 2007-06-03 12:10:31 UTC
(In reply to comment #20)
> I don't see where maybe_expire_xdg_user_dirs updates g_user_special_dirs_mtime
> ?

the mtime is updated each time the cache string vector is created; if maybe_expire_xdg_user_dirs() nullified the cache because the st_mtime of the user-dirs.dirs file was greater than the cache mtime we keep, then st_mtime will be surely smaller than the value returned by the call to time() we do when we recreate the cache. as we update the cache mtime when the cache was last expired then it'll be also the last time the file was actually stat()-ed by maybe_expire_xdg_user_dirs().

> Also, don't you want to keep two times around 
> 1) the mtime of user-dirs.dirs
> 2) the time you last stat'ed that file 
> ?

I don't think it's needed, but I can rework the logic to be more explicit.

Comment 22 Matthias Clasen 2007-06-03 20:40:04 UTC
I think you need both times. If you only ever update the mtime when you reread
the user-dirs.dirs file, then this check

+  if (now < g_user_special_dirs_mtime + 5)
+    return;

will not trigger anymore once the 5 seconds have passed, so you'll stat
the file in every may_expire_xdg_user_dirs() call after the 5 seconds, until
the file changes and you get a fresh mtime. I think the effect we want is that

a) we only reread the file if it actually changed
b) we don't stat the file more often that every 5 seconds

Your code achieves a), but it only achieves b) for the first 5 seconds after a 
reload. 

All of this analysis without actually running the code, so take it with a grain of salt...
Comment 23 Matthias Clasen 2007-06-04 00:20:06 UTC
looking some more at this, I think we want to handle the xdg-user-dirs case somewhat differently. The current code parses the user-dirs.dirs file once for
each directory that is looked up; and if that directory is NULL, it parses
the file over and over. 

Since we are caching, I'd say we should store all directories when we parse the file, and not reparse the file if a directory is NULL.
Comment 24 Matthias Clasen 2007-06-04 01:13:40 UTC
Created attachment 89307 [details] [review]
alternative approach
Comment 25 Matthias Clasen 2007-06-04 01:31:04 UTC
Here is a patch that does things a bit differently:

1) it keeps two separate timestamps for the last stat time and
  the mtime

2) it reads all dirs in one go

Note that I haven't tested it other than compiling the xdg version
Comment 26 Michael Natterer 2007-06-04 14:45:43 UTC
Created attachment 89334 [details] [review]
Combined patch

This one combines the stuff by ebassi and mclasen and fixes the
configure check for carbon.
Comment 27 Matthias Clasen 2007-06-04 14:55:55 UTC
2007-06-04  Matthias Clasen  <mclasen@redhat.com>

        Add support for a number of special directories, as
        defined by the xdg-user-dirs specification.  (#432651,
        Bastien Nocera, Emmanuele Bassi, Michael Natterer)

        * glib/glib.symbols:
        * glib/gutils.[hc]: Add the GUserDirectory enum and
        g_get_user_special_dir(), with implementations based
        on the xdg-user-dirs spec and on native interfaces
        for Win32 and Carbon.

        * configure.in: Add Carbon checks.

        * tests/tetsglib.c: Test g_get_user_special_dir().