Fix eglib on AIX/PASE (mono/mono#17476)
authorCalvin Buckley <calvin@cmpct.info>
Thu, 24 Oct 2019 16:04:20 +0000 (13:04 -0300)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Thu, 24 Oct 2019 16:04:20 +0000 (18:04 +0200)
* fix eglib on AIX/PASE

* Work around access(2) syscall bug on PASE
  On PASE, X_OK will always returns true. This is contrary to
  how AIX behaves (though corresponds to documentation!). This
  is probably because it's an upcall to the ILE version of
  access, and that seemingly always returns true.

* Always export the dummy function in the test suite
  The AIX linker didn't export this properly, without using the
  giant sledgehammer of -bexpall. Write an export file and use
  it. This required some build system changes to expose an
  AIX-only automake conditional.

* Use a file that exists on PASE for tests
  PASE doesn't use Unix-style DNS resolution, so /etc/hosts is
  missing. Use /etc/magic, since that seems to be present.

* Don't use /bin on AIX/PASE for tests
  This is a symlink to /usr/bin, and it seems chdir/getcwd
  follows links. Use /usr instead, that is unlikely to be a
  symlink.

* Make a note what directory we're in if we fail test_cwd

* Change manual executable access check change per Jay

* Change test on POSIXy platforms to always use root directory

Commit migrated from https://github.com/mono/mono/commit/638e2c6a8614d25aad591112d3414e28641b97e0

src/mono/configure.ac
src/mono/mono/eglib/gfile-unix.c
src/mono/mono/eglib/test/Makefile.am
src/mono/mono/eglib/test/file.c
src/mono/mono/eglib/test/path.c
src/mono/mono/eglib/test/test-eglib.exp [new file with mode: 0644]

index 1afcf0b..5936374 100644 (file)
@@ -473,6 +473,8 @@ case "$host" in
                mono_cv_clang=no
                ;;
        *-*-aix*|*-*-os400*)
+               AC_DEFINE(HOST_AIX,1,[Targeting the AIX and PASE platforms])
+               host_aix=yes
                dnl IMPORTANT: For svr4 sonames on AIX, you should set
                dnl `OBJECT_MODE=64` when configuring.
                dnl libtool cannot generate functioning svr4 sonames on
@@ -576,6 +578,7 @@ AM_CONDITIONAL(HOST_ANDROID, test x$platform_android = xyes)
 AM_CONDITIONAL(HOST_TIZEN, test x$platform_tizen = xyes)
 AM_CONDITIONAL(HOST_IOS, test x$platform_ios = xyes)
 AM_CONDITIONAL(HOST_WASM, test x$platform_wasm = xyes)
+AM_CONDITIONAL(HOST_AIX, test x$host_aix = xyes)
 
 if test -z "$HOST_DARWIN_TRUE"; then :
 PLATFORM_AOT_SUFFIX=.dylib
index 5ba01df..eab9066 100644 (file)
@@ -55,8 +55,26 @@ g_file_test (const gchar *filename, GFileTest test)
        }
 
        if ((test & G_FILE_TEST_IS_EXECUTABLE) != 0) {
+#if !defined(__PASE__)
                if (access (filename, X_OK) == 0)
                        return TRUE;
+#else
+               /*
+                * PASE always returns true for X_OK; contrary to how AIX
+                * behaves (but *does* correspond to how it's documented!).
+                * This behaviour is also consistent with the ILE, so it's
+                * probably just an upcall returning the same results. As
+                * such, workaround it.
+                */
+               if (!have_stat)
+                       have_stat = (stat (filename, &st) == 0);
+               /* Hairy parens, but just manually try all permission bits */
+               if (have_stat && (
+                       ((st.st_mode & S_IXOTH)
+                               || ((st.st_mode & S_IXUSR) && (st.st_uid == getuid()))
+                               || ((st.st_mode & S_IXGRP) && (st.st_gid == getgid())))))
+                       return TRUE;
+#endif
        }
 #ifdef HAVE_LSTAT
        if ((test & G_FILE_TEST_IS_SYMLINK) != 0) {
index 68b68d6..c925bad 100644 (file)
@@ -1,6 +1,6 @@
 include $(top_srcdir)/mk/common.mk
 
-EXTRA_DIST = UTF-8.txt UTF-16BE.txt UTF-16LE.txt UTF-32BE.txt UTF-32LE.txt
+EXTRA_DIST = UTF-8.txt UTF-16BE.txt UTF-16LE.txt UTF-32BE.txt UTF-32LE.txt test-eglib.exp
 
 SOURCES = \
        enum.cpp        \
@@ -37,6 +37,10 @@ test_eglib_SOURCES = $(SOURCES)
 GLIB_TEST_FLAGS_COMMON = -Wall -DEGLIB_TESTS=1 -D_FORTIFY_SOURCE=2 -I$(srcdir)/.. -I.. -DDRIVER_NAME=\"EGlib\"
 CFLAGS += $(GLIB_TEST_FLAGS_COMMON)
 CXXFLAGS += $(GLIB_TEST_FLAGS_COMMON) @CXXFLAGS_COMMON@
+if HOST_AIX
+# This export file is required so test symbols are visible.
+LDFLAGS += -Wl,-bE:test-eglib.exp
+endif
 
 test_eglib_LDADD = ../libeglib.la $(LTLIBICONV)
 assertf_LDADD = ../libeglib.la $(LTLIBICONV)
index 88023c3..25473c0 100644 (file)
@@ -22,6 +22,9 @@ test_file_get_contents (void)
        gsize length;
 #ifdef G_OS_WIN32
        const gchar *filename = "c:\\Windows\\system.ini";
+#elif defined(__PASE__)
+       /* Most etc files don't exist in PASE. Try one that should exist. */
+       const gchar *filename = "/etc/magic";
 #else
        const gchar *filename = "/etc/hosts";
 #endif
index bd62bb7..3af25b1 100644 (file)
@@ -300,7 +300,11 @@ test_cwd (void)
 #ifdef G_OS_WIN32
        const gchar *newdir = "C:\\Windows";
 #else
-       const gchar *newdir = "/bin";
+       /*
+        * AIX/PASE have /bin -> /usr/bin, and chdir/getcwd follows links.
+        * Use a directory available on all systems that shouldn't be a link.
+        */
+       const gchar *newdir = "/";
 #endif
 
        if (dir == NULL)
@@ -312,7 +316,7 @@ test_cwd (void)
        
        dir = g_get_current_dir ();
        if (strcmp (dir, newdir) != 0)
-               return FAILED("Did not go to %s?", newdir);
+               return FAILED("Did not go to %s? Instead in %s", newdir, dir);
        g_free (dir);
        
        return OK;
diff --git a/src/mono/mono/eglib/test/test-eglib.exp b/src/mono/mono/eglib/test/test-eglib.exp
new file mode 100644 (file)
index 0000000..9c7cce2
--- /dev/null
@@ -0,0 +1,3 @@
+* This file is required so that the symbol is visibile and not GCed on AIX.
+dummy_test_export
+