Liu Hao:
> There are a few resolution to this at different levels. The most ideal
> solution would be providing an `access()` function that behaves
> expectedly in gnulib or libiberty, so this recipe can be ported
> elsewhere. Modifying GCC source should be considered the least preferred
> and last option.

OK, that's what I thought. I've attached a new patch for libiberty,
could you please have a quick look at it before I submit it to GCC?

It currently only handles F_OK which is the only case which really
seems to matter for GCC. I do not know how to check if a file is effectively
readable/writeable/executable in the windows api. And it seems
reimplementing R_OK and all the other flags would mean effectively
rewriting the complete access function. What do you think?

Best regards,
Johannes

---
 gcc/gcc.c             | 26 +++++++--------
 include/libiberty.h   |  3 ++
 libiberty/Makefile.in | 19 ++++++++---
 libiberty/xaccess.c   | 74 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 104 insertions(+), 18 deletions(-)
 create mode 100644 libiberty/xaccess.c

diff --git a/gcc/gcc.c b/gcc/gcc.c
index 955a08cc8e8..7b4d3cc8326 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -2804,7 +2804,7 @@ access_check (const char *name, int mode)
        return -1;
     }
 
-  return access (name, mode);
+  return xaccess (name, mode);
 }
 
 /* Callback for find_a_file.  Appends the file name to the directory
@@ -2856,12 +2856,12 @@ find_a_file (const struct path_prefix *pprefix, const 
char *name, int mode,
   struct file_at_path_info info;
 
 #ifdef DEFAULT_ASSEMBLER
-  if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
+  if (! strcmp (name, "as") && xaccess (DEFAULT_ASSEMBLER, mode) == 0)
     return xstrdup (DEFAULT_ASSEMBLER);
 #endif
 
 #ifdef DEFAULT_LINKER
-  if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0)
+  if (! strcmp (name, "ld") && xaccess (DEFAULT_LINKER, mode) == 0)
     return xstrdup (DEFAULT_LINKER);
 #endif
 
@@ -2869,7 +2869,7 @@ find_a_file (const struct path_prefix *pprefix, const 
char *name, int mode,
 
   if (IS_ABSOLUTE_PATH (name))
     {
-      if (access (name, mode) == 0)
+      if (xaccess (name, mode) == 0)
        return xstrdup (name);
 
       return NULL;
@@ -4528,7 +4528,7 @@ process_command (unsigned int decoded_options_count,
          long offset;
          int consumed;
 #ifdef HAVE_TARGET_OBJECT_SUFFIX
-         arg = convert_filename (arg, 0, access (arg, F_OK));
+         arg = convert_filename (arg, 0, xaccess (arg, F_OK));
 #endif
          /* For LTO static archive support we handle input file
             specifications that are composed of a filename and
@@ -4543,7 +4543,7 @@ process_command (unsigned int decoded_options_count,
               fname[p - arg] = '\0';
              /* Only accept non-stdin and existing FNAME parts, otherwise
                 try with the full name.  */
-             if (strcmp (fname, "-") == 0 || access (fname, F_OK) < 0)
+             if (strcmp (fname, "-") == 0 || xaccess (fname, F_OK) < 0)
                {
                  free (fname);
                  fname = xstrdup (arg);
@@ -4552,9 +4552,9 @@ process_command (unsigned int decoded_options_count,
          else
            fname = xstrdup (arg);
 
-          if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
+          if (strcmp (fname, "-") != 0 && xaccess (fname, F_OK) < 0)
            {
-             bool resp = fname[0] == '@' && access (fname + 1, F_OK) < 0;
+             bool resp = fname[0] == '@' && xaccess (fname + 1, F_OK) < 0;
              error ("%s: %m", fname + resp);
            }
           else
@@ -5383,7 +5383,7 @@ do_spec_1 (const char *spec, int inswitch, const char 
*soft_matched_part)
 
              if ((!save_temps_flag)
                  && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR 
(st.st_mode))
-                 && (access (HOST_BIT_BUCKET, W_OK) == 0))
+                 && (xaccess (HOST_BIT_BUCKET, W_OK) == 0))
                {
                  obstack_grow (&obstack, HOST_BIT_BUCKET,
                                strlen (HOST_BIT_BUCKET));
@@ -7545,7 +7545,7 @@ driver::set_up_specs () const
   strcpy (specs_file, standard_exec_prefix);
   strcat (specs_file, spec_machine_suffix);
   strcat (specs_file, "specs");
-  if (access (specs_file, R_OK) == 0)
+  if (xaccess (specs_file, R_OK) == 0)
     read_specs (specs_file, true, false);
 
   /* Process any configure-time defaults specified for the command line
@@ -7865,7 +7865,7 @@ driver::maybe_print_and_exit () const
          if (ld == NULL)
 # endif
          ld = concat (DEFAULT_LINKER, use_ld, NULL);
-         if (access (ld, X_OK) == 0)
+         if (xaccess (ld, X_OK) == 0)
            {
              printf ("%s\n", ld);
              return (0);
@@ -9309,7 +9309,7 @@ static const char *
 if_exists_spec_function (int argc, const char **argv)
 {
   /* Must have only one argument.  */
-  if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
+  if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! xaccess (argv[0], R_OK))
     return argv[0];
 
   return NULL;
@@ -9327,7 +9327,7 @@ if_exists_else_spec_function (int argc, const char **argv)
   if (argc != 2)
     return NULL;
 
-  if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
+  if (IS_ABSOLUTE_PATH (argv[0]) && ! xaccess (argv[0], R_OK))
     return argv[0];
 
   return argv[1];
diff --git a/include/libiberty.h b/include/libiberty.h
index 0823614c00e..421fdb0e40a 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -713,6 +713,9 @@ extern void setproctitle (const char *name, ...);
 /* Increase stack limit if possible.  */
 extern void stack_limit_increase (unsigned long);
 
+/* Check if file is accessible.  */
+extern int xaccess (const char *pathname, int mode);
+
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
 
 /* Drastically simplified alloca configurator.  If we're using GCC,
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index ed1b334c361..65229842bdb 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -158,8 +158,8 @@ CFILES = alloca.c argv.c asprintf.c atexit.c                
                \
        vasprintf.c vfork.c vfprintf.c vprintf.c vprintf-support.c      \
         vsnprintf.c vsprintf.c                                         \
        waitpid.c                                                       \
-       xasprintf.c xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c     \
-        xstrerror.c xstrndup.c xvasprintf.c
+       xaccess.c xasprintf.c xatexit.c xexit.c xmalloc.c xmemdup.c     \
+        xstrdup.c xstrerror.c xstrndup.c xvasprintf.c
 
 # These are always included in the library.  The first four are listed
 # first and by compile time to optimize parallel builds.
@@ -191,9 +191,9 @@ REQUIRED_OFILES =                                           
        \
        ./splay-tree.$(objext) ./stack-limit.$(objext)                  \
        ./strerror.$(objext) ./strsignal.$(objext)                      \
        ./timeval-utils.$(objext) ./unlink-if-ordinary.$(objext)        \
-       ./xasprintf.$(objext) ./xatexit.$(objext) ./xexit.$(objext)     \
-       ./xmalloc.$(objext) ./xmemdup.$(objext) ./xstrdup.$(objext)     \
-       ./xstrerror.$(objext) ./xstrndup.$(objext)                      \
+       ./xaccess.$(objext) ./xasprintf.$(objext) ./xatexit.$(objext)   \
+       ./xexit.$(objext) ./xmalloc.$(objext) ./xmemdup.$(objext)       \
+       ./xstrdup.$(objext) ./xstrerror.$(objext) ./xstrndup.$(objext)  \
        ./xvasprintf.$(objext)
 
 # These are all the objects that configure may add to the library via
@@ -1630,6 +1630,15 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir
        else true; fi
        $(COMPILE.c) $(srcdir)/waitpid.c $(OUTPUT_OPTION)
 
+./xaccess.$(objext): $(srcdir)/xaccess.c
+       if [ x"$(PICFLAG)" != x ]; then \
+         $(COMPILE.c) $(PICFLAG) $(srcdir)/xaccess.c -o pic/$@; \
+       else true; fi
+       if [ x"$(NOASANFLAG)" != x ]; then \
+         $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/xaccess.c -o 
noasan/$@; \
+       else true; fi
+       $(COMPILE.c) $(srcdir)/xaccess.c $(OUTPUT_OPTION)
+
 ./xasprintf.$(objext): $(srcdir)/xasprintf.c config.h $(INCDIR)/ansidecl.h \
        $(INCDIR)/libiberty.h
        if [ x"$(PICFLAG)" != x ]; then \
diff --git a/libiberty/xaccess.c b/libiberty/xaccess.c
new file mode 100644
index 00000000000..e0183963cfa
--- /dev/null
+++ b/libiberty/xaccess.c
@@ -0,0 +1,74 @@
+/* check users permission to access files.
+   Copyright (C) 1989-2018 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth 
Floor,
+Boston, MA 02110-1301, USA.  */
+
+/*
+
+@deftypefn Replacement int xaccess (const char *pathname, int mode);
+
+Check whether the calling process can access pathname. This usually
+directly forwards to @code{access}, but some special cases are handled
+manually because of portability issues.
+
+@end deftypefn
+
+*/
+
+#ifdef _WIN32
+#include <windows.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+int
+xaccess (const char *pathname, int mode)
+{
+  /* Win32: only msvcrt.dll handles nul files, msvcr* does not. */
+#ifdef _WIN32
+  if (mode == F_OK)
+    {
+      if (GetFileAttributesA(pathname) == INVALID_FILE_ATTRIBUTES)
+        {
+          switch (GetLastError())
+            {
+              case ERROR_FILE_NOT_FOUND:
+              case ERROR_PATH_NOT_FOUND:
+                errno = ENOENT;
+                break;
+              case ERROR_ACCESS_DENIED:
+                errno = EACCES;
+                break;
+              default:
+                errno = EINVAL;
+            }
+          return -1;
+        }
+      else
+        {
+          return 0;
+        }
+    }
+  else
+    {
+      return access(pathname, mode);
+    }
+#else
+  return access(pathname, mode);
+#endif
+}
-- 
2.19.2



_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to