summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2003-03-10 00:07:01 +0000
committerChristopher Faylor <cgf@redhat.com>2003-03-10 00:07:01 +0000
commit9de384d5cbf6336cd062feae6334b8a5a71cbdd2 (patch)
tree62819ec88b1a51092dde45d706ae8ea6d44a0e38
parent2247a5b5b5ecb392107a270632634d9e0501d392 (diff)
downloadgdb-9de384d5cbf6336cd062feae6334b8a5a71cbdd2.tar.gz
merge from trunk
-rw-r--r--winsup/cygwin/ChangeLog51
-rw-r--r--winsup/cygwin/Makefile.in62
-rw-r--r--winsup/cygwin/cygserver_shm.h147
-rw-r--r--winsup/cygwin/cygwin.din20
-rw-r--r--winsup/cygwin/glob.c942
-rw-r--r--winsup/cygwin/include/cygwin/version.h7
-rw-r--r--winsup/cygwin/include/sys/cygwin.h2
-rw-r--r--winsup/cygwin/include/sys/mman.h54
-rw-r--r--winsup/cygwin/shm.cc693
-rw-r--r--winsup/cygwin/syscalls.cc29
-rw-r--r--winsup/cygwin/winsup.h20
-rw-r--r--winsup/cygwin/winver.rc53
12 files changed, 2066 insertions, 14 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 0218cc58e3f..60880a9e5f5 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,54 @@
+2003-03-09 Corinna Vinschen <corinna@vinschen.de>
+
+ * winver.rc: Change Copyright hint to include 2003.
+
+2003-03-09 Corinna Vinschen <corinna@vinschen.de>
+
+ Switch to 32/64 datatypes:
+ * Makefile.in (OBSOLETE_FUNCTIONS): Add open acl aclcheck aclfrommode
+ aclfrompbits aclfromtext aclsort acltomode acltopbits acltotext chown
+ facl fchown fgetpos fopen freopen fseeko fsetpos fstat ftello
+ ftruncate getegid geteuid getgid getgrent getgrgid getgrnam getgroups
+ getpwuid getpwuid_r getuid initgroups lchown lseek lstat mknod mmap
+ seekdir setegid seteuid setgid setgroups setregid setreuid setuid stat
+ telldir truncate.
+ (NEW_FUNCTIONS): Add _open64 acl32 aclcheck32 aclfrommode32
+ aclfrompbits32 aclfromtext32 aclsort32 acltomode32 acltopbits32
+ acltotext32 chown32 facl32 fchown32 fgetpos64 fopen64 freopen64
+ fseeko64 fsetpos64 fstat64 ftello64 ftruncate64 getegid32 geteuid32
+ getgid32 getgrent32 getgrgid32 getgrnam32 getgroups32 getpwuid32
+ getpwuid_r32 getuid32 initgroups32 lchown32 lseek64 lstat64 mknod32
+ mmap64 seekdir64 setegid32 seteuid32 setgid32 setgroups32 setregid32
+ setreuid32 setuid32 stat64 telldir64 truncate64 to substitute the
+ above.
+ * cygserver_shm.h (class client_request_shm): Change uid_t and gid_t
+ members to __uid32_t and __gid32_t.
+ * cygwin.din: Add symbols acl32 aclcheck32 aclfrommode32
+ aclfrompbits32 aclfromtext32 aclsort32 acltomode32 acltopbits32
+ acltotext32 facl32 fgetpos64 fopen64 freopen64 fseeko64 fsetpos64
+ _fstat64 ftello64 _lseek64 mknod32 _open64.
+ * glob.c: Include perprocess.h.
+ (globtilde): Call getpwuid32 and getuid32 instead of getpwuid and
+ getuid.
+ (g_lstat): Check for applications API version to call the appropriate
+ typed gl_lstat function.
+ (g_stat): Ditto for gl_stat.
+ * shm.cc (client_request_shm::client_request_shm): Call geteuid32
+ and getegid32 instead of geteuid and getegid throughout.
+ * syscalls.cc (_open64): New alias for open.
+ (_lseek64): New alias for lseek64.
+ (_fstat64): New alias for fseek64.
+ (mknod32): New function.
+ (mknod): Calls mknod32 now.
+ * winsup.h: Make function declarations for getuid32, geteuid32,
+ and getpwuid32 accessible for plain C sources. Add declarations
+ for getegid32 and getpwnam.
+ * include/cygwin/version.h: Bum API minor number to 78.
+ * include/sys/cygwin.h: Guard C++ specific members of struct
+ per_process against inclusion in plain C sources.
+ * include/sys/mman.h (mman): Add guard to avoid type clash when
+ compiling Cygwin.
+
2003-03-09 Christopher Faylor <cgf@redhat.com>
* include/cygwin/version.h: Bump DLL minor number to 22.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 7276b819623..27633b6d37d 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -172,11 +172,69 @@ DLL_OFILES:=assert.o autoload.o cxx.o cygheap.o cygserver_client.o \
GMON_OFILES:=gmon.o mcount.o profil.o
-OBSOLETE_FUNCTIONS:=regcomp regerror regexec regfree regsub
+OBSOLETE_FUNCTIONS:=regcomp regerror regexec regfree regsub \
+ open acl aclcheck aclfrommode aclfrompbits \
+ aclfromtext aclsort acltomode acltopbits \
+ acltotext chown facl fchown fgetpos fopen \
+ freopen fseeko fsetpos fstat ftello ftruncate \
+ getegid geteuid getgid getgrent getgrgid getgrnam \
+ getgroups getpwuid getpwuid_r getuid initgroups \
+ lchown lseek lstat mknod mmap seekdir setegid seteuid \
+ setgid setgroups setregid setreuid setuid stat \
+ telldir truncate
+
NEW_FUNCTIONS:=regcomp posix_regcomp \
regerror posix_regerror \
regexec posix_regexec \
- regfree posix_regfree
+ regfree posix_regfree \
+ open _open64 \
+ acl acl32 \
+ aclcheck aclcheck32 \
+ aclfrommode aclfrommode32 \
+ aclfrompbits aclfrompbits32 \
+ aclfromtext aclfromtext32 \
+ aclsort aclsort32 \
+ acltomode acltomode32 \
+ acltopbits acltopbits32 \
+ acltotext acltotext32 \
+ chown chown32 \
+ facl facl32 \
+ fchown fchown32 \
+ fgetpos fgetpos64 \
+ fopen fopen64 \
+ freopen freopen64 \
+ fseeko fseeko64 \
+ fsetpos fsetpos64 \
+ fstat fstat64 \
+ ftello ftello64 \
+ ftruncate ftruncate64 \
+ getegid getegid32 \
+ geteuid geteuid32 \
+ getgid getgid32 \
+ getgrent getgrent32 \
+ getgrgid getgrgid32 \
+ getgrnam getgrnam32 \
+ getgroups getgroups32 \
+ getpwuid getpwuid32 \
+ getpwuid_r getpwuid_r32 \
+ getuid getuid32 \
+ initgroups initgroups32 \
+ lchown lchown32 \
+ lseek lseek64 \
+ lstat lstat64 \
+ mknod mknod32 \
+ mmap mmap64 \
+ seekdir seekdir64 \
+ setegid setegid32 \
+ seteuid seteuid32 \
+ setgid setgid32 \
+ setgroups setgroups32 \
+ setregid setregid32 \
+ setreuid setreuid32 \
+ setuid setuid32 \
+ stat stat64 \
+ telldir telldir64 \
+ truncate truncate64
API_VER:=$(srcdir)/include/cygwin/version.h
diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h
new file mode 100644
index 00000000000..5a5ee38207e
--- /dev/null
+++ b/winsup/cygwin/cygserver_shm.h
@@ -0,0 +1,147 @@
+/* cygserver_shm.h: Single unix specification IPC interface for Cygwin.
+
+ Copyright 2002 Red Hat, Inc.
+
+ Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
+ Based on code by Robert Collins <robert.collins@hotmail.com>.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef __CYGSERVER_SHM_H__
+#define __CYGSERVER_SHM_H__
+
+#include <sys/types.h>
+#include <cygwin/shm.h>
+
+#include <assert.h>
+#include <limits.h>
+
+#include "cygserver_ipc.h"
+
+#include "cygwin/cygserver.h"
+
+/*---------------------------------------------------------------------------*
+ * Values for the shminfo entries.
+ *
+ * Nb. The values are segregated between two enums so that the `small'
+ * values aren't promoted to `unsigned long' equivalents.
+ *---------------------------------------------------------------------------*/
+
+enum
+ {
+ SHMMAX = ULONG_MAX,
+ SHMSEG = ULONG_MAX,
+ SHMALL = ULONG_MAX
+ };
+
+enum
+ {
+ SHMMIN = 1,
+ SHMMNI = IPCMNI // Must be <= IPCMNI.
+ };
+
+/*---------------------------------------------------------------------------*
+ * class client_request_shm
+ *---------------------------------------------------------------------------*/
+
+#ifndef __INSIDE_CYGWIN__
+class transport_layer_base;
+class process_cache;
+#endif
+
+class client_request_shm : public client_request
+{
+ friend class client_request;
+
+public:
+ enum shmop_t
+ {
+ SHMOP_shmat,
+ SHMOP_shmctl,
+ SHMOP_shmdt,
+ SHMOP_shmget
+ };
+
+#ifdef __INSIDE_CYGWIN__
+ client_request_shm (int shmid, int shmflg); // shmat
+ client_request_shm (int shmid, int cmd, const struct shmid_ds *); // shmctl
+ client_request_shm (int shmid); // shmdt
+ client_request_shm (key_t, size_t, int shmflg); // shmget
+#endif
+
+ // Accessors for out parameters.
+
+ int shmid () const
+ {
+ assert (!error_code ());
+ return _parameters.out.shmid;
+ }
+
+ HANDLE hFileMap () const
+ {
+ assert (!error_code ());
+ return _parameters.out.hFileMap;
+ }
+
+ const struct shmid_ds & ds () const
+ {
+ assert (!error_code ());
+ return _parameters.out.ds;
+ }
+
+ const struct shminfo & shminfo () const
+ {
+ assert (!error_code ());
+ return _parameters.out.shminfo;
+ }
+
+ const struct shm_info & shm_info () const
+ {
+ assert (!error_code ());
+ return _parameters.out.shm_info;
+ }
+
+private:
+ union
+ {
+ struct
+ {
+ shmop_t shmop;
+ key_t key;
+ size_t size;
+ int shmflg;
+ int shmid;
+ int cmd;
+ pid_t cygpid;
+ DWORD winpid;
+ __uid32_t uid;
+ __gid32_t gid;
+ struct shmid_ds ds;
+ } in;
+
+ struct {
+ int shmid;
+ union
+ {
+ HANDLE hFileMap;
+ struct shmid_ds ds;
+ struct shminfo shminfo;
+ struct shm_info shm_info;
+ };
+ } out;
+ } _parameters;
+
+#ifndef __INSIDE_CYGWIN__
+ client_request_shm ();
+#endif
+
+#ifndef __INSIDE_CYGWIN__
+ virtual void serve (transport_layer_base *, process_cache *);
+#endif
+};
+
+#endif /* __CYGSERVER_SHM_H__ */
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index d723c7260c6..3d1fd71ebe6 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -102,22 +102,31 @@ access
_access = access
acl
_acl = acl
+acl32
aclcheck
_aclcheck = aclcheck
+aclcheck32
aclfrommode
_aclfrommode = aclfrommode
+aclfrommode32
aclfrompbits
_aclfrompbits = aclfrompbits
+aclfrompbits32
aclfromtext
_aclfromtext = aclfromtext
+aclfromtext32
aclsort
_aclsort = aclsort
+aclsort32
acltomode
_acltomode = acltomode
+acltomode32
acltopbits
_acltopbits = acltopbits
+acltopbits32
acltotext
_acltotext = acltotext
+acltotext32
acos
_acos = acos
acosf
@@ -389,6 +398,7 @@ fabsf
_fabsf = fabsf
facl
_facl = facl
+facl32
fchdir
_fchdir = fchdir
fchmod
@@ -424,6 +434,7 @@ fgetc
_fgetc = fgetc
fgetpos
_fgetpos = fgetpos
+fgetpos64
fgets
_fgets = fgets
fileno
@@ -452,6 +463,7 @@ fnmatch
_fnmatch = fnmatch
fopen
_fopen = fopen
+fopen64
fork
_fork = fork
fpathconf
@@ -467,6 +479,7 @@ free
_free = free
freopen
_freopen = freopen
+freopen64
frexp
_frexp = frexp
frexpf
@@ -477,9 +490,12 @@ fseek
_fseek = fseek
fseeko
_fseeko = fseeko
+fseeko64
fsetpos
_fsetpos = fsetpos
+fsetpos64
fstat64
+_fstat64 = fstat64
fstatfs
_fstatfs = fstatfs
fsync
@@ -488,6 +504,7 @@ ftell
_ftell = ftell
ftello
_ftello = ftello
+ftello64
ftime
_ftime = ftime
ftruncate
@@ -766,6 +783,7 @@ lroundf
lseek
_lseek = lseek
lseek64
+_lseek64 = lseek64
lstat64
mallinfo
malloc
@@ -805,6 +823,7 @@ _mkdir = mkdir
mkfifo
mknod
_mknod = mknod
+mknod32
mkstemp
_mkstemp = mkstemp
mktemp
@@ -848,6 +867,7 @@ _ntohs = ntohs
on_exit
open
_open = open
+_open64
opendir
_opendir = opendir
openlog
diff --git a/winsup/cygwin/glob.c b/winsup/cygwin/glob.c
new file mode 100644
index 00000000000..47f8ee120bb
--- /dev/null
+++ b/winsup/cygwin/glob.c
@@ -0,0 +1,942 @@
+/* $NetBSD: __glob13.c,v 1.1.2.1 1997/10/22 06:41:27 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+#include "winsup.h"
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <windows.h>
+
+#include "perprocess.h"
+
+#ifdef __weak_alias
+#ifdef __LIBC12_SOURCE__
+__weak_alias(glob,_glob);
+__weak_alias(globfree,_globfree);
+#else
+#error "XXX THESE ARE NOT RIGHT!"
+__weak_alias(__glob13,___glob13);
+__weak_alias(__globfree13,___globfree13);
+#endif /* __LIBC12_SOURCE__ */
+#endif /* __weak_alias */
+
+#ifdef __LIBC12_SOURCE__
+#define STAT stat12
+#else
+#if defined (__INSIDE_CYGWIN__)
+#define STAT __stat64
+#else
+#define STAT stat
+#endif
+#endif
+
+#define DOLLAR '$'
+#define DOT '.'
+#define EOS '\0'
+#define LBRACKET '['
+#define NOT '!'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define RANGE '-'
+#define RBRACKET ']'
+#define SEP '/'
+#define STAR '*'
+#define TILDE '~'
+#define UNDERSCORE '_'
+#define LBRACE '{'
+#define RBRACE '}'
+#define SLASH '/'
+#define COMMA ','
+
+#ifndef DEBUG
+
+#define M_QUOTE 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+typedef u_short Char;
+
+#else
+
+#define M_QUOTE 0x80
+#define M_PROTECT 0x40
+#define M_MASK 0xff
+#define M_ASCII 0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((Char)((c)&M_ASCII))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+
+static int compare __P((const void *, const void *));
+static void g_Ctoc __P((const Char *, char *));
+static int g_lstat __P((Char *, struct STAT *, glob_t *));
+static DIR *g_opendir __P((Char *, glob_t *));
+static Char *g_strchr __P((Char *, int));
+#ifdef notdef
+static Char *g_strcat __P((Char *, const Char *));
+#endif
+static int g_stat __P((Char *, struct STAT *, glob_t *));
+static int glob0 __P((const Char *, glob_t *));
+static int glob1 __P((Char *, glob_t *));
+static int glob2 __P((Char *, Char *, Char *, glob_t *));
+static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *));
+static int globextend __P((const Char *, glob_t *));
+static const Char * globtilde __P((const Char *, Char *, glob_t *));
+static int globexp1 __P((const Char *, glob_t *));
+static int globexp2 __P((const Char *, const Char *, glob_t *, int *));
+static int match __P((Char *, Char *, Char *));
+#ifdef DEBUG
+static void qprintf __P((const char *, Char *));
+#endif
+
+#undef MAXPATHLEN
+#define MAXPATHLEN 16384
+
+extern BOOL ignore_case_with_glob;
+
+int
+glob(pattern, flags, errfunc, pglob)
+ const char *pattern;
+ int flags, (*errfunc) __P((const char *, int));
+ glob_t *pglob;
+{
+ const u_char *patnext;
+ int c;
+ Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
+
+ patnext = (u_char *) pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MAXPATHLEN;
+ if (flags & GLOB_QUOTE) {
+ /* Protect the quoted characters. */
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ if (c == QUOTE) {
+ if ((c = *patnext++) == EOS) {
+ c = QUOTE;
+ --patnext;
+ }
+ *bufnext++ = c | M_PROTECT;
+ }
+ else
+ *bufnext++ = c;
+ }
+ else
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ *bufnext++ = c;
+ *bufnext = EOS;
+
+ if (flags & GLOB_BRACE)
+ return globexp1(patbuf, pglob);
+ else
+ return glob0(patbuf, pglob);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int globexp1(pattern, pglob)
+ const Char *pattern;
+ glob_t *pglob;
+{
+ const Char* ptr = pattern;
+ int rv;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
+ return glob0(pattern, pglob);
+
+ while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
+ if (!globexp2(ptr, pattern, pglob, &rv))
+ return rv;
+
+ return glob0(pattern, pglob);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int globexp2(ptr, pattern, pglob, rv)
+ const Char *ptr, *pattern;
+ glob_t *pglob;
+ int *rv;
+{
+ int i;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pl;
+ Char patbuf[MAXPATHLEN + 1];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe; pe++)
+ if (*pe == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == LBRACE)
+ i++;
+ else if (*pe == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == EOS) {
+ *rv = glob0(patbuf, pglob);
+ return 0;
+ }
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+ switch (*pm) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pl;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case COMMA:
+ if (i && *pm == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ *rv = globexp1(patbuf, pglob);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *rv = 0;
+ return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(pattern, patbuf, pglob)
+ const Char *pattern;
+ Char *patbuf;
+ glob_t *pglob;
+{
+ struct passwd *pwd;
+ char *h;
+ const Char *p;
+ Char *b;
+
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return pattern;
+
+ /* Copy up to the end of the string or / */
+ for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH;
+ *h++ = *p++)
+ continue;
+
+ *h = EOS;
+
+ if (((char *) patbuf)[0] == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
+ * first and then trying the password file
+ */
+ if ((h = getenv("HOME")) == NULL) {
+ if ((pwd = getpwuid32(getuid32())) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ if ((pwd = getpwnam((char*) patbuf)) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ for (b = patbuf; *h; *b++ = *h++)
+ continue;
+
+ /* Append the rest of the pattern */
+ while ((*b++ = *p++) != EOS)
+ continue;
+
+ return patbuf;
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+static int
+glob0(pattern, pglob)
+ const Char *pattern;
+ glob_t *pglob;
+{
+ const Char *qpatnext;
+ int c, err, oldpathc;
+ Char *bufnext, patbuf[MAXPATHLEN+1];
+
+ qpatnext = globtilde(pattern, patbuf, pglob);
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == NOT)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob)) != 0)
+ return(err);
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the pattern did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if (pglob->gl_pathc == oldpathc &&
+ ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR))))
+ return(globextend(pattern, pglob));
+ else if (!(pglob->gl_flags & GLOB_NOSORT))
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+ return(0);
+}
+
+static int
+compare(p, q)
+ const void *p, *q;
+{
+ return(strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(pattern, pglob)
+ Char *pattern;
+ glob_t *pglob;
+{
+ Char pathbuf[MAXPATHLEN+1];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return(0);
+ return(glob2(pathbuf, pathbuf, pattern, pglob));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(pathbuf, pathend, pattern, pglob)
+ Char *pathbuf, *pathend, *pattern;
+ glob_t *pglob;
+{
+ struct STAT sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == EOS) { /* End of pattern? */
+ *pathend = EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return(0);
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
+ || (S_ISLNK(sb.st_mode) &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return(globextend(pathbuf, pglob));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && *p != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (*pattern == SEP)
+ *pathend++ = *pattern++;
+ } else /* Need expansion, recurse. */
+ return(glob3(pathbuf, pathend, pattern, p, pglob));
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(pathbuf, pathend, pattern, restpattern, pglob)
+ Char *pathbuf, *pathend, *pattern, *restpattern;
+ glob_t *pglob;
+{
+ register struct dirent *dp;
+ DIR *dirp;
+ int err;
+ char buf[MAXPATHLEN];
+
+ /*
+ * The readdirfunc declaration can't be prototyped, because it is
+ * assigned, below, to two functions which are prototyped in glob.h
+ * and dirent.h as taking pointers to differently typed opaque
+ * structures.
+ */
+ struct dirent *(*readdirfunc) __P((void *));
+
+ *pathend = EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ /* TODO: don't call for ENOENT or ENOTDIR? */
+ if (pglob->gl_errfunc) {
+ g_Ctoc(pathbuf, buf);
+ if (pglob->gl_errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return (GLOB_ABEND);
+ }
+ return(0);
+ }
+
+ err = 0;
+
+ /* Search directory for matching names. */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = pglob->gl_readdir;
+ else
+ readdirfunc = (struct dirent *(*)__P((void *))) readdir;
+ while ((dp = (*readdirfunc)(dirp))) {
+ register u_char *sc;
+ register Char *dc;
+
+ /* Initial DOT must be matched literally. */
+ if (dp->d_name[0] == DOT && *pattern != DOT)
+ continue;
+ for (sc = (u_char *) dp->d_name, dc = pathend;
+ (*dc++ = *sc++) != EOS;)
+ continue;
+ if (!match(pathend, pattern, restpattern)) {
+ *pathend = EOS;
+ continue;
+ }
+ err = glob2(pathbuf, --dc, restpattern, pglob);
+ if (err)
+ break;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+ return(err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(path, pglob)
+ const Char *path;
+ glob_t *pglob;
+{
+ register char **pathv;
+ register int i;
+ u_int newsize;
+ char *copy;
+ const Char *p;
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ pathv = pglob->gl_pathv ?
+ realloc((char *)pglob->gl_pathv, newsize) :
+ malloc(newsize);
+ if (pathv == NULL)
+ return(GLOB_NOSPACE);
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0;)
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ if ((copy = malloc(p - path)) != NULL) {
+ g_Ctoc(path, copy);
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ return(copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(name, pat, patend)
+ register Char *name, *pat, *patend;
+{
+ int ok, negate_range;
+ Char c, k;
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return(1);
+ do
+ if (match(name, pat, patend))
+ return(1);
+ while (*name++ != EOS);
+ return(0);
+ case M_ONE:
+ if (*name++ == EOS)
+ return(0);
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ return(0);
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
+ ++pat;
+ if (ignore_case_with_glob)
+ {
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (tolower(c) <= tolower(k) && tolower(k) <= tolower(pat[1]))
+ ok = 1;
+ pat += 2;
+ } else if (tolower(c) == tolower(k))
+ ok = 1;
+ }
+ else
+ {
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (c <= k && k <= pat[1])
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ }
+ if (ok == negate_range)
+ return(0);
+ break;
+ default:
+ if (ignore_case_with_glob)
+ {
+ if (tolower(*name) != tolower(c))
+ return(0);
+ ++name;
+ }
+ else
+ {
+ if (*name++ != c)
+ return(0);
+ }
+ break;
+ }
+ }
+ return(*name == EOS);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+globfree(pglob)
+ glob_t *pglob;
+{
+ register int i;
+ register char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ }
+}
+
+static DIR *
+g_opendir(str, pglob)
+ register Char *str;
+ glob_t *pglob;
+{
+ char buf[MAXPATHLEN];
+
+ if (!*str)
+ strcpy(buf, ".");
+ else
+ g_Ctoc(str, buf);
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_opendir)(buf));
+
+ return(opendir(buf));
+}
+
+static void
+stat32_to_STAT (struct __stat32 *src, struct STAT *dst)
+{
+ dst->st_dev = src->st_dev;
+ dst->st_ino = src->st_ino;
+ dst->st_mode = src->st_mode;
+ dst->st_nlink = src->st_nlink;
+ dst->st_uid = src->st_uid;
+ dst->st_gid = src->st_gid;
+ dst->st_rdev = src->st_rdev;
+ dst->st_size = src->st_size;
+ dst->st_atim = src->st_atim;
+ dst->st_mtim = src->st_mtim;
+ dst->st_ctim = src->st_ctim;
+ dst->st_blksize = src->st_blksize;
+ dst->st_blocks = src->st_blocks;
+}
+
+static int
+g_lstat(fn, sb, pglob)
+ register Char *fn;
+ struct STAT *sb;
+ glob_t *pglob;
+{
+ char buf[MAXPATHLEN];
+
+ g_Ctoc(fn, buf);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC) {
+ struct __stat32 lsb;
+ int ret;
+
+ if (user_data->api_major > 0 || user_data->api_minor > 77)
+ ret = (*pglob->gl_lstat)(buf, &sb);
+ else if (!(ret = (*pglob->gl_lstat)(buf, &lsb)))
+ stat32_to_STAT (&lsb, sb);
+ return ret;
+ }
+#ifdef __INSIDE_CYGWIN__
+ return(lstat64(buf, sb));
+#else
+ return(lstat(buf, sb));
+#endif
+}
+
+static int
+g_stat(fn, sb, pglob)
+ register Char *fn;
+ struct STAT *sb;
+ glob_t *pglob;
+{
+ char buf[MAXPATHLEN];
+
+ g_Ctoc(fn, buf);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC) {
+ struct __stat32 lsb;
+ int ret;
+
+ if (user_data->api_major > 0 || user_data->api_minor > 77)
+ ret = (*pglob->gl_stat)(buf, &sb);
+ if (!(ret = (*pglob->gl_stat)(buf, &lsb)))
+ stat32_to_STAT (&lsb, sb);
+ return ret;
+ }
+#ifdef __INSIDE_CYGWIN__
+ return(stat64(buf, sb));
+#else
+ return(stat(buf, sb));
+#endif
+}
+
+static Char *
+g_strchr(str, ch)
+ Char *str;
+ int ch;
+{
+ do {
+ if (*str == ch)
+ return (str);
+ } while (*str++);
+ return (NULL);
+}
+
+#ifdef notdef
+static Char *
+g_strcat(dst, src)
+ Char *dst;
+ const Char* src;
+{
+ Char *sdst = dst;
+
+ while (*dst++)
+ continue;
+ --dst;
+ while((*dst++ = *src++) != EOS)
+ continue;
+
+ return (sdst);
+}
+#endif
+
+static void
+g_Ctoc(str, buf)
+ register const Char *str;
+ char *buf;
+{
+ register char *dc;
+
+ for (dc = buf; (*dc++ = *str++) != EOS;)
+ continue;
+}
+
+#ifdef DEBUG
+static void
+qprintf(str, s)
+ const char *str;
+ register Char *s;
+{
+ register Char *p;
+
+ (void)printf("%s:\n", str);
+ for (p = s; *p; p++)
+ (void)printf("%c", CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", ismeta(*p) ? '_' : ' ');
+ (void)printf("\n");
+}
+#endif
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 89cd8b03b2d..adb3947b165 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -186,12 +186,17 @@ details. */
truncf
76: mallinfo
77: thread-safe exit/at_exit
+ 78: Export acl32 aclcheck32 aclfrommode32 aclfrompbits32 aclfromtext32
+ aclsort32 acltomode32 acltopbits32 acltotext32 facl32
+ fgetpos64 fopen64 freopen64 fseeko64 fsetpos64 ftello64
+ _open64 _lseek64 _fstat64 _stat64 mknod32
+
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 77
+#define CYGWIN_VERSION_API_MINOR 78
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index aa3619b2a22..cc5641c4a6f 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -183,7 +183,7 @@ struct per_process
add an item. */
DWORD unused2[5];
-#ifdef __INSIDE_CYGWIN__
+#if defined (__INSIDE_CYGWIN__) && defined (__cplusplus)
ResourceLocks *resourcelocks;
MTinterface *threadinterface;
#else
diff --git a/winsup/cygwin/include/sys/mman.h b/winsup/cygwin/include/sys/mman.h
new file mode 100644
index 00000000000..5059f894af8
--- /dev/null
+++ b/winsup/cygwin/include/sys/mman.h
@@ -0,0 +1,54 @@
+/* sys/mman.h
+
+ Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef _SYS_MMAN_H_
+#define _SYS_MMAN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+
+#define MAP_FILE 0
+#define MAP_SHARED 1
+#define MAP_PRIVATE 2
+#define MAP_TYPE 0xF
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+
+#define MAP_FAILED ((caddr_t)-1)
+
+/*
+ * Flags for msync.
+ */
+#define MS_ASYNC 1
+#define MS_SYNC 2
+#define MS_INVALIDATE 4
+
+#ifndef __INSIDE_CYGWIN__
+extern caddr_t mmap (caddr_t __addr, size_t __len, int __prot, int __flags, int __fd, off_t __off);
+#endif
+extern int munmap (caddr_t __addr, size_t __len);
+extern int mprotect (caddr_t __addr, size_t __len, int __prot);
+extern int msync (caddr_t __addr, size_t __len, int __flags);
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif /* _SYS_MMAN_H_ */
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
new file mode 100644
index 00000000000..618cac1823f
--- /dev/null
+++ b/winsup/cygwin/shm.cc
@@ -0,0 +1,693 @@
+/* shm.cc: Single unix specification IPC interface for Cygwin.
+
+ Copyright 2002 Red Hat, Inc.
+
+ Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
+ Based on code by Robert Collins <robert.collins@hotmail.com>.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "cygerrno.h"
+#include "safe_memory.h"
+#include "sigproc.h"
+
+#include "cygserver_ipc.h"
+#include "cygserver_shm.h"
+
+/*---------------------------------------------------------------------------*
+ * class client_shmmgr
+ *
+ * A singleton class.
+ *---------------------------------------------------------------------------*/
+
+#define shmmgr (client_shmmgr::instance ())
+
+class client_shmmgr
+{
+private:
+ class segment_t
+ {
+ public:
+ const int shmid;
+ const void *const shmaddr;
+ const int shmflg;
+ HANDLE hFileMap; // Updated by fixup_shms_after_fork ().
+
+ segment_t *next;
+
+ segment_t (const int shmid, const void *const shmaddr, const int shmflg,
+ const HANDLE hFileMap)
+ : shmid (shmid), shmaddr (shmaddr), shmflg (shmflg), hFileMap (hFileMap),
+ next (NULL)
+ {}
+ };
+
+public:
+ static client_shmmgr & instance ();
+
+ void *shmat (int shmid, const void *, int shmflg);
+ int shmctl (int shmid, int cmd, struct shmid_ds *);
+ int shmdt (const void *);
+ int shmget (key_t, size_t, int shmflg);
+
+ int fixup_shms_after_fork ();
+
+private:
+ static NO_COPY client_shmmgr *_instance;
+
+ CRITICAL_SECTION _segments_lock;
+ static segment_t *_segments_head; // List of attached segs by shmaddr.
+
+ static long _shmat_cnt; // No. of attached segs; for info. only.
+
+ client_shmmgr ();
+ ~client_shmmgr ();
+
+ // Undefined (as this class is a singleton):
+ client_shmmgr (const client_shmmgr &);
+ client_shmmgr & operator= (const client_shmmgr &);
+
+ segment_t *find (const void *, segment_t **previous = NULL);
+
+ void *attach (int shmid, const void *, int shmflg, HANDLE & hFileMap);
+
+ segment_t *new_segment (int shmid, const void *, int shmflg, HANDLE);
+};
+
+/* static */ NO_COPY client_shmmgr *client_shmmgr::_instance;
+
+/* The following two variables must be inherited by child processes
+ * since they are used by fixup_shms_after_fork () to re-attach to the
+ * parent's shm segments.
+ */
+/* static */ client_shmmgr::segment_t *client_shmmgr::_segments_head;
+/* static */ long client_shmmgr::_shmat_cnt;
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::instance ()
+ *---------------------------------------------------------------------------*/
+
+client_shmmgr &
+client_shmmgr::instance ()
+{
+ if (!_instance)
+ _instance = safe_new0 (client_shmmgr);
+
+ assert (_instance);
+
+ return *_instance;
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::shmat ()
+ *---------------------------------------------------------------------------*/
+
+void *
+client_shmmgr::shmat (const int shmid,
+ const void *const shmaddr,
+ const int shmflg)
+{
+ syscall_printf ("shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)",
+ shmid, shmaddr, shmflg);
+
+ EnterCriticalSection (&_segments_lock);
+
+ HANDLE hFileMap = NULL;
+
+ void *const ptr = attach (shmid, shmaddr, shmflg, hFileMap);
+
+ if (ptr)
+ new_segment (shmid, ptr, shmflg, hFileMap);
+
+ LeaveCriticalSection (&_segments_lock);
+
+ if (ptr)
+ syscall_printf ("%p = shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)",
+ ptr, shmid, shmaddr, shmflg);
+ // else
+ // See the syscall_printf in client_shmmgr::attach ().
+
+ return (ptr ? ptr : (void *) -1);
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::shmctl ()
+ *---------------------------------------------------------------------------*/
+
+int
+client_shmmgr::shmctl (const int shmid,
+ const int cmd,
+ struct shmid_ds *const buf)
+{
+ syscall_printf ("shmctl (shmid = %d, cmd = 0x%x, buf = %p)",
+ shmid, cmd, buf);
+
+ // Check parameters and set up in parameters as required.
+
+ const struct shmid_ds *in_buf = NULL;
+
+ switch (cmd)
+ {
+ case IPC_SET:
+ if (__check_invalid_read_ptr_errno (buf, sizeof (struct shmid_ds)))
+ {
+ syscall_printf (("-1 [EFAULT] = "
+ "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
+ shmid, cmd, buf);
+ set_errno (EFAULT);
+ return -1;
+ }
+ in_buf = buf;
+ break;
+
+ case IPC_STAT:
+ case SHM_STAT:
+ if (__check_null_invalid_struct_errno (buf, sizeof (struct shmid_ds)))
+ {
+ syscall_printf (("-1 [EFAULT] = "
+ "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
+ shmid, cmd, buf);
+ set_errno (EFAULT);
+ return -1;
+ }
+ break;
+
+ case IPC_INFO:
+ if (__check_null_invalid_struct_errno (buf, sizeof (struct shminfo)))
+ {
+ syscall_printf (("-1 [EFAULT] = "
+ "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
+ shmid, cmd, buf);
+ set_errno (EFAULT);
+ return -1;
+ }
+ break;
+
+ case SHM_INFO:
+ if (__check_null_invalid_struct_errno (buf, sizeof (struct shm_info)))
+ {
+ syscall_printf (("-1 [EFAULT] = "
+ "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
+ shmid, cmd, buf);
+ set_errno (EFAULT);
+ return -1;
+ }
+ break;
+ }
+
+ // Create and issue the command.
+
+ client_request_shm request (shmid, cmd, in_buf);
+
+ if (request.make_request () == -1 || request.error_code ())
+ {
+ syscall_printf (("-1 [%d] = "
+ "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
+ request.error_code (), shmid, cmd, buf);
+ set_errno (request.error_code ());
+ return -1;
+ }
+
+ // Some commands require special processing for their out parameters.
+
+ int result = 0;
+
+ switch (cmd)
+ {
+ case IPC_STAT:
+ *buf = request.ds ();
+ break;
+
+ case IPC_INFO:
+ *(struct shminfo *) buf = request.shminfo ();
+ break;
+
+ case SHM_STAT: // ipcs(8) i'face.
+ result = request.shmid ();
+ *buf = request.ds ();
+ break;
+
+ case SHM_INFO: // ipcs(8) i'face.
+ result = request.shmid ();
+ *(struct shm_info *) buf = request.shm_info ();
+ break;
+ }
+
+ syscall_printf ("%d = shmctl (shmid = %d, cmd = 0x%x, buf = %p)",
+ result, shmid, cmd, buf);
+
+ return result;
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::shmdt ()
+ *
+ * According to Posix, the only error condition for this system call
+ * is EINVAL if shmaddr is not the address of the start of an attached
+ * shared memory segment. Given that, all other errors just generate
+ * tracing noise.
+ *---------------------------------------------------------------------------*/
+
+int
+client_shmmgr::shmdt (const void *const shmaddr)
+{
+ syscall_printf ("shmdt (shmaddr = %p)", shmaddr);
+
+ EnterCriticalSection (&_segments_lock);
+
+ segment_t *previous = NULL;
+
+ segment_t *const segptr = find (shmaddr, &previous);
+
+ if (!segptr)
+ {
+ LeaveCriticalSection (&_segments_lock);
+ syscall_printf ("-1 [EINVAL] = shmdt (shmaddr = %p)", shmaddr);
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ assert (previous ? previous->next == segptr : _segments_head == segptr);
+
+ if (previous)
+ previous->next = segptr->next;
+ else
+ _segments_head = segptr->next;
+
+ LeaveCriticalSection (&_segments_lock);
+
+ const long cnt = InterlockedDecrement (&_shmat_cnt);
+ assert (cnt >= 0);
+
+ if (!UnmapViewOfFile ((void *) shmaddr))
+ syscall_printf (("failed to unmap view "
+ "[shmid = %d, handle = %p, shmaddr = %p]:"
+ "%E"),
+ segptr->shmid, segptr->hFileMap, shmaddr);
+
+ assert (segptr->hFileMap);
+
+ if (!CloseHandle (segptr->hFileMap))
+ syscall_printf (("failed to close file map handle "
+ "[shmid = %d, handle = %p]: %E"),
+ segptr->shmid, segptr->hFileMap);
+
+ client_request_shm request (segptr->shmid);
+
+ if (request.make_request () == -1 || request.error_code ())
+ syscall_printf ("shmdt request failed [shmid = %d, handle = %p]: %s",
+ segptr->shmid, segptr->hFileMap,
+ strerror (request.error_code ()));
+
+ safe_delete (segptr);
+
+ syscall_printf ("0 = shmdt (shmaddr = %p)", shmaddr);
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::shmget ()
+ *---------------------------------------------------------------------------*/
+
+int
+client_shmmgr::shmget (const key_t key, const size_t size, const int shmflg)
+{
+ syscall_printf ("shmget (key = 0x%016X, size = %u, shmflg = 0%o)",
+ key, size, shmflg);
+
+ client_request_shm request (key, size, shmflg);
+
+ if (request.make_request () == -1 || request.error_code ())
+ {
+ syscall_printf (("-1 [%d] = "
+ "shmget (key = 0x%016X, size = %u, shmflg = 0%o)"),
+ request.error_code (),
+ key, size, shmflg);
+ set_errno (request.error_code ());
+ return -1;
+ }
+
+ syscall_printf (("%d = shmget (key = 0x%016X, size = %u, shmflg = 0%o)"),
+ request.shmid (),
+ key, size, shmflg);
+
+ return request.shmid ();
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::fixup_shms_after_fork ()
+ *
+ * The hFileMap handles are non-inheritable: so they have to be
+ * re-acquired from cygserver.
+ *
+ * Nb. This routine need not be thread-safe as it is only called at startup.
+ *---------------------------------------------------------------------------*/
+
+int
+client_shmmgr::fixup_shms_after_fork ()
+{
+ debug_printf ("re-attaching to shm segments: %d attached", _shmat_cnt);
+
+ {
+ int length = 0;
+ for (segment_t *segptr = _segments_head; segptr; segptr = segptr->next)
+ length += 1;
+
+ if (_shmat_cnt != length)
+ {
+ system_printf (("state inconsistent: "
+ "_shmat_cnt = %d, length of segments list = %d"),
+ _shmat_cnt, length);
+ return 1;
+ }
+ }
+
+ for (segment_t *segptr = _segments_head; segptr; segptr = segptr->next)
+ if (!attach (segptr->shmid,
+ segptr->shmaddr,
+ segptr->shmflg & ~SHM_RND,
+ segptr->hFileMap))
+ {
+ system_printf ("fatal error re-attaching to shm segment %d",
+ segptr->shmid);
+ return 1;
+ }
+
+ if (_shmat_cnt)
+ debug_printf ("re-attached all %d shm segments", _shmat_cnt);
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::client_shmmgr ()
+ *---------------------------------------------------------------------------*/
+
+client_shmmgr::client_shmmgr ()
+{
+ InitializeCriticalSection (&_segments_lock);
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::~client_shmmgr ()
+ *---------------------------------------------------------------------------*/
+
+client_shmmgr::~client_shmmgr ()
+{
+ DeleteCriticalSection (&_segments_lock);
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::find ()
+ *---------------------------------------------------------------------------*/
+
+client_shmmgr::segment_t *
+client_shmmgr::find (const void *const shmaddr, segment_t **previous)
+{
+ if (previous)
+ *previous = NULL;
+
+ for (segment_t *segptr = _segments_head; segptr; segptr = segptr->next)
+ if (segptr->shmaddr == shmaddr)
+ return segptr;
+ else if (segptr->shmaddr > shmaddr) // The list is sorted by shmaddr.
+ return NULL;
+ else if (previous)
+ *previous = segptr;
+
+ return NULL;
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::attach ()
+ *
+ * The body of shmat (), also used by fixup_shms_after_fork ().
+ *---------------------------------------------------------------------------*/
+
+void *
+client_shmmgr::attach (const int shmid,
+ const void *shmaddr,
+ const int shmflg,
+ HANDLE & hFileMap)
+{
+ client_request_shm request (shmid, shmflg);
+
+ if (request.make_request () == -1 || request.error_code ())
+ {
+ syscall_printf (("-1 [%d] = "
+ "shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)"),
+ request.error_code (), shmid, shmaddr, shmflg);
+ set_errno (request.error_code ());
+ return NULL;
+ }
+
+ int result = 0;
+
+ const DWORD access = (shmflg & SHM_RDONLY) ? FILE_MAP_READ : FILE_MAP_WRITE;
+
+ if (shmaddr && (shmflg & SHM_RND))
+ shmaddr = (char *) shmaddr - ((ssize_t) shmaddr % SHMLBA);
+
+ void *const ptr =
+ MapViewOfFileEx (request.hFileMap (), access, 0, 0, 0, (void *) shmaddr);
+
+ if (!ptr)
+ {
+ syscall_printf (("failed to map view "
+ "[shmid = %d, handle = %p, shmaddr = %p]: %E"),
+ shmid, request.hFileMap (), shmaddr);
+ result = EINVAL; // FIXME
+ }
+ else if (shmaddr && ptr != shmaddr)
+ {
+ syscall_printf (("failed to map view at requested address "
+ "[shmid = %d, handle = %p]: "
+ "requested address = %p, mapped address = %p"),
+ shmid, request.hFileMap (),
+ shmaddr, ptr);
+ result = EINVAL; // FIXME
+ }
+
+ if (result != 0)
+ {
+ if (!CloseHandle (request.hFileMap ()))
+ syscall_printf (("failed to close file map handle "
+ "[shmid = %d, handle = %p]: %E"),
+ shmid, request.hFileMap ());
+
+ client_request_shm dt_req (shmid);
+
+ if (dt_req.make_request () == -1 || dt_req.error_code ())
+ syscall_printf ("shmdt request failed [shmid = %d, handle = %p]: %s",
+ shmid, request.hFileMap (),
+ strerror (dt_req.error_code ()));
+
+ set_errno (result);
+ return NULL;
+ }
+
+ hFileMap = request.hFileMap ();
+ return ptr;
+}
+
+/*---------------------------------------------------------------------------*
+ * client_shmmgr::new_segment ()
+ *
+ * Allocate a new segment for the given shmid, file map and address
+ * and insert into the segment map.
+ *---------------------------------------------------------------------------*/
+
+client_shmmgr::segment_t *
+client_shmmgr::new_segment (const int shmid,
+ const void *const shmaddr,
+ const int shmflg,
+ const HANDLE hFileMap)
+{
+ assert (ipc_ext2int_subsys (shmid) == IPC_SHMOP);
+ assert (hFileMap);
+ assert (shmaddr);
+
+ segment_t *previous = NULL; // Insert pointer.
+
+ const segment_t *const tmp = find (shmaddr, &previous);
+
+ assert (!tmp);
+ assert (previous \
+ ? (!previous->next || previous->next->shmaddr > shmaddr) \
+ : (!_segments_head || _segments_head->shmaddr > shmaddr));
+
+ segment_t *const segptr =
+ safe_new (segment_t, shmid, shmaddr, shmflg, hFileMap);
+
+ assert (segptr);
+
+ if (previous)
+ {
+ segptr->next = previous->next;
+ previous->next = segptr;
+ }
+ else
+ {
+ segptr->next = _segments_head;
+ _segments_head = segptr;
+ }
+
+ const long cnt = InterlockedIncrement (&_shmat_cnt);
+ assert (cnt > 0);
+
+ return segptr;
+}
+
+/*---------------------------------------------------------------------------*
+ * shmat ()
+ *---------------------------------------------------------------------------*/
+
+extern "C" void *
+shmat (const int shmid, const void *const shmaddr, const int shmflg)
+{
+ sigframe thisframe (mainthread);
+ return shmmgr.shmat (shmid, shmaddr, shmflg);
+}
+
+/*---------------------------------------------------------------------------*
+ * shmctl ()
+ *---------------------------------------------------------------------------*/
+
+extern "C" int
+shmctl (const int shmid, const int cmd, struct shmid_ds *const buf)
+{
+ sigframe thisframe (mainthread);
+ return shmmgr.shmctl (shmid, cmd, buf);
+}
+
+/*---------------------------------------------------------------------------*
+ * shmdt ()
+ *---------------------------------------------------------------------------*/
+
+extern "C" int
+shmdt (const void *const shmaddr)
+{
+ sigframe thisframe (mainthread);
+ return shmmgr.shmdt (shmaddr);
+}
+
+/*---------------------------------------------------------------------------*
+ * shmget ()
+ *---------------------------------------------------------------------------*/
+
+extern "C" int
+shmget (const key_t key, const size_t size, const int shmflg)
+{
+ sigframe thisframe (mainthread);
+ return shmmgr.shmget (key, size, shmflg);
+}
+
+/*---------------------------------------------------------------------------*
+ * fixup_shms_after_fork ()
+ *---------------------------------------------------------------------------*/
+
+int __stdcall
+fixup_shms_after_fork ()
+{
+ return shmmgr.fixup_shms_after_fork ();
+}
+
+/*---------------------------------------------------------------------------*
+ * client_request_shm::client_request_shm ()
+ *---------------------------------------------------------------------------*/
+
+client_request_shm::client_request_shm (const int shmid, const int shmflg)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
+{
+ _parameters.in.shmop = SHMOP_shmat;
+
+ _parameters.in.shmid = shmid;
+ _parameters.in.shmflg = shmflg;
+
+ _parameters.in.cygpid = getpid ();
+ _parameters.in.winpid = GetCurrentProcessId ();
+ _parameters.in.uid = geteuid32 ();
+ _parameters.in.gid = getegid32 ();
+
+ msglen (sizeof (_parameters.in));
+}
+
+/*---------------------------------------------------------------------------*
+ * client_request_shm::client_request_shm ()
+ *---------------------------------------------------------------------------*/
+
+client_request_shm::client_request_shm (const int shmid,
+ const int cmd,
+ const struct shmid_ds *const buf)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
+{
+ _parameters.in.shmop = SHMOP_shmctl;
+
+ _parameters.in.shmid = shmid;
+ _parameters.in.cmd = cmd;
+ if (buf)
+ _parameters.in.ds = *buf;
+
+ _parameters.in.cygpid = getpid ();
+ _parameters.in.winpid = GetCurrentProcessId ();
+ _parameters.in.uid = geteuid32 ();
+ _parameters.in.gid = getegid32 ();
+
+ msglen (sizeof (_parameters.in));
+}
+
+/*---------------------------------------------------------------------------*
+ * client_request_shm::client_request_shm ()
+ *---------------------------------------------------------------------------*/
+
+client_request_shm::client_request_shm (const int shmid)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
+{
+ _parameters.in.shmop = SHMOP_shmdt;
+
+ _parameters.in.shmid = shmid;
+
+ _parameters.in.cygpid = getpid ();
+ _parameters.in.winpid = GetCurrentProcessId ();
+ _parameters.in.uid = geteuid32 ();
+ _parameters.in.gid = getegid32 ();
+
+ msglen (sizeof (_parameters.in));
+}
+
+/*---------------------------------------------------------------------------*
+ * client_request_shm::client_request_shm ()
+ *---------------------------------------------------------------------------*/
+
+client_request_shm::client_request_shm (const key_t key,
+ const size_t size,
+ const int shmflg)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
+{
+ _parameters.in.shmop = SHMOP_shmget;
+
+ _parameters.in.key = key;
+ _parameters.in.size = size;
+ _parameters.in.shmflg = shmflg;
+
+ _parameters.in.cygpid = getpid ();
+ _parameters.in.winpid = GetCurrentProcessId ();
+ _parameters.in.uid = geteuid32 ();
+ _parameters.in.gid = getegid32 ();
+
+ msglen (sizeof (_parameters.in));
+}
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 22a73df67d5..520a6d5ed0f 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -13,6 +13,9 @@ details. */
#define _open __FOO_open__
#define _read __FOO_read__
#define _write __FOO_write__
+#define _open64 __FOO_open64__
+#define _lseek64 __FOO_lseek64__
+#define _fstat64 __FOO_fstat64__
#include "winsup.h"
#include <sys/stat.h>
@@ -52,6 +55,9 @@ details. */
#undef _open
#undef _read
#undef _write
+#undef _open64
+#undef _lseek64
+#undef _fstat64
SYSTEM_INFO system_info;
@@ -516,6 +522,9 @@ open (const char *unix_path, int flags, ...)
extern "C" int _open (const char *, int flags, ...)
__attribute__ ((alias ("open")));
+extern "C" int _open64 (const char *, int flags, ...)
+ __attribute__ ((alias ("open")));
+
extern "C" __off64_t
lseek64 (int fd, __off64_t pos, int dir)
{
@@ -540,6 +549,9 @@ lseek64 (int fd, __off64_t pos, int dir)
return res;
}
+extern "C" int _lseek64 (int fd, __off64_t pos, int dir)
+ __attribute__ ((alias ("lseek64")));
+
extern "C" __off32_t
lseek (int fd, __off32_t pos, int dir)
{
@@ -1020,6 +1032,9 @@ fstat64 (int fd, struct __stat64 *buf)
return res;
}
+extern "C" int _fstat64 (int fd, __off64_t pos, int dir)
+ __attribute__ ((alias ("fstat64")));
+
extern "C" int
_fstat (int fd, struct __stat32 *buf)
{
@@ -1954,7 +1969,7 @@ mknod_worker (const char *path, mode_t type, mode_t mode, _major_t major,
}
extern "C" int
-mknod (const char *path, mode_t mode, dev_t dev)
+mknod32 (const char *path, mode_t mode, __dev32_t dev)
{
if (check_null_empty_str_errno (path))
return -1;
@@ -1970,8 +1985,8 @@ mknod (const char *path, mode_t mode, dev_t dev)
}
mode_t type = mode & S_IFMT;
- _major_t major = dev >> 8 /* SIGH. _major (dev) */;
- _minor_t minor = dev & 0xff /* SIGH _minor (dev) */;
+ _major_t major = _major (dev);
+ _minor_t minor = _minor (dev);
switch (type)
{
case S_IFCHR:
@@ -1980,7 +1995,7 @@ mknod (const char *path, mode_t mode, dev_t dev)
case S_IFIFO:
major = _major (FH_FIFO);
- minor = _minor (FH_FIFO) & 0xff; /* SIGH again */
+ minor = _minor (FH_FIFO);
break;
case 0:
@@ -2002,6 +2017,12 @@ mknod (const char *path, mode_t mode, dev_t dev)
}
extern "C" int
+mknod (const char *_path, mode_t mode, __dev16_t dev)
+{
+ return mknod32 (_path, mode, (__dev32_t) dev);
+}
+
+extern "C" int
mkfifo (const char *_path, mode_t mode)
{
return -1;
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 3504265856c..4b59f0d3ad7 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -25,8 +25,6 @@ details. */
#define NO_COPY __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy")))
-#ifdef __cplusplus
-
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199900L
#define NEW_MACRO_VARARGS
#endif
@@ -38,6 +36,20 @@ details. */
#include <sys/types.h>
#include <sys/strace.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern __uid32_t getuid32 (void);
+extern __uid32_t geteuid32 (void);
+extern __gid32_t getegid32 (void);
+extern struct passwd *getpwuid32 (__uid32_t);
+struct passwd *getpwnam (const char *);
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
extern const char case_folded_lower[];
#define cyg_tolower(c) (case_folded_lower[(unsigned char)(c)])
extern const char case_folded_upper[];
@@ -155,10 +167,6 @@ void uinfo_init (void);
#define uid16touid32(u16) ((u16)==ILLEGAL_UID16?ILLEGAL_UID:(__uid32_t)(u16))
#define gid16togid32(g16) ((g16)==ILLEGAL_GID16?ILLEGAL_GID:(__gid32_t)(g16))
-extern "C" __uid32_t getuid32 (void);
-extern "C" __uid32_t geteuid32 (void);
-extern "C" struct passwd *getpwuid32 (__uid32_t);
-
/* various events */
void events_init (void);
void events_terminate (void);
diff --git a/winsup/cygwin/winver.rc b/winsup/cygwin/winver.rc
new file mode 100644
index 00000000000..5fc13044086
--- /dev/null
+++ b/winsup/cygwin/winver.rc
@@ -0,0 +1,53 @@
+#include <winver.h>
+#include <cygwin/version.h>
+
+#define STRINGIFY1(x) #x
+#define STRINGIFY(x) STRINGIFY1(x)
+
+#define CYGWIN_DLL_NAME CYGWIN_VERSION_DLL_IDENTIFIER STRINGIFY(.dll)
+
+#define CYGWIN_REGISTRY_KEY CYGWIN_INFO_CYGNUS_REGISTRY_NAME "\\" \
+ CYGWIN_INFO_CYGWIN_REGISTRY_NAME
+
+#define CYGWIN_API_VERSION STRINGIFY(CYGWIN_VERSION_API_MAJOR) "." \
+ STRINGIFY(CYGWIN_VERSION_API_MINOR)
+
+#define CYGWIN_BUILD_DATE_TIME STRINGIFY(CYGWIN_BUILD_DATE) " " \
+ STRINGIFY(CYGWIN_BUILD_TIME)
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION CYGWIN_VERSION_DLL_MAJOR,CYGWIN_VERSION_DLL_MINOR,0,0
+ PRODUCTVERSION CYGWIN_VERSION_DLL_MAJOR,CYGWIN_VERSION_DLL_MINOR,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef DEBUGGING
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Red Hat"
+ VALUE "FileDescription", "Cygwin\256 POSIX Emulation DLL"
+ VALUE "FileVersion", STRINGIFY(CYGWIN_VERSION)
+ VALUE "InternalName", CYGWIN_DLL_NAME
+ VALUE "LegalCopyright", "Copyright \251 Red Hat, Inc. 1996-2003"
+ VALUE "OriginalFilename", CYGWIN_DLL_NAME
+ VALUE "ProductName", "Cygwin"
+ VALUE "ProductVersion", STRINGIFY(CYGWIN_VERSION)
+ VALUE "APIVersion", CYGWIN_API_VERSION
+ VALUE "SharedMemoryVersion", STRINGIFY(CYGWIN_VERSION_SHARED_DATA)
+ VALUE "RegistryKey", CYGWIN_REGISTRY_KEY
+ VALUE "BuildDate", CYGWIN_BUILD_DATE_TIME
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END