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 778798 - gio cannot handle files in directories with strlen(realpath(..)) > PATH_MAX
gio cannot handle files in directories with strlen(realpath(..)) > PATH_MAX
Status: RESOLVED OBSOLETE
Product: glib
Classification: Platform
Component: gio
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2017-02-16 22:46 UTC by Phillip Berndt
Modified: 2018-05-24 19:24 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Example code which should not fail (817 bytes, text/x-csrc)
2017-02-16 22:46 UTC, Phillip Berndt
  Details
Patch to support long filenames in glib's stdio wrapper (9.55 KB, patch)
2017-02-24 17:05 UTC, Phillip Berndt
none Details | Review
Patch to support long filenames in glib's stdio wrapper (9.54 KB, patch)
2017-02-24 17:12 UTC, Phillip Berndt
none Details | Review
Patch to support long filenames in glib's stdio wrapper (9.57 KB, patch)
2017-02-24 17:15 UTC, Phillip Berndt
none Details | Review
Patch to support long filenames in GLocalFile (24.59 KB, patch)
2017-02-24 21:30 UTC, Phillip Berndt
none Details | Review

Description Phillip Berndt 2017-02-16 22:46:14 UTC
Created attachment 346024 [details]
Example code which should not fail

gio fails to do IO on files whose absolute path is longer than PATH_MAX. By this I do *not* mean that returning the absolute path fails. If you are in a directory that happens to have a long name and create a GFile on "./foo", then reading from this file fails. This should not happen and is a bug. *All* other tools I have at hand manage to handle this situation.

I'll attach example code that fails with

Error opening file: File name too long: File name too long

even though all it attempts to do is to g_file_read() on g_file_new_for_commandline_arg("my-file").
Comment 1 Philip Withnall 2017-02-21 11:06:48 UTC
That’s because GLocalFile canonicalises the file path as soon as the GFile is created, which makes the path absolute. This is necessary because it cannot rely on the cwd remaining the same throughout the lifetime of the GFile.

I guess this could be fixed by checking if the canonical filename is longer than PATH_MAX before calling g_open() on it in g_local_file_read(). If so, it would have to split the canonical filename into directory components and use dirfd() and openat() to open them in sequence, so that each individual openat() call doesn’t exceed PATH_MAX.

This would have to be done for all places in glocalfile.c where a canonical path is passed down to libc.

Patches welcome. :-)
Comment 2 Phillip Berndt 2017-02-24 17:05:04 UTC
Created attachment 346652 [details] [review]
Patch to support long filenames in glib's stdio wrapper

Thanks for getting back to me. I thought so. Thanks for the hints on an implementation. g_open isn't the only call that needs wrapping, but *any* I/O. I looked into this, and thought that GLib's stdio wrapper might be the best place to implement this.

However, things do become quite messy. I'll attach a patch which wraps every libc call with the corresponding __at version as a fallback in case a ENAMETOOLONG happens. You'll see what I mean. The code does what it should, and is quite clean considering what it does (well, except for the helper macro maybe), but it still is a severe reduction in maintainability.
Comment 3 Phillip Berndt 2017-02-24 17:12:49 UTC
Created attachment 346653 [details] [review]
Patch to support long filenames in glib's stdio wrapper
Comment 4 Phillip Berndt 2017-02-24 17:15:11 UTC
Created attachment 346654 [details] [review]
Patch to support long filenames in glib's stdio wrapper
Comment 5 Philip Withnall 2017-02-24 17:32:46 UTC
(In reply to Phillip Berndt from comment #2)
> Created attachment 346652 [details] [review] [review]
> Patch to support long filenames in glib's stdio wrapper

Thanks for the patch!

> Thanks for getting back to me. I thought so. Thanks for the hints on an
> implementation. g_open isn't the only call that needs wrapping, but *any*
> I/O. I looked into this, and thought that GLib's stdio wrapper might be the
> best place to implement this.

I don’t think the stdio wrapper is the right place to implement this, as it then breaks people’s expectations that g_open() behaves exactly like open() — it will no longer return ENAMETOOLONG in some situations.

I think glocalfile.c is the right place to do this, as that’s where the path canonicalisation is introduced, and it’s at a higher level of abstraction from g_open(), so we care less about behaving exactly like the underlying libc() call.

(The only real reason that g_open() exists is to abstract POSIX differences between platforms like Linux and Windows.)

> However, things do become quite messy. I'll attach a patch which wraps every
> libc call with the corresponding __at version as a fallback in case a
> ENAMETOOLONG happens. You'll see what I mean. The code does what it should,
> and is quite clean considering what it does (well, except for the helper
> macro maybe), but it still is a severe reduction in maintainability.

I think it would be better to move this code into glocalfile.c, and use the same approach to wrap all of its calls to g_open(), g_stat(), etc. IIRC all the relevant calls will be in glocalfile.c. I guess there might be some in the other glocal*.c files.
Comment 6 Phillip Berndt 2017-02-24 21:30:23 UTC
Created attachment 346669 [details] [review]
Patch to support long filenames in GLocalFile

Here's a variant that wraps the functions inside GLocalFile. Since paths are passed on to GLocalFileInfo and GLocalFileOutputStream, both are patched to use the wrappers as well.

With this patch, I am able to open files in deeply nested directories. Using gedit, I can open, edit and save files.

The save file/open file dialog however still shows an error. I've also noticed that some major programs appear to work under the assumption that they can throw the filename reported by GIO against arbitrary other glib functions, especially glib's file utility functions, and hence still cannot handle this case. Nemo (that is, Cinnamon's nautilus fork) is an example.
Comment 7 Philip Withnall 2017-02-27 08:53:56 UTC
(In reply to Phillip Berndt from comment #6)
> Created attachment 346669 [details] [review] [review]
> Patch to support long filenames in GLocalFile
> 
> Here's a variant that wraps the functions inside GLocalFile. Since paths are
> passed on to GLocalFileInfo and GLocalFileOutputStream, both are patched to
> use the wrappers as well.

That looks like a better approach. I’ve got some review comments (mostly relating to following the coding style in the surrounding file), but I think we should get some feedback on the overall approach from a GLib maintainer before any more time is spent on the patch.

Matthias, Allison, what do you think about an ENAMETOOLONG handling loop in GLocalFile and friends?

> With this patch, I am able to open files in deeply nested directories. Using
> gedit, I can open, edit and save files.

Great!

> The save file/open file dialog however still shows an error. I've also
> noticed that some major programs appear to work under the assumption that
> they can throw the filename reported by GIO against arbitrary other glib
> functions, especially glib's file utility functions, and hence still cannot
> handle this case. Nemo (that is, Cinnamon's nautilus fork) is an example.

I’m inclined to treat that as a bug in those applications, although the documentation in GLib could be improved (after applying this patch) to point out about ENAMETOOLONG.
Comment 8 Allison Karlitskaya (desrt) 2017-03-23 12:06:57 UTC
When did you actually hit this problem?
Comment 9 Allison Karlitskaya (desrt) 2017-03-23 12:08:38 UTC
just for reference:

/usr/include/linux/limits.h:#define PATH_MAX        4096	/* # chars in a path name including nul */
Comment 10 GNOME Infrastructure Team 2018-05-24 19:24:18 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glib/issues/1245.