diff options
author | Christopher Faylor <cgf@redhat.com> | 2003-03-10 00:07:01 +0000 |
---|---|---|
committer | Christopher Faylor <cgf@redhat.com> | 2003-03-10 00:07:01 +0000 |
commit | 9de384d5cbf6336cd062feae6334b8a5a71cbdd2 (patch) | |
tree | 62819ec88b1a51092dde45d706ae8ea6d44a0e38 | |
parent | 2247a5b5b5ecb392107a270632634d9e0501d392 (diff) | |
download | gdb-9de384d5cbf6336cd062feae6334b8a5a71cbdd2.tar.gz |
merge from trunk
-rw-r--r-- | winsup/cygwin/ChangeLog | 51 | ||||
-rw-r--r-- | winsup/cygwin/Makefile.in | 62 | ||||
-rw-r--r-- | winsup/cygwin/cygserver_shm.h | 147 | ||||
-rw-r--r-- | winsup/cygwin/cygwin.din | 20 | ||||
-rw-r--r-- | winsup/cygwin/glob.c | 942 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/version.h | 7 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/cygwin.h | 2 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/mman.h | 54 | ||||
-rw-r--r-- | winsup/cygwin/shm.cc | 693 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 29 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 20 | ||||
-rw-r--r-- | winsup/cygwin/winver.rc | 53 |
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 |