Marc Roessler
|
Behavior of readlink() on QNX
|
Marc Roessler
08/27/2009 5:43 AM
post36759
|
Behavior of readlink() on QNX
Hi,
I've noticed that on QNX one of the possible errnos of readlink() is ENOSYS,
which is returned in case the ResMgr offering the specified path does not support symlinks (e.g. true for /tmp on
embedded systems, which resides in shmen).
This breaks some apps, which don't expect ENOSYS. I've patched those to treat ENOSYS the same as EINVAL (which means:
checked path is not a symlink).
Is ENOSYS for readlink() part of POSIX or is this a QNX extension? Would returning EINVAL instead of ENOSYS break
anything?
Another thing I've noticed:
When calling readlink() on a path of "." on Linux, it correctly returns EINVAL ("is not a link").
When trying this on QNX (running the app via the IDE), the app runs in /tmp, which is symlinked to /dev/shmem. Calling
readlink() with path "." here returns ENOENT ("The named file doesn't exist").
Again, not sure what POSIX really says here, but I feel that the QNX readlink() behavior is not what I'd have expected..
.
Using realpath() before readlink() doesn't help as quick fix, since realpath() on /dev/shmem returns ENOENT as well
Greetings,
Marc
|
|
|
Steve Reid
|
Re: Behavior of readlink() on QNX
|
Steve Reid
08/27/2009 10:16 AM
post36776
|
Re: Behavior of readlink() on QNX
> Hi,
>
> I've noticed that on QNX one of the possible errnos of readlink() is ENOSYS,
> which is returned in case the ResMgr offering the specified path does not
> support symlinks (e.g. true for /tmp on embedded systems, which resides in
> shmen).
>
> This breaks some apps, which don't expect ENOSYS. I've patched those to treat
> ENOSYS the same as EINVAL (which means: checked path is not a symlink).
>
> Is ENOSYS for readlink() part of POSIX or is this a QNX extension? Would
> returning EINVAL instead of ENOSYS break anything?
Yes, ENOSYS is a Neutrino extension (resource managers are a Neutrino thing). I looked at the error codes that POSIX
gives, and none of them really covers the problem of the underlying filesystem not supporting symlinks. Someone else
might be able to comment further. At the very least, the documentation should say that ENOSYS is an extension.
>
>
> Another thing I've noticed:
> When calling readlink() on a path of "." on Linux, it correctly returns EINVAL
> ("is not a link").
> When trying this on QNX (running the app via the IDE), the app runs in /tmp,
> which is symlinked to /dev/shmem. Calling readlink() with path "." here
> returns ENOENT ("The named file doesn't exist").
> Again, not sure what POSIX really says here, but I feel that the QNX readlink(
> ) behavior is not what I'd have expected...
> Using realpath() before readlink() doesn't help as quick fix, since realpath()
> on /dev/shmem returns ENOENT as well
>
A RAM "filesystem" doesn't provide "." and ".." directory entries, so you could argue that readlink() is doing the right
thing (depending on the order that it checks things). If you run your program somewhere other than /dev/shmem, does it
give EINVAL?
Steve Reid (stever@qnx.com)
Technical Editor
QNX Software Systems
|
|
|
Neil Schellenberger(deleted)
|
Re: Behavior of readlink() on QNX
|
Neil Schellenberger(deleted)
08/27/2009 10:44 AM
post36785
|
Re: Behavior of readlink() on QNX
On Thu, 2009-08-27 at 10:16 -0400, Steve Reid wrote:
> > Is ENOSYS for readlink() part of POSIX or is this a QNX extension? Would
> > returning EINVAL instead of ENOSYS break anything?
>
> Yes, ENOSYS is a Neutrino extension (resource managers are a Neutrino
> thing). I looked at the error codes that POSIX gives, and none of them
> really covers the problem of the underlying filesystem not supporting
> symlinks. Someone else might be able to comment further. At the very
> least, the documentation should say that ENOSYS is an extension.
In general one the safest thing to assume is that the codes defined by
the standard are the minimal subset: any compliant implementation is
free to return others.... (I agree that our documentation should be as
complete as possible, though.)
Regards,
Neil
|
|
|
Marc Roessler
|
Re: Behavior of readlink() on QNX
|
Marc Roessler
08/27/2009 11:06 AM
post36797
|
Re: Behavior of readlink() on QNX
Neil, I think generally speaking you are right, but in this special case I don't fully agree...
What should an application do when it encounters a return/errno value that it doesn't know? It should log it and
probably exit, because something is not as expected and this probably means something is awfully wrong.
In this special case, EINVAL is not even an error, it is expected behavior: it happens whenever a path passed to
readlink() is not a link. ENOSYS means just the same: file system doesn't support symlinks, so of course the file is not
a symlink.
So ENOSYS needs to be handled the same way as EINVAL, but different from all other errnos that can occur. How does one
code that without the knowlwedge that EINVAL and ENOSYS practically mean the same on QNX? Exiting on unknown errnos
would be the wrong behavior, and continuing on unknown errors (hypothetical example: ENULL .. tha path is a NULL
pointer) would also be wrong.
So what this means is that an #ifdef QNX is required - which is kludgy.
Greetings,
Marc
|
|
|
Neil Schellenberger(deleted)
|
Re: Behavior of readlink() on QNX
|
Neil Schellenberger(deleted)
08/27/2009 11:14 AM
post36798
|
Re: Behavior of readlink() on QNX
On Thu, 2009-08-27 at 11:06 -0400, Marc Roessler wrote:
> Neil, I think generally speaking you are right, but in this special case I don't fully agree...
>
> What should an application do when it encounters a return/errno value that it doesn't know? It should log it and
probably exit, because something is not as expected and this probably means something is awfully wrong.
>
> In this special case, EINVAL is not even an error, it is expected behavior: it happens whenever a path passed to
readlink() is not a link. ENOSYS means just the same: file system doesn't support symlinks, so of course the file is not
a symlink.
> So ENOSYS needs to be handled the same way as EINVAL, but different from all other errnos that can occur. How does one
code that without the knowlwedge that EINVAL and ENOSYS practically mean the same on QNX? Exiting on unknown errnos
would be the wrong behavior, and continuing on unknown errors (hypothetical example: ENULL .. tha path is a NULL
pointer) would also be wrong.
>
> So what this means is that an #ifdef QNX is required - which is kludgy.
My observation was just a general one. However, I would argue -- again
from a general standpoint -- that if an application needs to perform a
certain way on a particular POSIX implementation, then it must perforce
contain implementation specific code. Consider the case where two
different implementations attach different semantics to a particular
errno return....
Regards,
Neil
P.S. Welcome to the joys of multi-platform programming ;-)
|
|
|
Marc Roessler
|
Re: Behavior of readlink() on QNX
|
Marc Roessler
08/27/2009 10:46 AM
post36787
|
Re: Behavior of readlink() on QNX
OK, considering that the shmem fs doesn't have . and .. entries, the readlink() behavior is indeed correct.
So the real question is whether the shmem RAM fs should have . and .. directory entries. Not being able to create
directories is one thing... but missing . and .., doesn't this break other things as well? Would "faking"those entries
without really creating directory support for the RAM/shmem fs break anything?
On the other hand, having real directory support for shmem filesystems also would be nice... Would it be hard to
implement? Or was this a design decision from the start not to have and directories in shmem?
Thanks & Greetings,
Marc
|
|
|
|