summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog11
-rw-r--r--winsup/cygwin/cygwin.din3
-rw-r--r--winsup/cygwin/include/cygwin/stdlib.h3
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/path.cc24
-rw-r--r--winsup/cygwin/posix.sgml3
-rw-r--r--winsup/cygwin/syscalls.cc30
7 files changed, 65 insertions, 12 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index f7cc25d6b..7eb216320 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,16 @@
2009-09-25 Eric Blake <ebb9@byu.net>
+ * syscalls.cc (fchmodat): lchmod is not yet implemented.
+ (euidaccess): New function.
+ * path.cc (realpath): Update comment.
+ (canonicalize_file_name): New function.
+ * include/cygwin/stdlib.h (canonicalize_file_name): Declare it.
+ * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
+ * cygwin.din: Export canonicalize_file_name, eaccess, euidaccess.
+ * posix.sgml: Mention them.
+
+2009-09-25 Eric Blake <ebb9@byu.net>
+
* fhandler.h (fhandler_base::fhaccess): Add parameter.
* security.h (check_file_access, check_registry_access): Likewise.
* security.cc (check_file_access, check_registry_access)
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 52cd362c2..bee9cd1c1 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -165,6 +165,7 @@ cabsf NOSIGFE
_cabsf = cabsf NOSIGFE
calloc SIGFE
_calloc = calloc SIGFE
+canonicalize_file_name SIGFE
cbrt NOSIGFE
_cbrt = cbrt NOSIGFE
cbrtf NOSIGFE
@@ -296,6 +297,7 @@ dup SIGFE
_dup = dup SIGFE
dup2 SIGFE
_dup2 = dup2 SIGFE
+eaccess = euidaccess SIGFE
ecvt SIGFE
_ecvt = ecvt SIGFE
ecvtbuf SIGFE
@@ -341,6 +343,7 @@ _erff = erff NOSIGFE
err SIGFE
__errno NOSIGFE
errx SIGFE
+euidaccess SIGFE
execl SIGFE
_execl = execl SIGFE
execle SIGFE
diff --git a/winsup/cygwin/include/cygwin/stdlib.h b/winsup/cygwin/include/cygwin/stdlib.h
index d16e4bbe8..edf00a073 100644
--- a/winsup/cygwin/include/cygwin/stdlib.h
+++ b/winsup/cygwin/include/cygwin/stdlib.h
@@ -1,6 +1,6 @@
/* stdlib.h
- Copyright 2005, 2006, 2007 Red Hat Inc.
+ Copyright 2005, 2006, 2007, 2008, 2009 Red Hat Inc.
This file is part of Cygwin.
@@ -23,6 +23,7 @@ void setprogname (const char *);
#ifndef __STRICT_ANSI__
char *realpath (const char *, char *);
+char *canonicalize_file_name (const char *);
int unsetenv (const char *);
char *initstate (unsigned seed, char *state, size_t size);
long random (void);
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index cf0a1168b..bd051031a 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -366,12 +366,13 @@ details. */
210: New ctype layout using variable ctype pointer. Export __ctype_ptr__.
211: Export fpurge, mkstemps.
212: Add and export libstdc++ malloc wrappers.
+ 213: Export canonicalize_file_name, eaccess, euidaccess.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 212
+#define CYGWIN_VERSION_API_MINOR 213
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 89552d999..e543dd4b7 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2845,7 +2845,7 @@ cygwin_conv_to_full_posix_path (const char *path, char *posix_path)
MAX_PATH);
}
-/* The realpath function is supported on some UNIX systems. */
+/* The realpath function is required by POSIX:2008. */
extern "C" char *
realpath (const char *path, char *resolved)
@@ -2876,11 +2876,9 @@ realpath (const char *path, char *resolved)
path_conv real_path (tpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
- /* Linux has this funny non-standard extension. If "resolved" is NULL,
- realpath mallocs the space by itself and returns it to the application.
- The application is responsible for calling free() then. This extension
- is backed by POSIX, which allows implementation-defined behaviour if
- "resolved" is NULL. That's good enough for us to do the same here. */
+ /* POSIX 2008 requires malloc'ing if resolved is NULL, and states
+ that using non-NULL resolved is asking for portability
+ problems. */
if (!real_path.error && real_path.exists ())
{
@@ -2894,14 +2892,24 @@ realpath (const char *path, char *resolved)
return resolved;
}
- /* FIXME: on error, we are supposed to put the name of the path
- component which could not be resolved into RESOLVED. */
+ /* FIXME: on error, Linux puts the name of the path
+ component which could not be resolved into RESOLVED, but POSIX
+ does not require this. */
if (resolved)
resolved[0] = '\0';
set_errno (real_path.error ?: ENOENT);
return NULL;
}
+/* Linux provides this extension. Since the only portable use of
+ realpath requires a NULL second argument, we might as well have a
+ one-argument wrapper. */
+extern "C" char *
+canonicalize_file_name (const char *path)
+{
+ return realpath (path, NULL);
+}
+
/* Return non-zero if path is a POSIX path list.
This is exported to the world as cygwin_foo by cygwin.din.
diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml
index 1b9d8259e..48dce6c96 100644
--- a/winsup/cygwin/posix.sgml
+++ b/winsup/cygwin/posix.sgml
@@ -890,6 +890,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
dn_expand
dn_skipname
drem
+ eaccess
endusershell
err
errx
@@ -1005,6 +1006,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
asnprintf
asprintf
asprintf_r
+ canonicalize_file_name
dremf
envz_add
envz_entry
@@ -1012,6 +1014,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
envz_merge
envz_remove
envz_strip
+ euidaccess
exp10
exp10f
fcloseall
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 3eb77fd07..da9cda507 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1580,6 +1580,29 @@ access (const char *fn, int flags)
return res;
}
+/* Linux provides this extension; it is basically a wrapper around the
+ POSIX:2008 faccessat (AT_FDCWD, fn, flags, AT_EACCESS). We also
+ provide eaccess as an alias for this, in cygwin.din. */
+extern "C" int
+euidaccess (const char *fn, int flags)
+{
+ // flags were incorrectly specified
+ int res = -1;
+ if (flags & ~(F_OK|R_OK|W_OK|X_OK))
+ set_errno (EINVAL);
+ else
+ {
+ fhandler_base *fh = build_fh_name (fn, NULL, PC_SYM_FOLLOW, stat_suffixes);
+ if (fh)
+ {
+ res = fh->fhaccess (flags, true);
+ delete fh;
+ }
+ }
+ debug_printf ("returning %d", res);
+ return res;
+}
+
static void
rename_append_suffix (path_conv &pc, const char *path, size_t len,
const char *suffix)
@@ -3878,9 +3901,12 @@ fchmodat (int dirfd, const char *pathname, mode_t mode, int flags)
myfault efault;
if (efault.faulted (EFAULT))
return -1;
- if (flags & ~AT_SYMLINK_NOFOLLOW)
+ if (flags)
{
- set_errno (EINVAL);
+ /* BSD has lchmod, but Linux does not. POSIX says
+ AT_SYMLINK_NOFOLLOW is allowed to fail on symlinks; but Linux
+ blindly fails even for non-symlinks. */
+ set_errno ((flags & ~AT_SYMLINK_NOFOLLOW) ? EINVAL : EOPNOTSUPP);
return -1;
}
char *path = tp.c_get ();