bitwiseworks / libc

LIBC Next (kLIBC fork)
9 stars 4 forks source link

readlink() #116

Closed SilvanScherrer closed 2 years ago

SilvanScherrer commented 3 years ago

when readlink() is used and the named file is not a symlink it sets errno = ENOENT, but according to linux manpage it should set EINVAL in this case.

When i'm not wrong this is set in lib/sys/fs.c in the end around liner 1320.

SilvanScherrer commented 3 years ago

this issue is seen while running the testcases of glib2

dmik commented 2 years ago

I cannot confirm this. This simple test.c compiled with gcc -Zomf test.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main (int argc, const char **argv)
{
  if (argc > 1)
  {
    char buf [260];
    ssize_t sz = readlink (argv [1], buf, sizeof (buf));
    buf [sz < 0 ? 0 : sz] = 0;
    printf ("readlink (%s) = %d [%s] %d (%s)\n", argv [1], sz, buf, errno, strerror (errno));
  }
  else
    printf ("Usage: %s <filename>\n", argv [0]);

  return 0;
}

gives the following output here:

D:>echo test.c >nosymlink.txt
D:>ln -s test.c symlink.txt

D:>test.exe symlink.txt
readlink (symlink.txt) = 6 [test.c] 0 (Error 0)

D:>test.exe nosymlink.txt
readlink (nosymlink.txt) = -1 [] 22 (Invalid argument)

I.e. when the argument to readlink is an existing regular file, this is properly reported as EINVAL.

ENOENT is only returned if this argument is a non-existing entity, which fully matches POSIX, see https://pubs.opengroup.org/onlinepubs/009696699/functions/readlink.html. Line 1320 in fs.c you refer to basically does just that.

Feel free to reopen if you prove me wrong.

SilvanScherrer commented 2 years ago

at least https://github.com/bitwiseworks/glib2-os2/blob/master/glib/tests/fileutils.c line 826 triggers it

dmik commented 2 years ago

This line refers LIBC bug #39, could you please specify which libc bug you meant there? #39 doesn't seem to be related at all...

I think that what happens there is that this line 806

oldpath = g_test_get_filename (G_TEST_DIST, "4096-random-bytes", NULL);

returns an invalid file name on OS/2 (because of an insufficient test env setup or such). The invalid name is fine for symlink — as soon as the symlink name is valid, all readlink will succeed because it doesn't check the target's (oldpath) existence, it just returns its value. However, when redlink tries to read oldpath itself, it discovers that the path is actually missing and returns ENOENT. If the file were not missing (as it should be with a proper setup), it would return EINVAL.

I suggest you to look at G_TEST_DIST definition and manually check if it points to a valid dir and if a file named 4096-random-bytes is actually there.