Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygserver/ChangeLog21
-rw-r--r--winsup/cygserver/Makefile.in4
-rw-r--r--winsup/cygserver/client.cc4
-rwxr-xr-xwinsup/cygserver/configure50
-rw-r--r--winsup/cygserver/configure.ac8
-rwxr-xr-xwinsup/cygserver/cygserver-config17
-rw-r--r--winsup/cygserver/pwdgrp.cc161
-rw-r--r--winsup/cygwin/ChangeLog1083
-rw-r--r--winsup/cygwin/Makefile.in1
-rw-r--r--winsup/cygwin/autoload.cc34
-rwxr-xr-xwinsup/cygwin/configure50
-rw-r--r--winsup/cygwin/configure.ac16
-rw-r--r--winsup/cygwin/cygerrno.h11
-rw-r--r--winsup/cygwin/cygheap.cc13
-rw-r--r--winsup/cygwin/cygheap.h144
-rw-r--r--winsup/cygwin/cygserver.h1
-rw-r--r--winsup/cygwin/cygserver_pwdgrp.h73
-rw-r--r--winsup/cygwin/cygtls.h11
-rw-r--r--winsup/cygwin/dcrt0.cc7
-rw-r--r--winsup/cygwin/dlfcn.cc4
-rw-r--r--winsup/cygwin/dll_init.sgml11
-rw-r--r--winsup/cygwin/dlmalloc.c3815
-rw-r--r--winsup/cygwin/dlmalloc.h93
-rw-r--r--winsup/cygwin/dtable.sgml20
-rw-r--r--winsup/cygwin/errno.cc17
-rw-r--r--winsup/cygwin/external.cc131
-rw-r--r--winsup/cygwin/external.sgml18
-rw-r--r--winsup/cygwin/fhandler.cc3
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc58
-rw-r--r--winsup/cygwin/fhandler_proc.cc5
-rw-r--r--winsup/cygwin/fhandler_process.cc8
-rw-r--r--winsup/cygwin/fhandler_procnet.cc6
-rw-r--r--winsup/cygwin/fhandler_procsys.cc56
-rw-r--r--winsup/cygwin/fhandler_procsysvipc.cc4
-rw-r--r--winsup/cygwin/fhandler_registry.cc4
-rw-r--r--winsup/cygwin/fhandler_socket.cc145
-rw-r--r--winsup/cygwin/fhandler_virtual.h25
-rw-r--r--winsup/cygwin/globals.cc3
-rw-r--r--winsup/cygwin/grp.cc530
-rw-r--r--winsup/cygwin/import/rexec.c391
-rw-r--r--winsup/cygwin/include/cygwin/acl.h4
-rw-r--r--winsup/cygwin/include/cygwin/version.h5
-rw-r--r--winsup/cygwin/include/sys/cygwin.h14
-rw-r--r--winsup/cygwin/ldap.cc629
-rw-r--r--winsup/cygwin/ldap.h80
-rw-r--r--winsup/cygwin/miscfuncs.cc76
-rw-r--r--winsup/cygwin/miscfuncs.h21
-rw-r--r--winsup/cygwin/mount.cc82
-rw-r--r--winsup/cygwin/passwd.cc674
-rw-r--r--winsup/cygwin/path.cc150
-rw-r--r--winsup/cygwin/path.h17
-rw-r--r--winsup/cygwin/path.sgml (renamed from winsup/doc/path.xml)30
-rw-r--r--winsup/cygwin/pinfo.cc4
-rw-r--r--winsup/cygwin/poll.cc5
-rw-r--r--winsup/cygwin/posix.sgml (renamed from winsup/doc/posix.xml)9
-rw-r--r--winsup/cygwin/pwdgrp.h256
-rw-r--r--winsup/cygwin/quotactl.cc1
-rw-r--r--winsup/cygwin/release/1.7.3322
-rw-r--r--winsup/cygwin/sec_acl.cc256
-rw-r--r--winsup/cygwin/sec_auth.cc112
-rw-r--r--winsup/cygwin/sec_helper.cc148
-rw-r--r--winsup/cygwin/security.cc114
-rw-r--r--winsup/cygwin/security.h80
-rw-r--r--winsup/cygwin/security.sgml (renamed from winsup/doc/logon-funcs.xml)27
-rw-r--r--winsup/cygwin/select.cc17
-rw-r--r--winsup/cygwin/setlsapwd.cc3
-rw-r--r--winsup/cygwin/shared.cc11
-rw-r--r--winsup/cygwin/shared_info.h2
-rw-r--r--winsup/cygwin/stackdump.sgml13
-rw-r--r--winsup/cygwin/syscalls.cc1
-rw-r--r--winsup/cygwin/tlsoffsets.h216
-rw-r--r--winsup/cygwin/tlsoffsets64.h216
-rw-r--r--winsup/cygwin/uinfo.cc1604
-rw-r--r--winsup/cygwin/uname.cc5
-rw-r--r--winsup/cygwin/wincap.cc7
-rw-r--r--winsup/cygwin/wincap.h4
-rw-r--r--winsup/cygwin/winlean.h2
-rw-r--r--winsup/cygwin/winsup.h23
-rw-r--r--winsup/doc/ChangeLog157
-rw-r--r--winsup/doc/Makefile.in58
-rwxr-xr-xwinsup/doc/configure156
-rw-r--r--winsup/doc/configure.ac11
-rw-r--r--winsup/doc/cygwin-api.in.xml34
-rw-r--r--winsup/doc/cygwin-api.xml26
-rw-r--r--winsup/doc/cygwin.xsl1
-rw-r--r--winsup/doc/doctool.c622
-rw-r--r--winsup/doc/doctool.txt146
-rw-r--r--winsup/doc/faq-programming.xml3
-rw-r--r--winsup/doc/faq-setup.xml15
-rw-r--r--winsup/doc/faq-using.xml21
-rw-r--r--winsup/doc/highlights.xml17
-rw-r--r--winsup/doc/misc-funcs.xml64
-rw-r--r--winsup/doc/new-features.xml33
-rw-r--r--winsup/doc/ntsec.xml1608
-rw-r--r--winsup/doc/pathnames.xml23
-rw-r--r--winsup/doc/using.xml2
-rwxr-xr-xwinsup/doc/xidepend2
-rw-r--r--winsup/lsaauth/ChangeLog5
-rwxr-xr-xwinsup/lsaauth/configure50
-rw-r--r--winsup/lsaauth/configure.ac21
-rw-r--r--winsup/testsuite/ChangeLog5
-rw-r--r--winsup/testsuite/configure257
-rwxr-xr-xwinsup/testsuite/configure.ac6
-rw-r--r--winsup/utils/ChangeLog112
-rwxr-xr-xwinsup/utils/configure50
-rw-r--r--winsup/utils/configure.ac7
-rw-r--r--winsup/utils/cygcheck.cc7
-rw-r--r--winsup/utils/getfacl.c10
-rw-r--r--winsup/utils/mkgroup.c433
-rw-r--r--winsup/utils/mkpasswd.c468
-rw-r--r--winsup/utils/passwd.c33
-rw-r--r--winsup/utils/setfacl.c182
-rw-r--r--winsup/utils/utils.xml (renamed from winsup/doc/utils.xml)255
113 files changed, 7375 insertions, 9521 deletions
diff --git a/winsup/cygserver/ChangeLog b/winsup/cygserver/ChangeLog
index 0b08894d2..653f531fb 100644
--- a/winsup/cygserver/ChangeLog
+++ b/winsup/cygserver/ChangeLog
@@ -1,12 +1,3 @@
-2014-11-06 Florian Friesdorf <flo@chaoflow.net>
-
- * cygserver-config: Add -N option to allow different service name.
-
-2014-08-15 Corinna Vinschen <corinna@vinschen.de>
-
- * configure.ac: Convert to new AC_INIT style.
- * configure: Regenerate.
-
2014-06-23 Corinna Vinschen <corinna@vinschen.de>
* bsd_helper.cc (ipcexit_creat_hookthread): Delete shs in another error
@@ -30,11 +21,6 @@
2014-04-16 Corinna Vinschen <corinna@vinschen.de>
- * pwdgrp.cc (client_request_pwdgrp::pwd_serve): Add 1 to the message
- length to account for the trailing NUL.
-
-2014-04-16 Corinna Vinschen <corinna@vinschen.de>
-
* cygserver-config: Use numeric id 18 instead of "system" in chown.
2014-04-07 Corinna Vinschen <corinna@vinschen.de>
@@ -44,13 +30,6 @@
2014-03-12 Corinna Vinschen <corinna@vinschen.de>
- * Makefile.in (OBJS): Add pwdgrp.o.
- * client.cc (client_request::handle_request): Handle
- CYGSERVER_REQUEST_PWDGRP message.
- * pwdgrp.cc: New file implementing CYGSERVER_REQUEST_PWDGRP.
-
-2014-03-12 Corinna Vinschen <corinna@vinschen.de>
-
* Throughout, fix format specifiers in debug statements to accommodate
x86_64.
diff --git a/winsup/cygserver/Makefile.in b/winsup/cygserver/Makefile.in
index 816f5b3db..e2fe30992 100644
--- a/winsup/cygserver/Makefile.in
+++ b/winsup/cygserver/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for Cygwin server
-# Copyright 2003, 2006, 2007, 2008, 2009, 2014 Red Hat, Inc.
+# Copyright 2003, 2006, 2007, 2008, 2009 Red Hat, Inc.
# This file is part of Cygwin.
@@ -46,7 +46,7 @@ AR:=@AR@
OBJS:= cygserver.o client.o process.o msg.o sem.o shm.o threaded_queue.o \
transport.o transport_pipes.o \
bsd_helper.o bsd_log.o bsd_mutex.o \
- sysv_msg.o sysv_sem.o sysv_shm.o setpwd.o pwdgrp.o
+ sysv_msg.o sysv_sem.o sysv_shm.o setpwd.o
LIBOBJS:=${patsubst %.o,lib%.o,$(OBJS)}
CYGWIN_OBJS:=$(cygwin_build)/version.o
diff --git a/winsup/cygserver/client.cc b/winsup/cygserver/client.cc
index 0c6c24ba9..9c890f7a8 100644
--- a/winsup/cygserver/client.cc
+++ b/winsup/cygserver/client.cc
@@ -26,7 +26,6 @@ details. */
#include "cygserver_sem.h"
#include "cygserver_shm.h"
#include "cygserver_setpwd.h"
-#include "cygserver_pwdgrp.h"
#include "cygserver.h"
#include "transport.h"
@@ -286,9 +285,6 @@ client_request::handle_request (transport_layer_base *const conn,
case CYGSERVER_REQUEST_SETPWD:
req = new client_request_setpwd;
break;
- case CYGSERVER_REQUEST_PWDGRP:
- req = new client_request_pwdgrp;
- break;
default:
syscall_printf ("unknown request code %d received: request ignored",
header.request_code);
diff --git a/winsup/cygserver/configure b/winsup/cygserver/configure
index a4feae10b..a79f22692 100755
--- a/winsup/cygserver/configure
+++ b/winsup/cygserver/configure
@@ -1,8 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Cygwin Cygserver 0.
-#
-# Report bugs to <cygwin@cygwin.com>.
+# Generated by GNU Autoconf 2.69.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -265,11 +263,10 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and cygwin@cygwin.com
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
exit 1
fi
@@ -577,12 +574,12 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME='Cygwin Cygserver'
-PACKAGE_TARNAME='cygwin'
-PACKAGE_VERSION='0'
-PACKAGE_STRING='Cygwin Cygserver 0'
-PACKAGE_BUGREPORT='cygwin@cygwin.com'
-PACKAGE_URL='https://cygwin.com'
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
ac_unique_file="cygserver.cc"
ac_no_link=no
@@ -728,7 +725,7 @@ sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
@@ -1228,7 +1225,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Cygwin Cygserver 0 to adapt to many kinds of systems.
+\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1276,7 +1273,7 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/cygwin]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
@@ -1293,9 +1290,7 @@ _ACEOF
fi
if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of Cygwin Cygserver 0:";;
- esac
+
cat <<\_ACEOF
Optional Features:
@@ -1326,8 +1321,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Cygserver home page: <https://cygwin.com>.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1390,7 +1384,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Cygwin Cygserver configure 0
+configure
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1520,7 +1514,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Cygwin Cygserver $as_me 0, which was
+It was created by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1868,7 +1862,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_aux_dir=
for ac_dir in .. "$srcdir"/..; do
if test -f "$ac_dir/install-sh"; then
@@ -4704,7 +4697,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Cygwin Cygserver $as_me 0, which was
+This file was extended by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4751,14 +4744,13 @@ Usage: $0 [OPTION]... [TAG]...
Configuration files:
$config_files
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Cygserver home page: <https://cygwin.com>."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Cygwin Cygserver config.status 0
+config.status
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/winsup/cygserver/configure.ac b/winsup/cygserver/configure.ac
index 4e2cb4582..48fb7c45e 100644
--- a/winsup/cygserver/configure.ac
+++ b/winsup/cygserver/configure.ac
@@ -1,5 +1,5 @@
-dnl Autoconf configure script for Cygserver.
-dnl Copyright 2003, 2012, 2013, 2014 Red Hat, Inc.
+dnl Autoconf configure script for Cygwin.
+dnl Copyright 2003 Red Hat, Inc.
dnl
dnl This file is part of Cygwin.
dnl
@@ -10,9 +10,7 @@ dnl
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)dnl
-AC_INIT([Cygwin Cygserver], 0,
- cygwin@cygwin.com, cygwin, https://cygwin.com)
-AC_CONFIG_SRCDIR(cygserver.cc)
+AC_INIT(cygserver.cc)
AC_CONFIG_AUX_DIR(..)
. ${srcdir}/../configure.cygwin
diff --git a/winsup/cygserver/cygserver-config b/winsup/cygserver/cygserver-config
index abe943c3f..b8f441c3d 100755
--- a/winsup/cygserver/cygserver-config
+++ b/winsup/cygserver/cygserver-config
@@ -10,7 +10,6 @@ LOCALSTATEDIR=/var
progname=$0
auto_answer=""
-service_name=cygserver
request()
{
@@ -64,11 +63,6 @@ do
auto_answer=no
;;
- -N | --name )
- service_name=$1
- shift
- ;;
-
*)
echo "usage: ${progname} [OPTION]..."
echo
@@ -78,7 +72,6 @@ do
echo " --debug -d Enable shell's debug output."
echo " --yes -y Answer all questions with \"yes\" automatically."
echo " --no -n Answer all questions with \"no\" automatically."
- echo " --name -N <name> cygserver windows service name."
echo
exit 1
;;
@@ -91,10 +84,10 @@ _sys="`uname`"
_nt=`expr "${_sys}" : "CYGWIN_NT"`
# Check for running cygserver processes first.
-if ps -ef | grep -v grep | grep -q ${service_name}
+if ps -ef | grep -v grep | grep -q cygserver
then
echo
- echo "There is a cygserver (${service_name}) already running. Nothing to do, apparently."
+ echo "There is a cygserver already running. Nothing to do, apparently."
echo
exit 1
fi
@@ -171,7 +164,7 @@ fi
if [ ${_nt} -gt 0 ]
then
# But only if it is not already installed
- if ! cygrunsrv -Q ${service_name} > /dev/null 2>&1
+ if ! cygrunsrv -Q cygserver > /dev/null 2>&1
then
echo
echo
@@ -180,7 +173,7 @@ then
echo "Do you want to install cygserver as service?"
if request "(Say \"no\" if it's already installed as service)"
then
- if ! cygrunsrv -I ${service_name} -d "CYGWIN cygserver" -p /usr/sbin/cygserver
+ if ! cygrunsrv -I cygserver -d "CYGWIN cygserver" -p /usr/sbin/cygserver
then
echo
echo "Installation of cygserver as service failed. Please check the"
@@ -193,7 +186,7 @@ then
fi
echo
echo "The service has been installed under LocalSystem account."
- echo "To start it, call \`net start ${service_name}' or \`cygrunsrv -S ${service_name}'."
+ echo "To start it, call \`net start cygserver' or \`cygrunsrv -S cygserver'."
fi
touch "${LOCALSTATEDIR}/log/cygserver.log"
chown 18.544 "${LOCALSTATEDIR}/log/cygserver.log"
diff --git a/winsup/cygserver/pwdgrp.cc b/winsup/cygserver/pwdgrp.cc
deleted file mode 100644
index cc12deadd..000000000
--- a/winsup/cygserver/pwdgrp.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/* pwdgrp.cc: Request account information
-
- Copyright 2014 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. */
-
-#ifdef __OUTSIDE_CYGWIN__
-#include "woutsup.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/cygwin.h>
-
-#include "cygserver.h"
-#include "process.h"
-#include "transport.h"
-
-#include "cygserver_pwdgrp.h"
-
-#include <sddl.h>
-
-client_request_pwdgrp::client_request_pwdgrp ()
- : client_request (CYGSERVER_REQUEST_PWDGRP,
- &_parameters, sizeof (_parameters))
-{
-}
-
-void
-client_request_pwdgrp::pwd_serve ()
-{
- struct passwd *pwd = NULL;
-
- switch (_parameters.in.type)
- {
- case SID_arg:
- pwd = (struct passwd *) cygwin_internal (CW_GETPWSID, 0,
- &_parameters.in.arg.sid);
- break;
- case NAME_arg:
- pwd = getpwnam (_parameters.in.arg.name);
- break;
- case ID_arg:
- pwd = getpwuid (_parameters.in.arg.id);
- break;
- }
- if (pwd)
- msglen (snprintf (_parameters.out.line, sizeof _parameters.out.line,
- "%s:%s:%u:%u:%s:%s:%s",
- pwd->pw_name ?: "",
- pwd->pw_passwd ?: "",
- (uint32_t) pwd->pw_uid,
- (uint32_t) pwd->pw_gid,
- pwd->pw_gecos ?: "",
- pwd->pw_dir ?: "",
- pwd->pw_shell ?: "") + 1);
- else
- {
- switch (_parameters.in.type)
- {
- case SID_arg:
- {
- char *str;
- if (ConvertSidToStringSid (&_parameters.in.arg.sid, &str))
- {
- debug_printf ("User <%s> failed", str);
- LocalFree (str);
- }
- }
- break;
- case NAME_arg:
- debug_printf ("User <%s> failed", _parameters.in.arg.name);
- break;
- case ID_arg:
- debug_printf ("User <%u> failed", _parameters.in.arg.id);
- break;
- }
- _parameters.out.line[0] = '\0';
- msglen (0);
- error_code (ENOENT);
- }
-}
-
-void
-client_request_pwdgrp::grp_serve ()
-{
- struct group *grp = NULL;
-
- switch (_parameters.in.type)
- {
- case SID_arg:
- grp = (struct group *) cygwin_internal (CW_GETGRSID, 0,
- &_parameters.in.arg.sid);
- break;
- case NAME_arg:
- grp = getgrnam (_parameters.in.arg.name);
- break;
- case ID_arg:
- grp = getgrgid (_parameters.in.arg.id);
- break;
- }
- if (grp)
- msglen (snprintf (_parameters.out.line, sizeof _parameters.out.line,
- "%s:%s:%u:",
- grp->gr_name ?: "",
- grp->gr_passwd ?: "",
- (uint32_t) grp->gr_gid) + 1);
- else
- {
- switch (_parameters.in.type)
- {
- case SID_arg:
- {
- char *str;
- if (ConvertSidToStringSid (&_parameters.in.arg.sid, &str))
- {
- debug_printf ("Group <%s> failed", str);
- LocalFree (str);
- }
- }
- break;
- case NAME_arg:
- debug_printf ("Group <%s> failed", _parameters.in.arg.name);
- break;
- case ID_arg:
- debug_printf ("Group <%u> failed", _parameters.in.arg.id);
- break;
- }
- _parameters.out.line[0] = '\0';
- msglen (0);
- error_code (ENOENT);
- }
-}
-
-void
-client_request_pwdgrp::serve (transport_layer_base *const conn,
- process_cache *const cache)
-{
- debug_printf ("Request account information");
- if (msglen () < __builtin_offsetof (struct _pwdgrp_param_t::_pwdgrp_in_t, arg)
- + sizeof (uint32_t)
- || msglen () > sizeof (_parameters.in))
- {
- syscall_printf ("bad request body length: got %lu", msglen ());
- error_code (EINVAL);
- msglen (0);
- return;
- }
- error_code (0);
- if (_parameters.in.group)
- grp_serve ();
- else
- pwd_serve ();
- debug_printf ("Request account information returns <%s> error %d", _parameters.out.line, error_code ());
-}
-#endif /* __OUTSIDE_CYGWIN__ */
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index fa5ca1947..51cc4e880 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -39,10 +39,6 @@
* cygheap.cc: Fix formatting.
-2014-10-30 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (cygheap_user::ontherange): Don't mention /etc/passwd.
-
2014-10-29 Corinna Vinschen <corinna@vinschen.de>
* cygheap.cc (init_cygheap::init_installation_root): Create content of
@@ -67,16 +63,9 @@
2014-10-27 Corinna Vinschen <corinna@vinschen.de>
- * dlfcn.cc (dlopen): Drop patch accommodating SetDllDiretory from
- 2014-10-14.
-
-2014-10-27 Corinna Vinschen <corinna@vinschen.de>
-
- * cygheap.cc (cygheap_fixup_in_child): Drop call to set_dll_dir.
- (init_cygheap::init_installation_root): Set installation_dir_len.
- (setup_cygheap): Drop call to set_dll_dir.
+ * cygheap.cc (init_cygheap::init_installation_root): Set
+ installation_dir_len.
* cygheap.h (struct init_cygheap): Add installation_dir_len member.
- (init_cygheap::set_dll_dir): Remove.
* environ.cc (win_env::add_cache): Use stpcpy for speed.
(posify_maybe): Use tmp_pathbuf buffer instead of stack.
(raise_envblock): New function to resize Windows environment block.
@@ -84,20 +73,6 @@
$PATH exists and is non-empty. If not, add PATH variable with Cygwin
installation directory as content to Windows environment. Explain why.
- * uinfo.cc (cygheap_pwdgrp::_nss_init): Fill UNICODE_STRING members
- on the fly. Drop call to RtlInitUnicodeString.
- (pwdgrp::check_file): Ditto.
-
-2014-10-26 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_socket.cc (fhandler_socket::af_local_connect): Drop
- setting connect_state to connect_credxchg.
- (fhandler_socket::af_local_accept): Ditto.
- (fhandler_socket::recv_internal): Drop ill-advised connect_state check.
- Add comment so as not to repeat the exercise.
- * fhandler.h (enum conn_state): Drop now unneeded connect_credxchg
- state.
-
2014-10-24 Corinna Vinschen <corinna@vinschen.de>
* fhandler_proc.cc (format_proc_cygdrive): Fix symlink path if cygdrive
@@ -108,12 +83,6 @@
* gendef (sigdelayed): 64 bit only: Fix seh_pushreg statements in
prologue.
-2014-10-24 Kai Tietz <corinna@vinschen.de>
- Corinna Vinschen <corinna@vinschen.de>
-
- * gendef (sigdelayed): 64 bit only: Push CPU flags before aligning
- stack to avoid changing flag values.
-
2014-10-22 Yaakov Selkowitz <yselkowi@redhat.com>
* common.din (stime): Export.
@@ -121,12 +90,6 @@
* include/cygwin/time.h (stime): Declare.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
-2014-10-21 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_auth.cc (get_user_groups): Remove experimental exception handler
- added 2014-09-05.
- (get_user_local_groups): Ditto.
-
2014-10-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler_serial.cc: Revert debug code accidentally checked in on
@@ -139,21 +102,11 @@
2014-10-17 Corinna Vinschen <corinna@vinschen.de>
- * cygheap.cc (cygheap_fixup_in_child): Call set_dll_dir.
- (init_cygheap::init_installation_root): Just memmove contents of
- installation_root instead of calling GetModuleFileNameW again.
- Copy installation_root to installation_dir before stripping of
- "bin" dir. Don't call SetDllDirectory here. Explain what we do.
- (setup_cygheap): New function taking over initial cygheap setup
- from memory_init. Additionally call set_dll_dir.
+ * cygheap.cc (init_cygheap::init_installation_root): Just memmove
+ contents of installation_root instead of calling GetModuleFileNameW
+ again. Copy installation_root to installation_dir before stripping of
+ "bin" dir. Explain what we do.
* cygheap.h (struct init_cygheap): Add installation_dir member.
- (init_cygheap::set_dll_dir): Define.
- (setup_cygheap): Declare.
- * dcrt0.cc: Throughout drop parameter from memory_init call.
- (dll_crt0_0): Call setup_cygheap prior to memory_init.
- * dlfcn.cc (dlopen): Change comment to point to the right function.
- * shared.cc (memory_init): Drop parameter. Drop cygheap setup.
- * shared_info.h (memory_init): Change declaration accordingly.
2014-10-17 Corinna Vinschen <corinna@vinschen.de>
@@ -189,31 +142,6 @@
* fhandler_proc.cc (format_proc_partitions): Extend output to print
the windows mount points the device is mounted on.
-2014-10-14 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_socket.cc (fhandler_socket::connect): Don't change state
- on WSAEALREADY error. Change comment accordingly.
-
-2014-10-14 Corinna Vinschen <corinna@vinschen.de>
-
- * cygheap.cc (init_cygheap::init_installation_root): Install Cygwin's
- installation dir as DLL search path, instead of ".".
- * cygheap.h (class cwdstuff): Add parameter names in function
- declarations for readability.
- (cwdstuff::get): Add inline implementation fetching the CWD as wide char
- string.
- * dlfcn.cc (dlopen): Add searching for dependent DLLs in DLL
- installation dir or CWD, if all else failed.
- Add comment to explain scenarios this is accommodating.
-
-2014-10-14 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_socket.cc (fhandler_socket::connect): Init connect_state to
- connect_pending only on unconnected socket. Set connect_state to
- connected on WSAEISCONN error. Set connect_state to connect_failed
- on any other error except WSAEWOULDBLOCK if connect is still pending.
- Add lots of comment to explain why all of the above.
-
2014-10-13 Corinna Vinschen <corinna@vinschen.de>
* net.cc (cygwin_setsockopt): Drop redundant test for AF_LOCAL and
@@ -250,63 +178,12 @@
sockets. Add comment to explain why we need it.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
-2014-10-11 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_socket.cc (fhandler_socket::af_local_connect): Drop outdated
- comment.
- (fhandler_socket::evaluate_events): Only set connect_state and call
- af_local_connect if connect_state is connect_pending. Explain why.
- Drop redundant test for socket family and type.
- (fhandler_socket::connect): Extend comment.
-
-2014-10-11 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_socket.cc (fhandler_socket::evaluate_events): Handle
- connect_state and af_local_connect connect call here, once, independent
- of FD_CONNECT being requested. Add comment to explain why.
- (fhandler_socket::connect): Drop connect_state handling and calling
- af_local_connect. Move remaining AF_LOCAL stuff prior to calling
- ::connect and explain why. Simplify error case.
- * poll.cc (poll): Handle connect state independently of POLLOUT being
- requested for the descriptor to allow setting POLLIN if connect failed.
- Add comment.
- * select.cc (set_bits): Drop connect_state and AF_LOCAL handling here.
-
-2014-10-11 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_socket.cc (fhandler_socket::evaluate_events): Slightly
- rearrange code. Rephrase a comment.
-
2014-10-10 Corinna Vinschen <corinna@vinschen.de>
* dlfcn.cc (dlopen): Disable old 32 bit code on 64 bit.
* dcrt0.cc (check_sanity_and_sync): Ditto.
* dll_init.cc (dll_dllcrt0_1): Fix typo in comment.
-2014-10-09 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_procsys.cc (fhandler_procsys::readdir): Just test
- ObjectTypeName for object types rather than calling lstat to avoid
- performance hit.
- * globals.cc (ro_u_natdir): Define.
- (ro_u_natsyml): Define.
- (ro_u_natdev): Define.
-
-2014-10-09 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Set d_type
- for virtual directories.
-
-2014-10-09 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler_proc.cc (fhandler_proc::readdir): Set dirent d_type.
- * fhandler_process.cc (fhandler_process::readdir): Ditto.
- * fhandler_procnet.cc (fhandler_procnet::readdir): Ditto.
- * fhandler_procsys.cc (fhandler_procsys::readdir): Ditto.
- * fhandler_procsysvipc.cc (fhandler_procsysvipc::readdir): Ditto.
- * fhandler_virtual.h (virt_ftype_to_dtype): Define new inline function
- to generate dirent d_type from virtual_ftype_t.
-
2014-10-08 Corinna Vinschen <corinna@vinschen.de>
* common.din (ffsl): Export.
@@ -333,68 +210,11 @@
2014-09-05 Corinna Vinschen <corinna@vinschen.de>
* exception.h (class exception): Remove unnecessary #ifdef.
- * uinfo.cc (client_request_pwdgrp::client_request_pwdgrp): Fix length
- counter to include trailing NUL.
-
- * sec_auth.cc (get_user_groups): Add experimental exception handler.
- (get_user_local_groups): Ditto.
2014-09-05 Corinna Vinschen <corinna@vinschen.de>
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Handle APPLICATION
- PACKAGE AUTHORITY SIDs.
* winlean.h (DNLEN): Raise to 31. Explain why.
-2014-09-03 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_acl.cc (aclcheck32): Check for required default entries as well.
- Enable check for missing CLASS_OBJ entries, now that setfacl creates
- them.
-
-2014-09-02 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_acl.cc (aclsort32): Set errno to EINVAL if aclcheck32 failed.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Disallow user accounts
- as groups. Add comment.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (cygheap_pwdgrp::init): Fix comment. Rearrange code for
- style.
- (cygheap_pwdgrp::nss_init_line): Disable db_prefix and db_separator
- settings. Add comment.
- (pwdgrp::fetch_account_from_windows): Drop outdated comment. Fix code
- fetching primary group gid of group setting in SAM description field.
- Change comment accordingly.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Disallow creating an
- entry for "NULL SID".
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_acl.cc (setacl): Add comment. Handle NULL ACE for SUID, SGID,
- and VTX bits. Create owner, group, other and NULL entries in the same
- way and in the same order as alloc_sd.
- (getacl): Skip NULL ACE.
-
-2014-08-28 Corinna Vinschen <corinna@vinschen.de>
-
- * fhandler.cc (fhandler_base::facl): Drop CLASS_OBJ entry.
- * fhandler_disk_file.cc (fhandler_disk_file::facl): Ditto in noacl case.
- * sec_acl.cc (getacl): Compute useful fake CLASS_OBJ and DEF_CLASS_OBJ
- permission bits based on how these values are generated on Linux.
- Add comments to explain what the code is doing.
- * security.cc (get_attribute_from_acl): Compute group permission based
- on the actual primary group permissions and all secondary user and group
- ACCESS_ALLOWED_ACEs to emulate Linux' behaviour more closely.
- (check_access): Fix typos im comment.
- * include/cygwin/acl.h (MIN_ACL_ENTRIES): Redefine as 3.
-
2014-08-28 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::fstatvfs): Try the
@@ -552,17 +372,6 @@
2014-08-19 Corinna Vinschen <corinna@vinschen.de>
- * fhandler.h (enum conn_state): Add "connect_credxchg" state.
- (class fhandler_socket): Grant another bit to connect_state flag.
- * fhandler_socket.cc (fhandler_socket::af_local_connect): Rearrange
- variable definition. Set connect_state to connect_credxchg.
- (fhandler_socket::af_local_accept): Ditto.
- (fhandler_socket::recv_internal): Accept connect_credxchg on connection
- oriented AF_LOCAL sockets as well to allow the credential exchange.
- Extend comment to explain.
-
-2014-08-19 Corinna Vinschen <corinna@vinschen.de>
-
* autoload.cc: Replace WNet[...]A with WNet[...]W imports.
* dcrt0.cc (initial_env): Drop strlwr calls. Call strcasestr instead.
* fhandler_netdrive.cc: Throughout, convert to calling WNet UNICODE
@@ -594,36 +403,11 @@
listener. Add comment.
(fhandler_socket::accept4): Explicitely check if the socket is listening
and fail with EINVAL, if not. Explain why we have to do that.
- (fhandler_socket::recv_internal): Explicitely check if the socket is
- connected if it's a stream socket. Explain why we have to do that.
(fhandler_socket::getpeereid): Drop now redundant test.
2014-08-15 Corinna Vinschen <corinna@vinschen.de>
* winsup.h (_GNU_SOURCE): Define. Explain why.
- * configure.ac: Convert to new AC_INIT style.
- * configure: Regenerate.
-
-2014-08-15 Corinna Vinschen <corinna@vinschen.de>
-
- * cygerrno.h (seterrno): Define as (always) inline function.
- * errno.cc (seterrno): Remove.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * dll_init.sgml: Remove.
- * dtable.sgml: Move into ../doc/misc-funcs.xml.
- * external.sgml: Ditto.
- * stackdump.sgml: Ditto.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * security.sgml: Move to ../doc dir and rename to logon-funcs.xml.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * path.sgml: Move to ../doc dir and rename to path.xml.
- * posix.sgml: Move to ../doc dir and rename to posix.xml.
2014-08-14 Corinna Vinschen <corinna@vinschen.de>
@@ -667,14 +451,6 @@
* common.din (__cxa_atexit): Export.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump to 274.
-2014-08-04 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Drop "plus_prepended"
- as naming style. Drop enum name_style_t, use a boolean
- "fully_qualified_name" value instead. Rework function to drop
- "plus_prepended" handling througout and default to "name only" style
- as replacement.
-
2014-07-31 Eric Blake <eblake@redhat.com>
* include/pthread.h: Decorate attribute names with __, for
@@ -684,27 +460,6 @@
* include/sys/cygwin.h: Likewise.
* include/sys/strace.h: Likewise.
-2014-07-30 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Fix comment.
-
-2014-07-29 Corinna Vinschen <corinna@vinschen.de>
-
- * cygheap.h (class cygheap_domain_info): Remove lowest_tdo_posix_offset.
- * ldap.cc (cyg_ldap::fetch_posix_offset_for_domain): Return UINT32_MAX
- in case of error.
- * security.h (PRIMARY_POSIX_OFFSET): Define.
- (NOACCESS_POSIX_OFFSET): Define.
- (UNUSABLE_POSIX_OFFSET): Define.
- * uinfo.cc (cygheap_domain_info::init): Drop initializing
- lowest_tdo_posix_offset.
- (pwdgrp::fetch_account_from_file): Set PosixOffset to either
- UNUSABLE_POSIX_OFFSET or NOACCESS_POSIX_OFFSET in case we don't get a
- sensible offset from AD. Explain why. Drop setting ch
- lowest_tdo_posix_offset.
- (pwdgrp::fetch_account_from_windows): Replace constant 0x100000 with
- PRIMARY_POSIX_OFFSET throughout.
-
2014-07-24 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::send_internal): Fix value of
@@ -720,10 +475,6 @@
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 32.
-2014-07-21 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc: Fix typo in comment.
-
2014-07-16 Corinna Vinschen <corinna@vinschen.de>
* thread.cc (pthread::create): Handle stackaddr as upper bound address.
@@ -757,13 +508,6 @@
* sigproc.cc (send_sig): Fix bad format in diagnostic output.
-2014-07-14 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (cygheap_domain_info::init): Correctly set
- lowest_tdo_posix_offset to UNIX_POSIX_OFFSET.
- (fetch_posix_offset): Redesign to fake a POSIX offset in all cases
- where we can't fetch a non-0 POSIX offset from our primary domain.
-
2014-07-14 Yaakov Selkowitz <yselkowitz@cygwin.com>
* thread.cc (pthread_mutex::pthread_mutex): Change default type
@@ -809,11 +553,6 @@
writing small buffers. Rename variables and add comments to help
understanding the code in years to come.
-2014-07-07 Corinna Vinschen <corinna@vinschen.de>
-
- * passwd.cc (pg_ent::enumerate_ad): Revert to simply skipping a domain
- if opening the connection to the domain fails.
-
2014-07-07 Pierre Humblet <Pierre.Humblet@ieee.org>
Corinna Vinschen <corinna@vinschen.de>
@@ -827,73 +566,6 @@
* fhandler_disk_file.cc (fhandler_disk_file::fstatvfs): Add debug
output.
-2014-06-25 Corinna Vinschen <corinna@vinschen.de>
-
- * errno.cc (errmap): Fix order of SERVICE_REQUEST_TIMEOUT.
-
-2014-06-25 Corinna Vinschen <corinna@vinschen.de>
-
- * errno.cc (errmap): Handle Windows error codes ERROR_CANCELLED,
- ERROR_CONNECTION_REFUSED, ERROR_DEV_NOT_EXIST, ERROR_DS_GENERIC_ERROR,
- ERROR_NOT_ENOUGH_QUOTA, ERROR_SERVICE_REQUEST_TIMEOUT, ERROR_TIMEOUT,
- ERROR_UNEXP_NET_ERR.
- * ldap.cc (cyg_ldap::map_ldaperr_to_errno): Drop explicit LDAP_TIMEOUT
- handling.
-
-2014-06-25 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (cyg_ldap::map_ldaperr_to_errno): Explicitely map LDAP_TIMEOUT
- to EIO.
-
-2014-06-25 Corinna Vinschen <corinna@vinschen.de>
-
- * autoload.cc (ldap_search_sW): Replace ldap_search_stW.
- (LdapMapErrorToWin32): Import.
- * fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Accommodate
- change to cyg_ldap::open.
- * ldap.cc (CYG_LDAP_TIMEOUT): Remove.
- (CYG_LDAP_ENUM_TIMEOUT): Remove.
- (def_tv): Remove.
- (enum_tv): Remove.
- (cyg_ldap::map_ldaperr_to_errno): New method to map LDAP error codes to
- POSIX errno codes. Explicitly map LDAP_NO_RESULTS_RETURNED to ENMFILE.
- (cyg_ldap::wait): Ditto.
- (struct cyg_ldap_init): New struct.
- (cyg_ldap::connect_ssl): Return ULONG. Drop setting LDAP_OPT_TIMELIMIT.
- Add call to ldap_search_sW to fetch root DSE.
- (cyg_ldap::connect_non_ssl): Ditto.
- (ldap_init_thr): New static thread function.
- (cyg_ldap::connect): New method to call connect_ssl/connect_non_ssl in
- an interruptible cygthread.
- (struct cyg_ldap_search): New struct.
- (cyg_ldap::search_s): New method to perform generic synchronous search.
- (ldap_search_thr): New static thread function.
- (cyg_ldap::search): New method to call search_s in an interruptible
- cygthread.
- (struct cyg_ldap_next_page): New struct.
- (cyg_ldap::next_page_s): New method to perform generic synchronous
- paged search.
- (ldap_next_page_thr): New static thread function.
- (cyg_ldap::next_page): New method to call next_page_s in an
- interruptible cygthread.
- (cyg_ldap::open): Return POSIX errno. Call connect method.
- (cyg_ldap::fetch_ad_account): Call search method rather than
- ldap_search_stW.
- (cyg_ldap::enumerate_ad_accounts): Return POSIX errno. Use infinite
- timeout in call to ldap_search_init_pageW.
- (cyg_ldap::next_account): Return POSIX errno. Call next_page method
- rather than ldap_get_next_page_s.
- (cyg_ldap::fetch_posix_offset_for_domain): Call search method rather
- than ldap_search_stW.
- (cyg_ldap::fetch_unix_sid_from_ad): Ditto.
- (cyg_ldap::fetch_unix_name_from_rfc2307): Ditto.
- * ldap.h (class cyg_ldap): Accommodate aforementioned changes.
- * passwd.cc (pg_ent::enumerate_ad): Ditto. Break search if one of
- cyg_ldap::enumerate_ad_accounts or cldap.next_account returns with
- an error code other than ENMFILE.
- * sec_helper.cc (cygpsid::get_id): Accommodate change to cyg_ldap::open.
- * uinfo.cc (fetch_posix_offset): Ditto.
-
2014-06-23 Corinna Vinschen <corinna@vinschen.de>
* spawn.cc (find_exec): Initialize err (CID 60111).
@@ -951,24 +623,6 @@
* dcrt0.cc (insert_file): Fix resource leaks (CIDs 59987, 59988).
-2014-06-23 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (CYG_LDAP_TIMEOUT): Set to 5 secs.
- (CYG_LDAP_ENUM_TIMEOUT): New timeout value for enumeration only. Set
- to 60 secs.
- (CYG_LDAP_ENUM_PAGESIZE): Define as number of entries per single
- search page. Set to 100. Use throughout.
- (def_tv): Rename from tv. Use throughout.
- (enum_tv): New variable. Use in call to ldap_get_next_page_s.
-
-2014-06-17 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (CYG_LDAP_TIMEOUT): Define as timeout value. Set to 30 secs
- for now. Use throughout.
- * uinfo.cc (colon_to_semicolon): New local function.
- (pwdgrp::fetch_account_from_windows): Convert all colons in AD gecos
- entry to semicolons.
-
2014-06-17 David Stacey <drstacey@tiscali.co.uk>
* libc/rexec.cc (cygwin_rexec): Make ahostbuf static to avoid returning
@@ -989,62 +643,12 @@
* timer.cc (timer_tracker::cancel): Demote api_fatal to system_printf,
printing more details about odd failure condition.
-2014-05-23 Corinna Vinschen <corinna@vinschen.de>
-
- * autoload.cc (ldap_memfreeW): Remove.
- (ldap_msgfree): Import.
- * ldap.cc: Throughout, use ldap_msgfree to free LDAPMessage memory,
- rather than ldap_memfreeW.
- (cyg_ldap::next_account): Immediately abandon search when quiting from
- search.
-
-2014-05-22 Corinna Vinschen <corinna@vinschen.de>
-
- * autoload.cc (ldap_abandon): Remove.
- (ldap_count_entries): Import.
- (ldap_get_next_page_s): Import.
- (ldap_result): Remove.
- (ldap_searchW): Remove.
- (ldap_search_abandon_page): Import.
- (ldap_search_init_pageW): Import.
- * ldap.cc (cyg_ldap::close): Use ldap_search_abandon_page to abandon
- search. Reset srch_id, srch_msg and srch_entry.
- (cyg_ldap::enumerate_ad_accounts): Use paged search to overcome server
- side search result set restriction.
- (cyg_ldap::next_account): Ditto.
- * ldap.h (class cyg_ldap): Add members srch_id, srch_msg and srch_entry.
- Remove member msg_id.
- (cyg_ldap::cyg_ldap): Change initialization accordingly.
-
-2014-05-22 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_auth.cc (get_server_groups): Call get_user_local_groups only if
- get_logon_server succeeded.
-
-2014-05-22 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (cyg_ldap::fetch_ad_account): Take additional domain string
- parameter. Convert into likely rootDSE string if not NULL, and use in
- subsequent call to ldap_search_stW. Add comment to explain that this
- is not the exactly correct solution.
- * ldap.h (cyg_ldap::fetch_ad_account): Change prototype accordingly.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Always use loc_ldap
- in call to fetch_posix_offset to make sure we're fetchoinmg the posix
- offsets from *our* domain controller. Only set domain variable to
- non-NULL if the account is from a trusted domain. Use domain in call
- to cyg_ldap::fetch_ad_account.
-
2014-05-22 Corinna Vinschen <corinna@vinschen.de>
* gmon.h: Pull in profile.h. Explain why.
2014-05-22 Corinna Vinschen <corinna@vinschen.de>
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Fix potential SEGV
- referencing NULL pointer.
-
-2014-05-22 Corinna Vinschen <corinna@vinschen.de>
-
* libc/bsdlib.cc (forkpty): Close master and slave if fork fails to
avoid resource leak (CID 59997).
* libc/fts.c: Update to FreeBSD version 1.39 (CID 59947).
@@ -1128,30 +732,6 @@
* syscalls.cc (getusershell): Fix buffer overrun (Coverity ID 59932).
-2014-05-15 Corinna Vinschen <corinna@vinschen.de>
-
- * external.cc (cygwin_internal): Use local name buffer instead of
- allocated one in CW_CYGNAME_FROM_WINNAME.
-
-2014-05-15 Corinna Vinschen <corinna@vinschen.de>
-
- * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump to 273.
-
-2014-05-15 Corinna Vinschen <corinna@vinschen.de>
-
- * external.cc (cygwin_internal): Implement CW_CYGNAME_FROM_WINNAME.
- Add lengthy comment to explain what we do and why.
- * include/sys/cygwin.h (cygwin_getinfo_types): Add
- CW_CYGNAME_FROM_WINNAME.
-
-2014-05-14 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_auth.cc (get_server_groups): Call get_logon_server only for
- non-builtin accounts.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Check incoming
- account name for validity in terms of the current name prefixing rules
- and refuse invalid names.
-
2014-05-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::ioctl): Handle the different
@@ -1165,72 +745,8 @@
* fhandler_console.cc (dev_console::save_restore): Only save current
dwEnd line rather than the one after that.
-2014-05-08 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (cygheap_user::init): Fix formatting in debug output.
- (struct cyg_USER_INFO_24): Define temporarily. Explain why.
- (pwdgrp::fetch_account_from_windows): Handle sane primary group
- setting for Microsoft Accounts. Explain why.
- * wincap.h (wincaps::has_microsoft_accounts): New element.
- * wincap.cc: Implement above element throughout.
-
-2014-05-08 Corinna Vinschen <corinna@vinschen.de>
-
- * grp.cc (gr_ent::enumerate_caches): Fix copy/paste bug introducing
- an endless loop.
-
-2014-05-07 Corinna Vinschen <corinna@vinschen.de>
-
- * passwd.cc (pwdgrp::parse_passwd): Fix an off by one computing the
- buffer len. Add comment.
- * uinfo.cc (internal_getlogin): Fix typo in comment.
-
-2014-05-07 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Tweak SID<->uid
- conversion to cover S-1-5-113, S-1-5-114, and S-1-5-1000 groups.
-
-2014-05-07 Corinna Vinschen <corinna@vinschen.de>
-
- * grp.cc (pwdgrp::parse_group): Set grp.len. Drop generating any
- gr_mem entries.
- (getgrgid_r): Don't try to copy gr_mem entries. Always set gr_mem
- to an empty list.
- (getgrnam_r): Ditto.
- (app_gr): New static struct to store group data propagated to the
- calling application via getgrgid/getgrnam.
- (getgr_cp): Fill app_gr and return pointer to app_gr.g.
- (getgrgid32): Call getgr_cp.
- (getgrnam32): Ditto.
- * passwd.cc (pwdgrp::parse_passwd): Set res.len.
- (app_pw): New static struct to store passwd data propagated to the
- calling application via getpwuid/getpwnam.
- (getpw_cp): Fill app_pw and return pointer to app_pw.p.
- (getpwuid32): Cal getpw_cp.
- (getpwnam): Ditto.
- * pwdgrp.h (struct pg_pwd): Add len member.
- (struct pg_grp): Ditto.
-
-2014-05-06 Corinna Vinschen <corinna@vinschen.de>
-
- * security.h (MAX_SUBAUTH_CNT): Drop. Use SID_MAX_SUB_AUTHORITIES
- instead throughout.
- (MAX_SID_LEN): Drop. Use SECURITY_MAX_SID_SIZE instead throughout.
-
2014-05-06 Corinna Vinschen <corinna@vinschen.de>
- * grp.cc (internal_getgroups): Drop unused cygsid variable.
- * sec_helper.cc (cygpsid::pstring): Use sid_sub_auth_count macro.
- (cygsid::get_sid): Use MAX_SUBAUTH_CNT rather than wrong constant 8.
- Don't call memcpy to copy subauthorities into SID, use assignment.
- (cygsid::getfromstr): Use MAX_SUBAUTH_CNT rather than wrong constant 8.
- * security.h (MAX_SUBAUTH_CNT): New definition. Set to 11 to cover
- Microsoft Accounts.
- (MAX_SID_LEN): Define in terms of SID member sizes and MAX_SUBAUTH_CNT.
- (DBGSID): Use MAX_SUBAUTH_CNT to define size of SubAuthority array.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Handle Micosoft
- Accounts. Handle them as well known group. Compare domain names
- case-insensitive.
* winlean.h (PIPE_REJECT_REMOTE_CLIENTS): Drop temporary definition
since Mingw64 catched up.
(DNLEN): Redefine as 16. Explain why.
@@ -1278,16 +794,6 @@
* miscfuncs.cc (check_iovec): Allow 0 as valid iovcnt value.
-2014-04-22 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (user_attr): Remove "uid" attribute.
- * ldap.h (LDAP_USER_NAME_ATTR): Remove. Change other attribute index
- values as required.
- (cyg_ldap::get_user_name): Remove inline function.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Remove code to handle
- Cygwin username different from Windows username.
- (pwdgrp::add_account_from_cygserver): Remove unnecessary cast.
-
2014-04-18 Corinna Vinschen <corinna@vinschen.de>
* winf.cc (linebuf::fromargv): Temporarily revert patch from 2014-01-24.
@@ -1318,11 +824,6 @@
* net.cc (cygwin_setsockopt): Ignore IPV6_TCLASS the same way as IP_TOS.
-2014-04-12 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Fix gid evaluation
- for local accounts.
-
2014-04-10 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 30.
@@ -1433,12 +934,6 @@
(exception::exception): Install unhandled exception filter.
* exceptions.cc (exception::handle_while_being_debugged): New method.
-2014-03-19 Corinna Vinschen <corinna@vinschen.de>
-
- * passwd.cc (pg_ent::enumerate_ad): Ignore primary domain in list of
- trusted domains only if all trusted domains are enumerated anyway.
- Explain why.
-
2014-03-18 Christopher Faylor <me.cygwin2014@cgf.cx>
* fhandler_dsp.cc (fhandler_dev_dsp::fixup_after_fork): Actually call
@@ -1485,58 +980,6 @@
2014-03-12 Corinna Vinschen <corinna@vinschen.de>
- * cygheap.h (enum cygheap_pwdgrp::cache_t): Remove.
- (cygheap_pwdgrp::caching): Convert to bool.
- (cygheap_pwdgrp::pwd_cache): Add cygserver member.
- (cygheap_pwdgrp::grp_cache): Ditto.
- (cygheap_pwdgrp::nss_db_caching): Drop.
- (cygheap_pwdgrp::nss_db_full_caching): Drop.
- (cygheap_pwdgrp::nss_cygserver_caching): New method.
- (cygheap_pwdgrp::nss_disable_cygserver_caching): New method.
- * cygserver.h (client_request::request_code_t): Add
- CYGSERVER_REQUEST_PWDGRP.
- * cygserver_pwdgrp.h: New file.
- * cygtls.h (struct _local_storage): Remove pwbuf and grbuf members.
- * grp.cc (pwdgrp::prep_tls_grbuf): Drop.
- (internal_getgrsid): Handle cygserver caching and rearrange to check
- the caches first.
- (internal_getgrnam): Ditto.
- (internal_getgrgid): Ditto.
- (gr_ent::enumerate_caches): Handle cygserver cache.
- * passwd.cc (pwdgrp::prep_tls_pwbuf): Drop.
- (internal_getpwsid): Handle cygserver caching and rearrange to check
- the caches first.
- (internal_getpwnam): Ditto.
- (internal_getpwuid): Ditto.
- (pw_ent::enumerate_caches): Handle cygserver cache.
- * pwdgrp.h (pwdgrp::add_account_from_cygserver): New method declaration.
- (pwdgrp::fetch_account_from_cygserver): New method declaration.
- (pwdgrp::prep_tls_pwbuf): Drop declaration.
- (pwdgrp::prep_tls_grbuf): Drop declaration.
- (pwdgrp::add_user_from_cygserver): New inline methods.
- (pwdgrp::add_group_from_cygserver): New inline methods.
- * tlsoffsets.h: Regenerate.
- * tlsoffsets64.h: Regenerate.
- * uinfo.cc (internal_getlogin): Call internal_getgroups if cygserver
- caching is not available.
- (cygheap_pwdgrp::init): Initialize pwd_cache.cygserver and
- grp_cache.cygserver. Set caching to true.
- (cygheap_pwdgrp::nss_init_line): Drop db_cache handling entirely.
- (pwdgrp::add_account_from_windows): Drop no caching handling.
- (client_request_pwdgrp::client_request_pwdgrp): New method.
- (pwdgrp::fetch_account_from_cygserver): New method.
- (pwdgrp::add_account_from_cygserver): New method.
-
- * fhandler_disk_file.cc (fhandler_base::fstat_helper): Fix formatting.
- * include/sys/cygwin.h: Ditto.
-
-2014-03-12 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Avoid crash on
- non-domain member machines if an unknown SID comes in.
-
-2014-03-12 Corinna Vinschen <corinna@vinschen.de>
-
* include/cygwin/socket.h (IPV6_JOIN_GROUP): Revert.
(IPV6_LEAVE_GROUP): Ditto.
@@ -1596,38 +1039,6 @@
* dir.cc (opendir): Propagate any errno from build_fh_name.
-2014-03-07 Corinna Vinschen <corinna@vinschen.de>
-
- * pwdgrp.h (pwdgrp::is_passwd): New inline method.
- (pwdgrp::is_group): New inline method.
- (add_account_from_windows): Drop group argument from declaration.
- (fetch_account_from_windows): Ditto.
- (check_file): Ditto.
- (add_user_from_windows): Call add_account_from_windows accordingly.
- (add_group_from_windows): Ditto.
- * uinfo.cc (pwdgrp::add_account_from_windows): Drop group argument.
- Use is_group method instead.
- (pwdgrp::check_file): Ditto.
- (pwdgrp::fetch_account_from_windows): Ditto.
- * grp.cc: Accommodate aforementioned changes.
- * passwd.cc: Ditto.
-
-2014-03-06 Corinna Vinschen <corinna@vinschen.de>
-
- * passwd.cc (pg_ent::enumerate_builtin): Convert pwd_builtins and
- grp_builtins to array of cygpsid pointers. Replace SID strings with
- pointers to well known SIDs.
- * sec_helper.cc (well_known_local_service_sid): Define.
- (well_known_network_service_sid): Define.
- (trusted_installer_sid): Define.
- * security.h (well_known_local_service_sid): Declare.
- (well_known_network_service_sid): Declare.
- (trusted_installer_sid): Declare.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Throughout set acc_type
- to SidTypeUnknown if LookupAccountXXX function failed. Create
- simplified passwd entry for non-user accounts, except for LocalSystem.
- Add comment.
-
2014-03-06 Corinna Vinschen <corinna@vinschen.de>
* setlsapwd.cc (setlsapwd): Use RtlSecureZeroMemory to delete password
@@ -1635,18 +1046,6 @@
2014-03-05 Corinna Vinschen <corinna@vinschen.de>
- * ldap.cc (rediscover_thread): Remove.
- (cyg_ldap::open): Remove code to rediscover DC. It just won't do the
- right thing.
- (cyg_ldap::enumerate_ad_accounts): Change to be self-sufficient (no
- explicit open call required). Enumerate on a DC of the domain itself
- instead of relying on delegation. Remove ill-advised code trying to
- generate rootdse from domain name.
- * passwd.cc (pg_ent::enumerate_ad): Drop explicit call to
- cyg_ldap::open.
-
-2014-03-05 Corinna Vinschen <corinna@vinschen.de>
-
* include/cygwin/config.h (__TM_GMTOFF): Define.
(__TM_ZONE): Define.
@@ -1673,115 +1072,6 @@
* exception.h (exception::exception): Install vectored exception
handler rather than vectored continue handler.
-2014-03-03 Corinna Vinschen <corinna@vinschen.de>
-
- * sec_helper.cc (cygpsid::get_id): Move Samba SID->uid/gid mapping
- from get_sids_info here.
- (get_sids_info): Vice versa.
- * security.cc (convert_samba_sd): New static function to map a Samba
- security descriptor to a security descriptor with UNIX users and groups
- converted to Windows SIDs per RFC 2307 mapping.
- (check_file_access): Call convert_samba_sd on Samba security
- descriptors.
-
-2014-02-28 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Only fetch extended
- user info if we're creating a passwd entry. Add comment.
-
-2014-02-28 Corinna Vinschen <corinna@vinschen.de>
-
- * cygheap.h (cygheap_user::sid): Return reference to cygpsid rather
- than PSID.
- (cygheap_user::saved_sid): Ditto.
- (cygheap_pwdgrp::cache_t): New type.
- (cygheap_pwdgrp::caching): Convert to cache_t.
- (cygheap_pwdgrp::nss_db_caching): Change accordingly.
- (cygheap_pwdgrp::nss_db_full_caching): New inline method.
- * grp.cc (internal_getgroups): Reinvent. Take cyg_ldap pointer as
- third parameter and use throughout.
- (getgroups32): Call internal_getgroups.
- * pwdgrp.h (internal_getgroups): Declare.
- * uinfo.cc (internal_getlogin): Partial rewrite to accommodate having
- no connection to the DC. Give primary group from user token more
- weight. Generate group entries for all groups in the user token if
- caching is set to NSS_FULL_CACHING.
- (cygheap_pwdgrp::init): Initialize caching to NSS_FULL_CACHING.
- (cygheap_pwdgrp::nss_init_line): Handle "db_cache: full".
- (pwdgrp::add_account_from_windows): Fix group handling in non-caching
- mode.
- (pwdgrp::fetch_account_from_windows): Default primary group for the
- current user to primary group from user token. Check for primary
- domain first after LookupAccountSid failed.
-
-2014-02-27 Corinna Vinschen <corinna@vinschen.de>
-
- * autoload.cc (CheckTokenMembership): Import.
- * external.cc (cygwin_internal): Call get_uid/get_gid instead of get_id.
- * grp.cc (internal_getgrsid): Take additional cyg_ldap pointer.
- Forward to pwdgrp::add_group_from_windows.
- (internal_getgrnam): Ditto.
- (internal_getgrgid): Ditto.
- (gr_ent::enumerate_local): Drop ugid_caching bool from call to
- pwdgrp::fetch_account_from_windows.
- (getgroups32): Rename from internal_getgroups and drop getgroups32 stub.
- Drop srchsid parameter and code handling it. Add local cyg_ldap
- instance and forward to internal_getgrXXX.
- (getgroups): Call getgroups32.
- (get_groups): Add local cyg_ldap instance and forward to
- internal_getgrXXX.
- (getgrouplist): Ditto.
- (setgroups32): Ditto.
- * ldap.cc (cyg_ldap::open): Don't call close. Return true if connection
- is already open.
- (cyg_ldap::remap_uid): Forward this to internal_getpwsid.
- (cyg_ldap::remap_gid): Forward this to internal_getgrsid.
- * passwd.cc (internal_getpwsid): Take additional cyg_ldap pointer.
- Forward to pwdgrp::add_user_from_windows.
- (internal_getpwnam): Ditto.
- (internal_getpwuid): Ditto.
- (pg_ent::enumerate_builtin): Drop ugid_caching bool from call to
- pwdgrp::fetch_account_from_windows.
- (pg_ent::enumerate_sam): Ditto.
- (pg_ent::enumerate_ad): Ditto. Forward local cldap instead.
- * pwdgrp.h (internal_getpwsid): Align declaration to above change.
- (internal_getpwnam): Ditto.
- (internal_getpwuid): Ditto.
- (internal_getgrsid): Ditto.
- (internal_getgrgid): Ditto.
- (internal_getgrnam): Ditto.
- (internal_getgroups): Drop declaration.
- (pwdgrp::add_account_from_windows): Align declaration to below change.
- (pwdgrp::add_user_from_windows): Ditto.
- (pwdgrp::add_group_from_windows): Ditto.
- * sec_acl.cc (setacl): Add local cyg_ldap instance and forward to
- internal_getpwuid and internal_getgrgid.
- (getacl): Add local cyg_ldap instance and forward to cygpsid::get_id.
- (aclfromtext32): Add local cyg_ldap instance and forward to
- internal_getpwnam and internal_getgrnam.
- * sec_helper.cc (cygpsid::get_id): Take additional cyg_ldap pointer.
- Forward to internal_getgrsid and internal_getpwsid.
- (get_sids_info): Drop ldap_open. Forward local cldap to
- internal_getpwsid and internal_getgrXXX. Call CheckTokenMembership
- rather than internal_getgroups.
- * security.h (cygpsid::get_id): Add cyg_ldap pointer, drop default
- parameter.
- (cygpsid::get_uid): Add cyg_ldap pointer. Call get_id accordingly.
- (cygpsid::get_gid): Ditto.
- * uinfo.cc (internal_getlogin): Add local cyg_ldap instance and forward
- to internal_getpwXXX and internal_getgrXXX calls.
- (pwdgrp::add_account_from_windows): Take additional cyg_ldap pointer.
- Forward to pwdgrp::fetch_account_from_windows.
- (fetch_posix_offset): Drop ldap_open argument and handling. Get
- cyg_ldap instance as pointer.
- (pwdgrp::fetch_account_from_windows): Take additional cyg_ldap pointer.
- Use it if it's not NULL, local instance otherwise. Drop ldap_open.
- Drop fetching extended group arguments from AD for speed.
-
-2014-02-27 Corinna Vinschen <corinna@vinschen.de>
-
- * path.cc (find_fast_cwd_pointer): Fix preceeding comment.
-
2014-02-25 Christopher Faylor <me.cygwin2014@cgf.cx>
* fhandler.h (fhandler_console::scroll_buffer_screen): New function.
@@ -1820,32 +1110,10 @@
2014-02-22 Corinna Vinschen <corinna@vinschen.de>
- * external.cc (cygwin_internal): Add cases for CW_GETNSSSEP,
- CW_GETPWSID and CW_GETGRSID.
- * grp.cc (internal_getgrsid_from_db): New function.
- * passwd.cc (internal_getpwsid_from_db): New function.
- (pg_ent::setent): Add special case for call from mkpasswd/mkgroup.
- * pwdgrp.h (internal_getpwsid_from_db): Declare.
- (internal_getgrsid_from_db): Declare.
- (enum nss_enum_t): Move to include/sys/cygwin.h.
- (class pg_ent): Add comment.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Fix typo in comment.
- Change "UNIX" to "Unix" in domain name.
- * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_GETNSSSEP,
- CW_GETPWSID and CW_GETGRSID.
- (enum nss_enum_t): Define here.
-
-2014-02-21 Corinna Vinschen <corinna@vinschen.de>
-
- * pwdgrp.h (pwdgrp::fetch_account_from_windows): Add bool parameter
- to declaration, set to true by default.
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Add bool parameter
- "ugid_caching". Only add account to ugid_cache if set to true.
- * grp.cc (gr_ent::enumerate_local): Call fetch_account_from_windows
- with ugid_caching parameter set to false.
- * passwd.cc (pg_ent::enumerate_builtin): Ditto.
- (pg_ent::enumerate_sam): Ditto.
- (pg_ent::enumerate_ad): Ditto.
+ * external.cc (cygwin_internal): Add cases for CW_GETPWSID and
+ CW_GETGRSID.
+ * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_SETENT, CW_GETENT,
+ CW_ENDENT, CW_GETNSSSEP, CW_GETPWSID and CW_GETGRSID.
2014-02-20 Corinna Vinschen <corinna@vinschen.de>
@@ -1857,115 +1125,11 @@
* grp.cc (get_groups): Don't add gid to list if it's ILLEGAL_GID.
(getgrouplist): Return number of groups, just like glibc.
-2014-02-19 Corinna Vinschen <corinna@vinschen.de>
-
- * passwd.cc (pg_ent::setent): Initialize cygheap domain info.
- * sec_auth.cc (get_logon_server): Ditto.
-
-2014-02-18 Corinna Vinschen <corinna@vinschen.de>
-
- * external.cc (cygwin_internal): Handle new CW_SETENT, CW_GETENT and
- CW_ENDENT info types.
- * grp.cc (setgrent_filtered): New function, called from cygwin_internal.
- (getgrent_filtered): Ditto.
- (endgrent_filtered): Ditto.
- * passwd.cc (pg_ent::setent): Set state explicitely to from_cache.
- (pg_ent::getent): Handle the fact that a DC has no SAM and enumerating
- local accounts is equivalent to enumerating domain accounts.
- (setpwent_filtered): New function, called from cygwin_internal.
- (getpwent_filtered): Ditto.
- (endpwent_filtered): Ditto.
- * pwdgrp.h (setpwent_filtered): Declare.
- (getgrent_filtered): Ditto.
- (endgrent_filtered): Ditto.
- (setpwent_filtered): Ditto.
- (getpwent_filtered): Ditto.
- (endpwent_filtered): Ditto.
- * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_SETENT, CW_GETENT,
- and CW_ENDENT.
-
2014-02-18 Corinna Vinschen <corinna@vinschen.de>
* setlsapwd.cc (setlsapwd): Fix conditional expression after breaking
it on 2014-01-23.
-2014-02-17 Corinna Vinschen <corinna@vinschen.de>
-
- * autoload.cc (ldap_abandon): Import.
- (ldap_result): Import.
- (ldap_searchW): Import.
- (NetGroupEnum): Import.
- (NetLocalGroupEnum): Import.
- (NetUserEnum): Import.
- * cygheap.h (class cygheap_pwdgrp): Add members enums and enum_tdoms.
- (cygheap_pwdgrp::nss_db_enums): New inline method.
- (cygheap_pwdgrp::nss_db_enum_tdoms): Ditto.
- * cygtls.h (struct _local_storage): Drop unused members pw_pos and
- grp_pos.
- * grp.cc (grent): New static variable of class gr_ent.
- (gr_ent::enumerate_caches): New method.
- (gr_ent::enumerate_local): New method.
- (gr_ent::getgrent): New method.
- (setgrent): Call gr_ent method.
- (getgrent32): Ditto.
- (endgrent): Ditto.
- * ldap.cc (sid_attr): Rename from nfs_attr.
- (cyg_ldap::close): Abandon still running asynchronous search.
- (cyg_ldap::fetch_ad_account): Reduce filter buffer size.
- (cyg_ldap::enumerate_ad_accounts): New method.
- (cyg_ldap::next_account): New method.
- (cyg_ldap::fetch_posix_offset_for_domain): Reduce filter buffer size.
- (cyg_ldap::fetch_unix_sid_from_ad): Ditto. Fix return value in case
- no value has been read.
- (cyg_ldap::fetch_unix_name_from_rfc2307): Reduce filter buffer size.
- * ldap.h (class cyg_ldap): Add msg_id member.
- (cyg_ldap::enumerate_ad_accounts): Declare.
- (cyg_ldap::next_account): Declare:
- * passwd.cc (pwent): New static variable of class pw_ent.
- (pg_ent::clear_cache): New method.
- (pg_ent::setent): New method.
- (pg_ent::getent): New method.
- (pg_ent::endent): New method.
- (pg_ent::enumerate_file): New method.
- (pg_ent::enumerate_builtin): New method.
- (pg_ent::enumerate_sam): New method.
- (pg_ent::enumerate_ad): New method.
- (pw_ent::enumerate_caches): New method.
- (pw_ent::enumerate_local): New method.
- (pw_ent::getpwent): New method.
- (setpwent): Call pw_ent method.
- (getpwent): Ditto.
- (endpwent): Ditto.
- * pwdgrp.h (class pwdgrp): Define pg_ent, pw_ent and gr_ent as friend
- classes.
- (pwdgrp::add_account_post_fetch): Declare with extra bool parameter.
- (pwdgrp::file_attr): New inline method.
- (enum nss_enum_t): Define.
- (class pg_ent): Define.
- (class pw_ent): Define.
- (class gr_ent): Define.
- * tlsoffsets.h: Regenerate.
- * tlsoffsets64.h: Ditto.
- * uinfo.cc (cygheap_pwdgrp::init): Initialize enums and enum_tdoms.
- (cygheap_pwdgrp::nss_init_line): Fix typo in preceeding comment.
- Handle new "db_enum" keyword.
- (pwdgrp::add_account_post_fetch): Take additional `bool lock' parameter
- and acquire pglock before adding element to array if lock is true.
- (pwdgrp::add_account_from_file): Call add_account_post_fetch with lock
- set to true.
- (pwdgrp::add_account_from_windows): Ditto in case of caching.
- (pwdgrp::fetch_account_from_windows): Handle builtin aliases only
- known to the domain controller. Only call NetLocalGroupGetInfo for
- aliases.
-
-2014-02-16 Corinna Vinschen <corinna@vinschen.de>
-
- * miscfuncs.h (NT_readline::close): New function to close handle.
- (NT_readline::~NT_readline): Call close.
- * sec_auth.cc (verify_token): Use constructor to initialize tok_usersid.
- * security.h (cygsid::cygsid): Add copy constructor taking cygsid as
- source.
-
2014-02-16 Corinna Vinschen <corinna@vinschen.de>
* dcrt0.cc (dll_crt0_1): Call initial_setlocale before fetching
@@ -2006,95 +1170,18 @@
when !winpid. Simplify logic. Don't do duplicate detection for
winpid.
-2014-02-14 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Default to /bin/bash
- as login shell.
-
-2014-02-13 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (cyg_ldap::fetch_posix_offset_for_domain): If domain name
- has no dot, it's a Netbios name. Change the search filter expression
- accordingly and filter by flatName. Add comment.
- * uinfo.cc (cygheap_domain_info::init): Gracefully handle NULL
- DnsDomainName and DomainSid members in DS_DOMAIN_TRUSTSW structure.
- Add comment. Fix comment preceeding fetching the mapping server
- from registry.
- (pwdgrp::fetch_account_from_file): Convert str to a local array.
- (fetch_posix_offset): New static function.
- (pwdgrp::fetch_account_from_windows): Add debug output in case
- LookupAccountSidW fails. Simplify code by calling fetch_posix_offset
- where appropriate. If LookupAccountSidW fails, check if the SID is
- one of the known trusted domains. If so, create a more informative
- account entry.
-
-2014-02-12 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (cygheap_pwdgrp::nss_init_line): Explicitely ignore a colon
- as separator char.
-
2014-02-11 Christopher Faylor <me.cygwin2014@cgf.cx>
- * winsup.h: Turn off previous workaround but leave a comment.
-
-2014-02-11 Corinna Vinschen <corinna@vinschen.de>
-
- * ldap.cc (rediscover_thread): Give argument a useful name.
- * miscfuncs.cc (NT_readline::init): It's a really bad idea trying to
- print a pointer to a PUNICODE_STRING as PUNICODE_STRING. Fix it.
- * uinfo.cc (cygheap_domain_info::init): Print status codes as hex
- values in debug output.
-
-2014-02-11 Corinna Vinschen <corinna@vinschen.de>
-
- * autoload.cc (NetLocalGroupGetInfo): Replace NetGroupGetInfo.
- * cygheap.h (class cygheap_ugid_cache): Move ugid_cache_t type here
- and rename.
- (struct init_cygheap): Add cygheap_ugid_cache member "ugid_cache".
- * pwdgrp.h (class ugid_cache_t): Remove here.
- * fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Accommodate
- move of ugid_cache to cygheap.
- * sec_helper.cc (get_sids_info): Ditto.
- * uinfo.cc (ugid_cache): Remove.
- (pwdgrp::fetch_account_from_windows): Define id_val globally.
- Move SidTypeAlias handling into SidTypeUser/SidTypeGroup branch since
- aliases are handled like groups in SAM. Accommodate move of ugid_cache
- to cygheap. Consolidate code reading SAM comments into a single branch
- for both, SidTypeUser and SidTypeAlias. For SidTypeAlias, fix thinko
- and call NetLocalGroupGetInfo rather than NetGroupGetInfo. Simplify
- code setting Cygwin primary group for SAM accounts. Add code to handle
- UNIX uid/gid from SAM comment.
-
-2014-02-11 Christopher Faylor <me.cygwin2014@cgf.cx>
-
- * winsup.h (Interlocked*): Use intrinsic versions of Interlocked
- functions.
-
* cygwin.sc.in: More closely emulate default pe/i386 linker script.
2014-02-10 Corinna Vinschen <corinna@vinschen.de>
- * uinfo.cc (cygheap_domain_info::init): Drop accidentally leftover if
- statement.
-
-2014-02-10 Corinna Vinschen <corinna@vinschen.de>
-
- * uinfo.cc (cygheap_domain_info::init): Fix handling of account domain
- on donmain controllers. Explain why.
-
-2014-02-10 Corinna Vinschen <corinna@vinschen.de>
-
* cygheap.cc (cwcsdup): Change parameter to correct PWCSTR.
(cwcsdup1): Ditto.
* cygheap_malloc.h: Change declarations accordingly.
2014-02-10 Corinna Vinschen <corinna@vinschen.de>
- * uinfo.cc (pwdgrp::fetch_account_from_windows): Add code to allow
- setting the primary group from the SAM comment field.
-
-2014-02-10 Corinna Vinschen <corinna@vinschen.de>
-
* dcrt0.cc (child_info_spawn::handle_spawn): Call fixup_lockf_after_exec
with additional argument to specify if the process has been execed
or spawned.
@@ -2112,161 +1199,11 @@
* environ.cc (strbrk): New function.
(parse_options): Use strbrk to parse CYGWIN environment variable.
-2014-02-09 Corinna Vinschen <corinna@vinschen.de>
-
- Introduce reading passwd/group entries from SAM/AD. Introduce
- /etc/nsswitch.conf file to configure it.
- * Makefile.in (DLL_OFILES): Add ldap.o.
- * autoload.cc: Import ldap functions from wldap32.dll.
- (DsEnumerateDomainTrustsW): Import.
- (NetGroupGetInfo): Import.
- * cygheap.h (class cygheap_domain_info): New class to keep global
- domain info.
- (class cygheap_pwdgrp): New class to keep passwd/group caches and
- configuration info from /etc/nssswitch.conf.
- (struct init_cygheap): Add cygheap_domain_info member "dom" and
- cygheap_pwdgrp member "pg".
- * cygtls.h (struct _local_storage): Remove unused member "res".
- Rearrange slightly, Add members pwbuf and grbuf to implement non-caching
- passwd/group fetching from SAM/AD. Make pw_pos and pw_pos unsigned.
- * fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Add RFC 2307
- uid/gid mapping.
- * fhandler_process.cc: Drop including pwdgrp.h.
- * fhandler_procsysvipc.cc: Ditto.
- * fhandler_registry.cc (fhandler_registry::fstat): Set key uid/gid
- to ILLEGAL_UID/ILLEGAL_GID rather than UNKNOWN_UID/UNKNOWN_GID.
- * grp.cc (group_buf): Drop.
- (gr): Drop.
- (pwdgrp::parse_group): Fill pg_grp.
- (pwdgrp::read_group): Remove.
- (pwdgrp::init_grp): New method.
- (pwdgrp::prep_tls_grbuf): New method.
- (pwdgrp::find_group): New methods.
- (internal_getgrsid): Convert to call new pwdgrp methods.
- (internal_getgrnam): Ditto.
- (internal_getgrgid): Ditto.
- (getgrgid_r): Drop 2nd parameter from internal_getgrgid call.
- (getgrgid32): Ditto.
- (getgrnam_r): Ditto for internal_getgrnam.
- (getgrnam32): Ditto.
- (getgrent32): Convert to call new pwdgrp methods.
- (internal_getgrent): Remove.
- (internal_getgroups): Simplify, especially drop calls to
- internal_getgrent.
- * ldap.cc: New file implementing cyg_ldap class for LDAP access to AD
- and RFC 2307 server.
- * ldap.h: New header, declaring cyg_ldap class.
- * passwd.cc (passwd_buf): Drop.
- (pr): Drop.
- (pwdgrp::parse_passwd): Fill pg_pwd.
- (pwdgrp::read_passwd): Remove.
- (pwdgrp::init_pwd): New method.
- (pwdgrp::prep_tls_pwbuf): New method.
- (find_user): New methods.
- (internal_getpwsid): Convert to call new pwdgrp methods.
- (internal_getpwnam): Ditto.
- (internal_getpwuid): Ditto.
- (getpwuid32): Drop 2nd parameter from internal_getpwuid call.
- (getpwuid_r): Ditto.
- (getpwnam): Ditto for internal_getpwnam.
- (getpwnam_r): Ditto.
- (getpwent): Convert to call new pwdgrp methods.
- * path.cc (class etc): Remove all methods.
- * path.h (class etc): Drop.
- * pinfo.cc (pinfo_basic::pinfo_basic): Set gid to ILLEGAL_GID rather
- than UNKNOWN_GID.
- (pinfo_init): Ditto.
- * pwdgrp.h (internal_getpwnam): Drop 2nd parameter from declaration.
- (internal_getpwuid): Ditto.
- (internal_getgrgid): Ditto.
- (internal_getgrnam): Ditto.
- (internal_getgrent): Drop declaration.
- (enum fetch_user_arg_type_t): New type.
- (struct fetch_user_arg_t): New type.
- (struct pg_pwd): New type.
- (struct pg_grp): New type.
- (class pwdgrp): Rework to provide functions for file and db requests
- and caching.
- (class ugid_cache_t): New class to provide RFC 2307 uid map caching.
- (ugid_cache): Declare.
- * sec_acl.cc: Drop including pwdgrp.h.
- * sec_auth.cc: Drop including dsgetdc.h and pwdgrp.h.
- (get_logon_server): Convert third parameter to ULONG flags argument
- to allow arbitrary flags values in DsGetDcNameW call and change calls
- to this function throughout. Use cached account domain name rather
- than calling GetComputerNameW.
- (get_unix_group_sidlist): Remove.
- (get_server_groups): Drop call to get_unix_group_sidlist.
- (verify_token): Rework token group check without calling
- internal_getgrent.
- * sec_helper.cc (cygpsid::pstring): New methods, like string() but
- return pointer to end of string.
- (cygsid::getfromstr): Add wide character implementation.
- (get_sids_info): Add RFC 2307 uid/gid mapping for Samba shares.
- * security.cc: Drop including pwdgrp.h.
- * security.h (DEFAULT_UID): Remove.
- (UNKNOWN_UID): Remove.
- (UNKNOWN_GID): Remove.
- (uinfo_init): Move here from winsup.h.
- (ILLEGAL_UID): Ditto.
- (ILLEGAL_GID): Ditto.
- (UNIX_POSIX_OFFSET): Define. Add lengthy comment.
- (UNIX_POSIX_MASK): Ditto.
- (MAP_UNIX_TO_CYGWIN_ID): Ditto.
- (ILLEGAL_UID16): Move here from winsup.h.
- (ILLEGAL_GID16): Ditto.
- (uid16touid32): Ditto.
- (gid16togid32): Ditto.
- (sid_id_auth): New convenience macro for SID component access.
- (sid_sub_auth_count): Ditto.
- (sid_sub_auth): Ditto.
- (sid_sub_auth_rid): Ditto.
- (cygpsid::pstring): Declare.
- (cygsid::getfromstr): Declare wide character variant.
- (cygsid::operator=): Ditto.
- (cygsid::operator*=): Ditto.
- (get_logon_server): Change declaration according to source code.
- * setlsapwd.cc (setlsapwd): Drop 2nd parameter from internal_getpwnam
- call.
- * shared.cc (memory_init): Call cygheap->pg.init in first process.
- * syscalls.cc: Drop including pwdgrp.h.
- * tlsoffsets.h: Regenerate.
- * tlsoffsets64.h: Ditto.
- * uinfo.cc (internal_getlogin): Drop gratuitious internal_getpwuid
- call. Fix debug output. Overwrite user gid in border case of a
- missing passwd file while a group file exists.
- (pwdgrp::add_line): Allocate memory on cygheap.
- (pwdgrp::load): Remove.
- (ugid_cache): Define.
- (cygheap_pwdgrp::init): New method.
- (cygheap_pwdgrp::nss_init_line): New method.
- (cygheap_pwdgrp::_nss_init): New method.
- (cygheap_domain_info::init): New method.
- (logon_sid): Define.
- (get_logon_sid): New function.
- (pwdgrp::add_account_post_fetch): New method.
- (pwdgrp::add_account_from_file): New methods.
- (pwdgrp::add_account_from_windows): New methods.
- (pwdgrp::check_file): New method.
- (pwdgrp::fetch_account_from_line): New method.
- (pwdgrp::fetch_account_from_file): New method.
- (pwdgrp::fetch_account_from_windows): New method.
- * winsup.h: Move aforementioned macros and declarations to security.h.
-
2014-02-09 Christopher Faylor <me.cygwin2014@cgf.cx>
* sigproc.cc (sig_send): Don't bother with an error message if we are
exiting.
-2014-02-08 Corinna Vinschen <corinna@vinschen.de>
-
- * miscfuncs.h (class NT_readline): New class to implement line-wise
- reading from file using native NT functions.
- * miscfuncs.cc (NT_readline::init): New method.
- (NT_readline::fgets): New method.
- * mount.cc (mount_info::from_fstab): Utilize NT_readline to read
- fstab files.
-
2014-02-06 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::fchown): Fix typo in
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 6f603d887..7daad7b54 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -226,7 +226,6 @@ DLL_OFILES:= \
ioctl.o \
ipc.o \
kernel32.o \
- ldap.o \
libstdcxx_wrapper.o \
localtime.o \
lsearch.o \
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 659898ba6..4351173be 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -1,7 +1,7 @@
/* autoload.cc: all dynamic load stuff.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -536,7 +536,6 @@ wsock_init ()
LoadDLLprime (ws2_32, _wsock_init, 0)
-LoadDLLfunc (CheckTokenMembership, 12, advapi32)
LoadDLLfunc (CreateProcessAsUserW, 44, advapi32)
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
LoadDLLfunc (LogonUserW, 24, advapi32)
@@ -581,46 +580,15 @@ LoadDLLfuncEx2 (IdnToAscii, 20, kernel32, 1, 0)
LoadDLLfuncEx2 (IdnToUnicode, 20, kernel32, 1, 0)
LoadDLLfunc (LocaleNameToLCID, 8, kernel32)
-/* ldap functions are cdecl! */
-#pragma push_macro ("mangle")
-#undef mangle
-#define mangle(name, n) #name
-LoadDLLfunc (ldap_bind_s, 0, wldap32)
-LoadDLLfunc (ldap_count_entries, 0, wldap32)
-LoadDLLfunc (ldap_count_valuesW, 0, wldap32)
-LoadDLLfunc (ldap_first_entry, 0, wldap32)
-LoadDLLfunc (ldap_get_next_page_s, 0, wldap32)
-LoadDLLfunc (ldap_get_valuesW, 0, wldap32)
-LoadDLLfunc (ldap_get_values_lenW, 0, wldap32)
-LoadDLLfunc (ldap_initW, 0, wldap32)
-LoadDLLfunc (ldap_msgfree, 0, wldap32)
-LoadDLLfunc (ldap_next_entry, 0, wldap32)
-LoadDLLfunc (ldap_search_abandon_page, 0, wldap32)
-LoadDLLfunc (ldap_search_init_pageW, 0, wldap32)
-LoadDLLfunc (ldap_search_sW, 0, wldap32)
-LoadDLLfunc (ldap_set_option, 0, wldap32)
-LoadDLLfunc (ldap_sslinitW, 0, wldap32)
-LoadDLLfunc (ldap_unbind, 0, wldap32)
-LoadDLLfunc (ldap_value_freeW, 0, wldap32)
-LoadDLLfunc (ldap_value_free_len, 0, wldap32)
-LoadDLLfunc (LdapGetLastError, 0, wldap32)
-LoadDLLfunc (LdapMapErrorToWin32, 0, wldap32)
-#pragma pop_macro ("mangle")
-
LoadDLLfunc (WNetCloseEnum, 4, mpr)
LoadDLLfunc (WNetEnumResourceW, 16, mpr)
LoadDLLfunc (WNetGetProviderNameW, 12, mpr)
LoadDLLfunc (WNetGetResourceInformationW, 16, mpr)
LoadDLLfunc (WNetOpenEnumW, 20, mpr)
-LoadDLLfunc (DsEnumerateDomainTrustsW, 16, netapi32)
LoadDLLfunc (DsGetDcNameW, 24, netapi32)
LoadDLLfunc (NetApiBufferFree, 4, netapi32)
-LoadDLLfunc (NetGroupEnum, 28, netapi32)
-LoadDLLfunc (NetLocalGroupEnum, 28, netapi32)
-LoadDLLfunc (NetLocalGroupGetInfo, 16, netapi32)
LoadDLLfunc (NetUseGetInfo, 16, netapi32)
-LoadDLLfunc (NetUserEnum, 32, netapi32)
LoadDLLfunc (NetUserGetGroups, 28, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
LoadDLLfunc (NetUserGetLocalGroups, 32, netapi32)
diff --git a/winsup/cygwin/configure b/winsup/cygwin/configure
index 522fae6df..6dc655e30 100755
--- a/winsup/cygwin/configure
+++ b/winsup/cygwin/configure
@@ -1,8 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Cygwin DLL 0.
-#
-# Report bugs to <cygwin@cygwin.com>.
+# Generated by GNU Autoconf 2.69.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -265,11 +263,10 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and cygwin@cygwin.com
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
exit 1
fi
@@ -577,12 +574,12 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME='Cygwin DLL'
-PACKAGE_TARNAME='cygwin'
-PACKAGE_VERSION='0'
-PACKAGE_STRING='Cygwin DLL 0'
-PACKAGE_BUGREPORT='cygwin@cygwin.com'
-PACKAGE_URL='https://cygwin.com'
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
ac_unique_file="Makefile.in"
ac_no_link=no
@@ -737,7 +734,7 @@ sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
@@ -1237,7 +1234,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Cygwin DLL 0 to adapt to many kinds of systems.
+\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1285,7 +1282,7 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/cygwin]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
@@ -1302,9 +1299,7 @@ _ACEOF
fi
if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of Cygwin DLL 0:";;
- esac
+
cat <<\_ACEOF
Optional Features:
@@ -1335,8 +1330,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <cygwin@cygwin.com>.
-Cygwin DLL home page: <https://cygwin.com>.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1399,7 +1393,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Cygwin DLL configure 0
+configure
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1529,7 +1523,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Cygwin DLL $as_me 0, which was
+It was created by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1877,7 +1871,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_config_headers="$ac_config_headers config.h"
ac_aux_dir=
@@ -4981,7 +4974,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Cygwin DLL $as_me 0, which was
+This file was extended by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -5037,14 +5030,13 @@ $config_files
Configuration headers:
$config_headers
-Report bugs to <cygwin@cygwin.com>.
-Cygwin DLL home page: <https://cygwin.com>."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Cygwin DLL config.status 0
+config.status
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/winsup/cygwin/configure.ac b/winsup/cygwin/configure.ac
index fc7697b3b..9d16e4edd 100644
--- a/winsup/cygwin/configure.ac
+++ b/winsup/cygwin/configure.ac
@@ -1,19 +1,5 @@
-dnl Autoconf configure script for Cygwin.
-dnl Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-dnl 2006, 2008, 2009, 2011, 2012, 2013, 2014 Red Hat, Inc.
-dnl
-dnl This file is part of Cygwin.
-dnl
-dnl This software is a copyrighted work licensed under the terms of the
-dnl Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-dnl details.
-dnl
-dnl Process this file with autoconf to produce a configure script.
-
AC_PREREQ(2.59)dnl
-AC_INIT([Cygwin DLL], 0,
- cygwin@cygwin.com, cygwin, https://cygwin.com)
-AC_CONFIG_SRCDIR(Makefile.in)
+AC_INIT(Makefile.in)
AC_CONFIG_HEADER(config.h)
AC_CONFIG_AUX_DIR(..)
diff --git a/winsup/cygwin/cygerrno.h b/winsup/cygwin/cygerrno.h
index b9ec7b61d..337dd75fc 100644
--- a/winsup/cygwin/cygerrno.h
+++ b/winsup/cygwin/cygerrno.h
@@ -1,7 +1,7 @@
/* cygerrno.h: main Cygwin header file.
- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010, 2011, 2012, 2013,
- 2014 Red Hat, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010, 2011, 2012, 2013
+ Red Hat, Inc.
This file is part of Cygwin.
@@ -16,15 +16,10 @@ details. */
void __reg3 seterrno_from_win_error (const char *file, int line, DWORD code);
void __reg3 seterrno_from_nt_status (const char *file, int line, NTSTATUS status);
+void __reg2 seterrno (const char *, int line);
int __reg2 geterrno_from_win_error (DWORD code = GetLastError (), int deferrno = 13 /*EACCESS*/);
int __reg2 geterrno_from_nt_status (NTSTATUS status, int deferrno = 13 /*EACCESS*/);
-inline void __attribute__ ((always_inline))
-seterrno (const char *file, int line)
-{
- seterrno_from_win_error (file, line, GetLastError ());
-}
-
#define __seterrno() seterrno (__FILE__, __LINE__)
#define __seterrno_from_win_error(val) seterrno_from_win_error (__FILE__, __LINE__, val)
#define __seterrno_from_nt_status(status) seterrno_from_nt_status (__FILE__, __LINE__, status)
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index ce7b02a86..26564ad9c 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -130,7 +130,7 @@ init_cygheap::close_ctty ()
cygcheck can print the paths into which the Cygwin DLL has been
installed for debugging purposes.
- Last but not least, the new cygwin properties datastructure is checked
+ Last but not least, the new cygwin properties datastrcuture is checked
for the "disabled_key" value, which is used to determine whether the
installation key is actually added to all object names or not. This is
used as a last resort for debugging purposes, usually. However, there
@@ -267,17 +267,6 @@ cygheap_init ()
cygheap->init_tls_list ();
}
-/* Initial Cygwin heap setup.
- Called by root process of a Cygwin process tree. */
-void
-setup_cygheap ()
-{
- cygheap_init ();
- cygheap->user.init ();
- cygheap->init_installation_root (); /* Requires user.init! */
- cygheap->pg.init ();
-}
-
#define nextpage(x) ((char *) roundup2 ((uintptr_t) (x), \
wincap.allocation_granularity ()))
#define allocsize(x) ((SIZE_T) nextpage (x))
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index ff86d5ef3..a83b3d7c7 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -11,7 +11,6 @@ details. */
#include "hires.h"
#include "cygheap_malloc.h"
-#include "pwdgrp.h"
#define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
@@ -156,8 +155,8 @@ public:
}
void set_sid (PSID new_sid) { effec_cygsid = new_sid;}
void set_saved_sid () { saved_cygsid = effec_cygsid; }
- cygpsid &sid () { return effec_cygsid; }
- cygpsid &saved_sid () { return saved_cygsid; }
+ PSID sid () { return effec_cygsid; }
+ PSID saved_sid () { return saved_cygsid; }
const char *ontherange (homebodies what, struct passwd * = NULL);
#define NO_IMPERSONATION NULL
bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
@@ -308,23 +307,14 @@ private:
available in shared memory avoids to test for the version every time
around. Default to new version. */
fcwd_version_t fast_cwd_version;
- void override_win32_cwd (bool init, ULONG old_dismount_count);
+ void override_win32_cwd (bool, ULONG);
public:
UNICODE_STRING win32;
static muto cwd_lock;
const char *get_posix () const { return posix; };
- void reset_posix (wchar_t *w_cwd);
- char *get (char *buf, int need_posix = 1, int with_chroot = 0,
- unsigned ulen = NT_MAX_PATH);
- PWCHAR get (PWCHAR buf, unsigned buflen = NT_MAX_PATH)
- {
- cwd_lock.acquire ();
- buf[0] = L'\0';
- wcsncat (buf, win32.Buffer, buflen - 1);
- cwd_lock.release ();
- return buf;
- }
+ void reset_posix (wchar_t *);
+ char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH);
HANDLE get_handle () { return dir; }
DWORD get_drive (char * dst)
{
@@ -365,126 +355,6 @@ struct user_heap_info
void __reg1 init ();
};
-class cygheap_domain_info
-{
- PWCHAR pdom_name;
- PWCHAR pdom_dns_name;
- cygsid pdom_sid;
-
- PWCHAR adom_name;
- cygsid adom_sid;
-
- PDS_DOMAIN_TRUSTSW tdom;
- ULONG tdom_count;
-
- PWCHAR rfc2307_domain_buf;
-
-public:
- bool init ();
-
- inline PCWSTR primary_flat_name () const { return pdom_name; }
- inline PCWSTR primary_dns_name () const { return pdom_dns_name; }
- inline cygsid &primary_sid () { return pdom_sid; }
-
- inline bool member_machine () const { return pdom_sid != NO_SID; }
-
- inline PCWSTR account_flat_name () const { return adom_name; }
- inline cygsid &account_sid () { return adom_sid; }
-
- inline PDS_DOMAIN_TRUSTSW trusted_domain (ULONG idx) const
- { return (idx < tdom_count) ? tdom + idx : NULL; }
-
- inline PWCHAR get_rfc2307_domain () const
- { return rfc2307_domain_buf ?: NULL; }
-};
-
-class cygheap_pwdgrp
-{
- static const int NSS_FILES = 1;
- static const int NSS_DB = 2;
- enum pfx_t {
- NSS_AUTO = 0,
- NSS_PRIMARY,
- NSS_ALWAYS
- };
- bool nss_inited;
- int pwd_src;
- int grp_src;
- pfx_t prefix;
- WCHAR separator[2];
- bool caching;
- int enums;
- PWCHAR enum_tdoms;
-
- void nss_init_line (const char *line);
- void _nss_init ();
-
-public:
- struct {
- pwdgrp cygserver;
- pwdgrp file;
- pwdgrp win;
- } pwd_cache;
- struct {
- pwdgrp cygserver;
- pwdgrp file;
- pwdgrp win;
- } grp_cache;
-
- void init ();
-
- inline void nss_init () { if (!nss_inited) _nss_init (); }
- inline bool nss_pwd_files () const { return !!(pwd_src & NSS_FILES); }
- inline bool nss_pwd_db () const { return !!(pwd_src & NSS_DB); }
- inline bool nss_grp_files () const { return !!(grp_src & NSS_FILES); }
- inline bool nss_grp_db () const { return !!(grp_src & NSS_DB); }
- inline bool nss_prefix_auto () const { return prefix == NSS_AUTO; }
- inline bool nss_prefix_primary () const { return prefix == NSS_PRIMARY; }
- inline bool nss_prefix_always () const { return prefix == NSS_ALWAYS; }
- inline PCWSTR nss_separator () const { return separator; }
- inline bool nss_cygserver_caching () const { return caching; }
- inline void nss_disable_cygserver_caching () { caching = false; }
- inline int nss_db_enums () const { return enums; }
- inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
-};
-
-class cygheap_ugid_cache
-{
- struct idmap {
- uint32_t nfs_id;
- uint32_t cyg_id;
- };
- class idmaps {
- uint32_t _cnt;
- uint32_t _max;
- idmap *_map;
- public:
- uint32_t get (uint32_t id) const
- {
- for (uint32_t i = 0; i < _cnt; ++i)
- if (_map[i].nfs_id == id)
- return _map[i].cyg_id;
- return (uint32_t) -1;
- }
- void add (uint32_t nfs_id, uint32_t cyg_id)
- {
- if (_cnt >= _max)
- _map = (idmap *) crealloc (_map, (_max += 10) * sizeof (*_map));
- _map[_cnt].nfs_id = nfs_id;
- _map[_cnt].cyg_id = cyg_id;
- ++_cnt;
- }
- };
- idmaps uids;
- idmaps gids;
-
-public:
- uid_t get_uid (uid_t uid) const { return uids.get (uid); }
- gid_t get_gid (gid_t gid) const { return gids.get (gid); }
- void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); }
- void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); }
-};
-
struct hook_chain
{
void **loc;
@@ -510,9 +380,6 @@ struct init_cygheap: public mini_cygheap
UNICODE_STRING installation_key;
WCHAR installation_key_buf[18];
cygheap_root root;
- cygheap_domain_info dom;
- cygheap_pwdgrp pg;
- cygheap_ugid_cache ugid_cache;
cygheap_user user;
user_heap_info user_heap;
mode_t umask;
@@ -668,5 +535,4 @@ class cygheap_fdenum : public cygheap_fdmanip
void __stdcall cygheap_fixup_in_child (bool);
void __stdcall cygheap_init ();
-void setup_cygheap ();
extern char _cygheap_start[] __attribute__((section(".idata")));
diff --git a/winsup/cygwin/cygserver.h b/winsup/cygwin/cygserver.h
index 1313d3c1e..8bcc271f3 100644
--- a/winsup/cygwin/cygserver.h
+++ b/winsup/cygwin/cygserver.h
@@ -52,7 +52,6 @@ protected:
CYGSERVER_REQUEST_SEM,
CYGSERVER_REQUEST_SHM,
CYGSERVER_REQUEST_SETPWD,
- CYGSERVER_REQUEST_PWDGRP,
CYGSERVER_REQUEST_LAST
} request_code_t;
diff --git a/winsup/cygwin/cygserver_pwdgrp.h b/winsup/cygwin/cygserver_pwdgrp.h
deleted file mode 100644
index 52b9b42ba..000000000
--- a/winsup/cygwin/cygserver_pwdgrp.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* cygserver_pwdgrp.h: Request account information
-
- Copyright 2014 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 __CYGSERVER_PWDGRP_H__
-#define __CYGSERVER_PWDGRP_H__
-
-#include <sys/types.h>
-#include "cygserver.h"
-
-class transport_layer_base;
-class process_cache;
-
-#ifdef __INSIDE_CYGWIN__
-#include "pwdgrp.h"
-#else
-/* Don't include pwdgrp.h, but keep this in sync. */
-enum fetch_user_arg_type_t {
- SID_arg,
- NAME_arg,
- ID_arg
-};
-#endif
-
-class client_request_pwdgrp : public client_request
-{
- friend class client_request;
-
-private:
- union _pwdgrp_param_t
- {
- struct _pwdgrp_in_t
- {
- bool group;
- fetch_user_arg_type_t type;
- union
- {
- BYTE sid[40];
- char name[UNLEN + 1];
- uint32_t id;
- } arg;
- } in;
-
- struct
- {
- char line[1024];
- } out;
- } _parameters;
-
-#ifndef __INSIDE_CYGWIN__
- client_request_pwdgrp ();
- virtual void serve (transport_layer_base *, process_cache *);
- void pwd_serve ();
- void grp_serve ();
-#endif
-
-public:
-
-#ifdef __INSIDE_CYGWIN__
- client_request_pwdgrp (fetch_user_arg_t &arg, bool group);
-#endif
-
- const char *line () const { return (msglen () > 0) ? _parameters.out.line
- : NULL; }
-};
-
-#endif /* __CYGSERVER_PWDGRP_H__ */
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index 91533f2a0..366d7da4d 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -89,13 +89,20 @@ public:
struct _local_storage
{
- /* passwd.cc */
- char pass[_PASSWORD_LEN];
+ /*
+ Needed for the group functions
+ */
+ int grp_pos;
/* dlfcn.cc */
int dl_error;
char dl_buffer[256];
+ /* passwd.cc */
+ struct passwd res;
+ char pass[_PASSWORD_LEN];
+ int pw_pos;
+
/* path.cc */
struct mntent mntbuf;
int iteration;
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 738860d0e..8d059144d 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -609,7 +609,7 @@ void
child_info_fork::handle_fork ()
{
cygheap_fixup_in_child (false);
- memory_init ();
+ memory_init (false);
myself.thisproc (NULL);
myself->uid = cygheap->user.real_uid;
myself->gid = cygheap->user.real_gid;
@@ -663,7 +663,7 @@ child_info_spawn::handle_spawn ()
if (!dynamically_loaded || get_parent_handle ())
{
cygheap_fixup_in_child (true);
- memory_init ();
+ memory_init (false);
}
if (!moreinfo->myself_pinfo ||
!DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
@@ -769,8 +769,7 @@ dll_crt0_0 ()
if (!child_proc_info)
{
- setup_cygheap ();
- memory_init ();
+ memory_init (true);
#ifndef __x86_64__
/* WOW64 process on XP/64 or Server 2003/64? Check if we have been
started from 64 bit process and if our stack is at an unusual
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
index 658551b70..46d654f0b 100644
--- a/winsup/cygwin/dlfcn.cc
+++ b/winsup/cygwin/dlfcn.cc
@@ -13,11 +13,7 @@ details. */
#include <psapi.h>
#include <stdlib.h>
#include <ctype.h>
-#include <wctype.h>
#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "cygheap.h"
#include "perprocess.h"
#include "dlfcn.h"
#include "cygtls.h"
diff --git a/winsup/cygwin/dll_init.sgml b/winsup/cygwin/dll_init.sgml
new file mode 100644
index 000000000..a66c43cb6
--- /dev/null
+++ b/winsup/cygwin/dll_init.sgml
@@ -0,0 +1,11 @@
+
+<sect1 id="func-cygwin-detach-dll">
+<title>cygwin_detach_dll</title>
+
+<funcsynopsis><funcprototype>
+<funcdef>extern "C" void
+<function>cygwin_detach_dll</function></funcdef>
+<paramdef>int <parameter>dll_index</parameter></paramdef>
+</funcprototype></funcsynopsis>
+
+</sect1>
diff --git a/winsup/cygwin/dlmalloc.c b/winsup/cygwin/dlmalloc.c
new file mode 100644
index 000000000..b64bed8eb
--- /dev/null
+++ b/winsup/cygwin/dlmalloc.c
@@ -0,0 +1,3815 @@
+/*
+ * To do:
+ * - strdup? maybe shouldn't bother yet, it seems difficult to get includes
+ * right using dlmalloc.h
+ * - add STD_C prototyping
+ * - adhere to comment conventions
+ * - maybe fix ALLOCFILL vs. MOATFILL in do_init_realloced_chunk()
+ * - keep a list of mmaped regions for checking in malloc_update_mallinfo()
+ * - I think memalign() is wrong: it aligns the chunk rather than the memory
+ * portion of the chunk.
+ * - "& -alignment" in memalign() is suspect: should use "& ~alignment"
+ * instead?
+ * - malloc.h doesn't need malloc_COPY or probably a bunch of other stuff
+ * - add mallopt options for e.g. fill?
+ * - come up with a non-BBC version of M_C
+ * - document necessity of checking chunk address in do_check_chunk prior to
+ * accessing any of its fields
+ * Done:
+ * minor speedup due to extend check before mremap
+ * minor speedup due to returning malloc() result in memalign() if aligned
+ * made malloc_update_mallinfo() check alloced regions at start of sbrk area
+ * fixed bug: After discovering foreign sbrk, if old_top was MINSIZE, would
+ * reduce old_top_size to 0, thus making inuse(old_top) return 0; other
+ * functions would consequently attempt to access old_top->{fd,bk}, which
+ * were invalid. This is in malloc_extend_top(), in the "double
+ * fencepost" section.
+ * Documentation:
+ * malloc_usable_size(P) is equivalent to realloc(P, malloc_usable_size(P))
+ *
+ * $Log$
+ * Revision 1.9 2004/05/12 16:21:18 cgf
+ * remove keyword stuff
+ *
+ * Revision 1.1 1997/12/24 18:34:47 nsd
+ * Initial revision
+ *
+ */
+/* ---------- To make a malloc.h, start cutting here ------------ */
+
+/*
+ A version of malloc/free/realloc written by Doug Lea and released to the
+ public domain. Send questions/comments/complaints/performance data
+ to dl@cs.oswego.edu
+
+* VERSION 2.6.4 Thu Nov 28 07:54:55 1996 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+ ftp://g.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+* Why use this malloc?
+
+ This is not the fastest, most space-conserving, most portable, or
+ most tunable malloc ever written. However it is among the fastest
+ while also being among the most space-conserving, portable and tunable.
+ Consistent balance across these factors results in a good general-purpose
+ allocator. For a high-level description, see
+ http://g.oswego.edu/dl/html/malloc.html
+
+* Synopsis of public routines
+
+ (Much fuller descriptions are contained in the program documentation below.)
+
+ malloc(size_t n);
+ Return a pointer to a newly allocated chunk of at least n bytes, or null
+ if no space is available.
+ free(Void_t* p);
+ Release the chunk of memory pointed to by p, or no effect if p is null.
+ realloc(Void_t* p, size_t n);
+ Return a pointer to a chunk of size n that contains the same data
+ as does chunk p up to the minimum of (n, p's size) bytes, or null
+ if no space is available. The returned pointer may or may not be
+ the same as p. If p is null, equivalent to malloc. Unless the
+ #define realloc_ZERO_BYTES_FREES below is set, realloc with a
+ size argument of zero (re)allocates a minimum-sized chunk.
+ memalign(size_t alignment, size_t n);
+ Return a pointer to a newly allocated chunk of n bytes, aligned
+ in accord with the alignment argument, which must be a power of
+ two.
+ valloc(size_t n);
+ Equivalent to memalign(pagesize, n), where pagesize is the page
+ size of the system (or as near to this as can be figured out from
+ all the includes/defines below.)
+ pvalloc(size_t n);
+ Equivalent to valloc(minimum-page-that-holds(n)), that is,
+ round up n to nearest pagesize.
+ calloc(size_t unit, size_t quantity);
+ Returns a pointer to quantity * unit bytes, with all locations
+ set to zero.
+ cfree(Void_t* p);
+ Equivalent to free(p).
+ malloc_trim(size_t pad);
+ Release all but pad bytes of freed top-most memory back
+ to the system. Return 1 if successful, else 0.
+ malloc_usable_size(Void_t* p);
+ Report the number usable allocated bytes associated with allocated
+ chunk p. This may or may not report more bytes than were requested,
+ due to alignment and minimum size constraints.
+ malloc_stats();
+ Prints brief summary statistics on stderr.
+ mallinfo()
+ Returns (by copy) a struct containing various summary statistics.
+ mallopt(int parameter_number, int parameter_value)
+ Changes one of the tunable parameters described below. Returns
+ 1 if successful in changing the parameter, else 0.
+
+* Vital statistics:
+
+ Alignment: 8-byte
+ 8 byte alignment is currently hardwired into the design. This
+ seems to suffice for all current machines and C compilers.
+
+ Assumed pointer representation: 4 or 8 bytes
+ Code for 8-byte pointers is untested by me but has worked
+ reliably by Wolfram Gloger, who contributed most of the
+ changes supporting this.
+
+ Assumed size_t representation: 4 or 8 bytes
+ Note that size_t is allowed to be 4 bytes even if pointers are 8.
+
+ Minimum overhead per allocated chunk: 4 or 8 bytes
+ Each malloced chunk has a hidden overhead of 4 bytes holding size
+ and status information.
+
+ Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead)
+ 8-byte ptrs: 24/32 bytes (including, 4/8 overhead)
+
+ When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
+ ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
+ needed; 4 (8) for a trailing size field
+ and 8 (16) bytes for free list pointers. Thus, the minimum
+ allocatable size is 16/24/32 bytes.
+
+ Even a request for zero bytes (i.e., malloc(0)) returns a
+ pointer to something of the minimum allocatable size.
+
+ Maximum allocated size: 4-byte size_t: 2^31 - 8 bytes
+ 8-byte size_t: 2^63 - 16 bytes
+
+ It is assumed that (possibly signed) size_t bit values suffice to
+ represent chunk sizes. `Possibly signed' is due to the fact
+ that `size_t' may be defined on a system as either a signed or
+ an unsigned type. To be conservative, values that would appear
+ as negative numbers are avoided.
+ Requests for sizes with a negative sign bit will return a
+ minimum-sized chunk.
+
+ Maximum overhead wastage per allocated chunk: normally 15 bytes
+
+ Alignnment demands, plus the minimum allocatable size restriction
+ make the normal worst-case wastage 15 bytes (i.e., up to 15
+ more bytes will be allocated than were requested in malloc), with
+ two exceptions:
+ 1. Because requests for zero bytes allocate non-zero space,
+ the worst case wastage for a request of zero bytes is 24 bytes.
+ 2. For requests >= mmap_threshold that are serviced via
+ mmap(), the worst case wastage is 8 bytes plus the remainder
+ from a system page (the minimal mmap unit); typically 4096 bytes.
+
+* Limitations
+
+ Here are some features that are NOT currently supported
+
+ * No user-definable hooks for callbacks and the like.
+ * No automated mechanism for fully checking that all accesses
+ to malloced memory stay within their bounds.
+ * No support for compaction.
+
+* Synopsis of compile-time options:
+
+ People have reported using previous versions of this malloc on all
+ versions of Unix, sometimes by tweaking some of the defines
+ below. It has been tested most extensively on Solaris and
+ Linux. It is also reported to work on WIN32 platforms.
+ People have also reported adapting this malloc for use in
+ stand-alone embedded systems.
+
+ The implementation is in straight, hand-tuned ANSI C. Among other
+ consequences, it uses a lot of macros. Because of this, to be at
+ all usable, this code should be compiled using an optimizing compiler
+ (for example gcc -O2) that can simplify expressions and control
+ paths.
+
+ __STD_C (default: derived from C compiler defines)
+ Nonzero if using ANSI-standard C compiler, a C++ compiler, or
+ a C compiler sufficiently close to ANSI to get away with it.
+ DEBUG (default: NOT defined)
+ Define to enable debugging. Adds fairly extensive assertion-based
+ checking to help track down memory errors, but noticeably slows down
+ execution.
+ realloc_ZERO_BYTES_FREES (default: NOT defined)
+ Define this if you think that realloc(p, 0) should be equivalent
+ to free(p). Otherwise, since malloc returns a unique pointer for
+ malloc(0), so does realloc(p, 0).
+ HAVE_memcpy (default: defined)
+ Define if you are not otherwise using ANSI STD C, but still
+ have memcpy and memset in your C library and want to use them.
+ Otherwise, simple internal versions are supplied.
+ USE_memcpy (default: 1 if HAVE_memcpy is defined, 0 otherwise)
+ Define as 1 if you want the C library versions of memset and
+ memcpy called in realloc and calloc (otherwise macro versions are used).
+ At least on some platforms, the simple macro versions usually
+ outperform libc versions.
+ HAVE_MMAP (default: defined as 1)
+ Define to non-zero to optionally make malloc() use mmap() to
+ allocate very large blocks.
+ HAVE_MREMAP (default: defined as 0 unless Linux libc set)
+ Define to non-zero to optionally make realloc() use mremap() to
+ reallocate very large blocks.
+ malloc_getpagesize (default: derived from system #includes)
+ Either a constant or routine call returning the system page size.
+ HAVE_USR_INCLUDE_malloc_H (default: NOT defined)
+ Optionally define if you are on a system with a /usr/include/malloc.h
+ that declares struct mallinfo. It is not at all necessary to
+ define this even if you do, but will ensure consistency.
+ INTERNAL_SIZE_T (default: size_t)
+ Define to a 32-bit type (probably `unsigned int') if you are on a
+ 64-bit machine, yet do not want or need to allow malloc requests of
+ greater than 2^31 to be handled. This saves space, especially for
+ very small chunks.
+ INTERNAL_LINUX_C_LIB (default: NOT defined)
+ Defined only when compiled as part of Linux libc.
+ Also note that there is some odd internal name-mangling via defines
+ (for example, internally, `malloc' is named `mALLOc') needed
+ when compiling in this case. These look funny but don't otherwise
+ affect anything.
+ WIN32 (default: undefined)
+ Define this on MS win (95, nt) platforms to compile in sbrk emulation.
+ LACKS_UNISTD_H (default: undefined)
+ Define this if your system does not have a <unistd.h>.
+ MORECORE (default: sbrk)
+ The name of the routine to call to obtain more memory from the system.
+ MORECORE_FAILURE (default: -1)
+ The value returned upon failure of MORECORE.
+ MORECORE_CLEARS (default 0)
+ True (1) if the routine mapped to MORECORE zeroes out memory (which
+ holds for sbrk).
+ DEFAULT_TRIM_THRESHOLD
+ DEFAULT_TOP_PAD
+ DEFAULT_MMAP_THRESHOLD
+ DEFAULT_MMAP_MAX
+ Default values of tunable parameters (described in detail below)
+ controlling interaction with host system routines (sbrk, mmap, etc).
+ These values may also be changed dynamically via mallopt(). The
+ preset defaults are those that give best performance for typical
+ programs/systems.
+
+
+*/
+
+
+
+
+/* Preliminaries */
+
+
+#ifndef __STD_C
+#ifdef __STDC__
+#define __STD_C 1
+#else
+#if __cplusplus
+#define __STD_C 1
+#else
+#define __STD_C 0
+#endif /*__cplusplus*/
+#endif /*__STDC__*/
+#endif /*__STD_C*/
+
+#ifndef Void_t
+#if __STD_C
+#define Void_t void
+#else
+#define Void_t char
+#endif
+#endif /*Void_t*/
+
+#define __MALLOC_H_INCLUDED
+
+#if __STD_C
+#include <stddef.h> /* for size_t */
+#else
+#include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include "cygmalloc.h"
+#define __INSIDE_CYGWIN__
+#include <stdio.h> /* needed for malloc_stats */
+#include <string.h>
+
+/*
+ Compile-time options
+*/
+
+
+/*
+ Debugging:
+
+ Because freed chunks may be overwritten with link fields, this
+ malloc will often die when freed memory is overwritten by user
+ programs. This can be very effective (albeit in an annoying way)
+ in helping track down dangling pointers.
+
+ If you compile with -DDEBUG, a number of assertion checks are
+ enabled that will catch more memory errors. You probably won't be
+ able to make much sense of the actual assertion errors, but they
+ should help you locate incorrectly overwritten memory. The
+ checking is fairly extensive, and will slow down execution
+ noticeably. Calling malloc_stats or mallinfo with DEBUG set will
+ attempt to check every non-mmapped allocated and free chunk in the
+ course of computing the summmaries. (By nature, mmapped regions
+ cannot be checked very much automatically.)
+
+ Setting DEBUG may also be helpful if you are trying to modify
+ this code. The assertions in the check routines spell out in more
+ detail the assumptions and invariants underlying the algorithms.
+
+*/
+
+#ifdef MALLOC_DEBUG
+#define DEBUG 1
+#define DEBUG1 1
+#define DEBUG2 1
+#define DEBUG3 1
+#endif
+
+#if DEBUG
+#include <assert.h>
+#else
+#define assert(x) ((void)0)
+#endif
+
+/*
+ INTERNAL_SIZE_T is the word-size used for internal bookkeeping
+ of chunk sizes. On a 64-bit machine, you can reduce malloc
+ overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
+ at the expense of not being able to handle requests greater than
+ 2^31. This limitation is hardly ever a concern; you are encouraged
+ to set this. However, the default version is the same as size_t.
+*/
+
+#ifndef INTERNAL_SIZE_T
+#define INTERNAL_SIZE_T size_t
+#endif
+
+/*
+ realloc_ZERO_BYTES_FREES should be set if a call to
+ realloc with zero bytes should be the same as a call to free.
+ Some people think it should. Otherwise, since this malloc
+ returns a unique pointer for malloc(0), so does realloc(p, 0).
+*/
+
+
+/* #define realloc_ZERO_BYTES_FREES */
+
+
+/*
+ WIN32 causes an emulation of sbrk to be compiled in
+ mmap-based options are not currently supported in WIN32.
+*/
+
+/* #define WIN32 */
+#ifdef WIN32
+#define MORECORE wsbrk
+#define HAVE_MMAP 0
+#endif
+
+
+/*
+ HAVE_memcpy should be defined if you are not otherwise using
+ ANSI STD C, but still have memcpy and memset in your C library
+ and want to use them in calloc and realloc. Otherwise simple
+ macro versions are defined here.
+
+ USE_memcpy should be defined as 1 if you actually want to
+ have memset and memcpy called. People report that the macro
+ versions are often enough faster than libc versions on many
+ systems that it is better to use them.
+
+*/
+
+#define HAVE_memcpy
+
+#ifndef USE_memcpy
+#ifdef HAVE_memcpy
+#define USE_memcpy 1
+#else
+#define USE_memcpy 0
+#endif
+#endif
+
+#if (__STD_C || defined(HAVE_memcpy))
+
+#if __STD_C
+void* memset(void*, int, size_t);
+void* memcpy(void*, const void*, size_t);
+#else
+Void_t* memset();
+Void_t* memcpy();
+#endif
+#endif
+
+#ifndef DEBUG3
+
+#if USE_memcpy
+
+/* The following macros are only invoked with (2n+1)-multiples of
+ INTERNAL_SIZE_T units, with a positive integer n. This is exploited
+ for fast inline execution when n is small. */
+
+#define malloc_ZERO(charp, nbytes) \
+do { \
+ INTERNAL_SIZE_T mzsz = (nbytes); \
+ if(mzsz <= 9*sizeof(mzsz)) { \
+ INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp); \
+ if(mzsz >= 5*sizeof(mzsz)) { *mz++ = 0; \
+ *mz++ = 0; \
+ if(mzsz >= 7*sizeof(mzsz)) { *mz++ = 0; \
+ *mz++ = 0; \
+ if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0; \
+ *mz++ = 0; }}} \
+ *mz++ = 0; \
+ *mz++ = 0; \
+ *mz = 0; \
+ } else memset((charp), 0, mzsz); \
+} while(0)
+
+#define malloc_COPY(dest,src,nbytes) \
+do { \
+ INTERNAL_SIZE_T mcsz = (nbytes); \
+ if(mcsz <= 9*sizeof(mcsz)) { \
+ INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src); \
+ INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest); \
+ if(mcsz >= 5*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
+ *mcdst++ = *mcsrc++; \
+ if(mcsz >= 7*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
+ *mcdst++ = *mcsrc++; \
+ if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \
+ *mcdst++ = *mcsrc++; }}} \
+ *mcdst++ = *mcsrc++; \
+ *mcdst++ = *mcsrc++; \
+ *mcdst = *mcsrc ; \
+ } else memcpy(dest, src, mcsz); \
+} while(0)
+
+#else /* !USE_memcpy */
+
+/* Use Duff's device for good zeroing/copying performance. */
+
+#define malloc_ZERO(charp, nbytes) \
+do { \
+ INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp); \
+ long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
+ if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
+ switch (mctmp) { \
+ case 0: for(;;) { *mzp++ = 0; \
+ case 7: *mzp++ = 0; \
+ case 6: *mzp++ = 0; \
+ case 5: *mzp++ = 0; \
+ case 4: *mzp++ = 0; \
+ case 3: *mzp++ = 0; \
+ case 2: *mzp++ = 0; \
+ case 1: *mzp++ = 0; if(mcn <= 0) break; mcn--; } \
+ } \
+} while(0)
+
+#define malloc_COPY(dest,src,nbytes) \
+do { \
+ INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src; \
+ INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest; \
+ long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
+ if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
+ switch (mctmp) { \
+ case 0: for(;;) { *mcdst++ = *mcsrc++; \
+ case 7: *mcdst++ = *mcsrc++; \
+ case 6: *mcdst++ = *mcsrc++; \
+ case 5: *mcdst++ = *mcsrc++; \
+ case 4: *mcdst++ = *mcsrc++; \
+ case 3: *mcdst++ = *mcsrc++; \
+ case 2: *mcdst++ = *mcsrc++; \
+ case 1: *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; } \
+ } \
+} while(0)
+
+#endif
+
+#else /* DEBUG3 */
+
+/* The trailing moat invalidates the above prediction about the nbytes
+ parameter to malloc_ZERO and malloc_COPY. */
+
+#define malloc_ZERO(charp, nbytes) \
+do { \
+ char *mzp = (char *)(charp); \
+ long mzn = (nbytes); \
+ while (mzn--) \
+ *mzp++ = '\0'; \
+} while(0)
+
+#define malloc_COPY(dest,src,nbytes) \
+do { \
+ char *mcsrc = (char *)(src); \
+ char *mcdst = (char *)(dest); \
+ long mcn = (nbytes); \
+ while (mcn--) \
+ *mcdst++ = *mcsrc++; \
+} while(0)
+
+#endif /* DEBUG3 */
+
+/*
+ Define HAVE_MMAP to optionally make malloc() use mmap() to
+ allocate very large blocks. These will be returned to the
+ operating system immediately after a free().
+*/
+
+#ifndef HAVE_MMAP
+#define HAVE_MMAP 1
+#endif
+
+/*
+ Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
+ large blocks. This is currently only possible on Linux with
+ kernel versions newer than 1.3.77.
+*/
+
+#ifndef HAVE_MREMAP
+#ifdef INTERNAL_LINUX_C_LIB
+#define HAVE_MREMAP 1
+#else
+#define HAVE_MREMAP 0
+#endif
+#endif
+
+#if HAVE_MMAP
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#endif /* HAVE_MMAP */
+
+/*
+ Access to system page size. To the extent possible, this malloc
+ manages memory from the system in page-size units.
+
+ The following mechanics for getpagesize were adapted from
+ bsd/gnu getpagesize.h
+*/
+
+#ifndef LACKS_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifndef malloc_getpagesize
+# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
+# ifndef _SC_PAGE_SIZE
+# define _SC_PAGE_SIZE _SC_PAGESIZE
+# endif
+# endif
+# ifdef _SC_PAGE_SIZE
+# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
+# else
+# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+# if __STD_C
+ extern size_t getpagesize(void);
+# else
+ extern size_t getpagesize();
+# endif
+# define malloc_getpagesize getpagesize()
+# else
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define malloc_getpagesize EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# ifndef CLSIZE
+# define malloc_getpagesize NBPG
+# else
+# define malloc_getpagesize (NBPG * CLSIZE)
+# endif
+# else
+# ifdef NBPC
+# define malloc_getpagesize NBPC
+# else
+# ifdef PAGESIZE
+# define malloc_getpagesize PAGESIZE
+# else
+# define malloc_getpagesize (4096) /* just guess */
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+
+
+/*
+
+ This version of malloc supports the standard SVID/XPG mallinfo
+ routine that returns a struct containing the same kind of
+ information you can get from malloc_stats. It should work on
+ any SVID/XPG compliant system that has a /usr/include/malloc.h
+ defining struct mallinfo. (If you'd like to install such a thing
+ yourself, cut out the preliminary declarations as described above
+ and below and save them in a malloc.h file. But there's no
+ compelling reason to bother to do this.)
+
+ The main declaration needed is the mallinfo struct that is returned
+ (by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a
+ bunch of fields, most of which are not even meaningful in this
+ version of malloc. Some of these fields are are instead filled by
+ mallinfo() with other numbers that might possibly be of interest.
+
+ HAVE_USR_INCLUDE_malloc_H should be set if you have a
+ /usr/include/malloc.h file that includes a declaration of struct
+ mallinfo. If so, it is included; else an SVID2/XPG2 compliant
+ version is declared below. These must be precisely the same for
+ mallinfo() to work.
+
+*/
+
+/* #define HAVE_USR_INCLUDE_malloc_H */
+
+#if HAVE_USR_INCLUDE_malloc_H
+#include "/usr/include/malloc.h"
+#else
+
+/* SVID2/XPG mallinfo structure */
+
+struct mallinfo {
+ int arena; /* total space allocated from system */
+ int ordblks; /* number of non-inuse chunks */
+ int smblks; /* unused -- always zero */
+ int hblks; /* number of mmapped regions */
+ int hblkhd; /* total space in mmapped regions */
+ int usmblks; /* unused -- always zero */
+ int fsmblks; /* unused -- always zero */
+ int uordblks; /* total allocated space */
+ int fordblks; /* total non-inuse space */
+ int keepcost; /* top-most, releasable (via malloc_trim) space */
+};
+
+/* SVID2/XPG mallopt options */
+
+#define M_MXFAST 1 /* UNUSED in this malloc */
+#define M_NLBLKS 2 /* UNUSED in this malloc */
+#define M_GRAIN 3 /* UNUSED in this malloc */
+#define M_KEEP 4 /* UNUSED in this malloc */
+
+#endif
+
+/* mallopt options that actually do something */
+
+#define M_TRIM_THRESHOLD -1
+#define M_TOP_PAD -2
+#define M_MMAP_THRESHOLD -3
+#define M_MMAP_MAX -4
+#define M_SCANHEAP -5
+#define M_FILL
+
+
+
+#ifndef DEFAULT_TRIM_THRESHOLD
+#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
+#endif
+
+/*
+ M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
+ to keep before releasing via malloc_trim in free().
+
+ Automatic trimming is mainly useful in long-lived programs.
+ Because trimming via sbrk can be slow on some systems, and can
+ sometimes be wasteful (in cases where programs immediately
+ afterward allocate more large chunks) the value should be high
+ enough so that your overall system performance would improve by
+ releasing.
+
+ The trim threshold and the mmap control parameters (see below)
+ can be traded off with one another. Trimming and mmapping are
+ two different ways of releasing unused memory back to the
+ system. Between these two, it is often possible to keep
+ system-level demands of a long-lived program down to a bare
+ minimum. For example, in one test suite of sessions measuring
+ the XF86 X server on Linux, using a trim threshold of 128K and a
+ mmap threshold of 192K led to near-minimal long term resource
+ consumption.
+
+ If you are using this malloc in a long-lived program, it should
+ pay to experiment with these values. As a rough guide, you
+ might set to a value close to the average size of a process
+ (program) running on your system. Releasing this much memory
+ would allow such a process to run in memory. Generally, it's
+ worth it to tune for trimming rather tham memory mapping when a
+ program undergoes phases where several large chunks are
+ allocated and released in ways that can reuse each other's
+ storage, perhaps mixed with phases where there are no such
+ chunks at all. And in well-behaved long-lived programs,
+ controlling release of large blocks via trimming versus mapping
+ is usually faster.
+
+ However, in most programs, these parameters serve mainly as
+ protection against the system-level effects of carrying around
+ massive amounts of unneeded memory. Since frequent calls to
+ sbrk, mmap, and munmap otherwise degrade performance, the default
+ parameters are set to relatively high values that serve only as
+ safeguards.
+
+ The default trim value is high enough to cause trimming only in
+ fairly extreme (by current memory consumption standards) cases.
+ It must be greater than page size to have any useful effect. To
+ disable trimming completely, you can set to (unsigned long)(-1);
+
+
+*/
+
+
+#ifndef DEFAULT_TOP_PAD
+#define DEFAULT_TOP_PAD (0)
+#endif
+
+/*
+ M_TOP_PAD is the amount of extra `padding' space to allocate or
+ retain whenever sbrk is called. It is used in two ways internally:
+
+ * When sbrk is called to extend the top of the arena to satisfy
+ a new malloc request, this much padding is added to the sbrk
+ request.
+
+ * When malloc_trim is called automatically from free(),
+ it is used as the `pad' argument.
+
+ In both cases, the actual amount of padding is rounded
+ so that the end of the arena is always a system page boundary.
+
+ The main reason for using padding is to avoid calling sbrk so
+ often. Having even a small pad greatly reduces the likelihood
+ that nearly every malloc request during program start-up (or
+ after trimming) will invoke sbrk, which needlessly wastes
+ time.
+
+ Automatic rounding-up to page-size units is normally sufficient
+ to avoid measurable overhead, so the default is 0. However, in
+ systems where sbrk is relatively slow, it can pay to increase
+ this value, at the expense of carrying around more memory than
+ the program needs.
+
+*/
+
+
+#ifndef DEFAULT_MMAP_THRESHOLD
+#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
+#endif
+
+/*
+
+ M_MMAP_THRESHOLD is the request size threshold for using mmap()
+ to service a request. Requests of at least this size that cannot
+ be allocated using already-existing space will be serviced via mmap.
+ (If enough normal freed space already exists it is used instead.)
+
+ Using mmap segregates relatively large chunks of memory so that
+ they can be individually obtained and released from the host
+ system. A request serviced through mmap is never reused by any
+ other request (at least not directly; the system may just so
+ happen to remap successive requests to the same locations).
+
+ Segregating space in this way has the benefit that mmapped space
+ can ALWAYS be individually released back to the system, which
+ helps keep the system level memory demands of a long-lived
+ program low. Mapped memory can never become `locked' between
+ other chunks, as can happen with normally allocated chunks, which
+ menas that even trimming via malloc_trim would not release them.
+
+ However, it has the disadvantages that:
+
+ 1. The space cannot be reclaimed, consolidated, and then
+ used to service later requests, as happens with normal chunks.
+ 2. It can lead to more wastage because of mmap page alignment
+ requirements
+ 3. It causes malloc performance to be more dependent on host
+ system memory management support routines which may vary in
+ implementation quality and may impose arbitrary
+ limitations. Generally, servicing a request via normal
+ malloc steps is faster than going through a system's mmap.
+
+ All together, these considerations should lead you to use mmap
+ only for relatively large requests.
+
+
+*/
+
+
+
+#ifndef DEFAULT_MMAP_MAX
+#if HAVE_MMAP
+#define DEFAULT_MMAP_MAX (64)
+#else
+#define DEFAULT_MMAP_MAX (0)
+#endif
+#endif
+
+/*
+ M_MMAP_MAX is the maximum number of requests to simultaneously
+ service using mmap. This parameter exists because:
+
+ 1. Some systems have a limited number of internal tables for
+ use by mmap.
+ 2. In most systems, overreliance on mmap can degrade overall
+ performance.
+ 3. If a program allocates many large regions, it is probably
+ better off using normal sbrk-based allocation routines that
+ can reclaim and reallocate normal heap memory. Using a
+ small value allows transition into this mode after the
+ first few allocations.
+
+ Setting to 0 disables all use of mmap. If HAVE_MMAP is not set,
+ the default value is 0, and attempts to set it to non-zero values
+ in mallopt will fail.
+*/
+
+
+
+
+/*
+
+ Special defines for linux libc
+
+ Except when compiled using these special defines for Linux libc
+ using weak aliases, this malloc is NOT designed to work in
+ multithreaded applications. No semaphores or other concurrency
+ control are provided to ensure that multiple malloc or free calls
+ don't run at the same time, which could be disasterous. A single
+ semaphore could be used across malloc, realloc, and free (which is
+ essentially the effect of the linux weak alias approach). It would
+ be hard to obtain finer granularity.
+
+*/
+
+
+#ifdef INTERNAL_LINUX_C_LIB
+
+#if __STD_C
+
+Void_t * __default_morecore_init (ptrdiff_t);
+Void_t *(*__morecore)(ptrdiff_t) = __default_morecore_init;
+
+#else
+
+Void_t * __default_morecore_init ();
+Void_t *(*__morecore)() = __default_morecore_init;
+
+#endif
+
+#define MORECORE (*__morecore)
+#define MORECORE_FAILURE 0
+#define MORECORE_CLEARS 1
+
+#else /* INTERNAL_LINUX_C_LIB */
+
+#if __STD_C
+/* extern Void_t* sbrk(ptrdiff_t);*/
+#else
+extern Void_t* sbrk();
+#endif
+
+#ifndef MORECORE
+#define MORECORE sbrk
+#endif
+
+#ifndef MORECORE_FAILURE
+#define MORECORE_FAILURE -1
+#endif
+
+#ifndef MORECORE_CLEARS
+#define MORECORE_CLEARS 0
+#endif
+
+#endif /* INTERNAL_LINUX_C_LIB */
+
+#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__)
+
+#define cALLOc __libc_calloc
+#define fREe __libc_free
+#define mALLOc __libc_malloc
+#define mEMALIGn __libc_memalign
+#define rEALLOc __libc_realloc
+#define vALLOc __libc_valloc
+#define pvALLOc __libc_pvalloc
+#define mALLINFo __libc_mallinfo
+#define mALLOPt __libc_mallopt
+
+#pragma weak calloc = __libc_calloc
+#pragma weak free = __libc_free
+#pragma weak cfree = __libc_free
+#pragma weak malloc = __libc_malloc
+#pragma weak memalign = __libc_memalign
+#pragma weak realloc = __libc_realloc
+#pragma weak valloc = __libc_valloc
+#pragma weak pvalloc = __libc_pvalloc
+#pragma weak mallinfo = __libc_mallinfo
+#pragma weak mallopt = __libc_mallopt
+
+#else
+
+#ifndef cALLOc
+#define cALLOc dlcalloc
+#endif
+#ifndef fREe
+#define fREe dlfree
+#endif
+#ifndef mALLOc
+#define mALLOc dlmalloc
+#endif
+#ifndef mEMALIGn
+#define mEMALIGn dlmemalign
+#endif
+#ifndef rEALLOc
+#define rEALLOc dlrealloc
+#endif
+#ifndef vALLOc
+#define vALLOc dlvalloc
+#endif
+#ifndef pvALLOc
+#define pvALLOc dlpvalloc
+#endif
+#ifndef mALLINFo
+#define mALLINFo dlmallinfo
+#endif
+#ifndef mALLOPt
+#define mALLOPt dlmallopt
+#endif
+
+#endif
+
+/* Public routines */
+
+#ifdef DEBUG2
+#define malloc(size) malloc_dbg(size, __FILE__, __LINE__)
+#define free(p) free_dbg(p, __FILE__, __LINE__)
+#define realloc(p, size) realloc_dbg(p, size, __FILE__, __LINE__)
+#define calloc(n, size) calloc_dbg(n, size, __FILE__, __LINE__)
+#define memalign(align, size) memalign_dbg(align, size, __FILE__, __LINE__)
+#define valloc(size) valloc_dbg(size, __FILE__, __LINE__)
+#define pvalloc(size) pvalloc_dbg(size, __FILE__, __LINE__)
+#define malloc_trim(pad) malloc_trim_dbg(pad, __FILE__, __LINE__)
+#define malloc_usable_size(p) malloc_usable_size_dbg(p, __FILE__, __LINE__)
+#define malloc_stats(void) malloc_stats_dbg(__FILE__, __LINE__)
+#define mallopt(flag, val) mallopt_dbg(flag, val, __FILE__, __LINE__)
+#define mallinfo(void) mallinfo_dbg(__FILE__, __LINE__)
+
+#if __STD_C
+Void_t* malloc_dbg(size_t, const char *, int);
+void free_dbg(Void_t*, const char *, int);
+Void_t* realloc_dbg(Void_t*, size_t, const char *, int);
+Void_t* calloc_dbg(size_t, size_t, const char *, int);
+Void_t* memalign_dbg(size_t, size_t, const char *, int);
+Void_t* valloc_dbg(size_t, const char *, int);
+Void_t* pvalloc_dbg(size_t, const char *, int);
+int malloc_trim_dbg(size_t, const char *, int);
+size_t malloc_usable_size_dbg(Void_t*, const char *, int);
+void malloc_stats_dbg(const char *, int);
+int mallopt_dbg(int, int, const char *, int);
+struct mallinfo mallinfo_dbg(const char *, int);
+#else
+Void_t* malloc_dbg();
+void free_dbg();
+Void_t* realloc_dbg();
+Void_t* calloc_dbg();
+Void_t* memalign_dbg();
+Void_t* valloc_dbg();
+Void_t* pvalloc_dbg();
+int malloc_trim_dbg();
+size_t malloc_usable_size_dbg();
+void malloc_stats_dbg();
+int mallopt_dbg();
+struct mallinfo mallinfo_dbg();
+#endif /* !__STD_C */
+
+#else /* !DEBUG2 */
+
+#if __STD_C
+
+Void_t* mALLOc(size_t);
+void fREe(Void_t*);
+Void_t* rEALLOc(Void_t*, size_t);
+Void_t* cALLOc(size_t, size_t);
+Void_t* mEMALIGn(size_t, size_t);
+Void_t* vALLOc(size_t);
+Void_t* pvALLOc(size_t);
+int malloc_trim(size_t);
+size_t malloc_usable_size(Void_t*);
+void malloc_stats(void);
+int mALLOPt(int, int);
+struct mallinfo mALLINFo(void);
+#else
+Void_t* mALLOc();
+void fREe();
+Void_t* rEALLOc();
+Void_t* cALLOc();
+Void_t* mEMALIGn();
+Void_t* vALLOc();
+Void_t* pvALLOc();
+int malloc_trim();
+size_t malloc_usable_size();
+void malloc_stats();
+int mALLOPt();
+struct mallinfo mALLINFo();
+#endif
+#endif /* !DEBUG2 */
+
+#ifdef __cplusplus
+}; /* end of extern "C" */
+#endif
+
+/* ---------- To make a malloc.h, end cutting here ------------ */
+
+#ifdef DEBUG2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef malloc
+#undef free
+#undef realloc
+#undef calloc
+#undef memalign
+#undef valloc
+#undef pvalloc
+#undef malloc_trim
+#undef malloc_usable_size
+#undef malloc_stats
+#undef mallopt
+#undef mallinfo
+
+#if __STD_C
+Void_t* mALLOc(size_t);
+void fREe(Void_t*);
+Void_t* rEALLOc(Void_t*, size_t);
+Void_t* cALLOc(size_t, size_t);
+Void_t* mEMALIGn(size_t, size_t);
+Void_t* vALLOc(size_t);
+Void_t* pvALLOc(size_t);
+int malloc_trim(size_t);
+size_t malloc_usable_size(Void_t*);
+void malloc_stats(void);
+int mALLOPt(int, int);
+struct mallinfo mALLINFo(void);
+#else
+Void_t* mALLOc();
+void fREe();
+Void_t* rEALLOc();
+Void_t* cALLOc();
+Void_t* mEMALIGn();
+Void_t* vALLOc();
+Void_t* pvALLOc();
+int malloc_trim();
+size_t malloc_usable_size();
+void malloc_stats();
+int mALLOPt();
+struct mallinfo mALLINFo();
+#endif
+
+#include <ctype.h> /* isprint() */
+#ifdef DEBUG3
+#include <stdlib.h> /* atexit() */
+#endif
+
+#ifdef __cplusplus
+}; /* end of extern "C" */
+#endif
+
+#endif /* DEBUG2 */
+
+/*
+ Emulation of sbrk for WIN32
+ All code within the ifdef WIN32 is untested by me.
+*/
+
+
+#ifdef WIN32
+
+#define AlignPage(add) (((add) + (malloc_getpagesize-1)) & \
+ ~(malloc_getpagesize-1))
+
+/* resrve 64MB to insure large contiguous space */
+#define RESERVED_SIZE (1024*1024*64)
+#define NEXT_SIZE (2048*1024)
+#define TOP_MEMORY ((unsigned long)2*1024*1024*1024)
+
+struct GmListElement;
+typedef struct GmListElement GmListElement;
+
+struct GmListElement
+{
+ GmListElement* next;
+ void* base;
+};
+
+static GmListElement* head = 0;
+static unsigned int gNextAddress = 0;
+static unsigned int gAddressBase = 0;
+static unsigned int gAllocatedSize = 0;
+
+static
+GmListElement* makeGmListElement (void* bas)
+{
+ GmListElement* this;
+ this = (GmListElement*)(void*)LocalAlloc (0, sizeof (GmListElement));
+ ASSERT (this);
+ if (this)
+ {
+ this->base = bas;
+ this->next = head;
+ head = this;
+ }
+ return this;
+}
+
+void gcleanup ()
+{
+ BOOL rval;
+ ASSERT ( (head == NULL) || (head->base == (void*)gAddressBase));
+ if (gAddressBase && (gNextAddress - gAddressBase))
+ {
+ rval = VirtualFree ((void*)gAddressBase,
+ gNextAddress - gAddressBase,
+ MEM_DECOMMIT);
+ ASSERT (rval);
+ }
+ while (head)
+ {
+ GmListElement* next = head->next;
+ rval = VirtualFree (head->base, 0, MEM_RELEASE);
+ ASSERT (rval);
+ LocalFree (head);
+ head = next;
+ }
+}
+
+static
+void* findRegion (void* start_address, unsigned long size)
+{
+ MEMORY_BASIC_INFORMATION info;
+ while ((unsigned long)start_address < TOP_MEMORY)
+ {
+ VirtualQuery (start_address, &info, sizeof (info));
+ if (info.State != MEM_FREE)
+ start_address = (char*)info.BaseAddress + info.RegionSize;
+ else if (info.RegionSize >= size)
+ return start_address;
+ else
+ start_address = (char*)info.BaseAddress + info.RegionSize;
+ }
+ return NULL;
+
+}
+
+
+void* wsbrk (long size)
+{
+ void* tmp;
+ if (size > 0)
+ {
+ if (gAddressBase == 0)
+ {
+ gAllocatedSize = max (RESERVED_SIZE, AlignPage (size));
+ gNextAddress = gAddressBase =
+ (unsigned int)VirtualAlloc (NULL, gAllocatedSize,
+ MEM_RESERVE, PAGE_NOACCESS);
+ } else if (AlignPage (gNextAddress + size) > (gAddressBase +
+gAllocatedSize))
+ {
+ long new_size = max (NEXT_SIZE, AlignPage (size));
+ void* new_address = (void*)(gAddressBase+gAllocatedSize);
+ do
+ {
+ new_address = findRegion (new_address, new_size);
+
+ if (new_address == 0)
+ return (void*)-1;
+
+ gAddressBase = gNextAddress =
+ (unsigned int)VirtualAlloc (new_address, new_size,
+ MEM_RESERVE, PAGE_NOACCESS);
+ // repeat in case of race condition
+ // The region that we found has been snagged
+ // by another thread
+ }
+ while (gAddressBase == 0);
+
+ ASSERT (new_address == (void*)gAddressBase);
+
+ gAllocatedSize = new_size;
+
+ if (!makeGmListElement ((void*)gAddressBase))
+ return (void*)-1;
+ }
+ if ((size + gNextAddress) > AlignPage (gNextAddress))
+ {
+ void* res;
+ res = VirtualAlloc ((void*)AlignPage (gNextAddress),
+ (size + gNextAddress -
+ AlignPage (gNextAddress)),
+ MEM_COMMIT, PAGE_READWRITE);
+ if (res == 0)
+ return (void*)-1;
+ }
+ tmp = (void*)gNextAddress;
+ gNextAddress = (unsigned int)tmp + size;
+ return tmp;
+ }
+ else if (size < 0)
+ {
+ unsigned int alignedGoal = AlignPage (gNextAddress + size);
+ /* Trim by releasing the virtual memory */
+ if (alignedGoal >= gAddressBase)
+ {
+ VirtualFree ((void*)alignedGoal, gNextAddress - alignedGoal,
+ MEM_DECOMMIT);
+ gNextAddress = gNextAddress + size;
+ return (void*)gNextAddress;
+ }
+ else
+ {
+ VirtualFree ((void*)gAddressBase, gNextAddress - gAddressBase,
+ MEM_DECOMMIT);
+ gNextAddress = gAddressBase;
+ return (void*)-1;
+ }
+ }
+ else
+ {
+ return (void*)gNextAddress;
+ }
+}
+
+#endif
+
+
+
+/*
+ Type declarations
+*/
+
+#ifdef DEBUG3
+# define MOATWIDTH 4 /* number of guard bytes at each end of
+ allocated region */
+# define MOATFILL 5 /* moat fill character */
+# define ALLOCFILL 1 /* fill char for allocated */
+# define FREEFILL 2 /* and freed regions */
+#endif
+
+typedef struct malloc_chunk
+{
+ INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
+ INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
+ struct malloc_chunk* fd; /* double links -- used only if free. */
+ struct malloc_chunk* bk;
+#ifdef DEBUG3
+ const char *file; /* file and */
+ int line; /* line number of [re]allocation */
+ size_t pad; /* nr pad bytes at mem end, excluding moat */
+ int alloced; /* whether the chunk is allocated -- less prone
+ to segv than inuse(chunk) */
+ char moat[MOATWIDTH]; /* actual leading moat is last MOATWIDTH bytes
+ of chunk header; those bytes may follow this
+ field due to header alignment padding */
+#endif
+} Chunk;
+
+typedef Chunk* mchunkptr;
+
+/*
+
+ malloc_chunk details:
+
+ (The following includes lightly edited explanations by Colin Plumb.)
+
+ Chunks of memory are maintained using a `boundary tag' method as
+ described in e.g., Knuth or Standish. (See the paper by Paul
+ Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
+ survey of such techniques.) Sizes of free chunks are stored both
+ in the front of each chunk and at the end. This makes
+ consolidating fragmented chunks into bigger chunks very fast. The
+ size fields also hold bits representing whether chunks are free or
+ in use.
+
+ An allocated chunk looks like this:
+
+
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of previous chunk, if allocated | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of chunk, in bytes |P|
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | User data starts here... .
+ . .
+ . (malloc_usable_space() bytes) .
+ . |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of chunk |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ Where "chunk" is the front of the chunk for the purpose of most of
+ the malloc code, but "mem" is the pointer that is returned to the
+ user. "Nextchunk" is the beginning of the next contiguous chunk.
+
+ Chunks always begin on even word boundries, so the mem portion
+ (which is returned to the user) is also on an even word boundary, and
+ thus double-word aligned.
+
+ Free chunks are stored in circular doubly-linked lists, and look like this:
+
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of previous chunk |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ `head:' | Size of chunk, in bytes |P|
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Forward pointer to next chunk in list |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Back pointer to previous chunk in list |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Unused space (may be 0 bytes long) .
+ . .
+ . |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ `foot:' | Size of chunk, in bytes |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The P (PREV_INUSE) bit, stored in the unused low-order bit of the
+ chunk size (which is always a multiple of two words), is an in-use
+ bit for the *previous* chunk. If that bit is *clear*, then the
+ word before the current chunk size contains the previous chunk
+ size, and can be used to find the front of the previous chunk.
+ (The very first chunk allocated always has this bit set,
+ preventing access to non-existent (or non-owned) memory.)
+
+ Note that the `foot' of the current chunk is actually represented
+ as the prev_size of the NEXT chunk. (This makes it easier to
+ deal with alignments etc).
+
+ The two exceptions to all this are
+
+ 1. The special chunk `top', which doesn't bother using the
+ trailing size field since there is no
+ next contiguous chunk that would have to index off it. (After
+ initialization, `top' is forced to always exist. If it would
+ become less than MINSIZE bytes long, it is replenished via
+ malloc_extend_top.)
+
+ 2. Chunks allocated via mmap, which have the second-lowest-order
+ bit (IS_MMAPPED) set in their size fields. Because they are
+ never merged or traversed from any other chunk, they have no
+ foot size or inuse information.
+
+ Available chunks are kept in any of several places (all declared below):
+
+ * `av': An array of chunks serving as bin headers for consolidated
+ chunks. Each bin is doubly linked. The bins are approximately
+ proportionally (log) spaced. There are a lot of these bins
+ (128). This may look excessive, but works very well in
+ practice. All procedures maintain the invariant that no
+ consolidated chunk physically borders another one. Chunks in
+ bins are kept in size order, with ties going to the
+ approximately least recently used chunk.
+
+ The chunks in each bin are maintained in decreasing sorted order by
+ size. This is irrelevant for the small bins, which all contain
+ the same-sized chunks, but facilitates best-fit allocation for
+ larger chunks. (These lists are just sequential. Keeping them in
+ order almost never requires enough traversal to warrant using
+ fancier ordered data structures.) Chunks of the same size are
+ linked with the most recently freed at the front, and allocations
+ are taken from the back. This results in LRU or FIFO allocation
+ order, which tends to give each chunk an equal opportunity to be
+ consolidated with adjacent freed chunks, resulting in larger free
+ chunks and less fragmentation.
+
+ * `top': The top-most available chunk (i.e., the one bordering the
+ end of available memory) is treated specially. It is never
+ included in any bin, is used only if no other chunk is
+ available, and is released back to the system if it is very
+ large (see M_TRIM_THRESHOLD).
+
+ * `last_remainder': A bin holding only the remainder of the
+ most recently split (non-top) chunk. This bin is checked
+ before other non-fitting chunks, so as to provide better
+ locality for runs of sequentially allocated chunks.
+
+ * Implicitly, through the host system's memory mapping tables.
+ If supported, requests greater than a threshold are usually
+ serviced via calls to mmap, and then later released via munmap.
+
+*/
+
+
+
+
+
+
+/* sizes, alignments */
+
+#define SIZE_SZ sizeof(INTERNAL_SIZE_T)
+#define ALIGNMENT (SIZE_SZ + SIZE_SZ)
+#define ALIGN_MASK (ALIGNMENT - 1)
+#ifndef DEBUG3
+# define MEMOFFSET (2*SIZE_SZ)
+# define OVERHEAD SIZE_SZ
+# define MMAP_EXTRA SIZE_SZ /* for correct alignment */
+# define MINSIZE sizeof(Chunk)
+#else
+typedef union {
+ char strut[(sizeof(Chunk) - 1) / ALIGNMENT + 1][ALIGNMENT];
+ Chunk chunk;
+} PaddedChunk;
+# define MEMOFFSET sizeof(PaddedChunk)
+# define OVERHEAD (MEMOFFSET + MOATWIDTH)
+# define MMAP_EXTRA 0
+# define MINSIZE ((OVERHEAD + ALIGN_MASK) & ~ALIGN_MASK)
+#endif
+
+/* conversion from malloc headers to user pointers, and back */
+
+#define chunk2mem(p) ((Void_t*)((char*)(p) + MEMOFFSET))
+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - MEMOFFSET))
+
+/* pad request bytes into a usable size, including overhead */
+
+#define request2size(req) \
+ ((long)((req) + OVERHEAD) < (long)MINSIZE ? MINSIZE : \
+ ((req) + OVERHEAD + ALIGN_MASK) & ~ALIGN_MASK)
+
+/* Check if m has acceptable alignment */
+
+#define aligned_OK(m) (((unsigned long)((m)) & ALIGN_MASK) == 0)
+
+
+
+
+/*
+ Physical chunk operations
+*/
+
+
+/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
+
+#define PREV_INUSE 0x1
+
+/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
+
+#define IS_MMAPPED 0x2
+
+/* Bits to mask off when extracting size */
+
+#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
+
+
+/* Ptr to next physical malloc_chunk. */
+
+#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
+
+/* Ptr to previous physical malloc_chunk */
+
+#define prev_chunk(p)\
+ ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
+
+
+/* Treat space at ptr + offset as a chunk */
+
+#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
+
+
+
+
+/*
+ Dealing with use bits
+*/
+
+/* extract p's inuse bit */
+
+#define inuse(p)\
+((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
+
+/* extract inuse bit of previous chunk */
+
+#define prev_inuse(p) ((p)->size & PREV_INUSE)
+
+/* check for mmap()'ed chunk */
+
+#if HAVE_MMAP
+# define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+#else
+# define chunk_is_mmapped(p) 0
+#endif
+
+/* set/clear chunk as in use without otherwise disturbing */
+
+#define set_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
+
+#define clear_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
+
+/* check/set/clear inuse bits in known places */
+
+#define inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
+
+#define set_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
+
+#define clear_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
+
+
+
+
+/*
+ Dealing with size fields
+*/
+
+/* Get size, ignoring use bits */
+
+#define chunksize(p) ((p)->size & ~(SIZE_BITS))
+
+/* Set size at head, without disturbing its use bit */
+
+#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
+
+/* Set size/use ignoring previous bits in header */
+
+#define set_head(p, s) ((p)->size = (s))
+
+/* Set size at footer (only when chunk is not in use) */
+
+#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
+
+
+
+
+
+/*
+ Bins
+
+ The bins, `av_' are an array of pairs of pointers serving as the
+ heads of (initially empty) doubly-linked lists of chunks, laid out
+ in a way so that each pair can be treated as if it were in a
+ malloc_chunk. (This way, the fd/bk offsets for linking bin heads
+ and chunks are the same).
+
+ Bins for sizes < 512 bytes contain chunks of all the same size, spaced
+ 8 bytes apart. Larger bins are approximately logarithmically
+ spaced. (See the table below.) The `av_' array is never mentioned
+ directly in the code, but instead via bin access macros.
+
+ Bin layout:
+
+ 64 bins of size 8
+ 32 bins of size 64
+ 16 bins of size 512
+ 8 bins of size 4096
+ 4 bins of size 32768
+ 2 bins of size 262144
+ 1 bin of size what's left
+
+ There is actually a little bit of slop in the numbers in bin_index
+ for the sake of speed. This makes no difference elsewhere.
+
+ The special chunks `top' and `last_remainder' get their own bins,
+ (this is implemented via yet more trickery with the av_ array),
+ although `top' is never properly linked to its bin since it is
+ always handled specially.
+
+*/
+
+#define NAV 128 /* number of bins */
+
+typedef Chunk* mbinptr;
+
+/* access macros */
+
+#define bin_at(i) ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ))
+#define next_bin(b) ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr)))
+#define prev_bin(b) ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr)))
+
+/*
+ The first 2 bins are never indexed. The corresponding av_ cells are instead
+ used for bookkeeping. This is not to save space, but to simplify
+ indexing, maintain locality, and avoid some initialization tests.
+*/
+
+#define top (bin_at(0)->fd) /* The topmost chunk */
+#define last_remainder (bin_at(1)) /* remainder from last split */
+
+
+/*
+ Because top initially points to its own bin with initial
+ zero size, thus forcing extension on the first malloc request,
+ we avoid having any special code in malloc to check whether
+ it even exists yet. But we still need to in malloc_extend_top.
+*/
+
+#define initial_top ((mchunkptr)(bin_at(0)))
+
+/* Helper macro to initialize bins */
+
+#define IAV(i) bin_at(i), bin_at(i)
+
+static mbinptr av_[NAV * 2 + 2] = {
+ 0, 0,
+ IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7),
+ IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15),
+ IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23),
+ IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31),
+ IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39),
+ IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47),
+ IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55),
+ IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63),
+ IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71),
+ IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79),
+ IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87),
+ IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95),
+ IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), IAV(103),
+ IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111),
+ IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
+ IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
+};
+
+
+
+/* field-extraction macros */
+
+#define first(b) ((b)->fd)
+#define last(b) ((b)->bk)
+
+/*
+ Indexing into bins
+*/
+
+#define bin_index(sz) \
+(((((unsigned long)(sz)) >> 9) == 0) ? (((unsigned long)(sz)) >> 3): \
+ ((((unsigned long)(sz)) >> 9) <= 4) ? 56 + (((unsigned long)(sz)) >> 6): \
+ ((((unsigned long)(sz)) >> 9) <= 20) ? 91 + (((unsigned long)(sz)) >> 9): \
+ ((((unsigned long)(sz)) >> 9) <= 84) ? 110 + (((unsigned long)(sz)) >> 12): \
+ ((((unsigned long)(sz)) >> 9) <= 340) ? 119 + (((unsigned long)(sz)) >> 15): \
+ ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \
+ 126)
+/*
+ bins for chunks < 512 are all spaced 8 bytes apart, and hold
+ identically sized chunks. This is exploited in malloc.
+*/
+
+#define MAX_SMALLBIN 63
+#define MAX_SMALLBIN_SIZE 512
+#define SMALLBIN_WIDTH 8
+
+#define smallbin_index(sz) (((unsigned long)(sz)) >> 3)
+
+/*
+ Requests are `small' if both the corresponding and the next bin are small
+*/
+
+#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)
+
+
+
+/*
+ To help compensate for the large number of bins, a one-level index
+ structure is used for bin-by-bin searching. `binblocks' is a
+ one-word bitvector recording whether groups of BINBLOCKWIDTH bins
+ have any (possibly) non-empty bins, so they can be skipped over
+ all at once during during traversals. The bits are NOT always
+ cleared as soon as all bins in a block are empty, but instead only
+ when all are noticed to be empty during traversal in malloc.
+*/
+
+#define BINBLOCKWIDTH 4 /* bins per block */
+
+#define binblocks (bin_at(0)->size) /* bitvector of nonempty blocks */
+
+/* bin<->block macros */
+
+#define idx2binblock(ix) ((unsigned)1 << (ix / BINBLOCKWIDTH))
+#define mark_binblock(ii) (binblocks |= idx2binblock(ii))
+#define clear_binblock(ii) (binblocks &= ~(idx2binblock(ii)))
+
+
+
+
+
+/* Other static bookkeeping data */
+
+/* variables holding tunable values */
+
+static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD;
+static unsigned long top_pad = DEFAULT_TOP_PAD;
+static unsigned int n_mmaps_max = DEFAULT_MMAP_MAX;
+static unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD;
+#ifdef DEBUG2
+static int scanheap = 1;
+#endif
+
+/* The first value returned from sbrk */
+static char* sbrk_base = (char*)(-1);
+
+/* The maximum memory obtained from system via sbrk */
+static unsigned long max_sbrked_mem = 0;
+
+/* The maximum via either sbrk or mmap */
+static unsigned long max_total_mem = 0;
+
+/* internal working copy of mallinfo */
+static struct mallinfo current_mallinfo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* The total memory obtained from system via sbrk */
+#define sbrked_mem (current_mallinfo.arena)
+
+/* Tracking mmaps */
+
+static unsigned int n_mmaps = 0;
+static unsigned long mmapped_mem = 0;
+#if HAVE_MMAP
+static unsigned int max_n_mmaps = 0;
+static unsigned long max_mmapped_mem = 0;
+#endif
+
+
+
+/*
+ Debugging support
+*/
+
+#if DEBUG
+
+#ifndef DEBUG2
+# define unless(cond, err, p) assert(cond)
+#else
+# define unless(cond, err, p) do { if (!(cond)) malloc_err(err, p); } while (0)
+
+/*
+ * When debug_file is non-null, it and debug_line respectively contain the
+ * file and line number of the current invocation of malloc(), calloc(),
+ * realloc(), or free().
+ */
+static const char *debug_file = NULL;
+static int debug_line;
+
+/*
+ * Avoid dereferencing invalid chunk.file pointers by tracking the range of
+ * valid ones. Could add an "unallocated" flag to init_freed_chunk() for
+ * more protection, but that's probably not necessary.
+ */
+static const char *debug_file_min = (char *)~0;
+static const char *debug_file_max = NULL;
+
+static char *itos(int n)
+{
+#define NDIGITS (sizeof(int) * 3)
+ static char s[NDIGITS + 1];
+ int i = NDIGITS;
+ do {
+ s[--i] = '0' + n % 10;
+ n /= 10;
+ } while (n);
+ return s + i;
+#undef NDIGITS
+}
+
+static int recurs = 0;
+
+static void errprint(const char *file, int line, const char *err)
+{
+ if (recurs++) {
+ recurs--;
+ return;
+ }
+
+ if (file) {
+ write(2, file, strlen(file));
+ if (line) {
+ write(2, ":", 1);
+ write(2, itos(line), strlen(itos(line)));
+ }
+ write(2, ": ", 2);
+ }
+ write(2, err, strlen(err));
+ write(2, "\n", 1);
+ recurs--;
+}
+
+static void malloc_err(const char *err, mchunkptr p)
+{
+ /*
+ * Display ERR on stderr, accompanying it with the caller's file and line
+ * number if available. If P is non-null, also attempt to display the file
+ * and line number at which P was most recently [re]allocated.
+ *
+ * This function's name begins with "malloc_" to make setting debugger
+ * breakpoints here more convenient.
+ */
+ errprint(debug_file, debug_line, err);
+
+# ifndef DEBUG3
+ p = 0; /* avoid "unused param" warning */
+# else
+ if (p && p->file &&
+ /* avoid invalid pointers */
+ debug_file_min &&
+ p->file >= debug_file_min &&
+ p->file <= debug_file_max)
+ errprint(p->file, p->line, "in block allocated here");
+# endif
+}
+
+#undef malloc
+#undef free
+#undef realloc
+#undef memalign
+#undef valloc
+#undef pvalloc
+#undef calloc
+#undef malloc_trim
+#undef malloc_usable_size
+#undef malloc_stats
+#undef mallopt
+#undef mallinfo
+
+static void malloc_update_mallinfo(void);
+
+/*
+ * Define front-end functions for all user-visible entry points that may
+ * trigger error().
+ */
+#define skel(retdecl, retassign, call, retstmt) \
+ retdecl \
+ debug_file = file; \
+ debug_line = line; \
+ if (debug_file < debug_file_min) \
+ debug_file_min = debug_file; \
+ if (debug_file > debug_file_max) \
+ debug_file_max = debug_file; \
+ if (scanheap) \
+ malloc_update_mallinfo(); \
+ retassign call; \
+ if (scanheap) \
+ malloc_update_mallinfo(); \
+ debug_file = NULL; \
+ retstmt
+
+/*
+ * The final letter of the names of the following macros is either r or v,
+ * indicating that the macro handles functions with or without a return value,
+ * respectively.
+ */
+# define skelr(rettype, call) \
+ skel(rettype ret;, ret = , call, return ret)
+/*
+ * AIX's xlc compiler doesn't like empty macro args, so specify useless but
+ * compilable retdecl, retassign, and retstmt args:
+ */
+#define skelv(call) \
+ skel(line += 0;, if (1), call, return)
+
+#define dbgargs const char *file, int line
+
+/*
+ * Front-end function definitions:
+ */
+Void_t* malloc_dbg(size_t bytes, dbgargs) {
+ skelr(Void_t*, malloc(bytes));
+}
+void free_dbg(Void_t *mem, dbgargs) {
+ skelv(free(mem));
+}
+Void_t* realloc_dbg(Void_t *oldmem, size_t bytes, dbgargs) {
+ skelr(Void_t*, realloc(oldmem, bytes));
+}
+Void_t* memalign_dbg(size_t alignment, size_t bytes, dbgargs) {
+ skelr(Void_t*, dlmemalign(alignment, bytes));
+}
+Void_t* valloc_dbg(size_t bytes, dbgargs) {
+ skelr(Void_t*, dlvalloc(bytes));
+}
+Void_t* pvalloc_dbg(size_t bytes, dbgargs) {
+ skelr(Void_t*, dlpvalloc(bytes));
+}
+Void_t* calloc_dbg(size_t n, size_t elem_size, dbgargs) {
+ skelr(Void_t*, calloc(n, elem_size));
+}
+int malloc_trim_dbg(size_t pad, dbgargs) {
+ skelr(int, malloc_trim(pad));
+}
+size_t malloc_usable_size_dbg(Void_t *mem, dbgargs) {
+ skelr(size_t, malloc_usable_size(mem));
+}
+void malloc_stats_dbg(dbgargs) {
+ skelv(malloc_stats());
+}
+int mallopt_dbg(int flag, int value, dbgargs) {
+ skelr(int, dlmallopt(flag, value));
+}
+struct mallinfo mallinfo_dbg(dbgargs) {
+ skelr(struct mallinfo, dlmallinfo());
+}
+
+#undef skel
+#undef skelr
+#undef skelv
+#undef dbgargs
+
+#endif /* DEBUG2 */
+
+/*
+ These routines make a number of assertions about the states
+ of data structures that should be true at all times. If any
+ are not true, it's very likely that a user program has somehow
+ trashed memory. (It's also possible that there is a coding error
+ in malloc. In which case, please report it!)
+*/
+
+#ifdef DEBUG3
+static int memtest(void *s, int c, size_t n)
+{
+ /*
+ * Return whether the N-byte memory region starting at S consists
+ * entirely of bytes with value C.
+ */
+ unsigned char *p = (unsigned char *)s;
+ size_t i;
+ for (i = 0; i < n; i++)
+ if (p[i] != (unsigned char)c)
+ return 0;
+ return 1;
+}
+#endif /* DEBUG3 */
+
+#ifndef DEBUG3
+#define check_moats(P)
+#else
+#define check_moats do_check_moats
+static void do_check_moats(mchunkptr p)
+{
+ INTERNAL_SIZE_T sz = chunksize(p);
+ unless(memtest((char *)chunk2mem(p) - MOATWIDTH, MOATFILL,
+ MOATWIDTH), "region underflow", p);
+ unless(memtest((char *)p + sz - MOATWIDTH - p->pad, MOATFILL,
+ MOATWIDTH + p->pad), "region overflow", p);
+}
+#endif /* DEBUG3 */
+
+#if __STD_C
+static void do_check_chunk(mchunkptr p)
+#else
+static void do_check_chunk(p) mchunkptr p;
+#endif
+{
+ /* Try to ensure legal addresses before accessing any chunk fields, in the
+ * hope of issuing an informative message rather than causing a segv.
+ *
+ * The following chunk_is_mmapped() call accesses p->size #if HAVE_MMAP.
+ * This is unavoidable without maintaining a record of mmapped regions.
+ */
+ if (!chunk_is_mmapped(p))
+ {
+ INTERNAL_SIZE_T sz;
+
+ unless((char*)p >= sbrk_base, "chunk precedes sbrk_base", p);
+ unless((char*)p + MINSIZE <= (char*)top + chunksize(top),
+ "chunk past sbrk area", p);
+
+ sz = chunksize(p);
+ if (p != top)
+ unless((char*)p + sz <= (char*)top, "chunk extends beyond top", p);
+ else
+ unless((char*)p + sz <= sbrk_base + sbrked_mem,
+ "chunk extends past sbrk area", p);
+ }
+ check_moats(p);
+}
+
+#if __STD_C
+static void do_check_free_chunk(mchunkptr p)
+#else
+static void do_check_free_chunk(p) mchunkptr p;
+#endif
+{
+ INTERNAL_SIZE_T sz = chunksize(p);
+ mchunkptr next = chunk_at_offset(p, sz);
+
+ do_check_chunk(p);
+
+ /* Check whether it claims to be free ... */
+ unless(!inuse(p), "free chunk marked inuse", p);
+
+ /* Unless a special marker, must have OK fields */
+ if ((long)sz >= (long)MINSIZE)
+ {
+ unless((sz & ALIGN_MASK) == 0, "freed size defies alignment", p);
+ unless(aligned_OK(chunk2mem(p)), "misaligned freed region", p);
+ /* ... matching footer field */
+ unless(next->prev_size == sz, "chunk size mismatch", p);
+ /* ... and is fully consolidated */
+ unless(prev_inuse(p), "free chunk not joined with prev", p);
+ unless(next == top || inuse(next), "free chunk not joined with next", p);
+
+ /* ... and has minimally sane links */
+ unless(p->fd->bk == p, "broken forward link", p);
+ unless(p->bk->fd == p, "broken backward link", p);
+ }
+ else /* markers are always of size SIZE_SZ */
+ unless(sz == SIZE_SZ, "invalid small chunk size", p);
+}
+
+#if __STD_C
+static void do_check_inuse_chunk(mchunkptr p)
+#else
+static void do_check_inuse_chunk(p) mchunkptr p;
+#endif
+{
+ mchunkptr next;
+ do_check_chunk(p);
+
+ if (chunk_is_mmapped(p))
+ return;
+
+ /* Check whether it claims to be in use ... */
+#ifdef DEBUG3
+ unless(p->alloced, "memory not allocated", p);
+#endif
+ unless(inuse(p), "memory not allocated", p);
+
+ /* ... and is surrounded by OK chunks.
+ Since more things can be checked with free chunks than inuse ones,
+ if an inuse chunk borders them and debug is on, it's worth doing them.
+ */
+ if (!prev_inuse(p))
+ {
+ mchunkptr prv = prev_chunk(p);
+ unless(next_chunk(prv) == p, "prev link scrambled", p);
+ do_check_free_chunk(prv);
+ }
+ next = next_chunk(p);
+ if (next == top)
+ {
+ unless(prev_inuse(next), "top chunk wrongly thinks prev is unused", p);
+ unless(chunksize(next) >= MINSIZE, "top chunk too small", p);
+ }
+ else if (!inuse(next))
+ do_check_free_chunk(next);
+}
+
+#if __STD_C
+static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
+#else
+static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
+#endif
+{
+ INTERNAL_SIZE_T sz = chunksize(p);
+ long room = sz - s;
+
+ do_check_inuse_chunk(p);
+
+ /* Legal size ... */
+ unless((long)sz >= (long)MINSIZE, "chunk size too small", p);
+ unless((sz & ALIGN_MASK) == 0, "malloced size defies alignment", p);
+ unless(room >= 0, "chunk size too small for contents", p);
+ unless(room < (long)MINSIZE, "chunk size leaves too much spare room", p);
+
+ /* ... and alignment */
+ unless(aligned_OK(chunk2mem(p)), "misaligned malloced region", p);
+
+
+ /* ... and was allocated at front of an available chunk */
+ unless(prev_inuse(p), "malloced from the middle of a free chunk", p);
+}
+
+#ifdef DEBUG3
+static void init_alloced_chunk(mchunkptr p, size_t bytes)
+{
+ Void_t* mem = chunk2mem(p);
+ p->file = debug_file;
+ p->line = debug_line;
+ p->pad = chunksize(p) - OVERHEAD - bytes;
+ p->alloced = 1;
+ memset((char *)mem + bytes, MOATFILL, p->pad + MOATWIDTH);
+}
+
+static void do_init_malloced_chunk(mchunkptr p, size_t bytes)
+{
+ Void_t* mem = chunk2mem(p);
+ init_alloced_chunk(p, bytes);
+ memset((char *)mem - MOATWIDTH, MOATFILL, MOATWIDTH);
+ memset(mem, ALLOCFILL, bytes);
+}
+
+static void do_init_realloced_chunk(mchunkptr p, size_t bytes,
+ INTERNAL_SIZE_T oldsize)
+{
+ Void_t* mem = chunk2mem(p);
+ INTERNAL_SIZE_T newsize = chunksize(p);
+ init_alloced_chunk(p, bytes);
+ if (oldsize < newsize)
+ /* This incorrectly leaves the leading pad area of the old trailing moat
+ * set to MOATFILL rather than ALLOCFILL. An alternative is to save the
+ * old p->pad in rEALLOc() below and pass it to this function.
+ */
+ memset((char *)mem + oldsize - OVERHEAD, ALLOCFILL,
+ bytes - (oldsize - OVERHEAD));
+}
+
+static void do_check_freefill(mchunkptr p, long newsize,
+ INTERNAL_SIZE_T oldsize)
+{
+ /* The first newsize bytes of oldsize-byte chunk p are about to be
+ * allocated. Issue a warning if any freefill locations in p that are about
+ * to be overwritten do not contain the character FREEFILL.
+ */
+ size_t bytes, maxbytes;
+ if (newsize <= 0)
+ return;
+ bytes = newsize - MEMOFFSET /* don't check p's header */
+ + MEMOFFSET; /* header of split-off remainder */
+ maxbytes = oldsize - OVERHEAD;
+ if (bytes > maxbytes)
+ bytes = maxbytes;
+ unless(memtest(chunk2mem(p), FREEFILL, bytes),
+ "detected write to freed region", p);
+}
+
+static void do_init_freed_chunk(mchunkptr p, INTERNAL_SIZE_T freehead,
+ INTERNAL_SIZE_T freetail)
+{
+ /* freehead and freetail are the number of bytes at the beginning of p and
+ * end of p respectively that should already be initialized as free regions.
+ */
+ Void_t* mem = chunk2mem(p);
+ size_t size = chunksize(p);
+ size_t bytes = size - OVERHEAD;
+ p->pad = 0;
+ p->alloced = 0;
+ memset((char *)mem - MOATWIDTH, MOATFILL, MOATWIDTH);
+ memset((char *)mem + bytes, MOATFILL, MOATWIDTH);
+
+ /* To avoid terrible O(n^2) performance when free() repeatedly grows a free
+ * chunk, it's important not to free-fill regions that are already
+ * free-filled.
+ */
+ if (freehead + freetail < size) {
+ Void_t* start = !freehead ? mem : (char *)p + freehead - MOATWIDTH;
+ size_t len = (char *)p + size - (char *)start -
+ (!freetail ? MOATWIDTH : freetail - OVERHEAD);
+ memset(start, FREEFILL, len);
+ }
+}
+
+static void do_init_freeable_chunk(mchunkptr p)
+{
+ /* Arrange for the subsequent fREe(p) not to generate any warnings. */
+ init_alloced_chunk(p, chunksize(p) - OVERHEAD);
+ memset((char *)chunk2mem(p) - MOATWIDTH, MOATFILL, MOATWIDTH);
+}
+
+static void do_maximize_chunk(mchunkptr p)
+{
+ if (p->pad) {
+ Void_t* mem = chunk2mem(p);
+ size_t bytes = chunksize(p) - OVERHEAD - p->pad;
+ memset((char *)mem + bytes, ALLOCFILL, p->pad);
+ p->pad = 0;
+ }
+}
+
+static int do_check_init(void)
+{
+ /* Called from the first invocation of malloc_extend_top(), as detected by
+ * sbrk_base == -1. Return whether this function allocated any memory.
+ */
+ static int state = 0; /* 1 => initializing, 2 => initialized */
+ if (state == 1)
+ return 0;
+ unless(state == 0, "multiple calls to check_init", NULL);
+ state++;
+ atexit(malloc_update_mallinfo); /* calls malloc on WinNT */
+ return sbrk_base != (char *)-1;
+}
+#endif /* DEBUG3 */
+
+static mchunkptr lowest_chunk;
+
+#define check_free_chunk(P) do_check_free_chunk(P)
+#define check_inuse_chunk(P) do_check_inuse_chunk(P)
+#define check_chunk(P) do_check_chunk(P)
+#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
+#else /* !DEBUG */
+#define check_free_chunk(P)
+#define check_inuse_chunk(P)
+#define check_chunk(P)
+#define check_malloced_chunk(P,N)
+#endif /* !DEBUG */
+
+#ifdef DEBUG3
+#define check_init do_check_init
+#define init_malloced_chunk do_init_malloced_chunk
+#define init_realloced_chunk do_init_realloced_chunk
+#define check_freefill do_check_freefill
+#define init_freed_chunk do_init_freed_chunk
+#define init_freeable_chunk do_init_freeable_chunk
+#define maximize_chunk do_maximize_chunk
+#else
+#define check_init() 0
+#define init_malloced_chunk(P,B)
+#define init_realloced_chunk(P,B,O)
+#define check_freefill(P,N,O)
+#define init_freed_chunk(P,H,T)
+#define init_freeable_chunk(P)
+#define maximize_chunk(P)
+#endif /* !DEBUG3 */
+
+
+
+/*
+ Macro-based internal utilities
+*/
+
+
+/*
+ Linking chunks in bin lists.
+ Call these only with variables, not arbitrary expressions, as arguments.
+*/
+
+/*
+ Place chunk p of size s in its bin, in size order,
+ putting it ahead of others of same size.
+*/
+
+
+#define frontlink(P, S, IDX, BK, FD) \
+{ \
+ if (S < MAX_SMALLBIN_SIZE) \
+ { \
+ IDX = smallbin_index(S); \
+ mark_binblock(IDX); \
+ BK = bin_at(IDX); \
+ FD = BK->fd; \
+ P->bk = BK; \
+ P->fd = FD; \
+ FD->bk = BK->fd = P; \
+ } \
+ else \
+ { \
+ IDX = bin_index(S); \
+ BK = bin_at(IDX); \
+ FD = BK->fd; \
+ if (FD == BK) mark_binblock(IDX); \
+ else \
+ { \
+ while (FD != BK && S < chunksize(FD)) FD = FD->fd; \
+ BK = FD->bk; \
+ } \
+ P->bk = BK; \
+ P->fd = FD; \
+ FD->bk = BK->fd = P; \
+ } \
+}
+
+
+/* take a chunk off a list */
+
+#define unlink(P, BK, FD) \
+{ \
+ BK = P->bk; \
+ FD = P->fd; \
+ FD->bk = BK; \
+ BK->fd = FD; \
+} \
+
+/* Place p as the last remainder */
+
+#define link_last_remainder(P) \
+{ \
+ last_remainder->fd = last_remainder->bk = P; \
+ P->fd = P->bk = last_remainder; \
+}
+
+/* Clear the last_remainder bin */
+
+#define clear_last_remainder \
+ (last_remainder->fd = last_remainder->bk = last_remainder)
+
+
+
+
+
+
+/* Routines dealing with mmap(). */
+
+#if HAVE_MMAP
+
+#if __STD_C
+static mchunkptr mmap_chunk(size_t size)
+#else
+static mchunkptr mmap_chunk(size) size_t size;
+#endif
+{
+ size_t page_mask = malloc_getpagesize - 1;
+ mchunkptr p;
+
+#ifndef MAP_ANONYMOUS
+ static int fd = -1;
+#endif
+
+ if(n_mmaps >= n_mmaps_max) return 0; /* too many regions */
+
+ size = (size + MMAP_EXTRA + page_mask) & ~page_mask;
+
+#ifdef MAP_ANONYMOUS
+ p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+#else /* !MAP_ANONYMOUS */
+ if (fd < 0)
+ {
+ fd = open("/dev/zero", O_RDWR);
+ if(fd < 0) return 0;
+ }
+ p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+#endif
+
+ if(p == (mchunkptr)-1) return 0;
+
+ n_mmaps++;
+ if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps;
+
+ /* We demand that eight bytes into a page must be 8-byte aligned. */
+ assert(aligned_OK(chunk2mem(p)));
+
+ /* The offset to the start of the mmapped region is stored
+ * in the prev_size field of the chunk; normally it is zero,
+ * but that can be changed in memalign().
+ */
+ p->prev_size = 0;
+ set_head(p, size|IS_MMAPPED);
+
+ mmapped_mem += size;
+ if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
+ max_mmapped_mem = mmapped_mem;
+ if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
+ max_total_mem = mmapped_mem + sbrked_mem;
+ return p;
+}
+
+#if __STD_C
+static void munmap_chunk(mchunkptr p)
+#else
+static void munmap_chunk(p) mchunkptr p;
+#endif
+{
+ INTERNAL_SIZE_T size = chunksize(p);
+ int ret;
+
+ assert (chunk_is_mmapped(p));
+ assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
+ assert((n_mmaps > 0));
+ assert(((p->prev_size + size) & (malloc_getpagesize-1)) == 0);
+
+ n_mmaps--;
+ mmapped_mem -= (size + p->prev_size);
+
+ ret = munmap((char *)p - p->prev_size, size + p->prev_size);
+
+ /* munmap returns non-zero on failure */
+ assert(ret == 0);
+}
+
+#if HAVE_MREMAP
+
+#if __STD_C
+static mchunkptr mremap_chunk(mchunkptr p, size_t new_size)
+#else
+static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
+#endif
+{
+ size_t page_mask = malloc_getpagesize - 1;
+ INTERNAL_SIZE_T offset = p->prev_size;
+ INTERNAL_SIZE_T size = chunksize(p);
+ char *cp;
+
+ assert (chunk_is_mmapped(p));
+ assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
+ assert((n_mmaps > 0));
+ assert(((size + offset) & (malloc_getpagesize-1)) == 0);
+
+ new_size = (new_size + offset + MMAP_EXTRA + page_mask) & ~page_mask;
+
+ cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1);
+
+ if (cp == (char *)-1) return 0;
+
+ p = (mchunkptr)(cp + offset);
+
+ assert(aligned_OK(chunk2mem(p)));
+
+ assert(p->prev_size == offset);
+ set_head(p, (new_size - offset)|IS_MMAPPED);
+
+ mmapped_mem -= size + offset;
+ mmapped_mem += new_size;
+ if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
+ max_mmapped_mem = mmapped_mem;
+ if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
+ max_total_mem = mmapped_mem + sbrked_mem;
+ return p;
+}
+
+#endif /* HAVE_MREMAP */
+
+#endif /* HAVE_MMAP */
+
+
+
+
+/*
+ Extend the top-most chunk by obtaining memory from system.
+ Main interface to sbrk (but see also malloc_trim).
+*/
+
+#if __STD_C
+static void malloc_extend_top(INTERNAL_SIZE_T nb)
+#else
+static void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
+#endif
+{
+ char* lim; /* return value from sbrk */
+ INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */
+ INTERNAL_SIZE_T correction; /* bytes for 2nd sbrk call */
+ char* new_lim; /* return of 2nd sbrk call */
+ INTERNAL_SIZE_T top_size; /* new size of top chunk */
+
+ mchunkptr old_top = top; /* Record state of old top */
+ INTERNAL_SIZE_T old_top_size = chunksize(old_top);
+ char* old_end = (char*)(chunk_at_offset(old_top, old_top_size));
+
+ /* Pad request with top_pad plus minimal overhead */
+
+ INTERNAL_SIZE_T sbrk_size = nb + top_pad + MINSIZE;
+ unsigned long pagesz = malloc_getpagesize;
+
+ /* If not the first time through, round to preserve page boundary */
+ /* Otherwise, we need to correct to a page size below anyway. */
+ /* (We also correct below if an intervening foreign sbrk call.) */
+
+ if (sbrk_base != (char*)(-1))
+ sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1);
+
+ else if (check_init()) {
+ if (chunksize(top) - nb < (long)MINSIZE)
+ malloc_extend_top(nb);
+ return;
+ }
+
+ lim = (char*)(MORECORE (sbrk_size));
+
+ /* Fail if sbrk failed or if a foreign sbrk call killed our space */
+ if (lim == (char*)(MORECORE_FAILURE) ||
+ (lim < old_end && old_top != initial_top))
+ return;
+
+ sbrked_mem += sbrk_size;
+
+ if (lim == old_end) /* can just add bytes to current top */
+ {
+ top_size = sbrk_size + old_top_size;
+ set_head(top, top_size | PREV_INUSE);
+ }
+ else
+ {
+#ifdef SBRKDBG
+ INTERNAL_SIZE_T padding = (char *)sbrk (0) - (lim + sbrk_size);
+ sbrk_size += padding;
+ sbrked_mem += padding;
+#endif
+
+ if (sbrk_base == (char*)(-1)) /* First time through. Record base */
+ sbrk_base = lim;
+ else /* Someone else called sbrk(). Count those bytes as sbrked_mem. */
+ sbrked_mem += lim - (char*)old_end;
+
+ /* Guarantee alignment of first new chunk made from this space */
+ front_misalign = (unsigned long)chunk2mem(lim) & ALIGN_MASK;
+ if (front_misalign > 0)
+ {
+ correction = (ALIGNMENT) - front_misalign;
+ lim += correction;
+ }
+ else
+ correction = 0;
+
+ /* Guarantee the next brk will be at a page boundary */
+ correction += pagesz - ((unsigned long)(lim + sbrk_size) & (pagesz - 1));
+
+ /* Allocate correction */
+ new_lim = (char*)(MORECORE (correction));
+ if (new_lim == (char*)(MORECORE_FAILURE)) return;
+
+ sbrked_mem += correction;
+
+ top = (mchunkptr)lim;
+ top_size = new_lim - lim + correction;
+ set_head(top, top_size | PREV_INUSE);
+#if DEBUG
+ lowest_chunk = top;
+#endif
+
+#ifdef OTHER_SBRKS
+ if (old_top != initial_top)
+ {
+
+ /* There must have been an intervening foreign sbrk call. */
+ /* A double fencepost is necessary to prevent consolidation */
+
+ /* If not enough space to do this, then user did something very wrong */
+ if (old_top_size < MINSIZE)
+ {
+ set_head(top, PREV_INUSE); /* will force null return from malloc */
+ return;
+ }
+
+ old_top_size -= 2*SIZE_SZ;
+ chunk_at_offset(old_top, old_top_size )->size =
+ SIZE_SZ|PREV_INUSE;
+ chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =
+ SIZE_SZ|PREV_INUSE;
+ set_head_size(old_top, old_top_size);
+ /* If possible, release the rest. */
+ if (old_top_size >= MINSIZE) {
+ init_freeable_chunk(old_top);
+ fREe(chunk2mem(old_top));
+ }
+ }
+#endif /* OTHER_SBRKS */
+ }
+
+ init_freed_chunk(top, old_top == initial_top ? old_top_size : 0, 0);
+
+ if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem)
+ max_sbrked_mem = sbrked_mem;
+ if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
+ max_total_mem = mmapped_mem + sbrked_mem;
+
+ /* We always land on a page boundary */
+ assert(((unsigned long)((char*)top + top_size) & (pagesz - 1)) == 0);
+}
+
+
+
+
+/* Main public routines */
+
+
+/*
+ Malloc Algorthim:
+
+ The requested size is first converted into a usable form, `nb'.
+ This currently means to add 4 bytes overhead plus possibly more to
+ obtain 8-byte alignment and/or to obtain a size of at least
+ MINSIZE (currently 16 bytes), the smallest allocatable size.
+ (All fits are considered `exact' if they are within MINSIZE bytes.)
+
+ From there, the first successful of the following steps is taken:
+
+ 1. The bin corresponding to the request size is scanned, and if
+ a chunk of exactly the right size is found, it is taken.
+
+ 2. The most recently remaindered chunk is used if it is big
+ enough. This is a form of (roving) first fit, used only in
+ the absence of exact fits. Runs of consecutive requests use
+ the remainder of the chunk used for the previous such request
+ whenever possible. This limited use of a first-fit style
+ allocation strategy tends to give contiguous chunks
+ coextensive lifetimes, which improves locality and can reduce
+ fragmentation in the long run.
+
+ 3. Other bins are scanned in increasing size order, using a
+ chunk big enough to fulfill the request, and splitting off
+ any remainder. This search is strictly by best-fit; i.e.,
+ the smallest (with ties going to approximately the least
+ recently used) chunk that fits is selected.
+
+ 4. If large enough, the chunk bordering the end of memory
+ (`top') is split off. (This use of `top' is in accord with
+ the best-fit search rule. In effect, `top' is treated as
+ larger (and thus less well fitting) than any other available
+ chunk since it can be extended to be as large as necessary
+ (up to system limitations).
+
+ 5. If the request size meets the mmap threshold and the
+ system supports mmap, and there are few enough currently
+ allocated mmapped regions, and a call to mmap succeeds,
+ the request is allocated via direct memory mapping.
+
+ 6. Otherwise, the top of memory is extended by
+ obtaining more space from the system (normally using sbrk,
+ but definable to anything else via the MORECORE macro).
+ Memory is gathered from the system (in system page-sized
+ units) in a way that allows chunks obtained across different
+ sbrk calls to be consolidated, but does not require
+ contiguous memory. Thus, it should be safe to intersperse
+ mallocs with other sbrk calls.
+
+
+ All allocations are made from the the `lowest' part of any found
+ chunk. (The implementation invariant is that prev_inuse is
+ always true of any allocated chunk; i.e., that each allocated
+ chunk borders either a previously allocated and still in-use chunk,
+ or the base of its memory arena.)
+
+*/
+
+#if __STD_C
+Void_t* mALLOc(size_t bytes)
+#else
+Void_t* mALLOc(bytes) size_t bytes;
+#endif
+{
+ mchunkptr victim; /* inspected/selected chunk */
+ INTERNAL_SIZE_T victim_size; /* its size */
+ int idx; /* index for bin traversal */
+ mbinptr bin; /* associated bin */
+ mchunkptr remainder; /* remainder from a split */
+ long remainder_size; /* its size */
+ int remainder_index; /* its bin index */
+ unsigned long block; /* block traverser bit */
+ int startidx; /* first bin of a traversed block */
+ mchunkptr fwd; /* misc temp for linking */
+ mchunkptr bck; /* misc temp for linking */
+ mbinptr q; /* misc temp */
+
+ INTERNAL_SIZE_T nb = request2size(bytes); /* padded request size; */
+
+ /* Check for exact match in a bin */
+
+ if (is_small_request(nb)) /* Faster version for small requests */
+ {
+ idx = smallbin_index(nb);
+
+ /* No traversal or size check necessary for small bins. */
+
+ q = bin_at(idx);
+ victim = last(q);
+
+ /* Also scan the next one, since it would have a remainder < MINSIZE */
+ if (victim == q)
+ {
+ q = next_bin(q);
+ victim = last(q);
+ }
+ if (victim != q)
+ {
+ victim_size = chunksize(victim);
+ unlink(victim, bck, fwd);
+ set_inuse_bit_at_offset(victim, victim_size);
+ check_freefill(victim, victim_size, victim_size);
+ init_malloced_chunk(victim, bytes);
+ check_malloced_chunk(victim, nb);
+
+ return chunk2mem(victim);
+ }
+
+ idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
+
+ }
+ else
+ {
+ idx = bin_index(nb);
+ bin = bin_at(idx);
+
+ for (victim = last(bin); victim != bin; victim = victim->bk)
+ {
+ victim_size = chunksize(victim);
+ remainder_size = victim_size - nb;
+
+ if (remainder_size >= (long)MINSIZE) /* too big */
+ {
+ --idx; /* adjust to rescan below after checking last remainder */
+ break;
+ }
+
+ else if (remainder_size >= 0) /* exact fit */
+ {
+ unlink(victim, bck, fwd);
+ set_inuse_bit_at_offset(victim, victim_size);
+ check_freefill(victim, victim_size, victim_size);
+ init_malloced_chunk(victim, bytes);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+
+ ++idx;
+
+ }
+
+ /* Try to use the last split-off remainder */
+
+ if ( (victim = last_remainder->fd) != last_remainder)
+ {
+ victim_size = chunksize(victim);
+ remainder_size = victim_size - nb;
+
+ if (remainder_size >= (long)MINSIZE) /* re-split */
+ {
+ remainder = chunk_at_offset(victim, nb);
+ set_head(victim, nb | PREV_INUSE);
+ check_freefill(victim, nb, victim_size);
+ init_malloced_chunk(victim, bytes);
+ link_last_remainder(remainder);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+ init_freed_chunk(remainder, remainder_size, 0);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ clear_last_remainder;
+
+ if (remainder_size >= 0) /* exhaust */
+ {
+ set_inuse_bit_at_offset(victim, victim_size);
+ check_freefill(victim, victim_size, victim_size);
+ init_malloced_chunk(victim, bytes);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* Else place in bin */
+
+ frontlink(victim, victim_size, remainder_index, bck, fwd);
+ }
+
+ /*
+ If there are any possibly nonempty big-enough blocks,
+ search for best fitting chunk by scanning bins in blockwidth units.
+ */
+
+ if ( (block = idx2binblock(idx)) <= binblocks)
+ {
+
+ /* Get to the first marked block */
+
+ if ( (block & binblocks) == 0)
+ {
+ /* force to an even block boundary */
+ idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH;
+ block <<= 1;
+ while ((block & binblocks) == 0)
+ {
+ idx += BINBLOCKWIDTH;
+ block <<= 1;
+ }
+ }
+
+ /* For each possibly nonempty block ... */
+ for (;;)
+ {
+ startidx = idx; /* (track incomplete blocks) */
+ q = bin = bin_at(idx);
+
+ /* For each bin in this block ... */
+ do
+ {
+ /* Find and use first big enough chunk ... */
+
+ for (victim = last(bin); victim != bin; victim = victim->bk)
+ {
+ victim_size = chunksize(victim);
+ remainder_size = victim_size - nb;
+
+ if (remainder_size >= (long)MINSIZE) /* split */
+ {
+ remainder = chunk_at_offset(victim, nb);
+ set_head(victim, nb | PREV_INUSE);
+ check_freefill(victim, nb, victim_size);
+ unlink(victim, bck, fwd);
+ init_malloced_chunk(victim, bytes);
+ link_last_remainder(remainder);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+ init_freed_chunk(remainder, remainder_size, 0);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ else if (remainder_size >= 0) /* take */
+ {
+ check_freefill(victim, victim_size, victim_size);
+ set_inuse_bit_at_offset(victim, victim_size);
+ unlink(victim, bck, fwd);
+ init_malloced_chunk(victim, bytes);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ }
+
+ bin = next_bin(bin);
+
+ } while ((++idx & (BINBLOCKWIDTH - 1)) != 0);
+
+ /* Clear out the block bit. */
+
+ do /* Possibly backtrack to try to clear a partial block */
+ {
+ if ((startidx & (BINBLOCKWIDTH - 1)) == 0)
+ {
+ binblocks &= ~block;
+ break;
+ }
+ --startidx;
+ q = prev_bin(q);
+ } while (first(q) == q);
+
+ /* Get to the next possibly nonempty block */
+
+ if ( (block <<= 1) <= binblocks && (block != 0) )
+ {
+ while ((block & binblocks) == 0)
+ {
+ idx += BINBLOCKWIDTH;
+ block <<= 1;
+ }
+ }
+ else
+ break;
+ }
+ }
+
+
+ /* Try to use top chunk */
+
+ /* Require that there be a remainder, ensuring top always exists */
+ if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
+ {
+
+#if HAVE_MMAP
+ /* If big and would otherwise need to extend, try to use mmap instead */
+ if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
+ (victim = mmap_chunk(nb)) != 0) {
+ init_malloced_chunk(victim, bytes);
+ return chunk2mem(victim);
+ }
+#endif
+
+ /* Try to extend */
+ malloc_extend_top(nb);
+ if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
+ return 0; /* propagate failure */
+ }
+
+ victim = top;
+ set_head(victim, nb | PREV_INUSE);
+ check_freefill(victim, nb, nb + remainder_size);
+ init_malloced_chunk(victim, bytes);
+ top = chunk_at_offset(victim, nb);
+ set_head(top, remainder_size | PREV_INUSE);
+ init_freed_chunk(top, remainder_size, 0);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+
+}
+
+
+
+
+/*
+
+ free() algorithm :
+
+ cases:
+
+ 1. free(0) has no effect.
+
+ 2. If the chunk was allocated via mmap, it is release via munmap().
+
+ 3. If a returned chunk borders the current high end of memory,
+ it is consolidated into the top, and if the total unused
+ topmost memory exceeds the trim threshold, malloc_trim is
+ called.
+
+ 4. Other chunks are consolidated as they arrive, and
+ placed in corresponding bins. (This includes the case of
+ consolidating with the current `last_remainder').
+
+*/
+
+
+#if __STD_C
+void fREe(Void_t* mem)
+#else
+void fREe(mem) Void_t* mem;
+#endif
+{
+ mchunkptr p; /* chunk corresponding to mem */
+ INTERNAL_SIZE_T hd; /* its head field */
+ INTERNAL_SIZE_T sz; /* its size */
+ int idx; /* its bin index */
+ mchunkptr next; /* next contiguous chunk */
+ INTERNAL_SIZE_T nextsz; /* its size */
+ INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+ int islr; /* track whether merging with last_remainder */
+
+ if (mem == 0) /* free(0) has no effect */
+ return;
+
+ p = mem2chunk(mem);
+ check_inuse_chunk(p);
+
+ hd = p->size;
+
+#if HAVE_MMAP
+ if (hd & IS_MMAPPED) /* release mmapped memory. */
+ {
+ munmap_chunk(p);
+ return;
+ }
+#endif
+
+ sz = hd & ~PREV_INUSE;
+ next = chunk_at_offset(p, sz);
+ nextsz = chunksize(next);
+ prevsz = 0; /* avoid compiler warnings */
+
+ if (next == top) /* merge with top */
+ {
+ sz += nextsz;
+
+ if (!(hd & PREV_INUSE)) /* consolidate backward */
+ {
+ prevsz = p->prev_size;
+ p = chunk_at_offset(p, -(long)prevsz);
+ sz += prevsz;
+ unlink(p, bck, fwd);
+ }
+
+ set_head(p, sz | PREV_INUSE);
+ top = p;
+ init_freed_chunk(top, !(hd & PREV_INUSE) ? prevsz : 0, nextsz);
+ if ((unsigned long)(sz) >= trim_threshold)
+ malloc_trim(top_pad);
+ return;
+ }
+
+ set_head(next, nextsz); /* clear inuse bit */
+
+ islr = 0;
+
+ if (!(hd & PREV_INUSE)) /* consolidate backward */
+ {
+ prevsz = p->prev_size;
+ p = chunk_at_offset(p, -(long)prevsz);
+ sz += prevsz;
+
+ if (p->fd == last_remainder) /* keep as last_remainder */
+ islr = 1;
+ else
+ unlink(p, bck, fwd);
+ }
+
+ if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */
+ {
+ sz += nextsz;
+
+ if (!islr && next->fd == last_remainder) /* re-insert last_remainder */
+ {
+ islr = 1;
+ link_last_remainder(p);
+ }
+ else
+ unlink(next, bck, fwd);
+ }
+
+
+ set_head(p, sz | PREV_INUSE);
+ set_foot(p, sz);
+ if (!islr)
+ frontlink(p, sz, idx, bck, fwd);
+ init_freed_chunk(p, !(hd & PREV_INUSE) ? prevsz : 0,
+ !inuse_bit_at_offset(next, nextsz) ? nextsz : 0);
+}
+
+
+
+
+
+/*
+
+ Realloc algorithm:
+
+ Chunks that were obtained via mmap cannot be extended or shrunk
+ unless HAVE_MREMAP is defined, in which case mremap is used.
+ Otherwise, if their reallocation is for additional space, they are
+ copied. If for less, they are just left alone.
+
+ Otherwise, if the reallocation is for additional space, and the
+ chunk can be extended, it is, else a malloc-copy-free sequence is
+ taken. There are several different ways that a chunk could be
+ extended. All are tried:
+
+ * Extending forward into following adjacent free chunk.
+ * Shifting backwards, joining preceding adjacent space
+ * Both shifting backwards and extending forward.
+ * Extending into newly sbrked space
+
+ Unless the #define realloc_ZERO_BYTES_FREES is set, realloc with a
+ size argument of zero (re)allocates a minimum-sized chunk.
+
+ If the reallocation is for less space, and the new request is for
+ a `small' (<512 bytes) size, then the newly unused space is lopped
+ off and freed.
+
+ The old unix realloc convention of allowing the last-free'd chunk
+ to be used as an argument to realloc is no longer supported.
+ I don't know of any programs still relying on this feature,
+ and allowing it would also allow too many other incorrect
+ usages of realloc to be sensible.
+
+
+*/
+
+
+#if __STD_C
+Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
+#else
+Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
+#endif
+{
+ INTERNAL_SIZE_T nb; /* padded request size */
+
+ mchunkptr oldp; /* chunk corresponding to oldmem */
+ INTERNAL_SIZE_T oldsize; /* its size */
+
+ mchunkptr newp; /* chunk to return */
+ INTERNAL_SIZE_T newsize; /* its size */
+ Void_t* newmem; /* corresponding user mem */
+
+ mchunkptr next; /* next contiguous chunk after oldp */
+ INTERNAL_SIZE_T nextsize; /* its size */
+
+ mchunkptr prev; /* previous contiguous chunk before oldp */
+ INTERNAL_SIZE_T prevsize; /* its size */
+
+ mchunkptr remainder; /* holds split off extra space from newp */
+ INTERNAL_SIZE_T remainder_size; /* its size */
+
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+
+#ifdef realloc_ZERO_BYTES_FREES
+ if (bytes == 0) { fREe(oldmem); return 0; }
+#endif
+
+
+ /* realloc of null is supposed to be same as malloc */
+ if (oldmem == 0) return mALLOc(bytes);
+
+ newp = oldp = mem2chunk(oldmem);
+ newsize = oldsize = chunksize(oldp);
+
+
+ nb = request2size(bytes);
+
+ check_inuse_chunk(oldp);
+
+#if HAVE_MMAP
+ if (chunk_is_mmapped(oldp))
+ {
+ if (oldsize - MMAP_EXTRA >= nb) {
+ init_realloced_chunk(oldp, bytes, oldsize);
+ return oldmem; /* do nothing */
+ }
+#if HAVE_MREMAP
+ newp = mremap_chunk(oldp, nb);
+ if (newp) {
+ init_realloced_chunk(newp, bytes, oldsize);
+ return chunk2mem(newp);
+ }
+#endif
+ /* Must alloc, copy, free. */
+ newmem = mALLOc(bytes);
+ if (newmem == 0) return 0; /* propagate failure */
+ malloc_COPY(newmem, oldmem, oldsize - OVERHEAD - MMAP_EXTRA);
+ munmap_chunk(oldp);
+ return newmem;
+ }
+#endif
+
+ if (oldsize < nb)
+ {
+
+ /* Try expanding forward */
+
+ next = chunk_at_offset(oldp, oldsize);
+ if (next == top || !inuse(next))
+ {
+ nextsize = chunksize(next);
+
+ /* Forward into top only if a remainder */
+ if (next == top)
+ {
+ if ((long)(nextsize + newsize) >= (long)(nb + MINSIZE))
+ {
+ check_freefill(next, nb - oldsize, nextsize);
+ newsize += nextsize;
+ top = chunk_at_offset(oldp, nb);
+ set_head(top, (newsize - nb) | PREV_INUSE);
+ init_freed_chunk(top, newsize - nb, 0);
+ set_head_size(oldp, nb);
+ init_realloced_chunk(oldp, bytes, oldsize);
+ return chunk2mem(oldp);
+ }
+ }
+
+ /* Forward into next chunk */
+ else if (((long)(nextsize + newsize) >= (long)nb))
+ {
+ check_freefill(next, nb - oldsize, nextsize);
+ unlink(next, bck, fwd);
+ newsize += nextsize;
+ goto split;
+ }
+ }
+ else
+ {
+ next = 0;
+ nextsize = 0;
+ }
+
+ /* Try shifting backwards. */
+
+ if (!prev_inuse(oldp))
+ {
+ prev = prev_chunk(oldp);
+ prevsize = chunksize(prev);
+
+ /* try forward + backward first to save a later consolidation */
+
+ if (next != 0)
+ {
+ /* into top */
+ if (next == top)
+ {
+ if ((long)(nextsize + prevsize + newsize) >= (long)(nb + MINSIZE))
+ {
+ check_freefill(prev, nb, prevsize);
+ check_freefill(next, nb - (prevsize + newsize), nextsize);
+ unlink(prev, bck, fwd);
+ newp = prev;
+ newsize += prevsize + nextsize;
+ newmem = chunk2mem(newp);
+ malloc_COPY(newmem, oldmem, oldsize - OVERHEAD);
+ top = chunk_at_offset(newp, nb);
+ set_head(top, (newsize - nb) | PREV_INUSE);
+ init_freed_chunk(top, newsize - nb, 0);
+ set_head_size(newp, nb);
+ init_realloced_chunk(newp, bytes, oldsize);
+ return newmem;
+ }
+ }
+
+ /* into next chunk */
+ else if (((long)(nextsize + prevsize + newsize) >= (long)(nb)))
+ {
+ check_freefill(prev, nb, prevsize);
+ check_freefill(next, nb - (prevsize + newsize), nextsize);
+ unlink(next, bck, fwd);
+ unlink(prev, bck, fwd);
+ newp = prev;
+ newsize += nextsize + prevsize;
+ newmem = chunk2mem(newp);
+ malloc_COPY(newmem, oldmem, oldsize - OVERHEAD);
+ goto split;
+ }
+ }
+
+ /* backward only */
+ if (prev != 0 && (long)(prevsize + newsize) >= (long)nb)
+ {
+ check_freefill(prev, nb, prevsize);
+ unlink(prev, bck, fwd);
+ newp = prev;
+ newsize += prevsize;
+ newmem = chunk2mem(newp);
+ malloc_COPY(newmem, oldmem, oldsize - OVERHEAD);
+ goto split;
+ }
+ }
+
+ /* Must allocate */
+
+ newmem = mALLOc (bytes);
+
+ if (newmem == 0) /* propagate failure */
+ return 0;
+
+ /* Avoid copy if newp is next chunk after oldp. */
+ /* (This can only happen when new chunk is sbrk'ed.) */
+
+ if ( (newp = mem2chunk(newmem)) == next_chunk(oldp))
+ {
+ newsize += chunksize(newp);
+ newp = oldp;
+ goto split;
+ }
+
+ /* Otherwise copy, free, and exit */
+ malloc_COPY(newmem, oldmem, oldsize - OVERHEAD);
+ fREe(oldmem);
+ return newmem;
+ }
+
+
+ split: /* split off extra room in old or expanded chunk */
+
+ if (newsize - nb >= MINSIZE) /* split off remainder */
+ {
+ remainder = chunk_at_offset(newp, nb);
+ remainder_size = newsize - nb;
+ set_head_size(newp, nb);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_inuse_bit_at_offset(remainder, remainder_size);
+ init_malloced_chunk(remainder, remainder_size - OVERHEAD);
+ fREe(chunk2mem(remainder)); /* let free() deal with it */
+ }
+ else
+ {
+ set_head_size(newp, newsize);
+ set_inuse_bit_at_offset(newp, newsize);
+ }
+
+ init_realloced_chunk(newp, bytes, oldsize);
+ check_inuse_chunk(newp);
+ return chunk2mem(newp);
+}
+
+
+
+
+/*
+
+ memalign algorithm:
+
+ memalign requests more than enough space from malloc, finds a spot
+ within that chunk that meets the alignment request, and then
+ possibly frees the leading and trailing space.
+
+ The alignment argument must be a power of two. This property is not
+ checked by memalign, so misuse may result in random runtime errors.
+
+ 8-byte alignment is guaranteed by normal malloc calls, so don't
+ bother calling memalign with an argument of 8 or less.
+
+ Overreliance on memalign is a sure way to fragment space.
+
+*/
+
+
+#if __STD_C
+Void_t* mEMALIGn(size_t alignment, size_t bytes)
+#else
+Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
+#endif
+{
+ INTERNAL_SIZE_T nb; /* padded request size */
+ char* m; /* memory returned by malloc call */
+ mchunkptr p; /* corresponding chunk */
+ char* lim; /* alignment point within p */
+ mchunkptr newp; /* chunk to return */
+ INTERNAL_SIZE_T newsize; /* its size */
+ INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */
+ mchunkptr remainder; /* spare room at end to split off */
+ long remainder_size; /* its size */
+
+ /* If need less alignment than we give anyway, just relay to malloc */
+
+ if (alignment <= ALIGNMENT) return mALLOc(bytes);
+
+ /* Otherwise, ensure that it is at least a minimum chunk size */
+
+ if (alignment < MINSIZE) alignment = MINSIZE;
+
+ /* Call malloc with worst case padding to hit alignment. */
+
+ nb = request2size(bytes);
+ m = (char*)mALLOc(nb + alignment + MINSIZE);
+
+ if (m == 0) return 0; /* propagate failure */
+
+ p = mem2chunk(m);
+
+ if ((((unsigned long)(m)) % alignment) == 0) /* aligned */
+ {
+ init_realloced_chunk(p, bytes, chunksize(p));
+ return chunk2mem(p); /* nothing more to do */
+ }
+ else /* misaligned */
+ {
+ /*
+ Find an aligned spot inside chunk.
+ Since we need to give back leading space in a chunk of at
+ least MINSIZE, if the first calculation places us at
+ a spot with less than MINSIZE leader, we can move to the
+ next aligned spot -- we've allocated enough total room so that
+ this is always possible.
+ */
+
+ lim = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) &
+ ~(alignment - 1));
+ if ((lim - (char*)p) < (long)MINSIZE) lim = lim + alignment;
+
+ newp = (mchunkptr)lim;
+ leadsize = lim - (char*)p;
+ newsize = chunksize(p) - leadsize;
+
+#if HAVE_MMAP
+ if(chunk_is_mmapped(p))
+ {
+ newp->prev_size = p->prev_size + leadsize;
+ set_head(newp, newsize|IS_MMAPPED);
+ init_malloced_chunk(newp, bytes);
+ return chunk2mem(newp);
+ }
+#endif
+
+ /* give back leader, use the rest */
+
+ set_head(newp, newsize | PREV_INUSE);
+ set_inuse_bit_at_offset(newp, newsize);
+ set_head_size(p, leadsize);
+ init_freeable_chunk(p);
+ fREe(chunk2mem(p));
+ p = newp;
+
+ assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0);
+ }
+
+ /* Also give back spare room at the end */
+
+ remainder_size = chunksize(p) - nb;
+
+ if (remainder_size >= (long)MINSIZE)
+ {
+ remainder = chunk_at_offset(p, nb);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_head_size(p, nb);
+ init_freeable_chunk(remainder);
+ fREe(chunk2mem(remainder));
+ }
+
+ init_malloced_chunk(p, bytes);
+ check_inuse_chunk(p);
+ return chunk2mem(p);
+
+}
+
+
+
+
+/*
+ valloc just invokes memalign with alignment argument equal
+ to the page size of the system (or as near to this as can
+ be figured out from all the includes/defines above.)
+*/
+
+#if __STD_C
+Void_t* vALLOc(size_t bytes)
+#else
+Void_t* vALLOc(bytes) size_t bytes;
+#endif
+{
+ return mEMALIGn (malloc_getpagesize, bytes);
+}
+
+/*
+ pvalloc just invokes valloc for the nearest pagesize
+ that will accommodate request
+*/
+
+
+#if __STD_C
+Void_t* pvALLOc(size_t bytes)
+#else
+Void_t* pvALLOc(bytes) size_t bytes;
+#endif
+{
+ size_t pagesize = malloc_getpagesize;
+ return mEMALIGn (pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
+}
+
+/*
+
+ calloc calls malloc, then zeroes out the allocated chunk.
+
+*/
+
+#if __STD_C
+Void_t* cALLOc(size_t n, size_t elem_size)
+#else
+Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
+#endif
+{
+ mchunkptr p;
+ INTERNAL_SIZE_T csz;
+
+ INTERNAL_SIZE_T sz = n * elem_size;
+
+ /* check if expand_top called, in which case don't need to clear */
+#if MORECORE_CLEARS
+ mchunkptr oldtop = top;
+ INTERNAL_SIZE_T oldtopsize = chunksize(top);
+#endif
+ Void_t* mem = mALLOc (sz);
+
+ if (mem == 0)
+ return 0;
+ else
+ {
+ p = mem2chunk(mem);
+
+ /* Two optional cases in which clearing not necessary */
+
+
+#if HAVE_MMAP
+ if (chunk_is_mmapped(p)) return mem;
+#endif
+
+ csz = chunksize(p);
+
+#if MORECORE_CLEARS
+ if (p == oldtop && csz > oldtopsize)
+ {
+ /* clear only the bytes from non-freshly-sbrked memory */
+ csz = oldtopsize;
+ }
+#endif
+
+ malloc_ZERO(mem, csz - OVERHEAD);
+ /* reinstate moat fill in pad region */
+ init_realloced_chunk(p, sz, chunksize(p));
+ return mem;
+ }
+}
+
+
+
+/*
+
+ Malloc_trim gives memory back to the system (via negative
+ arguments to sbrk) if there is unused memory at the `high' end of
+ the malloc pool. You can call this after freeing large blocks of
+ memory to potentially reduce the system-level memory requirements
+ of a program. However, it cannot guarantee to reduce memory. Under
+ some allocation patterns, some large free blocks of memory will be
+ locked between two used chunks, so they cannot be given back to
+ the system.
+
+ The `pad' argument to malloc_trim represents the amount of free
+ trailing space to leave untrimmed. If this argument is zero,
+ only the minimum amount of memory to maintain internal data
+ structures will be left (one page or less). Non-zero arguments
+ can be supplied to maintain enough trailing space to service
+ future expected allocations without having to re-obtain memory
+ from the system.
+
+ Malloc_trim returns 1 if it actually released any memory, else 0.
+
+*/
+
+#if __STD_C
+int dlmalloc_trim(size_t pad)
+#else
+int malloc_trim(pad) size_t pad;
+#endif
+{
+ long top_size; /* Amount of top-most memory */
+ long extra; /* Amount to release */
+ char* current_lim; /* address returned by pre-check sbrk call */
+ char* new_lim; /* address returned by negative sbrk call */
+
+ unsigned long pagesz = malloc_getpagesize;
+
+ top_size = chunksize(top);
+ extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
+
+ if (extra < (long)pagesz) /* Not enough memory to release */
+ return 0;
+
+ else
+ {
+#ifdef OTHER_SBRKS
+ /* Test to make sure no one else called sbrk */
+ current_lim = (char*)(MORECORE (0));
+ if (current_lim != (char*)(top) + top_size)
+ return 0; /* Apparently we don't own memory; must fail */
+
+ else
+#endif
+ {
+ new_lim = (char*)(MORECORE (-extra));
+
+ if (new_lim == (char*)(MORECORE_FAILURE)) /* sbrk failed? */
+ {
+ /* Try to figure out what we have */
+ current_lim = (char*)(MORECORE (0));
+ top_size = current_lim - (char*)top;
+ if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */
+ {
+ sbrked_mem = current_lim - sbrk_base;
+ set_head(top, top_size | PREV_INUSE);
+ init_freed_chunk(top, top_size, 0);
+ }
+ check_chunk(top);
+ return 0;
+ }
+
+ else
+ {
+ /* Success. Adjust top accordingly. */
+ set_head(top, (top_size - extra) | PREV_INUSE);
+ sbrked_mem -= extra;
+ init_freed_chunk(top, top_size - extra, 0);
+ check_chunk(top);
+ return 1;
+ }
+ }
+ }
+}
+
+
+
+/*
+ malloc_usable_size:
+
+ This routine tells you how many bytes you can actually use in an
+ allocated chunk, which may be more than you requested (although
+ often not). You can use this many bytes without worrying about
+ overwriting other allocated objects. Not a particularly great
+ programming practice, but still sometimes useful.
+
+*/
+
+#if __STD_C
+size_t dlmalloc_usable_size(Void_t* mem)
+#else
+size_t malloc_usable_size(mem) Void_t* mem;
+#endif
+{
+ mchunkptr p;
+ if (mem == 0)
+ return 0;
+ else
+ {
+ p = mem2chunk(mem);
+ check_inuse_chunk(p);
+ maximize_chunk(p);
+ if(!chunk_is_mmapped(p))
+ {
+ if (!inuse(p)) return 0;
+ return chunksize(p) - OVERHEAD;
+ }
+ return chunksize(p) - OVERHEAD - MMAP_EXTRA;
+ }
+}
+
+
+
+
+/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
+
+static void malloc_update_mallinfo(void)
+{
+ int i;
+ mbinptr b;
+ mchunkptr p;
+#if DEBUG
+ mchunkptr q;
+#endif
+
+ INTERNAL_SIZE_T avail = chunksize(top);
+ int navail = avail >= MINSIZE ? 1 : 0;
+ check_freefill(top, avail, avail);
+
+#if DEBUG
+ if (lowest_chunk)
+ for (p = lowest_chunk;
+ p < top && inuse(p) && chunksize(p) >= MINSIZE;
+ p = next_chunk(p))
+ check_inuse_chunk(p);
+#endif
+
+ for (i = 1; i < NAV; ++i)
+ {
+ b = bin_at(i);
+ for (p = last(b); p != b; p = p->bk)
+ {
+#if DEBUG
+ check_free_chunk(p);
+ check_freefill(p, chunksize(p), chunksize(p));
+ for (q = next_chunk(p);
+ q < top && inuse(q) && chunksize(q) >= MINSIZE;
+ q = next_chunk(q))
+ check_inuse_chunk(q);
+#endif
+ avail += chunksize(p);
+ navail++;
+ }
+ }
+
+ current_mallinfo.ordblks = navail;
+ current_mallinfo.uordblks = sbrked_mem - avail;
+ current_mallinfo.fordblks = avail;
+ current_mallinfo.hblks = n_mmaps;
+ current_mallinfo.hblkhd = mmapped_mem;
+ current_mallinfo.keepcost = chunksize(top);
+
+}
+
+
+
+/*
+
+ malloc_stats:
+
+ Prints on stderr the amount of space obtain from the system (both
+ via sbrk and mmap), the maximum amount (which may be more than
+ current if malloc_trim and/or munmap got called), the maximum
+ number of simultaneous mmap regions used, and the current number
+ of bytes allocated via malloc (or realloc, etc) but not yet
+ freed. (Note that this is the number of bytes allocated, not the
+ number requested. It will be larger than the number requested
+ because of alignment and bookkeeping overhead.)
+
+*/
+
+void dlmalloc_stats(void)
+{
+ malloc_update_mallinfo();
+ fprintf(stderr, "max system bytes = %10u\n",
+ (unsigned int)(max_total_mem));
+ fprintf(stderr, "system bytes = %10u\n",
+ (unsigned int)(sbrked_mem + mmapped_mem));
+ fprintf(stderr, "in use bytes = %10u\n",
+ (unsigned int)(current_mallinfo.uordblks + mmapped_mem));
+#if HAVE_MMAP
+ fprintf(stderr, "max mmap regions = %10u\n",
+ (unsigned int)max_n_mmaps);
+#endif
+}
+
+/*
+ mallinfo returns a copy of updated current mallinfo.
+*/
+
+struct mallinfo mALLINFo(void)
+{
+ malloc_update_mallinfo();
+ return current_mallinfo;
+}
+
+
+
+
+/*
+ mallopt:
+
+ mallopt is the general SVID/XPG interface to tunable parameters.
+ The format is to provide a (parameter-number, parameter-value) pair.
+ mallopt then sets the corresponding parameter to the argument
+ value if it can (i.e., so long as the value is meaningful),
+ and returns 1 if successful else 0.
+
+ See descriptions of tunable parameters above.
+
+*/
+
+#if __STD_C
+int mALLOPt(int param_number, int value)
+#else
+int mALLOPt(param_number, value) int param_number; int value;
+#endif
+{
+ switch(param_number)
+ {
+ case M_TRIM_THRESHOLD:
+ trim_threshold = value; return 1;
+ case M_TOP_PAD:
+ top_pad = value; return 1;
+ case M_MMAP_THRESHOLD:
+ mmap_threshold = value; return 1;
+ case M_MMAP_MAX:
+#if HAVE_MMAP
+ n_mmaps_max = value; return 1;
+#else
+ if (value != 0) return 0; else n_mmaps_max = value; return 1;
+#endif
+ case M_SCANHEAP:
+#ifdef DEBUG2
+ scanheap = value;
+#endif
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/*
+
+History:
+
+ V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
+ * Added pvalloc, as recommended by H.J. Liu
+ * Added 64bit pointer support mainly from Wolfram Gloger
+ * Added anonymously donated WIN32 sbrk emulation
+ * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
+ * malloc_extend_top: fix mask error that caused wastage after
+ foreign sbrks
+ * Add linux mremap support code from HJ Liu
+
+ V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
+ * Integrated most documentation with the code.
+ * Add support for mmap, with help from
+ Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+ * Use last_remainder in more cases.
+ * Pack bins using idea from colin@nyx10.cs.du.edu
+ * Use ordered bins instead of best-fit threshhold
+ * Eliminate block-local decls to simplify tracing and debugging.
+ * Support another case of realloc via move into top
+ * Fix error occuring when initial sbrk_base not word-aligned.
+ * Rely on page size for units instead of SBRK_UNIT to
+ avoid surprises about sbrk alignment conventions.
+ * Add mallinfo, mallopt. Thanks to Raymond Nijssen
+ (raymond@es.ele.tue.nl) for the suggestion.
+ * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
+ * More precautions for cases where other routines call sbrk,
+ courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+ * Added macros etc., allowing use in linux libc from
+ H.J. Lu (hjl@gnu.ai.mit.edu)
+ * Inverted this history list
+
+ V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
+ * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
+ * Removed all preallocation code since under current scheme
+ the work required to undo bad preallocations exceeds
+ the work saved in good cases for most test programs.
+ * No longer use return list or unconsolidated bins since
+ no scheme using them consistently outperforms those that don't
+ given above changes.
+ * Use best fit for very large chunks to prevent some worst-cases.
+ * Added some support for debugging
+
+ V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
+ * Removed footers when chunks are in use. Thanks to
+ Paul Wilson (wilson@cs.texas.edu) for the suggestion.
+
+ V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
+ * Added malloc_trim, with help from Wolfram Gloger
+ (wmglo@Dent.MED.Uni-Muenchen.DE).
+
+ V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
+
+ V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
+ * realloc: try to expand in both directions
+ * malloc: swap order of clean-bin strategy;
+ * realloc: only conditionally expand backwards
+ * Try not to scavenge used bins
+ * Use bin counts as a guide to preallocation
+ * Occasionally bin return list chunks in first scan
+ * Add a few optimizations from colin@nyx10.cs.du.edu
+
+ V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
+ * faster bin computation & slightly different binning
+ * merged all consolidations to one part of malloc proper
+ (eliminating old malloc_find_space & malloc_clean_bin)
+ * Scan 2 returns chunks (not just 1)
+ * Propagate failure in realloc if malloc returns 0
+ * Add stuff to allow compilation on non-ANSI compilers
+ from kpv@research.att.com
+
+ V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
+ * removed potential for odd address access in prev_chunk
+ * removed dependency on getpagesize.h
+ * misc cosmetics and a bit more internal documentation
+ * anticosmetics: mangled names in macros to evade debugger strangeness
+ * tested on sparc, hp-700, dec-mips, rs6000
+ with gcc & native cc (hp, dec only) allowing
+ Detlefs & Zorn comparison study (in SIGPLAN Notices.)
+
+ Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
+ * Based loosely on libg++-1.2X malloc. (It retains some of the overall
+ structure of old version, but most details differ.)
+
+*/
diff --git a/winsup/cygwin/dlmalloc.h b/winsup/cygwin/dlmalloc.h
new file mode 100644
index 000000000..d7bd86927
--- /dev/null
+++ b/winsup/cygwin/dlmalloc.h
@@ -0,0 +1,93 @@
+
+/*
+ * Header file for BBCized version of Doug Lea's malloc.c, automatically
+ * generated by
+ * /source/prod/libbbc/compat/dlmalloc/cvt
+ * from
+ * /source/prod/libbbc/compat/dlmalloc/malloc.c
+ *
+ * bbclabel: autogenerated
+ */
+#define _INCLUDE_MALLOC_H_ 1
+void malloc_outofmem(void (*)(void));
+
+
+struct mallinfo {
+ int arena; /* total space allocated from system */
+ int ordblks; /* number of non-inuse chunks */
+ int smblks; /* unused -- always zero */
+ int hblks; /* number of mmapped regions */
+ int hblkhd; /* total space in mmapped regions */
+ int usmblks; /* unused -- always zero */
+ int fsmblks; /* unused -- always zero */
+ int uordblks; /* total allocated space */
+ int fordblks; /* total non-inuse space */
+ int keepcost; /* top-most, releasable (via malloc_trim) space */
+};
+
+
+#define M_MXFAST 1 /* UNUSED in this malloc */
+#define M_NLBLKS 2 /* UNUSED in this malloc */
+#define M_GRAIN 3 /* UNUSED in this malloc */
+#define M_KEEP 4 /* UNUSED in this malloc */
+
+
+#define M_TRIM_THRESHOLD -1
+#define M_TOP_PAD -2
+#define M_MMAP_THRESHOLD -3
+#define M_MMAP_MAX -4
+#define M_SCANHEAP -5
+#define M_FILL
+
+#ifdef MALLOC_DEBUG
+
+#define dlmalloc(size) malloc_dbg(size, __FILE__, __LINE__)
+#define dlfree(p) free_dbg(p, __FILE__, __LINE__)
+#define dlrealloc(p, size) realloc_dbg(p, size, __FILE__, __LINE__)
+#define dlcalloc(n, size) calloc_dbg(n, size, __FILE__, __LINE__)
+#define dlmemalign(align, size) memalign_dbg(align, size, __FILE__, __LINE__)
+#define dlvalloc(size) valloc_dbg(size, __FILE__, __LINE__)
+#define dlpvalloc(size) pvalloc_dbg(size, __FILE__, __LINE__)
+#define dlmalloc_trim(pad) malloc_trim_dbg(pad, __FILE__, __LINE__)
+#define dlmalloc_usable_size(p) malloc_usable_size_dbg(p, __FILE__, __LINE__)
+#define dlmalloc_stats() malloc_stats_dbg(__FILE__, __LINE__)
+#define dlmallopt(flag, val) mallopt_dbg(flag, val, __FILE__, __LINE__)
+#define dlmallinfo() mallinfo_dbg(__FILE__, __LINE__)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void* malloc_dbg(size_t, const char *, int);
+void free_dbg(void*, const char *, int);
+void* realloc_dbg(void*, size_t, const char *, int);
+void* calloc_dbg(size_t, size_t, const char *, int);
+void* memalign_dbg(size_t, size_t, const char *, int);
+void* valloc_dbg(size_t, const char *, int);
+void* pvalloc_dbg(size_t, const char *, int);
+int malloc_trim_dbg(size_t, const char *, int);
+size_t malloc_usable_size_dbg(void*, const char *, int);
+void malloc_stats_dbg(const char *, int);
+int mallopt_dbg(int, int, const char *, int);
+struct mallinfo mallinfo_dbg(const char *, int);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MALLOC_DEBUG */
+
+#ifndef MALLOC_DEBUG
+
+void* malloc(size_t);
+void free(void*);
+void* realloc(void*, size_t);
+void* calloc(size_t, size_t);
+void* memalign(size_t, size_t);
+void* valloc(size_t);
+void* pvalloc(size_t);
+int malloc_trim(size_t);
+size_t malloc_usable_size(void*);
+void malloc_stats(void);
+int mallopt(int, int);
+struct mallinfo mallinfo(void);
+#endif /* !MALLOC_DEBUG */
diff --git a/winsup/cygwin/dtable.sgml b/winsup/cygwin/dtable.sgml
new file mode 100644
index 000000000..73d8b78cc
--- /dev/null
+++ b/winsup/cygwin/dtable.sgml
@@ -0,0 +1,20 @@
+
+<sect1 id="func-cygwin-attach-handle-to-fd">
+<title>cygwin_attach_handle_to_fd</title>
+
+<funcsynopsis><funcprototype>
+<funcdef>extern "C" int
+<function>cygwin_attach_handle_to_fd</function></funcdef>
+<paramdef>char *<parameter>name</parameter></paramdef>
+<paramdef>int <parameter>fd</parameter></paramdef>
+<paramdef>HANDLE <parameter>handle</parameter></paramdef>
+<paramdef>int <parameter>bin</parameter></paramdef>
+<paramdef>int <parameter>access</parameter></paramdef>
+</funcprototype></funcsynopsis>
+
+<para>This function can be used to turn a Win32 "handle" into a
+posix-style file handle. <parameter>fd</parameter> may be -1 to
+make cygwin allocate a handle; the actual handle is returned
+in all cases.</para>
+
+</sect1>
diff --git a/winsup/cygwin/errno.cc b/winsup/cygwin/errno.cc
index 589410a9a..2a5f711bd 100644
--- a/winsup/cygwin/errno.cc
+++ b/winsup/cygwin/errno.cc
@@ -1,7 +1,7 @@
/* errno.cc: errno-related functions
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -59,21 +59,17 @@ static const struct
X (BUSY, EBUSY),
X (BUS_RESET, EIO),
X (CALL_NOT_IMPLEMENTED, ENOSYS),
- X (CANCELLED, EINTR),
X (CANNOT_MAKE, EPERM),
X (CHILD_NOT_COMPLETE, EBUSY),
X (COMMITMENT_LIMIT, EAGAIN),
- X (CONNECTION_REFUSED, ECONNREFUSED),
X (CRC, EIO),
X (DEVICE_DOOR_OPEN, EIO),
X (DEVICE_IN_USE, EAGAIN),
X (DEVICE_REQUIRES_CLEANING, EIO),
- X (DEV_NOT_EXIST, ENOENT),
X (DIRECTORY, ENOTDIR),
X (DIR_NOT_EMPTY, ENOTEMPTY),
X (DISK_CORRUPT, EIO),
X (DISK_FULL, ENOSPC),
- X (DS_GENERIC_ERROR, EIO),
X (DUP_NAME, ENOTUNIQ),
X (EAS_DIDNT_FIT, ENOSPC),
X (EAS_NOT_SUPPORTED, ENOTSUP),
@@ -119,7 +115,6 @@ static const struct
X (NONPAGED_SYSTEM_RESOURCES, EAGAIN),
X (NOT_CONNECTED, ENOLINK),
X (NOT_ENOUGH_MEMORY, ENOMEM),
- X (NOT_ENOUGH_QUOTA, EIO),
X (NOT_OWNER, EPERM),
X (NOT_READY, ENOMEDIUM),
X (NOT_SAME_DEVICE, EXDEV),
@@ -151,7 +146,6 @@ static const struct
X (REM_NOT_LIST, ENONET),
X (SECTOR_NOT_FOUND, EINVAL),
X (SEEK, EINVAL),
- X (SERVICE_REQUEST_TIMEOUT, EBUSY),
X (SETMARK_DETECTED, EIO),
X (SHARING_BUFFER_EXCEEDED, ENOLCK),
X (SHARING_VIOLATION, EBUSY),
@@ -159,10 +153,8 @@ static const struct
X (SIGNAL_REFUSED, EIO),
X (SXS_CANT_GEN_ACTCTX, ELIBBAD),
X (THREAD_1_INACTIVE, EINVAL),
- X (TIMEOUT, EBUSY),
X (TOO_MANY_LINKS, EMLINK),
X (TOO_MANY_OPEN_FILES, EMFILE),
- X (UNEXP_NET_ERR, EIO),
X (WAIT_NO_CHILDREN, ECHILD),
X (WORKING_SET_QUOTA, EAGAIN),
X (WRITE_PROTECT, EROFS),
@@ -363,6 +355,13 @@ seterrno_from_nt_status (const char *file, int line, NTSTATUS status)
errno = _impure_ptr->_errno = geterrno_from_win_error (code, EACCES);
}
+/* seterrno: Set `errno' based on GetLastError (). */
+void __reg2
+seterrno (const char *file, int line)
+{
+ seterrno_from_win_error (file, line, GetLastError ());
+}
+
static char *
strerror_worker (int errnum)
{
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc
index fce161192..fd0c46864 100644
--- a/winsup/cygwin/external.cc
+++ b/winsup/cygwin/external.cc
@@ -382,13 +382,13 @@ cygwin_internal (cygwin_getinfo_types t, ...)
case CW_GET_UID_FROM_SID:
{
cygpsid psid = va_arg (arg, PSID);
- res = psid.get_uid (NULL);
+ res = psid.get_id (false, NULL);
}
break;
case CW_GET_GID_FROM_SID:
{
cygpsid psid = va_arg (arg, PSID);
- res = psid.get_gid (NULL);
+ res = psid.get_id (true, NULL);
}
break;
case CW_GET_BINMODE:
@@ -556,123 +556,22 @@ cygwin_internal (cygwin_getinfo_types t, ...)
}
break;
- case CW_SETENT:
- {
- int group = va_arg (arg, int);
- int enums = va_arg (arg, int);
- PCWSTR enum_tdoms = va_arg (arg, PCWSTR);
- if (group)
- res = (uintptr_t) setgrent_filtered (enums, enum_tdoms);
- else
- res = (uintptr_t) setpwent_filtered (enums, enum_tdoms);
- }
- break;
-
- case CW_GETENT:
- {
- int group = va_arg (arg, int);
- void *obj = va_arg (arg, void *);
- if (obj)
- {
- if (group)
- res = (uintptr_t) getgrent_filtered (obj);
- else
- res = (uintptr_t) getpwent_filtered (obj);
- }
- }
- break;
-
- case CW_ENDENT:
- {
- int group = va_arg (arg, int);
- void *obj = va_arg (arg, void *);
- if (obj)
- {
- if (group)
- endgrent_filtered (obj);
- else
- endpwent_filtered (obj);
- res = 0;
- }
- }
- break;
-
- case CW_GETNSSSEP:
- res = (uintptr_t) cygheap->pg.nss_separator ();
- break;
-
case CW_GETPWSID:
- {
- int db_only = va_arg (arg, int);
- PSID psid = va_arg (arg, PSID);
- cygpsid sid (psid);
- res = (uintptr_t) (db_only ? internal_getpwsid_from_db (sid)
- : internal_getpwsid (sid));
- }
- break;
+ {
+ va_arg (arg, int);
+ PSID psid = va_arg (arg, PSID);
+ cygpsid sid (psid);
+ res = (uintptr_t) internal_getpwsid (sid);
+ }
+ break;
case CW_GETGRSID:
- {
- int db_only = va_arg (arg, int);
- PSID psid = va_arg (arg, PSID);
- cygpsid sid (psid);
- res = (uintptr_t) (db_only ? internal_getgrsid_from_db (sid)
- : internal_getgrsid (sid));
- }
- break;
-
- case CW_CYGNAME_FROM_WINNAME:
- {
- /* This functionality has been added mainly for sshd. Sshd
- calls getpwnam() with the username of the non-privileged
- user used for privilege separation. This is usually a
- fixed string "sshd". However, when using usernames from
- the Windows DBs, it's no safe bet anymore if the username
- is "sshd", it could also be "DOMAIN+sshd". So what we do
- here is this:
-
- Sshd calls cygwin_internal (CW_CYGNAME_FROM_WINNAME,
- "sshd",
- username_buffer,
- sizeof username_buffer);
-
- If this call succeeds, sshd expects the correct Cygwin
- username of the unprivileged sshd account in username_buffer.
-
- The below code checks for a Windows username matching the
- incoming username, and then fetches the Cygwin username with
- the matching SID. This is our username used for privsep then.
-
- Of course, other applications with similar needs can use the
- same method. */
- const char *winname = va_arg (arg, const char *);
- char *buffer = va_arg (arg, char *);
- size_t buflen = va_arg (arg, size_t);
-
- if (!winname || !buffer || !buflen)
- break;
-
- WCHAR name[UNLEN + 1];
- sys_mbstowcs (name, sizeof name, winname);
-
- cygsid sid;
- DWORD slen = SECURITY_MAX_SID_SIZE;
- WCHAR dom[DNLEN + 1];
- DWORD dlen = DNLEN + 1;
- SID_NAME_USE acc_type;
-
- if (!LookupAccountNameW (NULL, name, sid, &slen, dom, &dlen,
- &acc_type))
- break;
-
- struct passwd *pw = internal_getpwsid (sid);
- if (!pw)
- break;
-
- buffer[0] = '\0';
- strncat (buffer, pw->pw_name, buflen - 1);
- res = 0;
- }
+ {
+ va_arg (arg, int);
+ PSID psid = va_arg (arg, PSID);
+ cygpsid sid (psid);
+ res = (uintptr_t) internal_getgrsid (sid);
+ }
break;
case CW_FIXED_ATEXIT:
diff --git a/winsup/cygwin/external.sgml b/winsup/cygwin/external.sgml
new file mode 100644
index 000000000..bbfdd0fb8
--- /dev/null
+++ b/winsup/cygwin/external.sgml
@@ -0,0 +1,18 @@
+
+<sect1 id="func-cygwin-internal">
+<title>cygwin_internal</title>
+
+<funcsynopsis><funcprototype>
+<funcdef>extern "C" DWORD
+<function>cygwin_internal</function></funcdef>
+<paramdef>cygwin_getinfo_types <parameter>t</parameter></paramdef>
+<paramdef><parameter>...</parameter></paramdef>
+</funcprototype></funcsynopsis>
+
+<para>This function gives you access to various internal data and functions.
+It takes two arguments. The first argument is a type from the 'cygwin_getinfo_types'
+enum. The second is an optional pointer.</para>
+<para>Stay away unless you know what you're doing.</para>
+
+</sect1>
+
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 8444d4abc..c64fc33b1 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1737,6 +1737,9 @@ fhandler_base::facl (int cmd, int nentries, aclent_t *aclbufp)
aclbufp[2].a_type = OTHER_OBJ;
aclbufp[2].a_id = ILLEGAL_GID;
aclbufp[2].a_perm = S_IROTH | S_IWOTH;
+ aclbufp[3].a_type = CLASS_OBJ;
+ aclbufp[3].a_id = ILLEGAL_GID;
+ aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
res = MIN_ACL_ENTRIES;
}
break;
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index ba615c26f..22709ffdf 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -10,8 +10,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <winioctl.h>
-#include <lm.h>
#include <stdlib.h>
#include <sys/acl.h>
#include <sys/statvfs.h>
@@ -25,8 +23,10 @@ details. */
#include "pinfo.h"
#include "ntdll.h"
#include "tls_pbuf.h"
+#include "pwdgrp.h"
+#include <winioctl.h>
+#include <lm.h>
#include "devices.h"
-#include "ldap.h"
#define _COMPILING_NEWLIB
#include <dirent.h>
@@ -323,9 +323,6 @@ int __reg2
fhandler_base::fstat_by_nfs_ea (struct stat *buf)
{
fattr3 *nfs_attr = pc.nfsattr ();
- PWCHAR domain;
- cyg_ldap cldap;
- bool ldap_open = false;
if (get_io_handle ())
{
@@ -343,36 +340,14 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
buf->st_mode = (nfs_attr->mode & 0xfff)
| nfs_type_mapping[nfs_attr->type & 7];
buf->st_nlink = nfs_attr->nlink;
- /* Try to map UNIX uid/gid to Cygwin uid/gid. If there's no mapping in
- the cache, try to fetch it from the configured RFC 2307 domain (see
- last comment in cygheap_domain_info::init() for more information) and
- add it to the mapping cache. */
- buf->st_uid = cygheap->ugid_cache.get_uid (nfs_attr->uid);
- buf->st_gid = cygheap->ugid_cache.get_gid (nfs_attr->gid);
- if (buf->st_uid == ILLEGAL_UID)
- {
- uid_t map_uid = ILLEGAL_UID;
-
- domain = cygheap->dom.get_rfc2307_domain ();
- if ((ldap_open = (cldap.open (domain) == NO_ERROR)))
- map_uid = cldap.remap_uid (nfs_attr->uid);
- if (map_uid == ILLEGAL_UID)
- map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid);
- cygheap->ugid_cache.add_uid (nfs_attr->uid, map_uid);
- buf->st_uid = map_uid;
- }
- if (buf->st_gid == ILLEGAL_GID)
- {
- gid_t map_gid = ILLEGAL_GID;
-
- domain = cygheap->dom.get_rfc2307_domain ();
- if ((ldap_open || cldap.open (domain) == NO_ERROR))
- map_gid = cldap.remap_gid (nfs_attr->gid);
- if (map_gid == ILLEGAL_GID)
- map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid);
- cygheap->ugid_cache.add_gid (nfs_attr->gid, map_gid);
- buf->st_gid = map_gid;
- }
+ /* FIXME: How to convert UNIX uid/gid to Windows SIDs? */
+#if 0
+ buf->st_uid = nfs_attr->uid;
+ buf->st_gid = nfs_attr->gid;
+#else
+ buf->st_uid = myself->uid;
+ buf->st_gid = myself->gid;
+#endif
buf->st_rdev = makedev (nfs_attr->rdev.specdata1,
nfs_attr->rdev.specdata2);
buf->st_size = nfs_attr->size;
@@ -534,7 +509,8 @@ fhandler_base::fstat_fs (struct stat *buf)
}
int __reg3
-fhandler_base::fstat_helper (struct stat *buf, DWORD nNumberOfLinks)
+fhandler_base::fstat_helper (struct stat *buf,
+ DWORD nNumberOfLinks)
{
IO_STATUS_BLOCK st;
FILE_COMPRESSION_INFORMATION fci;
@@ -822,7 +798,7 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
}
else
debug_printf ("%y = NtQueryVolumeInformationFile"
- "(%S, FileFsFullSizeInformation)",
+ "(%S, FileFsFullSizeInformation)",
status, pc.get_nt_native_path ());
out:
if (opened)
@@ -1045,6 +1021,9 @@ cant_access_acl:
aclbufp[2].a_type = OTHER_OBJ;
aclbufp[2].a_id = ILLEGAL_GID;
aclbufp[2].a_perm = st.st_mode & S_IRWXO;
+ aclbufp[3].a_type = CLASS_OBJ;
+ aclbufp[3].a_id = ILLEGAL_GID;
+ aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
res = MIN_ACL_ENTRIES;
}
}
@@ -2046,8 +2025,7 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
fname->Length = 0;
return geterrno_from_win_error (w32_err);
}
- if (de->d_ino == 2) /* Inode number for virtual dirs. */
- de->d_type = DT_DIR;
+
attr = 0;
dir->__flags &= ~dirent_set_d_ino;
}
diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc
index 0fd2e569c..34acf4ed1 100644
--- a/winsup/cygwin/fhandler_proc.cc
+++ b/winsup/cygwin/fhandler_proc.cc
@@ -254,9 +254,7 @@ fhandler_proc::readdir (DIR *dir, dirent *de)
int res;
if (dir->__d_position < PROC_LINK_COUNT)
{
- strcpy (de->d_name, proc_tab[dir->__d_position].name);
- de->d_type = virt_ftype_to_dtype (proc_tab[dir->__d_position].type);
- dir->__d_position++;
+ strcpy (de->d_name, proc_tab[dir->__d_position++].name);
dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
res = 0;
}
@@ -269,7 +267,6 @@ fhandler_proc::readdir (DIR *dir, dirent *de)
if (found++ == dir->__d_position - PROC_LINK_COUNT)
{
__small_sprintf (de->d_name, "%d", pids[i]->pid);
- de->d_type = DT_DIR;
dir->__d_position++;
res = 0;
break;
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index e2de05b3c..01de47436 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -24,6 +24,7 @@ details. */
#include "cygheap.h"
#include "ntdll.h"
#include "cygtls.h"
+#include "pwdgrp.h"
#include "mount.h"
#include "tls_pbuf.h"
#include <sys/sysmacros.h>
@@ -230,14 +231,9 @@ fhandler_process::readdir (DIR *dir, dirent *de)
{
int *p = (int *) filebuf;
__small_sprintf (de->d_name, "%d", p[dir->__d_position++ - 2]);
- de->d_type = DT_LNK;
}
else
- {
- strcpy (de->d_name, process_tab[dir->__d_position].name);
- de->d_type = virt_ftype_to_dtype (process_tab[dir->__d_position].type);
- dir->__d_position++;
- }
+ strcpy (de->d_name, process_tab[dir->__d_position++].name);
dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
res = 0;
out:
diff --git a/winsup/cygwin/fhandler_procnet.cc b/winsup/cygwin/fhandler_procnet.cc
index 1961fdda3..0ba64aeea 100644
--- a/winsup/cygwin/fhandler_procnet.cc
+++ b/winsup/cygwin/fhandler_procnet.cc
@@ -1,6 +1,6 @@
/* fhandler_procnet.cc: fhandler for /proc/net virtual filesystem
- Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -115,9 +115,7 @@ fhandler_procnet::readdir (DIR *dir, dirent *de)
if (procnet_tab[dir->__d_position].type == virt_file
&& !get_adapters_addresses (NULL, AF_INET6))
goto out;
- strcpy (de->d_name, procnet_tab[dir->__d_position].name);
- de->d_type = virt_ftype_to_dtype (procnet_tab[dir->__d_position].type);
- dir->__d_position++;
+ strcpy (de->d_name, procnet_tab[dir->__d_position++].name);
dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
res = 0;
out:
diff --git a/winsup/cygwin/fhandler_procsys.cc b/winsup/cygwin/fhandler_procsys.cc
index 1e937c89d..759712f04 100644
--- a/winsup/cygwin/fhandler_procsys.cc
+++ b/winsup/cygwin/fhandler_procsys.cc
@@ -1,6 +1,6 @@
/* fhandler_procsys.cc: fhandler for native NT namespace.
- Copyright 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ Copyright 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -177,28 +177,30 @@ fhandler_procsys::exists (struct stat *buf)
/* Don't call NtQueryInformationFile unless we know it's a safe type.
The call is known to crash machines, if the underlying driver is
badly written. */
- if (NT_SUCCESS (status))
+ if (!NT_SUCCESS (status))
+ {
+ NtClose (h);
+ return file_type;
+ }
+ if (ffdi.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
+ file_type = virt_blk;
+ else if (ffdi.DeviceType == FILE_DEVICE_NAMED_PIPE)
+ file_type = internal ? virt_blk : virt_pipe;
+ else if (ffdi.DeviceType == FILE_DEVICE_DISK
+ || ffdi.DeviceType == FILE_DEVICE_CD_ROM
+ || ffdi.DeviceType == FILE_DEVICE_DFS
+ || ffdi.DeviceType == FILE_DEVICE_VIRTUAL_DISK)
{
- if (ffdi.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
+ /* Check for file attributes. If we get them, we peeked
+ into a real FS through /proc/sys. */
+ status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
+ FileBasicInformation);
+ debug_printf ("NtQueryInformationFile: %y", status);
+ if (!NT_SUCCESS (status))
file_type = virt_blk;
- else if (ffdi.DeviceType == FILE_DEVICE_NAMED_PIPE)
- file_type = internal ? virt_blk : virt_pipe;
- else if (ffdi.DeviceType == FILE_DEVICE_DISK
- || ffdi.DeviceType == FILE_DEVICE_CD_ROM
- || ffdi.DeviceType == FILE_DEVICE_DFS
- || ffdi.DeviceType == FILE_DEVICE_VIRTUAL_DISK)
- {
- /* Check for file attributes. If we get them, we peeked
- into a real FS through /proc/sys. */
- status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
- FileBasicInformation);
- debug_printf ("NtQueryInformationFile: %y", status);
- if (!NT_SUCCESS (status))
- file_type = virt_blk;
- else
- file_type = (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- ? virt_fsdir : virt_fsfile;
- }
+ else
+ file_type = (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ ? virt_fsdir : virt_fsfile;
}
NtClose (h);
}
@@ -358,17 +360,7 @@ fhandler_procsys::readdir (DIR *dir, dirent *de)
sys_wcstombs (de->d_name, NAME_MAX + 1, f.dbi.ObjectName.Buffer,
f.dbi.ObjectName.Length / sizeof (WCHAR));
de->d_ino = hash_path_name (get_ino (), de->d_name);
- if (RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natdir,
- FALSE))
- de->d_type = DT_DIR;
- else if (RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natsyml,
- FALSE))
- de->d_type = DT_LNK;
- else if (!RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natdev,
- FALSE))
- de->d_type = DT_CHR;
- else /* Can't nail down "Device" objects without further testing. */
- de->d_type = DT_UNKNOWN;
+ de->d_type = 0;
res = 0;
}
}
diff --git a/winsup/cygwin/fhandler_procsysvipc.cc b/winsup/cygwin/fhandler_procsysvipc.cc
index bd1eee0a1..1c0ea287a 100644
--- a/winsup/cygwin/fhandler_procsysvipc.cc
+++ b/winsup/cygwin/fhandler_procsysvipc.cc
@@ -125,9 +125,7 @@ fhandler_procsysvipc::readdir (DIR *dir, dirent *de)
if (cygserver_running != CYGSERVER_OK)
goto out;
}
- strcpy (de->d_name, procsysvipc_tab[dir->__d_position].name);
- de->d_type = virt_ftype_to_dtype (procsysvipc_tab[dir->__d_position].type);
- dir->__d_position++;
+ strcpy (de->d_name, procsysvipc_tab[dir->__d_position++].name);
dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
res = 0;
out:
diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc
index fd3b76824..d4b6706c7 100644
--- a/winsup/cygwin/fhandler_registry.cc
+++ b/winsup/cygwin/fhandler_registry.cc
@@ -586,8 +586,8 @@ fhandler_registry::fstat (struct stat *buf)
and it's also rather unlikely that the user is the owner.
Therefore it's probably most safe to assume unknown ownership
and no permissions for nobody. */
- buf->st_uid = ILLEGAL_UID;
- buf->st_gid = ILLEGAL_GID;
+ buf->st_uid = UNKNOWN_UID;
+ buf->st_gid = UNKNOWN_GID;
buf->st_mode &= ~0777;
}
}
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 59561bc58..8f38712a8 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -396,8 +396,7 @@ fhandler_socket::af_local_send_cred ()
int
fhandler_socket::af_local_connect ()
{
- bool orig_async_io, orig_is_nonblocking;
-
+ /* This keeps the test out of select. */
if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
return 0;
@@ -405,6 +404,7 @@ fhandler_socket::af_local_connect ()
if (no_getpeereid ())
return 0;
+ bool orig_async_io, orig_is_nonblocking;
af_local_setblocking (orig_async_io, orig_is_nonblocking);
if (!af_local_send_secret () || !af_local_recv_secret ()
|| !af_local_send_cred () || !af_local_recv_cred ())
@@ -421,12 +421,11 @@ fhandler_socket::af_local_connect ()
int
fhandler_socket::af_local_accept ()
{
- bool orig_async_io, orig_is_nonblocking;
-
debug_printf ("af_local_accept called, no_getpeereid=%d", no_getpeereid ());
if (no_getpeereid ())
return 0;
+ bool orig_async_io, orig_is_nonblocking;
af_local_setblocking (orig_async_io, orig_is_nonblocking);
if (!af_local_recv_secret () || !af_local_send_secret ()
|| !af_local_recv_cred () || !af_local_send_cred ())
@@ -644,35 +643,7 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
wsock_events->events |= evts.lNetworkEvents;
events_now = (wsock_events->events & event_mask);
if (evts.lNetworkEvents & FD_CONNECT)
- {
- wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT];
-
- /* Setting the connect_state and calling the AF_LOCAL handshake
- here allows to handle this stuff from a single point. This
- is independent of FD_CONNECT being requested. Consider a
- server calling connect(2) and then immediately poll(2) with
- only polling for POLLIN (example: postfix), or select(2) just
- asking for descriptors ready to read.
-
- Something weird occurs in Winsock: If you fork off and call
- recv/send on the duplicated, already connected socket, another
- FD_CONNECT event is generated in the child process. This
- would trigger a call to af_local_connect which obviously fail.
- Avoid this by calling set_connect_state only if connect_state
- is connect_pending. */
- if (connect_state () == connect_pending)
- {
- if (wsock_events->connect_errorcode)
- connect_state (connect_failed);
- else if (af_local_connect ())
- {
- wsock_events->connect_errorcode = WSAGetLastError ();
- connect_state (connect_failed);
- }
- else
- connect_state (connected);
- }
- }
+ wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT];
UNLOCK_EVENTS;
if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner)
kill (wsock_events->owner, SIGURG);
@@ -685,15 +656,15 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
{
if (events & FD_CONNECT)
{
- int wsa_err = wsock_events->connect_errorcode;
- if (wsa_err)
+ int wsa_err = 0;
+ if ((wsa_err = wsock_events->connect_errorcode) != 0)
{
/* CV 2014-04-23: This is really weird. If you call connect
asynchronously on a socket and then select, an error like
"Connection refused" is set in the event and in the SO_ERROR
socket option. If you call connect, then dup, then select,
the error is set in the event, but not in the SO_ERROR socket
- option, despite the dup'ed socket handle referring to the same
+ option, even if the dup'ed socket handle refers to the same
socket. We're trying to workaround this problem here by
taking the connect errorcode from the event and write it back
into the SO_ERROR socket option.
@@ -1135,45 +1106,21 @@ out:
int
fhandler_socket::connect (const struct sockaddr *name, int namelen)
{
+ bool in_progress = false;
struct sockaddr_storage sst;
+ DWORD err;
int type;
if (get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret)
== SOCKET_ERROR)
return SOCKET_ERROR;
- if (get_addr_family () == AF_LOCAL)
+ if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
{
- if (get_socket_type () != type)
- {
- WSASetLastError (WSAEPROTOTYPE);
- set_winsock_errno ();
- return SOCKET_ERROR;
- }
-
- set_peer_sun_path (name->sa_data);
-
- /* Don't move af_local_set_cred into af_local_connect which may be called
- via select, possibly running under another identity. Call early here,
- because af_local_connect is called in wait_for_events. */
- if (get_socket_type () == SOCK_STREAM)
- af_local_set_cred ();
+ WSASetLastError (WSAEPROTOTYPE);
+ set_winsock_errno ();
+ return SOCKET_ERROR;
}
-
- /* Initialize connect state to "connect_pending". State is ultimately set
- to "connected" or "connect_failed" in wait_for_events when the FD_CONNECT
- event occurs. Note that the underlying OS sockets are always non-blocking
- and a successfully initiated non-blocking Winsock connect always returns
- WSAEWOULDBLOCK. Thus it's safe to rely on event handling.
-
- Check for either unconnected or connect_failed since in both cases it's
- allowed to retry connecting the socket. It's also ok (albeit ugly) to
- call connect to check if a previous non-blocking connect finished.
-
- Set connect_state before calling connect, otherwise a race condition with
- an already running select or poll might occur. */
- if (connect_state () == unconnected || connect_state () == connect_failed)
- connect_state (connect_pending);
int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen);
if (!is_nonblocking ()
@@ -1181,31 +1128,48 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
&& WSAGetLastError () == WSAEWOULDBLOCK)
res = wait_for_events (FD_CONNECT | FD_CLOSE, 0);
- if (res)
+ if (!res)
+ err = 0;
+ else
{
- DWORD err = WSAGetLastError ();
-
- /* Some applications use the ugly technique to check if a non-blocking
- connect succeeded by calling connect again, until it returns EISCONN.
- This circumvents the event handling and connect_state is never set.
- Thus we check for this situation here. */
- if (err == WSAEISCONN)
- connect_state (connected);
- /* Winsock returns WSAEWOULDBLOCK if the non-blocking socket cannot be
- conected immediately. Convert to POSIX/Linux compliant EINPROGRESS. */
- else if (is_nonblocking () && err == WSAEWOULDBLOCK)
- WSASetLastError (WSAEINPROGRESS);
- /* Winsock returns WSAEINVAL if the socket is already a listener.
- Convert to POSIX/Linux compliant EISCONN. */
- else if (err == WSAEINVAL && connect_state () == listener)
- WSASetLastError (WSAEISCONN);
- /* Any other error except WSAEALREADY during connect_pending means the
- connect failed. */
- else if (connect_state () == connect_pending && err != WSAEALREADY)
- connect_state (connect_failed);
+ err = WSAGetLastError ();
+ /* Special handling for connect to return the correct error code
+ when called on a non-blocking socket. */
+ if (is_nonblocking ())
+ {
+ if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
+ in_progress = true;
+
+ if (err == WSAEWOULDBLOCK)
+ WSASetLastError (err = WSAEINPROGRESS);
+ }
+ if (err == WSAEINVAL)
+ WSASetLastError (err = WSAEISCONN);
set_winsock_errno ();
}
+ if (get_addr_family () == AF_LOCAL && (!res || in_progress))
+ set_peer_sun_path (name->sa_data);
+
+ if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
+ {
+ af_local_set_cred (); /* Don't move into af_local_connect since
+ af_local_connect is called from select,
+ possibly running under another identity. */
+ if (!res && af_local_connect ())
+ {
+ set_winsock_errno ();
+ return SOCKET_ERROR;
+ }
+ }
+
+ if (err == WSAEINPROGRESS || err == WSAEALREADY)
+ connect_state (connect_pending);
+ else if (err)
+ connect_state (connect_failed);
+ else
+ connect_state (connected);
+
return res;
}
@@ -1463,13 +1427,6 @@ fhandler_socket::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
static NO_COPY LPFN_WSARECVMSG WSARecvMsg;
int orig_namelen = wsamsg->namelen;
- /* CV 2014-10-26: Do not check for the connect_state at this point. In
- certain scenarios there's no way to check the connect state reliably.
- Example (hexchat): Parent process creates socket, forks, child process
- calls connect, parent process calls read. Even if the event handling
- allows to check for FD_CONNECT in the parent, there is always yet another
- scenario we can easily break. */
-
DWORD wait_flags = wsamsg->dwFlags;
bool waitall = !!(wait_flags & MSG_WAITALL);
wsamsg->dwFlags &= (MSG_OOB | MSG_PEEK | MSG_DONTROUTE);
diff --git a/winsup/cygwin/fhandler_virtual.h b/winsup/cygwin/fhandler_virtual.h
index f92c06b89..9747dd2cb 100644
--- a/winsup/cygwin/fhandler_virtual.h
+++ b/winsup/cygwin/fhandler_virtual.h
@@ -1,6 +1,6 @@
/* fhandler_virtual.h: Header for virtual fhandlers
- Copyright 2009, 2010, 2011, 2014 Red Hat, Inc.
+ Copyright 2009, 2010, 2011 Red Hat, Inc.
This file is part of Cygwin.
@@ -20,26 +20,3 @@ struct virt_tab_t {
extern virt_tab_t *virt_tab_search (const char *, bool, const virt_tab_t *,
size_t);
-
-static inline unsigned char
-virt_ftype_to_dtype (virtual_ftype_t type)
-{
- unsigned char d_type;
-
- switch (type)
- {
- case virt_directory:
- d_type = DT_DIR;
- break;
- case virt_symlink:
- d_type = DT_LNK;
- break;
- case virt_file:
- d_type = DT_REG;
- break;
- default:
- d_type = DT_UNKNOWN;
- break;
- }
- return d_type;
-}
diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc
index 92f9acc8a..a37175469 100644
--- a/winsup/cygwin/globals.cc
+++ b/winsup/cygwin/globals.cc
@@ -148,9 +148,6 @@ extern "C" {
extern UNICODE_STRING _RDATA ro_u_pipedir = _ROU (L"\\\\?\\PIPE\\");
extern UNICODE_STRING _RDATA ro_u_globalroot = _ROU (L"\\\\.\\GLOBALROOT");
extern UNICODE_STRING _RDATA ro_u_null = _ROU (L"\\Device\\Null");
- extern UNICODE_STRING _RDATA ro_u_natdir = _ROU (L"Directory");
- extern UNICODE_STRING _RDATA ro_u_natsyml = _ROU (L"SymbolicLink");
- extern UNICODE_STRING _RDATA ro_u_natdev = _ROU (L"Device");
#undef _ROU
/* Cygwin properties are meant to be readonly data placed in the DLL, but
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index f7ce61b08..d4d1b653f 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -1,7 +1,7 @@
/* grp.cc
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2008, 2009, 2011, 2012, 2013 Red Hat, Inc.
Original stubs by Jason Molenda of Cygnus Support, crash@cygnus.com
First implementation by Gunther Ebert, gunther.ebert@ixos-leipzig.de
@@ -13,7 +13,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <lm.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -24,166 +23,134 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "ntdll.h"
-#include "miscfuncs.h"
-#include "ldap.h"
-#include "tls_pbuf.h"
+#include "pwdgrp.h"
+static group *group_buf;
+static pwdgrp gr (group_buf);
static char * NO_COPY_RO null_ptr;
bool
pwdgrp::parse_group ()
{
- pg_grp &grp = group ()[curr_lines];
- grp.g.gr_name = next_str (':');
- if (!*grp.g.gr_name)
+ group &grp = (*group_buf)[curr_lines];
+ grp.gr_name = next_str (':');
+ if (!*grp.gr_name)
return false;
- grp.g.gr_passwd = next_str (':');
- /* Note that lptr points to the first byte of the gr_gid field.
- We deliberately ignore the gr_gid and gr_mem entries when copying
- the buffer content since they are not referenced anymore. */
- grp.len = lptr - grp.g.gr_name;
- if (!next_num (grp.g.gr_gid))
+
+ grp.gr_passwd = next_str (':');
+
+ if (!next_num (grp.gr_gid))
return false;
- /* Don't generate gr_mem entries. */
- grp.g.gr_mem = &null_ptr;
- grp.sid.getfromgr (&grp.g);
+
+ int n;
+ char *dp = raw_ptr ();
+ for (n = 0; *next_str (','); n++)
+ continue;
+
+ grp.gr_mem = &null_ptr;
+ if (n)
+ {
+ char **namearray = (char **) calloc (n + 1, sizeof (char *));
+ if (namearray)
+ {
+ for (int i = 0; i < n; i++, dp = strchr (dp, '\0') + 1)
+ namearray[i] = dp;
+ grp.gr_mem = namearray;
+ }
+ }
+
return true;
}
-muto NO_COPY pwdgrp::pglock;
-
+/* Cygwin internal */
+/* Read in /etc/group and save contents in the group cache */
+/* This sets group_in_memory_p to 1 so functions in this file can
+ tell that /etc/group has been read in */
void
-pwdgrp::init_grp ()
+pwdgrp::read_group ()
{
- pwdgrp_buf_elem_size = sizeof (pg_grp);
- parse = &pwdgrp::parse_group;
-}
+ for (int i = 0; i < gr.curr_lines; i++)
+ if ((*group_buf)[i].gr_mem != &null_ptr)
+ free ((*group_buf)[i].gr_mem);
-struct group *
-pwdgrp::find_group (cygpsid &sid)
-{
- for (ULONG i = 0; i < curr_lines; i++)
- if (sid == group ()[i].sid)
- return &group ()[i].g;
- return NULL;
+ load (L"\\etc\\group");
+
+ /* Complete /etc/group in memory if needed */
+ if (!internal_getgrgid (myself->gid))
+ {
+ static char linebuf [200];
+ char group_name [UNLEN + 1] = "mkgroup";
+ char strbuf[128] = "";
+ struct group *gr;
+
+ cygheap->user.groups.pgsid.string (strbuf);
+ if ((gr = internal_getgrsid (cygheap->user.groups.pgsid)))
+ snprintf (group_name, sizeof (group_name),
+ "passwd/group_GID_clash(%u/%u)", myself->gid, gr->gr_gid);
+ if (myself->uid == UNKNOWN_UID)
+ strcpy (group_name, "mkpasswd"); /* Feedback... */
+ snprintf (linebuf, sizeof (linebuf), "%s:%s:%u:%s",
+ group_name, strbuf, myself->gid, cygheap->user.name ());
+ debug_printf ("Completing /etc/group: %s", linebuf);
+ add_line (linebuf);
+ }
+ static char NO_COPY pretty_ls[] = "????????::-1:";
+ add_line (pretty_ls);
}
-struct group *
-pwdgrp::find_group (const char *name)
+muto NO_COPY pwdgrp::pglock;
+
+pwdgrp::pwdgrp (passwd *&pbuf) :
+ pwdgrp_buf_elem_size (sizeof (*pbuf)), passwd_buf (&pbuf)
{
- for (ULONG i = 0; i < curr_lines; i++)
- if (strcasematch (group ()[i].g.gr_name, name))
- return &group ()[i].g;
- return NULL;
+ read = &pwdgrp::read_passwd;
+ parse = &pwdgrp::parse_passwd;
+ pglock.init ("pglock");
}
-struct group *
-pwdgrp::find_group (gid_t gid)
+pwdgrp::pwdgrp (group *&gbuf) :
+ pwdgrp_buf_elem_size (sizeof (*gbuf)), group_buf (&gbuf)
{
- for (ULONG i = 0; i < curr_lines; i++)
- if (gid == group ()[i].g.gr_gid)
- return &group ()[i].g;
- return NULL;
+ read = &pwdgrp::read_group;
+ parse = &pwdgrp::parse_group;
+ pglock.init ("pglock");
}
struct group *
-internal_getgrsid (cygpsid &sid, cyg_ldap *pldap)
+internal_getgrsid (cygpsid &sid)
{
- struct group *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.grp_cache.cygserver.find_group (sid)))
- return ret;
- if (cygheap->pg.nss_grp_files ()
- && (ret = cygheap->pg.grp_cache.file.find_group (sid)))
- return ret;
- if (cygheap->pg.nss_grp_db ()
- && (ret = cygheap->pg.grp_cache.win.find_group (sid)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.grp_cache.cygserver.add_group_from_cygserver (sid)))
- return ret;
- if (cygheap->pg.nss_grp_files ())
- {
- cygheap->pg.grp_cache.file.check_file ();
- if ((ret = cygheap->pg.grp_cache.file.add_group_from_file (sid)))
- return ret;
- }
- if (cygheap->pg.nss_grp_db ())
- return cygheap->pg.grp_cache.win.add_group_from_windows (sid, pldap);
+ char sid_string[128];
+
+ gr.refresh (false);
+
+ if (sid.string (sid_string))
+ for (int i = 0; i < gr.curr_lines; i++)
+ if (!strcmp (sid_string, group_buf[i].gr_passwd))
+ return group_buf + i;
return NULL;
}
-/* This function gets only called from mkgroup via cygwin_internal. */
struct group *
-internal_getgrsid_from_db (cygpsid &sid)
+internal_getgrgid (gid_t gid, bool check)
{
- cygheap->pg.nss_init ();
- return cygheap->pg.grp_cache.win.add_group_from_windows (sid);
-}
+ gr.refresh (check);
-struct group *
-internal_getgrnam (const char *name, cyg_ldap *pldap)
-{
- struct group *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.grp_cache.cygserver.find_group (name)))
- return ret;
- if (cygheap->pg.nss_grp_files ()
- && (ret = cygheap->pg.grp_cache.file.find_group (name)))
- return ret;
- if (cygheap->pg.nss_grp_db ()
- && (ret = cygheap->pg.grp_cache.win.find_group (name)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.grp_cache.cygserver.add_group_from_cygserver (name)))
- return ret;
- if (cygheap->pg.nss_grp_files ())
- {
- cygheap->pg.grp_cache.file.check_file ();
- if ((ret = cygheap->pg.grp_cache.file.add_group_from_file (name)))
- return ret;
- }
- if (cygheap->pg.nss_grp_db ())
- return cygheap->pg.grp_cache.win.add_group_from_windows (name, pldap);
+ for (int i = 0; i < gr.curr_lines; i++)
+ if (group_buf[i].gr_gid == gid)
+ return group_buf + i;
return NULL;
}
struct group *
-internal_getgrgid (gid_t gid, cyg_ldap *pldap)
+internal_getgrnam (const char *name, bool check)
{
- struct group *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.grp_cache.cygserver.find_group (gid)))
- return ret;
- if (cygheap->pg.nss_grp_files ()
- && (ret = cygheap->pg.grp_cache.file.find_group (gid)))
- return ret;
- if (cygheap->pg.nss_grp_db ()
- && (ret = cygheap->pg.grp_cache.win.find_group (gid)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.grp_cache.cygserver.add_group_from_cygserver (gid)))
- return ret;
- if (cygheap->pg.nss_grp_files ())
- {
- cygheap->pg.grp_cache.file.check_file ();
- if ((ret = cygheap->pg.grp_cache.file.add_group_from_file (gid)))
- return ret;
- }
- if (cygheap->pg.nss_grp_db () || gid == ILLEGAL_GID)
- return cygheap->pg.grp_cache.win.add_group_from_windows (gid, pldap);
+ gr.refresh (check);
+
+ for (int i = 0; i < gr.curr_lines; i++)
+ if (strcasematch (group_buf[i].gr_name, name))
+ return group_buf + i;
+
+ /* Didn't find requested group */
return NULL;
}
@@ -214,65 +181,37 @@ getgrgid_r (gid_t gid, struct group *grp, char *buffer, size_t bufsize,
if (!grp || !buffer)
return ERANGE;
- struct group *tempgr = internal_getgrgid (gid);
+ struct group *tempgr = internal_getgrgid (gid, true);
pthread_testcancel ();
if (!tempgr)
return 0;
- /* Check needed buffer size. Deliberately ignore gr_mem. */
+ /* check needed buffer size. */
+ int i;
size_t needsize = strlen (tempgr->gr_name) + strlen (tempgr->gr_passwd)
+ 2 + sizeof (char *);
+ for (i = 0; tempgr->gr_mem[i]; ++i)
+ needsize += strlen (tempgr->gr_mem[i]) + 1 + sizeof (char *);
if (needsize > bufsize)
return ERANGE;
- /* Make a copy of tempgr. Deliberately ignore gr_mem. */
+ /* make a copy of tempgr */
*result = grp;
grp->gr_gid = tempgr->gr_gid;
buffer = stpcpy (grp->gr_name = buffer, tempgr->gr_name);
buffer = stpcpy (grp->gr_passwd = buffer + 1, tempgr->gr_passwd);
grp->gr_mem = (char **) (buffer + 1);
- grp->gr_mem[0] = NULL;
+ buffer = (char *) grp->gr_mem + (i + 1) * sizeof (char *);
+ for (i = 0; tempgr->gr_mem[i]; ++i)
+ buffer = stpcpy (grp->gr_mem[i] = buffer, tempgr->gr_mem[i]) + 1;
+ grp->gr_mem[i] = NULL;
return 0;
}
-/* getgrgid/getgrnam are not reentrant. */
-static struct {
- struct group g;
- char *buf;
- size_t bufsiz;
-} app_gr;
-
-static struct group *
-getgr_cp (struct group *tempgr)
-{
- if (!tempgr)
- return NULL;
- pg_grp *gr = (pg_grp *) tempgr;
- if (app_gr.bufsiz < gr->len)
- {
- char *newbuf = (char *) realloc (app_gr.buf, gr->len);
- if (!newbuf)
- {
- set_errno (ENOMEM);
- return NULL;
- }
- app_gr.buf = newbuf;
- app_gr.bufsiz = gr->len;
- }
- memcpy (app_gr.buf, gr->g.gr_name, gr->len);
- memcpy (&app_gr.g, &gr->g, sizeof gr->g);
- ptrdiff_t diff = app_gr.buf - gr->g.gr_name;
- app_gr.g.gr_name += diff;
- app_gr.g.gr_passwd += diff;
- return &app_gr.g;
-}
-
extern "C" struct group *
getgrgid32 (gid_t gid)
{
- struct group *tempgr = internal_getgrgid (gid);
- pthread_testcancel ();
- return getgr_cp (tempgr);
+ return internal_getgrgid (gid, true);
}
#ifdef __x86_64__
@@ -296,33 +235,37 @@ getgrnam_r (const char *nam, struct group *grp, char *buffer,
if (!grp || !buffer)
return ERANGE;
- struct group *tempgr = internal_getgrnam (nam);
+ struct group *tempgr = internal_getgrnam (nam, true);
pthread_testcancel ();
if (!tempgr)
return 0;
- /* Check needed buffer size. Deliberately ignore gr_mem. */
+ /* check needed buffer size. */
+ int i;
size_t needsize = strlen (tempgr->gr_name) + strlen (tempgr->gr_passwd)
+ 2 + sizeof (char *);
+ for (i = 0; tempgr->gr_mem[i]; ++i)
+ needsize += strlen (tempgr->gr_mem[i]) + 1 + sizeof (char *);
if (needsize > bufsize)
return ERANGE;
- /* Make a copy of tempgr. Deliberately ignore gr_mem. */
+ /* make a copy of tempgr */
*result = grp;
grp->gr_gid = tempgr->gr_gid;
buffer = stpcpy (grp->gr_name = buffer, tempgr->gr_name);
buffer = stpcpy (grp->gr_passwd = buffer + 1, tempgr->gr_passwd);
grp->gr_mem = (char **) (buffer + 1);
- grp->gr_mem[0] = NULL;
+ buffer = (char *) grp->gr_mem + (i + 1) * sizeof (char *);
+ for (i = 0; tempgr->gr_mem[i]; ++i)
+ buffer = stpcpy (grp->gr_mem[i] = buffer, tempgr->gr_mem[i]) + 1;
+ grp->gr_mem[i] = NULL;
return 0;
}
extern "C" struct group *
getgrnam32 (const char *name)
{
- struct group *tempgr = internal_getgrnam (name);
- pthread_testcancel ();
- return getgr_cp (tempgr);
+ return internal_getgrnam (name, true);
}
#ifdef __x86_64__
@@ -337,119 +280,21 @@ getgrnam (const char *name)
}
#endif
-/* getgrent functions are not reentrant. */
-static gr_ent grent;
-
-void *
-gr_ent::enumerate_caches ()
-{
- switch (max)
- {
- case 0:
- if (cygheap->pg.nss_cygserver_caching ())
- {
- pwdgrp &grc = cygheap->pg.grp_cache.cygserver;
- if (cnt < grc.cached_groups ())
- return &grc.group ()[cnt++].g;
- }
- cnt = 0;
- max = 1;
- /*FALLTHRU*/
- case 1:
- if (from_files)
- {
- pwdgrp &grf = cygheap->pg.grp_cache.file;
- grf.check_file ();
- if (cnt < grf.cached_groups ())
- return &grf.group ()[cnt++].g;
- }
- cnt = 0;
- max = 2;
- /*FALLTHRU*/
- case 2:
- if (from_db)
- {
- pwdgrp &grw = cygheap->pg.grp_cache.win;
- if (cnt < grw.cached_groups ())
- return &grw.group ()[cnt++].g;
- }
- break;
- }
- cnt = max = 0;
- return NULL;
-}
-
-void *
-gr_ent::enumerate_local ()
-{
- while (true)
- {
- if (!cnt)
- {
- DWORD total;
- NET_API_STATUS ret;
-
- if (buf)
- {
- NetApiBufferFree (buf);
- buf = NULL;
- }
- if (resume == ULONG_MAX)
- ret = ERROR_NO_MORE_ITEMS;
- else
- ret = NetLocalGroupEnum (NULL, 0, (PBYTE *) &buf,
- MAX_PREFERRED_LENGTH,
- &max, &total, &resume);
- if (ret == NERR_Success)
- resume = ULONG_MAX;
- else if (ret != ERROR_MORE_DATA)
- {
- cnt = max = resume = 0;
- return NULL;
- }
- }
- while (cnt < max)
- {
- cygsid sid;
- DWORD slen = SECURITY_MAX_SID_SIZE;
- WCHAR dom[DNLEN + 1];
- DWORD dlen = DNLEN + 1;
- SID_NAME_USE acc_type;
-
- LookupAccountNameW (NULL,
- ((PLOCALGROUP_INFO_0) buf)[cnt++].lgrpi0_name,
- sid, &slen, dom, &dlen, &acc_type);
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg);
- if (line)
- return pg.add_account_post_fetch (line, false);
- }
- cnt = 0;
- }
-}
-
-struct group *
-gr_ent::getgrent (void)
-{
- if (state == rewound)
- setent (true);
- else
- clear_cache ();
- return (struct group *) getent ();
-}
-
extern "C" void
-setgrent ()
+endgrent ()
{
- grent.setgrent ();
+ _my_tls.locals.grp_pos = 0;
}
extern "C" struct group *
-getgrent32 (void)
+getgrent32 ()
{
- return grent.getgrent ();
+ if (_my_tls.locals.grp_pos == 0)
+ gr.refresh (true);
+ if (_my_tls.locals.grp_pos < gr.curr_lines)
+ return group_buf + _my_tls.locals.grp_pos++;
+
+ return NULL;
}
#ifdef __x86_64__
@@ -465,85 +310,90 @@ getgrent ()
#endif
extern "C" void
-endgrent (void)
-{
- grent.endgrent ();
-}
-
-/* *_filtered functions are called from mkgroup */
-void *
-setgrent_filtered (int enums, PCWSTR enum_tdoms)
+setgrent ()
{
- gr_ent *gr = new gr_ent;
- if (gr)
- gr->setgrent (enums, enum_tdoms);
- return (void *) gr;
+ _my_tls.locals.grp_pos = 0;
}
-void *
-getgrent_filtered (void *gr)
+/* Internal function. ONLY USE THIS INTERNALLY, NEVER `getgrent'!!! */
+struct group *
+internal_getgrent (int pos)
{
- return (void *) ((gr_ent *) gr)->getgrent ();
-}
+ gr.refresh (false);
-void
-endgrent_filtered (void *gr)
-{
- ((gr_ent *) gr)->endgrent ();
+ if (pos < gr.curr_lines)
+ return group_buf + pos;
+ return NULL;
}
int
-internal_getgroups (int gidsetsize, gid_t *grouplist, cyg_ldap *pldap)
+internal_getgroups (int gidsetsize, gid_t *grouplist, cygpsid * srchsid)
{
NTSTATUS status;
- HANDLE tok;
+ HANDLE hToken = NULL;
ULONG size;
int cnt = 0;
- struct group *grp;
+ struct group *gr;
- if (cygheap->user.groups.issetgroups ())
+ if (!srchsid && cygheap->user.groups.issetgroups ())
{
- for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg)
- if ((grp = internal_getgrsid (cygheap->user.groups.sgsids.sids[pg],
- pldap)))
- {
- if (cnt < gidsetsize)
- grouplist[cnt] = grp->gr_gid;
- ++cnt;
- if (gidsetsize && cnt > gidsetsize)
- goto error;
- }
+ cygsid sid;
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ if (sid.getfromgr (gr))
+ for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg)
+ if (sid == cygheap->user.groups.sgsids.sids[pg]
+ && sid != well_known_world_sid)
+ {
+ if (cnt < gidsetsize)
+ grouplist[cnt] = gr->gr_gid;
+ ++cnt;
+ if (gidsetsize && cnt > gidsetsize)
+ goto error;
+ break;
+ }
return cnt;
}
+
/* If impersonated, use impersonation token. */
- tok = cygheap->user.issetuid () ? cygheap->user.primary_token () : hProcToken;
+ if (cygheap->user.issetuid ())
+ hToken = cygheap->user.primary_token ();
+ else
+ hToken = hProcToken;
- status = NtQueryInformationToken (tok, TokenGroups, NULL, 0, &size);
+ status = NtQueryInformationToken (hToken, TokenGroups, NULL, 0, &size);
if (NT_SUCCESS (status) || status == STATUS_BUFFER_TOO_SMALL)
{
PTOKEN_GROUPS groups = (PTOKEN_GROUPS) alloca (size);
- status = NtQueryInformationToken (tok, TokenGroups, groups, size, &size);
+ status = NtQueryInformationToken (hToken, TokenGroups, groups,
+ size, &size);
if (NT_SUCCESS (status))
{
- for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
+ cygsid sid;
+
+ if (srchsid)
{
- cygpsid sid = groups->Groups[pg].Sid;
- if ((grp = internal_getgrsid (sid, pldap)))
- {
- if ((groups->Groups[pg].Attributes
- & (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
+ for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
+ if ((cnt = (*srchsid == groups->Groups[pg].Sid)))
+ break;
+ }
+ else
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ if (sid.getfromgr (gr))
+ for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
+ if (sid == groups->Groups[pg].Sid
+ && (groups->Groups[pg].Attributes
+ & (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
&& sid != well_known_world_sid)
{
if (cnt < gidsetsize)
- grouplist[cnt] = grp->gr_gid;
+ grouplist[cnt] = gr->gr_gid;
++cnt;
if (gidsetsize && cnt > gidsetsize)
goto error;
+ break;
}
- }
- }
}
}
else
@@ -558,9 +408,7 @@ error:
extern "C" int
getgroups32 (int gidsetsize, gid_t *grouplist)
{
- cyg_ldap cldap;
-
- return internal_getgroups (gidsetsize, grouplist, &cldap);
+ return internal_getgroups (gidsetsize, grouplist);
}
#ifdef __x86_64__
@@ -579,7 +427,7 @@ getgroups (int gidsetsize, __gid16_t *grouplist)
if (gidsetsize > 0 && grouplist)
grouplist32 = (gid_t *) alloca (gidsetsize * sizeof (gid_t));
- int ret = getgroups32 (gidsetsize, grouplist32);
+ int ret = internal_getgroups (gidsetsize, grouplist32);
if (gidsetsize > 0 && grouplist)
for (int i = 0; i < ret; ++ i)
@@ -593,15 +441,13 @@ getgroups (int gidsetsize, __gid16_t *grouplist)
static void
get_groups (const char *user, gid_t gid, cygsidlist &gsids)
{
- cyg_ldap cldap;
-
cygheap->user.deimpersonate ();
- struct passwd *pw = internal_getpwnam (user, &cldap);
- struct group *grp = internal_getgrgid (gid, &cldap);
+ struct passwd *pw = internal_getpwnam (user);
+ struct group *gr = internal_getgrgid (gid);
cygsid usersid, grpsid;
if (usersid.getfrompw (pw))
get_server_groups (gsids, usersid, pw);
- if (gid != ILLEGAL_GID && grpsid.getfromgr (grp))
+ if (gid != ILLEGAL_GID && grpsid.getfromgr (gr))
gsids += grpsid;
cygheap->user.reimpersonate ();
}
@@ -636,8 +482,7 @@ getgrouplist (const char *user, gid_t gid, gid_t *groups, int *ngroups)
{
int ret = 0;
int cnt = 0;
- struct group *grp;
- cyg_ldap cldap;
+ struct group *gr;
/* Note that it's not defined if groups or ngroups may be NULL!
GLibc does not check the pointers on entry and just uses them.
@@ -650,10 +495,10 @@ getgrouplist (const char *user, gid_t gid, gid_t *groups, int *ngroups)
cygsidlist tmp_gsids (cygsidlist_auto, 12);
get_groups (user, gid, tmp_gsids);
for (int i = 0; i < tmp_gsids.count (); i++)
- if ((grp = internal_getgrsid (tmp_gsids.sids[i], &cldap)) != NULL)
+ if ((gr = internal_getgrsid (tmp_gsids.sids[i])) != NULL)
{
if (groups && cnt < *ngroups)
- groups[cnt] = grp->gr_gid;
+ groups[cnt] = gr->gr_gid;
++cnt;
}
if (cnt > *ngroups)
@@ -679,16 +524,15 @@ setgroups32 (int ngroups, const gid_t *grouplist)
}
cygsidlist gsids (cygsidlist_alloc, ngroups);
- struct group *grp;
- cyg_ldap cldap;
+ struct group *gr;
if (ngroups && !gsids.sids)
return -1;
for (int gidx = 0; gidx < ngroups; ++gidx)
{
- if ((grp = internal_getgrgid (grouplist[gidx], &cldap))
- && gsids.addfromgr (grp))
+ if ((gr = internal_getgrgid (grouplist[gidx]))
+ && gsids.addfromgr (gr))
continue;
debug_printf ("No sid found for gid %u", grouplist[gidx]);
gsids.free_sids ();
diff --git a/winsup/cygwin/import/rexec.c b/winsup/cygwin/import/rexec.c
deleted file mode 100644
index 4e01eb659..000000000
--- a/winsup/cygwin/import/rexec.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (c) 1980, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * 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.
- * 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.
- *
- * $FreeBSD$
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rexec.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <netinet/in.h>
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <netdb.h>
-#include <errno.h>
-#include <ctype.h>
-#include <err.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-int rexecoptions;
-char *getpass(), *getlogin();
-
-/*
- * Options and other state info.
- */
-struct macel {
- char mac_name[9]; /* macro name */
- char *mac_start; /* start of macro in macbuf */
- char *mac_end; /* end of macro in macbuf */
-};
-
-int macnum; /* number of defined macros */
-struct macel macros[16];
-char macbuf[4096];
-
-static FILE *cfile;
-
-#define DEFAULT 1
-#define LOGIN 2
-#define PASSWD 3
-#define ACCOUNT 4
-#define MACDEF 5
-#define ID 10
-#define MACH 11
-
-static char tokval[100];
-
-static struct toktab {
- char *tokstr;
- int tval;
-} toktab[]= {
- { "default", DEFAULT },
- { "login", LOGIN },
- { "password", PASSWD },
- { "passwd", PASSWD },
- { "account", ACCOUNT },
- { "machine", MACH },
- { "macdef", MACDEF },
- { NULL, 0 }
-};
-
-static int
-token()
-{
- char *cp;
- int c;
- struct toktab *t;
-
- if (feof(cfile) || ferror(cfile))
- return (0);
- while ((c = getc(cfile)) != EOF &&
- (c == '\n' || c == '\t' || c == ' ' || c == ','))
- continue;
- if (c == EOF)
- return (0);
- cp = tokval;
- if (c == '"') {
- while ((c = getc(cfile)) != EOF && c != '"') {
- if (c == '\\')
- c = getc(cfile);
- *cp++ = c;
- }
- } else {
- *cp++ = c;
- while ((c = getc(cfile)) != EOF
- && c != '\n' && c != '\t' && c != ' ' && c != ',') {
- if (c == '\\')
- c = getc(cfile);
- *cp++ = c;
- }
- }
- *cp = 0;
- if (tokval[0] == 0)
- return (0);
- for (t = toktab; t->tokstr; t++)
- if (!strcmp(t->tokstr, tokval))
- return (t->tval);
- return (ID);
-}
-
-static int
-ruserpass(host, aname, apass, aacct)
- char *host, **aname, **apass, **aacct;
-{
- char *hdir, buf[BUFSIZ], *tmp;
- char myname[MAXHOSTNAMELEN], *mydomain;
- int t, i, c, usedefault = 0;
- struct stat stb;
-
- hdir = getenv("HOME");
- if (hdir == NULL)
- hdir = ".";
- if (strlen(hdir) + 8 > sizeof(buf))
- return (0);
- (void) sprintf(buf, "%s/.netrc", hdir);
- cfile = fopen(buf, "r");
- if (cfile == NULL) {
- if (errno != ENOENT)
- warn("%s", buf);
- return (0);
- }
- if (gethostname(myname, sizeof(myname)) < 0)
- myname[0] = '\0';
- if ((mydomain = strchr(myname, '.')) == NULL)
- mydomain = "";
-next:
- while ((t = token())) switch(t) {
-
- case DEFAULT:
- usedefault = 1;
- /* FALL THROUGH */
-
- case MACH:
- if (!usedefault) {
- if (token() != ID)
- continue;
- /*
- * Allow match either for user's input host name
- * or official hostname. Also allow match of
- * incompletely-specified host in local domain.
- */
- if (strcasecmp(host, tokval) == 0)
- goto match;
- if ((tmp = strchr(host, '.')) != NULL &&
- strcasecmp(tmp, mydomain) == 0 &&
- strncasecmp(host, tokval, tmp - host) == 0 &&
- tokval[tmp - host] == '\0')
- goto match;
- continue;
- }
- match:
- while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
-
- case LOGIN:
- if (token())
- if (*aname == 0) {
- *aname = malloc((unsigned) strlen(tokval) + 1);
- (void) strcpy(*aname, tokval);
- } else {
- if (strcmp(*aname, tokval))
- goto next;
- }
- break;
- case PASSWD:
- if ((*aname == 0 || strcmp(*aname, "anonymous")) &&
- fstat(fileno(cfile), &stb) >= 0 &&
- (stb.st_mode & 077) != 0) {
- warnx("Error: .netrc file is readable by others.");
- warnx("Remove password or make file unreadable by others.");
- goto bad;
- }
- if (token() && *apass == 0) {
- *apass = malloc((unsigned) strlen(tokval) + 1);
- (void) strcpy(*apass, tokval);
- }
- break;
- case ACCOUNT:
- if (fstat(fileno(cfile), &stb) >= 0
- && (stb.st_mode & 077) != 0) {
- warnx("Error: .netrc file is readable by others.");
- warnx("Remove account or make file unreadable by others.");
- goto bad;
- }
- if (token() && *aacct == 0) {
- *aacct = malloc((unsigned) strlen(tokval) + 1);
- (void) strcpy(*aacct, tokval);
- }
- break;
- case MACDEF:
- while ((c=getc(cfile)) != EOF &&
- (c == ' ' || c == '\t'))
- ;
- if (c == EOF || c == '\n') {
- printf("Missing macdef name argument.\n");
- goto bad;
- }
- if (macnum == 16) {
- printf("Limit of 16 macros have already been defined\n");
- goto bad;
- }
- tmp = macros[macnum].mac_name;
- *tmp++ = c;
- for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
- !isspace(c); ++i) {
- *tmp++ = c;
- }
- if (c == EOF) {
- printf("Macro definition missing null line terminator.\n");
- goto bad;
- }
- *tmp = '\0';
- if (c != '\n') {
- while ((c=getc(cfile)) != EOF && c != '\n');
- }
- if (c == EOF) {
- printf("Macro definition missing null line terminator.\n");
- goto bad;
- }
- if (macnum == 0) {
- macros[macnum].mac_start = macbuf;
- }
- else {
- macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
- }
- tmp = macros[macnum].mac_start;
- while (tmp != macbuf + 4096) {
- if ((c=getc(cfile)) == EOF) {
- printf("Macro definition missing null line terminator.\n");
- goto bad;
- }
- *tmp = c;
- if (*tmp == '\n') {
- if (*(tmp-1) == '\0') {
- macros[macnum++].mac_end = tmp - 1;
- break;
- }
- *tmp = '\0';
- }
- tmp++;
- }
- if (tmp == macbuf + 4096) {
- printf("4K macro buffer exceeded\n");
- goto bad;
- }
- break;
- default:
- warnx("Unknown .netrc keyword %s", tokval);
- break;
- }
- goto done;
- }
-done:
- (void) fclose(cfile);
- return (0);
-bad:
- (void) fclose(cfile);
- return (-1);
-}
-
-int
-rexec(ahost, rport, name, pass, cmd, fd2p)
- char **ahost;
- int rport;
- char *name, *pass, *cmd;
- int *fd2p;
-{
- struct sockaddr_in sin, sin2, from;
- struct hostent *hp;
- u_short port;
- int s, timo = 1, s3;
- char c, *acct;
-
- hp = gethostbyname(*ahost);
- if (hp == 0) {
- herror(*ahost);
- return (-1);
- }
- *ahost = hp->h_name;
- acct = NULL;
- ruserpass(hp->h_name, &name, &pass, &acct);
- free(acct);
-retry:
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0) {
- perror("rexec: socket");
- return (-1);
- }
- sin.sin_family = hp->h_addrtype;
- sin.sin_port = rport;
- bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- if (errno == ECONNREFUSED && timo <= 16) {
- (void) close(s);
- sleep(timo);
- timo *= 2;
- goto retry;
- }
- perror(hp->h_name);
- return (-1);
- }
- if (fd2p == 0) {
- (void) write(s, "", 1);
- port = 0;
- } else {
- char num[8];
- int s2, sin2len;
-
- s2 = socket(AF_INET, SOCK_STREAM, 0);
- if (s2 < 0) {
- (void) close(s);
- return (-1);
- }
- listen(s2, 1);
- sin2len = sizeof (sin2);
- if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 ||
- sin2len != sizeof (sin2)) {
- perror("getsockname");
- (void) close(s2);
- goto bad;
- }
- port = ntohs((u_short)sin2.sin_port);
- (void) sprintf(num, "%u", port);
- (void) write(s, num, strlen(num)+1);
- { int len = sizeof (from);
- s3 = accept(s2, (struct sockaddr *)&from, &len);
- close(s2);
- if (s3 < 0) {
- perror("accept");
- port = 0;
- goto bad;
- }
- }
- *fd2p = s3;
- }
- (void) write(s, name, strlen(name) + 1);
- /* should public key encypt the password here */
- (void) write(s, pass, strlen(pass) + 1);
- (void) write(s, cmd, strlen(cmd) + 1);
- if (read(s, &c, 1) != 1) {
- perror(*ahost);
- goto bad;
- }
- if (c != 0) {
- while (read(s, &c, 1) == 1) {
- (void) write(2, &c, 1);
- if (c == '\n')
- break;
- }
- goto bad;
- }
- return (s);
-bad:
- if (port)
- (void) close(*fd2p);
- (void) close(s);
- return (-1);
-}
diff --git a/winsup/cygwin/include/cygwin/acl.h b/winsup/cygwin/include/cygwin/acl.h
index 8fa5a65a5..9a62e325e 100644
--- a/winsup/cygwin/include/cygwin/acl.h
+++ b/winsup/cygwin/include/cygwin/acl.h
@@ -1,6 +1,6 @@
/* cygwin/acl.h header file for Cygwin.
- Copyright 1999, 2000, 2001, 2002, 2010, 2014 Red Hat, Inc.
+ Copyright 1999, 2000, 2001, 2002, 2010 Red Hat, Inc.
Written by C. Vinschen.
This file is part of Cygwin.
@@ -25,7 +25,7 @@ extern "C" {
#define GETACL (0x1)
#define GETACLCNT (0x2)
-#define MIN_ACL_ENTRIES (3) // minimal acl entries from GETACLCNT
+#define MIN_ACL_ENTRIES (4) // minimal acl entries from GETACLCNT
#define MAX_ACL_ENTRIES (256) // max entries of each type
// Return values of aclcheck(3) in case of error */
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index e1ac2cee9..6c46a0b43 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -448,9 +448,8 @@ details. */
272: Export tm_gmtoff and tm_zone members.
273: Skipped.
274: Export __cxa_atexit and __cxa_finalize.
- 275: Introduce account mapping from Windows account DBs. Add CW_SETENT,
- CW_GETENT, CW_ENDENT, CW_GETNSSSEP, CW_GETPWSID, CW_GETGRSID,
- CW_CYGNAME_FROM_WINNAME.
+ 275: Add CW_SETENT, CW_GETENT, CW_ENDENT, CW_GETNSSSEP, CW_GETPWSID,
+ CW_GETGRSID, CW_CYGNAME_FROM_WINNAME as no-ops for forward compat.
276: Export ffsl, ffsll.
277: Add setsockopt(SO_PEERCRED).
278: Add quotactl.
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index 7f40475e8..6dbf2d322 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -218,20 +218,6 @@ enum
CW_TOKEN_RESTRICTED = 1
};
-/* Enumeration source constants for CW_SETENT called from mkpasswd/mkgroup. */
-enum nss_enum_t
-{
- ENUM_NONE = 0x00,
- ENUM_CACHE = 0x01,
- ENUM_FILES = 0x02,
- ENUM_BUILTIN = 0x04,
- ENUM_LOCAL = 0x08,
- ENUM_PRIMARY = 0x10,
- ENUM_TDOMS = 0x20,
- ENUM_TDOMS_ALL = 0x40,
- ENUM_ALL = 0x7f
-};
-
#define CW_NEXTPID 0x80000000 /* or with pid to get next one */
uintptr_t cygwin_internal (cygwin_getinfo_types, ...);
diff --git a/winsup/cygwin/ldap.cc b/winsup/cygwin/ldap.cc
deleted file mode 100644
index df7756809..000000000
--- a/winsup/cygwin/ldap.cc
+++ /dev/null
@@ -1,629 +0,0 @@
-/* ldap.cc: Helper functions for ldap access to Active Directory.
-
- Copyright 2014 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. */
-
-#include "winsup.h"
-#include "ldap.h"
-#include "cygerrno.h"
-#include "security.h"
-#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "cygheap.h"
-#include "registry.h"
-#include "pinfo.h"
-#include "lm.h"
-#include "dsgetdc.h"
-#include "tls_pbuf.h"
-
-#define CYG_LDAP_ENUM_PAGESIZE 100 /* entries per page */
-
-static PWCHAR rootdse_attr[] =
-{
- (PWCHAR) L"defaultNamingContext",
- (PWCHAR) L"supportedCapabilities",
- NULL
-};
-
-static PWCHAR user_attr[] =
-{
- (PWCHAR) L"primaryGroupID",
- (PWCHAR) L"gecos",
- (PWCHAR) L"unixHomeDirectory",
- (PWCHAR) L"loginShell",
- (PWCHAR) L"uidNumber",
- NULL
-};
-
-static PWCHAR group_attr[] =
-{
- (PWCHAR) L"cn",
- (PWCHAR) L"gidNumber",
- NULL
-};
-
-PWCHAR tdom_attr[] =
-{
- (PWCHAR) L"trustPosixOffset",
- NULL
-};
-
-PWCHAR sid_attr[] =
-{
- (PWCHAR) L"objectSid",
- NULL
-};
-
-PWCHAR rfc2307_uid_attr[] =
-{
- (PWCHAR) L"uid",
- NULL
-};
-
-PWCHAR rfc2307_gid_attr[] =
-{
- (PWCHAR) L"cn",
- NULL
-};
-
-/* ================================================================= */
-/* Helper methods. */
-/* ================================================================= */
-
-inline int
-cyg_ldap::map_ldaperr_to_errno (ULONG lerr)
-{
- switch (lerr)
- {
- case LDAP_SUCCESS:
- return NO_ERROR;
- case LDAP_NO_RESULTS_RETURNED:
- /* LdapMapErrorToWin32 maps LDAP_NO_RESULTS_RETURNED to ERROR_MORE_DATA,
- which in turn is mapped to EMSGSIZE by geterrno_from_win_error. This
- is SO wrong, especially considering that LDAP_MORE_RESULTS_TO_RETURN
- is mapped to ERROR_MORE_DATA as well :-P */
- return ENMFILE;
- default:
- break;
- }
- return geterrno_from_win_error (LdapMapErrorToWin32 (lerr));
-}
-
-inline int
-cyg_ldap::wait (cygthread *thr)
-{
- if (!thr)
- return EIO;
- if (cygwait (*thr, INFINITE, cw_sig | cw_sig_eintr) != WAIT_OBJECT_0)
- {
- thr->terminate_thread ();
- _my_tls.call_signal_handler ();
- return EINTR;
- }
- thr->detach ();
- return 0;
-}
-
-/* ================================================================= */
-/* Helper struct and functions for interruptible LDAP initalization. */
-/* ================================================================= */
-
-struct cyg_ldap_init {
- cyg_ldap *that;
- PCWSTR domain;
- bool ssl;
- ULONG ret;
-};
-
-ULONG
-cyg_ldap::connect_ssl (PCWSTR domain)
-{
- ULONG ret;
-
- if (!(lh = ldap_sslinitW ((PWCHAR) domain, LDAP_SSL_PORT, 1)))
- {
- debug_printf ("ldap_init(%W) error 0x%02x", domain, LdapGetLastError ());
- return LdapGetLastError ();
- }
- if ((ret = ldap_bind_s (lh, NULL, NULL, LDAP_AUTH_NEGOTIATE)) != LDAP_SUCCESS)
- debug_printf ("ldap_bind(%W) 0x%02x", domain, ret);
- else if ((ret = ldap_search_sW (lh, NULL, LDAP_SCOPE_BASE,
- (PWCHAR) L"(objectclass=*)", rootdse_attr,
- 0, &msg))
- != LDAP_SUCCESS)
- debug_printf ("ldap_search(%W, ROOTDSE) error 0x%02x", domain, ret);
- return ret;
-}
-
-ULONG
-cyg_ldap::connect_non_ssl (PCWSTR domain)
-{
- ULONG ret;
-
- if (!(lh = ldap_initW ((PWCHAR) domain, LDAP_PORT)))
- {
- debug_printf ("ldap_init(%W) error 0x%02x", domain, LdapGetLastError ());
- return LdapGetLastError ();
- }
- if ((ret = ldap_set_option (lh, LDAP_OPT_SIGN, LDAP_OPT_ON))
- != LDAP_SUCCESS)
- debug_printf ("ldap_set_option(LDAP_OPT_SIGN) error 0x%02x", ret);
- if ((ret = ldap_set_option (lh, LDAP_OPT_ENCRYPT, LDAP_OPT_ON))
- != LDAP_SUCCESS)
- debug_printf ("ldap_set_option(LDAP_OPT_ENCRYPT) error 0x%02x", ret);
- if ((ret = ldap_bind_s (lh, NULL, NULL, LDAP_AUTH_NEGOTIATE)) != LDAP_SUCCESS)
- debug_printf ("ldap_bind(%W) 0x%02x", domain, ret);
- else if ((ret = ldap_search_sW (lh, NULL, LDAP_SCOPE_BASE,
- (PWCHAR) L"(objectclass=*)", rootdse_attr,
- 0, &msg))
- != LDAP_SUCCESS)
- debug_printf ("ldap_search(%W, ROOTDSE) error 0x%02x", domain, ret);
- return ret;
-}
-
-static DWORD WINAPI
-ldap_init_thr (LPVOID param)
-{
- cyg_ldap_init *cl = (cyg_ldap_init *) param;
- cl->ret = cl->ssl ? cl->that->connect_ssl (cl->domain)
- : cl->that->connect_non_ssl (cl->domain);
- return 0;
-}
-
-inline int
-cyg_ldap::connect (PCWSTR domain)
-{
- /* FIXME? connect_ssl can take ages even when failing, so we're trying to
- do everything the non-SSL (but still encrypted) way. */
- cyg_ldap_init cl = { this, domain, false, NO_ERROR };
- cygthread *thr = new cygthread (ldap_init_thr, &cl, "ldap_init");
- return wait (thr) ?: map_ldaperr_to_errno (cl.ret);
-}
-
-/* ================================================================= */
-/* Helper struct and functions for interruptible LDAP search. */
-/* ================================================================= */
-
-struct cyg_ldap_search {
- cyg_ldap *that;
- PWCHAR base;
- PWCHAR filter;
- PWCHAR *attrs;
- ULONG ret;
-};
-
-ULONG
-cyg_ldap::search_s (PWCHAR base, PWCHAR filter, PWCHAR *attrs)
-{
- ULONG ret;
-
- if ((ret = ldap_search_sW (lh, base, LDAP_SCOPE_SUBTREE, filter,
- attrs, 0, &msg)) != LDAP_SUCCESS)
- debug_printf ("ldap_search_sW(%W,%W) error 0x%02x", base, filter, ret);
- return ret;
-}
-
-static DWORD WINAPI
-ldap_search_thr (LPVOID param)
-{
- cyg_ldap_search *cl = (cyg_ldap_search *) param;
- cl->ret = cl->that->search_s (cl->base, cl->filter, cl->attrs);
- return 0;
-}
-
-inline int
-cyg_ldap::search (PWCHAR base, PWCHAR filter, PWCHAR *attrs)
-{
- cyg_ldap_search cl = { this, base, filter, attrs, NO_ERROR };
- cygthread *thr = new cygthread (ldap_search_thr, &cl, "ldap_search");
- return wait (thr) ?: map_ldaperr_to_errno (cl.ret);
-}
-
-/* ================================================================= */
-/* Helper struct and functions for interruptible LDAP page search. */
-/* ================================================================= */
-
-struct cyg_ldap_next_page {
- cyg_ldap *that;
- ULONG ret;
-};
-
-ULONG
-cyg_ldap::next_page_s ()
-{
- ULONG total;
- ULONG ret;
-
- do
- {
- ret = ldap_get_next_page_s (lh, srch_id, NULL, CYG_LDAP_ENUM_PAGESIZE,
- &total, &srch_msg);
- }
- while (ret == LDAP_SUCCESS && ldap_count_entries (lh, srch_msg) == 0);
- if (ret && ret != LDAP_NO_RESULTS_RETURNED)
- debug_printf ("ldap_result() error 0x%02x", ret);
- return ret;
-}
-
-static DWORD WINAPI
-ldap_next_page_thr (LPVOID param)
-{
- cyg_ldap_next_page *cl = (cyg_ldap_next_page *) param;
- cl->ret = cl->that->next_page_s ();
- return 0;
-}
-
-inline int
-cyg_ldap::next_page ()
-{
- cyg_ldap_next_page cl = { this, NO_ERROR };
- cygthread *thr = new cygthread (ldap_next_page_thr, &cl, "ldap_next_page");
- return wait (thr) ?: map_ldaperr_to_errno (cl.ret);
-}
-
-/* ================================================================= */
-/* Public methods. */
-/* ================================================================= */
-
-int
-cyg_ldap::open (PCWSTR domain)
-{
- int ret = 0;
-
- /* Already open? */
- if (lh)
- return 0;
-
- if ((ret = connect (domain)) != NO_ERROR)
- goto err;
- /* Prime `ret' and fetch ROOTDSE search result. */
- ret = EIO;
- if (!(entry = ldap_first_entry (lh, msg)))
- {
- debug_printf ("No ROOTDSE entry for %W", domain);
- goto err;
- }
- if (!(val = ldap_get_valuesW (lh, entry, rootdse_attr[0])))
- {
- debug_printf ("No ROOTDSE value for %W", domain);
- goto err;
- }
- if (!(rootdse = wcsdup (val[0])))
- {
- debug_printf ("wcsdup(%W, ROOTDSE) %d", domain, get_errno ());
- goto err;
- }
- ldap_value_freeW (val);
- if ((val = ldap_get_valuesW (lh, entry, rootdse_attr[1])))
- {
- for (ULONG idx = 0; idx < ldap_count_valuesW (val); ++idx)
- if (!wcscmp (val[idx], LDAP_CAP_ACTIVE_DIRECTORY_OID_W))
- {
- isAD = true;
- break;
- }
- }
- ldap_value_freeW (val);
- val = NULL;
- ldap_msgfree (msg);
- msg = entry = NULL;
- return 0;
-err:
- close ();
- return ret;
-}
-
-void
-cyg_ldap::close ()
-{
- if (srch_id != NULL)
- ldap_search_abandon_page (lh, srch_id);
- if (lh)
- ldap_unbind (lh);
- if (srch_msg)
- ldap_msgfree (srch_msg);
- if (msg)
- ldap_msgfree (msg);
- if (val)
- ldap_value_freeW (val);
- if (rootdse)
- free (rootdse);
- lh = NULL;
- msg = entry = NULL;
- val = NULL;
- rootdse = NULL;
- srch_id = NULL;
- srch_msg = srch_entry = NULL;
-}
-
-bool
-cyg_ldap::fetch_ad_account (PSID sid, bool group, PCWSTR domain)
-{
- WCHAR filter[140], *f, *rdse = rootdse;
- LONG len = (LONG) RtlLengthSid (sid);
- PBYTE s = (PBYTE) sid;
- static WCHAR hex_wchars[] = L"0123456789abcdef";
- tmp_pathbuf tp;
-
- if (msg)
- {
- ldap_msgfree (msg);
- msg = entry = NULL;
- }
- if (val)
- {
- ldap_value_freeW (val);
- val = NULL;
- }
- f = wcpcpy (filter, L"(objectSid=");
- while (len-- > 0)
- {
- *f++ = L'\\';
- *f++ = hex_wchars[*s >> 4];
- *f++ = hex_wchars[*s++ & 0xf];
- }
- wcpcpy (f, L")");
- if (domain)
- {
- /* FIXME: This is a hack. The most correct solution is probably to
- open a connection to the DC of the trusted domain. But this always
- takes extra time, so we're trying to avoid it. If this results in
- problems, we know what to do. */
- rdse = tp.w_get ();
- PWCHAR r = rdse;
- for (PWCHAR dotp = (PWCHAR) domain; dotp && *dotp; domain = dotp)
- {
- dotp = wcschr (domain, L'.');
- if (dotp)
- *dotp++ = L'\0';
- if (r > rdse)
- *r++ = L',';
- r = wcpcpy (r, L"DC=");
- r = wcpcpy (r, domain);
- }
- }
- attr = group ? group_attr : user_attr;
- if (search (rdse, filter, attr) != 0)
- return false;
- if (!(entry = ldap_first_entry (lh, msg)))
- {
- debug_printf ("No entry for %W in rootdse %W", filter, rdse);
- return false;
- }
- return true;
-}
-
-int
-cyg_ldap::enumerate_ad_accounts (PCWSTR domain, bool group)
-{
- int ret;
- tmp_pathbuf tp;
- PCWSTR filter;
-
- close ();
- if ((ret = open (domain)) != NO_ERROR)
- return ret;
-
- if (!group)
- filter = L"(&(objectClass=User)"
- "(objectCategory=Person)"
- /* 512 == ADS_UF_NORMAL_ACCOUNT */
- "(userAccountControl:" LDAP_MATCHING_RULE_BIT_AND ":=512)"
- "(objectSid=*))";
- else if (!domain)
- filter = L"(&(objectClass=Group)"
- "(objectSid=*))";
- else
- filter = L"(&(objectClass=Group)"
- /* 1 == ACCOUNT_GROUP */
- "(!(groupType:" LDAP_MATCHING_RULE_BIT_AND ":=1))"
- "(objectSid=*))";
- srch_id = ldap_search_init_pageW (lh, rootdse, LDAP_SCOPE_SUBTREE,
- (PWCHAR) filter, sid_attr, 0, NULL, NULL,
- INFINITE, CYG_LDAP_ENUM_PAGESIZE, NULL);
- if (srch_id == NULL)
- {
- debug_printf ("ldap_search_init_pageW(%W,%W) error 0x%02x",
- rootdse, filter, LdapGetLastError ());
- return map_ldaperr_to_errno (LdapGetLastError ());
- }
- return NO_ERROR;
-}
-
-int
-cyg_ldap::next_account (cygsid &sid)
-{
- ULONG ret;
- PLDAP_BERVAL *bval;
-
- if (srch_entry)
- {
- if ((srch_entry = ldap_next_entry (lh, srch_entry))
- && (bval = ldap_get_values_lenW (lh, srch_entry, sid_attr[0])))
- {
- sid = (PSID) bval[0]->bv_val;
- ldap_value_free_len (bval);
- return NO_ERROR;
- }
- ldap_msgfree (srch_msg);
- srch_msg = srch_entry = NULL;
- }
- ret = next_page ();
- if (ret == NO_ERROR)
- {
- if ((srch_entry = ldap_first_entry (lh, srch_msg))
- && (bval = ldap_get_values_lenW (lh, srch_entry, sid_attr[0])))
- {
- sid = (PSID) bval[0]->bv_val;
- ldap_value_free_len (bval);
- return NO_ERROR;
- }
- ret = EIO;
- }
- ldap_search_abandon_page (lh, srch_id);
- srch_id = NULL;
- return ret;
-}
-
-/* Return UINT32_MAX on error to allow differing between not being able
- to fetch a value and a real 0 offset. */
-uint32_t
-cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain)
-{
- WCHAR filter[300];
-
- if (msg)
- {
- ldap_msgfree (msg);
- msg = entry = NULL;
- }
- if (val)
- {
- ldap_value_freeW (val);
- val = NULL;
- }
- /* If domain name has no dot, it's a Netbios name. In that case, filter
- by flatName rather than by name. */
- __small_swprintf (filter, L"(&(objectClass=trustedDomain)(%W=%W))",
- wcschr (domain, L'.') ? L"name" : L"flatName", domain);
- if (search (rootdse, filter, attr = tdom_attr) != 0)
- return UINT32_MAX;
- if (!(entry = ldap_first_entry (lh, msg)))
- {
- debug_printf ("No entry for %W in rootdse %W", filter, rootdse);
- return UINT32_MAX;
- }
- return get_num_attribute (0);
-}
-
-PWCHAR
-cyg_ldap::get_string_attribute (int idx)
-{
- if (val)
- ldap_value_freeW (val);
- val = ldap_get_valuesW (lh, entry, attr[idx]);
- if (val)
- return val[0];
- return NULL;
-}
-
-uint32_t
-cyg_ldap::get_num_attribute (int idx)
-{
- PWCHAR ret = get_string_attribute (idx);
- if (ret)
- return (uint32_t) wcstoul (ret, NULL, 10);
- return (uint32_t) -1;
-}
-
-bool
-cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group)
-{
- WCHAR filter[48];
- PLDAP_BERVAL *bval;
-
- if (msg)
- {
- ldap_msgfree (msg);
- msg = entry = NULL;
- }
- if (group)
- __small_swprintf (filter, L"(&(objectClass=Group)(gidNumber=%u))", id);
- else
- __small_swprintf (filter, L"(&(objectClass=User)(uidNumber=%u))", id);
- if (search (rootdse, filter, sid_attr) != 0)
- return false;
- if ((entry = ldap_first_entry (lh, msg))
- && (bval = ldap_get_values_lenW (lh, entry, sid_attr[0])))
- {
- sid = (PSID) bval[0]->bv_val;
- ldap_value_free_len (bval);
- return true;
- }
- return false;
-}
-
-PWCHAR
-cyg_ldap::fetch_unix_name_from_rfc2307 (uint32_t id, bool group)
-{
- WCHAR filter[52];
-
- if (msg)
- {
- ldap_msgfree (msg);
- msg = entry = NULL;
- }
- if (val)
- {
- ldap_value_freeW (val);
- val = NULL;
- }
- attr = group ? rfc2307_gid_attr : rfc2307_uid_attr;
- if (group)
- __small_swprintf (filter, L"(&(objectClass=posixGroup)(gidNumber=%u))", id);
- else
- __small_swprintf (filter, L"(&(objectClass=posixAccount)(uidNumber=%u))",
- id);
- if (search (rootdse, filter, attr) != 0)
- return NULL;
- if (!(entry = ldap_first_entry (lh, msg)))
- {
- debug_printf ("No entry for %W in rootdse %W", filter, rootdse);
- return NULL;
- }
- return get_string_attribute (0);
-}
-
-uid_t
-cyg_ldap::remap_uid (uid_t uid)
-{
- cygsid user (NO_SID);
- PWCHAR name;
- struct passwd *pw;
-
- if (isAD)
- {
- if (fetch_unix_sid_from_ad (uid, user, false)
- && user != NO_SID
- && (pw = internal_getpwsid (user, this)))
- return pw->pw_uid;
- }
- else if ((name = fetch_unix_name_from_rfc2307 (uid, false)))
- {
- char *mbname = NULL;
- sys_wcstombs_alloc (&mbname, HEAP_NOTHEAP, name);
- if ((pw = internal_getpwnam (mbname)))
- return pw->pw_uid;
- }
- return ILLEGAL_UID;
-}
-
-gid_t
-cyg_ldap::remap_gid (gid_t gid)
-{
- cygsid group (NO_SID);
- PWCHAR name;
- struct group *gr;
-
- if (isAD)
- {
- if (fetch_unix_sid_from_ad (gid, group, true)
- && group != NO_SID
- && (gr = internal_getgrsid (group, this)))
- return gr->gr_gid;
- }
- else if ((name = fetch_unix_name_from_rfc2307 (gid, true)))
- {
- char *mbname = NULL;
- sys_wcstombs_alloc (&mbname, HEAP_NOTHEAP, name);
- if ((gr = internal_getgrnam (mbname)))
- return gr->gr_gid;
- }
- return ILLEGAL_GID;
-}
diff --git a/winsup/cygwin/ldap.h b/winsup/cygwin/ldap.h
deleted file mode 100644
index 7f90a3821..000000000
--- a/winsup/cygwin/ldap.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* ldap.h.
-
- Copyright 2014 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. */
-
-#pragma once
-
-#pragma push_macro ("DECLSPEC_IMPORT")
-#undef DECLSPEC_IMPORT
-#define DECLSPEC_IMPORT
-#include <winldap.h>
-#include <ntldap.h>
-#pragma pop_macro ("DECLSPEC_IMPORT")
-
-#define LDAP_USER_PGRP_ATTR 0
-#define LDAP_USER_GECOS_ATTR 1
-#define LDAP_USER_HOME_ATTR 2
-#define LDAP_USER_SHELL_ATTR 3
-#define LDAP_USER_UID_ATTR 4
-
-#define LDAP_GROUP_NAME_ATTR 0
-#define LDAP_GROUP_GID_ATTR 1
-
-class cyg_ldap {
- PLDAP lh;
- PWCHAR rootdse;
- PLDAPMessage msg, entry;
- PWCHAR *val;
- PWCHAR *attr;
- bool isAD;
- PLDAPSearch srch_id;
- PLDAPMessage srch_msg, srch_entry;
-
- inline int map_ldaperr_to_errno (ULONG lerr);
- inline int wait (cygthread *thr);
- inline int connect (PCWSTR domain);
- inline int search (PWCHAR base, PWCHAR filter, PWCHAR *attrs);
- inline int next_page ();
- bool fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group);
- PWCHAR fetch_unix_name_from_rfc2307 (uint32_t id, bool group);
- PWCHAR get_string_attribute (int idx);
- uint32_t get_num_attribute (int idx);
-
-public:
- cyg_ldap () : lh (NULL), rootdse (NULL), msg (NULL), entry (NULL), val (NULL),
- isAD (false), srch_id (NULL), srch_msg (NULL), srch_entry (NULL)
- {}
- ~cyg_ldap () { close (); }
-
- ULONG connect_ssl (PCWSTR domain);
- ULONG connect_non_ssl (PCWSTR domain);
- ULONG search_s (PWCHAR base, PWCHAR filter, PWCHAR *attrs);
- ULONG next_page_s ();
-
- operator PLDAP () const { return lh; }
- int open (PCWSTR in_domain);
- void close ();
- bool fetch_ad_account (PSID sid, bool group, PCWSTR domain = NULL);
- int enumerate_ad_accounts (PCWSTR domain, bool group);
- int next_account (cygsid &sid);
- uint32_t fetch_posix_offset_for_domain (PCWSTR domain);
- uid_t remap_uid (uid_t uid);
- gid_t remap_gid (gid_t gid);
- /* User only */
- gid_t get_primary_gid () { return get_num_attribute (LDAP_USER_PGRP_ATTR); }
- PWCHAR get_gecos () { return get_string_attribute (LDAP_USER_GECOS_ATTR); }
- PWCHAR get_home ()
- { return get_string_attribute (LDAP_USER_HOME_ATTR); }
- PWCHAR get_shell () { return get_string_attribute (LDAP_USER_SHELL_ATTR); }
- gid_t get_unix_uid () { return get_num_attribute (LDAP_USER_UID_ATTR); }
- /* group only */
- PWCHAR get_group_name ()
- { return get_string_attribute (LDAP_GROUP_NAME_ATTR); }
- gid_t get_unix_gid () { return get_num_attribute (LDAP_GROUP_GID_ATTR); }
-};
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index eee47a53a..3787853d5 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -387,82 +387,6 @@ WritePipeOverlapped (HANDLE h, LPCVOID buf, DWORD len, LPDWORD ret_len,
return ret;
}
-bool
-NT_readline::init (POBJECT_ATTRIBUTES attr, PCHAR in_buf, ULONG in_buflen)
-{
- NTSTATUS status;
- IO_STATUS_BLOCK io;
-
- status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, attr, &io,
- FILE_SHARE_VALID_FLAGS,
- FILE_SYNCHRONOUS_IO_NONALERT
- | FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
- {
- paranoid_printf ("NtOpenFile(%S) failed, status %y",
- attr->ObjectName, status);
- return false;
- }
- buf = in_buf;
- buflen = in_buflen;
- got = end = buf;
- len = 0;
- line = 1;
- return true;
-}
-
-PCHAR
-NT_readline::gets ()
-{
- IO_STATUS_BLOCK io;
-
- while (true)
- {
- /* len == 0 indicates we have to read from the file. */
- if (!len)
- {
- if (!NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, got,
- (buflen - 2) - (got - buf), NULL, NULL)))
- return NULL;
- len = io.Information;
- /* Set end marker. */
- got[len] = got[len + 1] = '\0';
- /* Set len to the absolute len of bytes in buf. */
- len += got - buf;
- /* Reset got to start reading at the start of the buffer again. */
- got = end = buf;
- }
- else
- {
- got = end + 1;
- ++line;
- }
- /* Still some valid full line? */
- if (got < buf + len)
- {
- if ((end = strchr (got, '\n')))
- {
- end[end[-1] == '\r' ? -1 : 0] = '\0';
- return got;
- }
- /* Last line missing a \n at EOF? */
- if (len < buflen - 2)
- {
- len = 0;
- return got;
- }
- }
- /* We have to read once more. Move remaining bytes to the start of
- the buffer and reposition got so that it points to the end of
- the remaining bytes. */
- len = buf + len - got;
- memmove (buf, got, len);
- got = buf + len;
- buf[len] = buf[len + 1] = '\0';
- len = 0;
- }
-}
-
/* backslashify: Convert all forward slashes in src path to back slashes
in dst path. Add a trailing slash to dst when trailing_slash_p arg
is set to 1. */
diff --git a/winsup/cygwin/miscfuncs.h b/winsup/cygwin/miscfuncs.h
index e42940c1a..bc36a1987 100644
--- a/winsup/cygwin/miscfuncs.h
+++ b/winsup/cygwin/miscfuncs.h
@@ -1,7 +1,7 @@
/* miscfuncs.h: main Cygwin header file.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -23,25 +23,6 @@ BOOL WINAPI ReadPipeOverlapped (HANDLE h, PVOID buf, DWORD len,
BOOL WINAPI WritePipeOverlapped (HANDLE h, LPCVOID buf, DWORD len,
LPDWORD ret_len, DWORD timeout);
-/* class for per-line reading using native functions. The caller provides
- the file as an POBJECT_ATTRIBUTES, and the buffer space. */
-class NT_readline
-{
- HANDLE fh;
- PCHAR buf;
- PCHAR got;
- PCHAR end;
- ULONG buflen;
- ULONG len;
- ULONG line;
-public:
- NT_readline () : fh (NULL) {}
- bool init (POBJECT_ATTRIBUTES attr, char *buf, ULONG buflen);
- PCHAR gets ();
- void close () { if (fh) NtClose (fh); fh = NULL; }
- ~NT_readline () { close (); }
-};
-
extern "C" void yield ();
#define import_address(x) __import_address ((void *)(x))
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index 94e305489..2d8d38a15 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -1177,9 +1177,10 @@ mount_info::from_fstab (bool user, WCHAR fstab[], PWCHAR fstab_end)
{
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
- NT_readline rl;
+ IO_STATUS_BLOCK io;
+ NTSTATUS status;
+ HANDLE fh;
tmp_pathbuf tp;
- char *buf = tp.c_get ();
if (user)
{
@@ -1194,10 +1195,81 @@ mount_info::from_fstab (bool user, WCHAR fstab[], PWCHAR fstab_end)
RtlInitUnicodeString (&upath, fstab);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
debug_printf ("Try to read mounts from %W", fstab);
- if (rl.init (&attr, buf, NT_MAX_PATH))
- while ((buf = rl.gets ()))
- if (!from_fstab_line (buf, user))
+ status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS (status))
+ {
+ debug_printf ("NtOpenFile(%S) failed, %y", &upath, status);
+ return false;
+ }
+
+ char *buf = tp.c_get ();
+ char *got = buf;
+ DWORD len = 0;
+ unsigned line = 1;
+ /* Using buffer size - 2 leaves space to append two \0. */
+ while (NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, got,
+ (NT_MAX_PATH - 2) - (got - buf), NULL, NULL)))
+ {
+ char *end;
+
+ len = io.Information;
+ /* Set end marker. */
+ got[len] = got[len + 1] = '\0';
+ /* Set len to the absolute len of bytes in buf. */
+ len += got - buf;
+ /* Reset got to start reading at the start of the buffer again. */
+ got = buf;
+retry:
+ bool got_nl = false;
+ while (got < buf + len && (end = strchr (got, '\n')))
+ {
+ got_nl = true;
+ end[end[-1] == '\r' ? -1 : 0] = '\0';
+ if (!from_fstab_line (got, user))
+ goto done;
+ got = end + 1;
+ ++line;
+ }
+ if (len < (NT_MAX_PATH - 2))
break;
+ /* Check if the buffer contained at least one \n. If not, the
+ line length is > 32K. We don't take such long lines. Print
+ a debug message and skip this line entirely. */
+ if (!got_nl)
+ {
+ system_printf ("%W: Line %d too long, skipping...", fstab, line);
+ while (NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, buf,
+ (NT_MAX_PATH - 2), NULL, NULL)))
+ {
+ len = io.Information;
+ buf[len] = buf[len + 1] = '\0';
+ got = strchr (buf, '\n');
+ if (got)
+ {
+ ++got;
+ ++line;
+ goto retry;
+ }
+ }
+ got = buf;
+ break;
+ }
+ /* We have to read once more. Move remaining bytes to the start of
+ the buffer and reposition got so that it points to the end of
+ the remaining bytes. */
+ len = buf + len - got;
+ memmove (buf, got, len);
+ got = buf + len;
+ buf[len] = buf[len + 1] = '\0';
+ }
+ /* Catch a last line without trailing \n. */
+ if (got > buf)
+ from_fstab_line (got, user);
+done:
+ NtClose (fh);
return true;
}
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc
index b8ed09466..88690e379 100644
--- a/winsup/cygwin/passwd.cc
+++ b/winsup/cygwin/passwd.cc
@@ -10,7 +10,6 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <lm.h>
#include <stdlib.h>
#include <stdio.h>
#include "cygerrno.h"
@@ -20,210 +19,127 @@ details. */
#include "dtable.h"
#include "pinfo.h"
#include "cygheap.h"
+#include "pwdgrp.h"
#include "shared_info.h"
-#include "miscfuncs.h"
-#include "ldap.h"
-#include "tls_pbuf.h"
+
+/* Read /etc/passwd only once for better performance. This is done
+ on the first call that needs information from it. */
+
+passwd *passwd_buf;
+static pwdgrp pr (passwd_buf);
/* Parse /etc/passwd line into passwd structure. */
bool
pwdgrp::parse_passwd ()
{
- pg_pwd &res = passwd ()[curr_lines];
- res.p.pw_name = next_str (':');
- res.p.pw_passwd = next_str (':');
- if (!next_num (res.p.pw_uid))
+ passwd &res = (*passwd_buf)[curr_lines];
+ res.pw_name = next_str (':');
+ res.pw_passwd = next_str (':');
+ if (!next_num (res.pw_uid))
return false;
- if (!next_num (res.p.pw_gid))
+ if (!next_num (res.pw_gid))
return false;
- res.p.pw_comment = NULL;
- res.p.pw_gecos = next_str (':');
- res.p.pw_dir = next_str (':');
- res.p.pw_shell = next_str (':');
- res.sid.getfrompw (&res.p);
- /* lptr points to the \0 after pw_shell. Increment by one to get the correct
- required buffer len in getpw_cp. */
- res.len = lptr - res.p.pw_name + 1;
+ res.pw_comment = NULL;
+ res.pw_gecos = next_str (':');
+ res.pw_dir = next_str (':');
+ res.pw_shell = next_str (':');
return true;
}
+/* Read in /etc/passwd and save contents in the password cache.
+ This sets pr to loaded or emulated so functions in this file can
+ tell that /etc/passwd has been read in or will be emulated. */
void
-pwdgrp::init_pwd ()
-{
- pwdgrp_buf_elem_size = sizeof (pg_pwd);
- parse = &pwdgrp::parse_passwd;
+pwdgrp::read_passwd ()
+{
+ load (L"\\etc\\passwd");
+
+ char strbuf[128] = "";
+ bool searchentry = true;
+ struct passwd *pw;
+ /* must be static */
+ static char NO_COPY pretty_ls[] = "????????:*:-1:-1:::";
+
+ add_line (pretty_ls);
+ cygsid tu = cygheap->user.sid ();
+ tu.string (strbuf);
+ if (!user_shared->cb || myself->uid == ILLEGAL_UID)
+ searchentry = !internal_getpwsid (tu);
+ if (searchentry
+ && (!(pw = internal_getpwnam (cygheap->user.name ()))
+ || !user_shared->cb
+ || (myself->uid != ILLEGAL_UID
+ && myself->uid != pw->pw_uid
+ && !internal_getpwuid (myself->uid))))
+ {
+ static char linebuf[1024]; // must be static and
+ // should not be NO_COPY
+ snprintf (linebuf, sizeof (linebuf), "%s:*:%u:%u:,%s:%s:/bin/sh",
+ cygheap->user.name (),
+ (!user_shared->cb || myself->uid == ILLEGAL_UID)
+ ? UNKNOWN_UID : myself->uid,
+ !user_shared->cb ? UNKNOWN_GID : myself->gid,
+ strbuf, getenv ("HOME") ?: "");
+ debug_printf ("Completing /etc/passwd: %s", linebuf);
+ add_line (linebuf);
+ }
}
struct passwd *
-pwdgrp::find_user (cygpsid &sid)
+internal_getpwsid (cygpsid &sid)
{
- for (ULONG i = 0; i < curr_lines; i++)
- if (sid == passwd ()[i].sid)
- return &passwd ()[i].p;
- return NULL;
-}
+ struct passwd *pw;
+ char *ptr1, *ptr2, *endptr;
+ char sid_string[128] = {0,','};
-struct passwd *
-pwdgrp::find_user (const char *name)
-{
- for (ULONG i = 0; i < curr_lines; i++)
- /* on Windows NT user names are case-insensitive */
- if (strcasematch (name, passwd ()[i].p.pw_name))
- return &passwd ()[i].p;
- return NULL;
-}
+ pr.refresh (false);
-struct passwd *
-pwdgrp::find_user (uid_t uid)
-{
- for (ULONG i = 0; i < curr_lines; i++)
- if (uid == passwd ()[i].p.pw_uid)
- return &passwd ()[i].p;
- return NULL;
-}
-
-struct passwd *
-internal_getpwsid (cygpsid &sid, cyg_ldap *pldap)
-{
- struct passwd *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.find_user (sid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ()
- && (ret = cygheap->pg.pwd_cache.file.find_user (sid)))
- return ret;
- if (cygheap->pg.nss_pwd_db ()
- && (ret = cygheap->pg.pwd_cache.win.find_user (sid)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.add_user_from_cygserver (sid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ())
+ if (sid.string (sid_string + 2))
{
- cygheap->pg.pwd_cache.file.check_file ();
- if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (sid)))
- return ret;
+ endptr = strchr (sid_string + 2, 0) - 1;
+ for (int i = 0; i < pr.curr_lines; i++)
+ {
+ pw = passwd_buf + i;
+ if (pw->pw_dir > pw->pw_gecos + 8)
+ for (ptr1 = endptr, ptr2 = pw->pw_dir - 2;
+ *ptr1 == *ptr2; ptr2--)
+ if (!*--ptr1)
+ return pw;
+ }
}
- if (cygheap->pg.nss_pwd_db ())
- return cygheap->pg.pwd_cache.win.add_user_from_windows (sid, pldap);
return NULL;
}
-/* This function gets only called from mkpasswd via cygwin_internal. */
struct passwd *
-internal_getpwsid_from_db (cygpsid &sid)
+internal_getpwuid (uid_t uid, bool check)
{
- cygheap->pg.nss_init ();
- return cygheap->pg.pwd_cache.win.add_user_from_windows (sid);
-}
+ pr.refresh (check);
-struct passwd *
-internal_getpwnam (const char *name, cyg_ldap *pldap)
-{
- struct passwd *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.find_user (name)))
- return ret;
- if (cygheap->pg.nss_pwd_files ()
- && (ret = cygheap->pg.pwd_cache.file.find_user (name)))
- return ret;
- if (cygheap->pg.nss_pwd_db ()
- && (ret = cygheap->pg.pwd_cache.win.find_user (name)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.add_user_from_cygserver (name)))
- return ret;
- if (cygheap->pg.nss_pwd_files ())
- {
- cygheap->pg.pwd_cache.file.check_file ();
- if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (name)))
- return ret;
- }
- if (cygheap->pg.nss_pwd_db ())
- return cygheap->pg.pwd_cache.win.add_user_from_windows (name, pldap);
+ for (int i = 0; i < pr.curr_lines; i++)
+ if (uid == passwd_buf[i].pw_uid)
+ return passwd_buf + i;
return NULL;
}
struct passwd *
-internal_getpwuid (uid_t uid, cyg_ldap *pldap)
+internal_getpwnam (const char *name, bool check)
{
- struct passwd *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.find_user (uid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ()
- && (ret = cygheap->pg.pwd_cache.file.find_user (uid)))
- return ret;
- if (cygheap->pg.nss_pwd_db ()
- && (ret = cygheap->pg.pwd_cache.win.find_user (uid)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.add_user_from_cygserver (uid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ())
- {
- cygheap->pg.pwd_cache.file.check_file ();
- if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (uid)))
- return ret;
- }
- if (cygheap->pg.nss_pwd_db () || uid == ILLEGAL_UID)
- return cygheap->pg.pwd_cache.win.add_user_from_windows (uid, pldap);
+ pr.refresh (check);
+
+ for (int i = 0; i < pr.curr_lines; i++)
+ /* on Windows NT user names are case-insensitive */
+ if (strcasematch (name, passwd_buf[i].pw_name))
+ return passwd_buf + i;
return NULL;
}
-/* getpwuid/getpwnam are not reentrant. */
-static struct {
- struct passwd p;
- char *buf;
- size_t bufsiz;
-} app_pw;
-
-static struct passwd *
-getpw_cp (struct passwd *temppw)
-{
- if (!temppw)
- return NULL;
- pg_pwd *pw = (pg_pwd *) temppw;
- if (app_pw.bufsiz < pw->len)
- {
- char *newbuf = (char *) realloc (app_pw.buf, pw->len);
- if (!newbuf)
- {
- set_errno (ENOMEM);
- return NULL;
- }
- app_pw.buf = newbuf;
- app_pw.bufsiz = pw->len;
- }
- memcpy (app_pw.buf, pw->p.pw_name, pw->len);
- memcpy (&app_pw.p, &pw->p, sizeof pw->p);
- ptrdiff_t diff = app_pw.buf - pw->p.pw_name;
- app_pw.p.pw_name += diff;
- app_pw.p.pw_passwd += diff;
- app_pw.p.pw_gecos += diff;
- app_pw.p.pw_dir += diff;
- app_pw.p.pw_shell += diff;
- return &app_pw.p;
-}
extern "C" struct passwd *
getpwuid32 (uid_t uid)
{
- struct passwd *temppw = internal_getpwuid (uid);
+ struct passwd *temppw = internal_getpwuid (uid, true);
pthread_testcancel ();
- return getpw_cp (temppw);
+ return temppw;
}
#ifdef __x86_64__
@@ -244,7 +160,7 @@ getpwuid_r32 (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struc
if (!pwd || !buffer)
return ERANGE;
- struct passwd *temppw = internal_getpwuid (uid);
+ struct passwd *temppw = internal_getpwuid (uid, true);
pthread_testcancel ();
if (!temppw)
return 0;
@@ -282,9 +198,9 @@ getpwuid_r (__uid16_t uid, struct passwd *pwd, char *buffer, size_t bufsize, str
extern "C" struct passwd *
getpwnam (const char *name)
{
- struct passwd *temppw = internal_getpwnam (name);
+ struct passwd *temppw = internal_getpwnam (name, true);
pthread_testcancel ();
- return getpw_cp (temppw);
+ return temppw;
}
@@ -300,7 +216,7 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s
if (!pwd || !buffer || !nam)
return ERANGE;
- struct passwd *temppw = internal_getpwnam (nam);
+ struct passwd *temppw = internal_getpwnam (nam, true);
pthread_testcancel ();
if (!temppw)
@@ -326,429 +242,37 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s
return 0;
}
-/* getpwent functions are not reentrant. */
-static pw_ent pwent;
-
-void
-pg_ent::clear_cache ()
-{
- if (pg.curr_lines)
- {
- if (state > from_file)
- cfree (group ? grp.g.gr_name : pwd.p.pw_name);
- pg.curr_lines = 0;
- }
-}
-
-void
-pg_ent::setent (bool _group, int _enums, PCWSTR _enum_tdoms)
-{
- cygheap->dom.init ();
- endent (_group);
- if (!_enums && !_enum_tdoms)
- {
- /* This is the default, when called from the usual setpwent/setgrent
- functions. */
- enums = cygheap->pg.nss_db_enums ();
- enum_tdoms = cygheap->pg.nss_db_enum_tdoms ();
- if (_group)
- {
- from_files = cygheap->pg.nss_grp_files ();
- from_db = cygheap->pg.nss_grp_db ();
- }
- else
- {
- from_files = cygheap->pg.nss_pwd_files ();
- from_db = cygheap->pg.nss_pwd_db ();
- }
- }
- else
- {
- /* This case is when called from mkpasswd/mkgroup via cygwin_internal. */
- enums = _enums;
- enum_tdoms = _enum_tdoms;
- from_files = false;
- from_db = true;
- }
- state = from_cache;
-}
-
-void *
-pg_ent::getent (void)
-{
- void *entry;
-
- switch (state)
- {
- case rewound:
- state = from_cache;
- /*FALLTHRU*/
- case from_cache:
- if (nss_db_enum_caches ()
- && (entry = enumerate_caches ()))
- return entry;
- state = from_file;
- /*FALLTHRU*/
- case from_file:
- if (from_files
- && nss_db_enum_files ()
- && (entry = enumerate_file ()))
- return entry;
- state = from_builtin;
- /*FALLTHRU*/
- case from_builtin:
- if (from_db
- && nss_db_enum_builtin ()
- && (entry = enumerate_builtin ()))
- return entry;
- state = from_local;
- /*FALLTHRU*/
- case from_local:
- if (from_db
- && nss_db_enum_local ()
- && (!cygheap->dom.member_machine ()
- || !nss_db_enum_primary ())
- && (entry = enumerate_local ()))
- return entry;
- state = from_sam;
- /*FALLTHRU*/
- case from_sam:
- if (from_db
- && nss_db_enum_local ()
- /* Domain controller? If so, sam and ad are one and the same
- and "local ad" would list all domain accounts twice without
- this test. */
- && (cygheap->dom.account_flat_name ()[0] != L'@'
- || !nss_db_enum_primary ())
- && (entry = enumerate_sam ()))
- return entry;
- state = from_ad;
- /*FALLTHRU*/
- case from_ad:
- if (cygheap->dom.member_machine ()
- && from_db
- && (entry = enumerate_ad ()))
- return entry;
- state = finished;
- /*FALLTHRU*/
- case finished:
- break;
- }
- return NULL;
-}
-
-void
-pg_ent::endent (bool _group)
-{
- if (buf)
- {
- if (state == from_file)
- free (buf);
- else if (state == from_local || state == from_sam)
- NetApiBufferFree (buf);
- buf = NULL;
- }
- if (!pg.curr_lines)
- {
- if ((group = _group))
- {
- pg.init_grp ();
- pg.pwdgrp_buf = (void *) &grp;
- }
- else
- {
- pg.init_pwd ();
- pg.pwdgrp_buf = (void *) &pwd;
- }
- pg.max_lines = 1;
- }
- else
- clear_cache ();
- cldap.close ();
- rl.close ();
- cnt = max = resume = 0;
- enums = 0;
- enum_tdoms = NULL;
- state = rewound;
-}
-
-void *
-pg_ent::enumerate_file ()
-{
- void *entry;
-
- if (!cnt)
- {
- pwdgrp &prf = group ? cygheap->pg.grp_cache.file
- : cygheap->pg.pwd_cache.file;
- if (prf.check_file ())
- {
- if (!buf)
- buf = (char *) malloc (NT_MAX_PATH);
- if (buf
- && !rl.init (prf.file_attr (), buf, NT_MAX_PATH))
- {
- free (buf);
- buf = NULL;
- }
- }
- }
- ++cnt;
- if ((entry = pg.add_account_post_fetch (rl.gets (), false)))
- return entry;
- rl.close ();
- free (buf);
- buf = NULL;
- cnt = max = resume = 0;
- return NULL;
-}
-
-void *
-pg_ent::enumerate_builtin ()
-{
- static cygpsid *pwd_builtins[] = {
- &well_known_system_sid,
- &well_known_local_service_sid,
- &well_known_network_service_sid,
- &well_known_admins_sid,
- &trusted_installer_sid,
- NULL
- };
- static cygpsid *grp_builtins[] = {
- &well_known_system_sid,
- &trusted_installer_sid,
- NULL
- };
-
- cygpsid **builtins = group ? grp_builtins : pwd_builtins;
- if (!builtins[cnt])
- {
- cnt = max = resume = 0;
- return NULL;
- }
- cygsid sid (*builtins[cnt++]);
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg);
- return pg.add_account_post_fetch (line, false);
-}
-
-void *
-pg_ent::enumerate_sam ()
-{
- while (true)
- {
- if (!cnt)
- {
- DWORD total;
- NET_API_STATUS ret;
-
- if (buf)
- {
- NetApiBufferFree (buf);
- buf = NULL;
- }
- if (resume == ULONG_MAX)
- ret = ERROR_NO_MORE_ITEMS;
- else if (group)
- ret = NetGroupEnum (NULL, 2, (PBYTE *) &buf, MAX_PREFERRED_LENGTH,
- &max, &total, &resume);
- else
- ret = NetUserEnum (NULL, 20, FILTER_NORMAL_ACCOUNT, (PBYTE *) &buf,
- MAX_PREFERRED_LENGTH, &max, &total,
- (PDWORD) &resume);
- if (ret == NERR_Success)
- resume = ULONG_MAX;
- else if (ret != ERROR_MORE_DATA)
- {
- cnt = max = resume = 0;
- return NULL;
- }
- }
- while (cnt < max)
- {
- cygsid sid (cygheap->dom.account_sid ());
- sid_sub_auth (sid, sid_sub_auth_count (sid)) =
- group ? ((PGROUP_INFO_2) buf)[cnt].grpi2_group_id
- : ((PUSER_INFO_20) buf)[cnt].usri20_user_id;
- ++cnt;
- ++sid_sub_auth_count (sid);
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg);
- if (line)
- return pg.add_account_post_fetch (line, false);
- }
- cnt = 0;
- }
-}
-
-void *
-pg_ent::enumerate_ad ()
+extern "C" struct passwd *
+getpwent (void)
{
- while (true)
- {
- if (!cnt)
- {
- PDS_DOMAIN_TRUSTSW td;
-
- if (!resume)
- {
- ++resume;
- if (!nss_db_enum_primary ()
- || cldap.enumerate_ad_accounts (NULL, group) != NO_ERROR)
- continue;
- }
- else if ((td = cygheap->dom.trusted_domain (resume - 1)))
- {
- ++resume;
- /* Ignore primary domain in list of trusted domains only if all
- trusted domains are enumerated anyway. This handles an
- annoying backward compatibility problem in mkpasswd/mkgroup.
- Without this test, `mkpasswd -d PRIMARY_DOMAIN' wouldn't
- work as expected. */
- if (((enums & ENUM_TDOMS_ALL) && td->Flags & DS_DOMAIN_PRIMARY)
- || !td->DomainSid
- || (!nss_db_enum_tdom (td->NetbiosDomainName)
- && !nss_db_enum_tdom (td->DnsDomainName))
- || cldap.enumerate_ad_accounts (td->DnsDomainName, group)
- != NO_ERROR)
- continue;
- }
- else
- {
- cldap.close ();
- return NULL;
- }
- }
- ++cnt;
- cygsid sid;
- int ret = cldap.next_account (sid);
- if (ret == NO_ERROR)
- {
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg, &cldap);
- if (line)
- return pg.add_account_post_fetch (line, false);
- ret = EIO;
- }
- if (ret != ENMFILE)
- {
- cldap.close ();
- set_errno (ret);
- return NULL;
- }
- cnt = 0;
- }
-}
+ if (_my_tls.locals.pw_pos == 0)
+ pr.refresh (true);
+ if (_my_tls.locals.pw_pos < pr.curr_lines)
+ return passwd_buf + _my_tls.locals.pw_pos++;
-void *
-pw_ent::enumerate_caches ()
-{
- switch (max)
- {
- case 0:
- if (cygheap->pg.nss_cygserver_caching ())
- {
- pwdgrp &prc = cygheap->pg.pwd_cache.cygserver;
- if (cnt < prc.cached_users ())
- return &prc.passwd ()[cnt++].p;
- }
- cnt = 0;
- max = 1;
- /*FALLTHRU*/
- case 1:
- if (from_files)
- {
- pwdgrp &prf = cygheap->pg.pwd_cache.file;
- prf.check_file ();
- if (cnt < prf.cached_users ())
- return &prf.passwd ()[cnt++].p;
- }
- cnt = 0;
- max = 2;
- /*FALLTHRU*/
- default:
- if (from_db)
- {
- pwdgrp &prw = cygheap->pg.pwd_cache.win;
- if (cnt < prw.cached_users ())
- return &prw.passwd ()[cnt++].p;
- }
- break;
- }
- cnt = max = 0;
return NULL;
}
-void *
-pw_ent::enumerate_local ()
+#ifndef __x86_64__
+extern "C" struct passwd *
+getpwduid (__uid16_t)
{
return NULL;
}
-
-struct passwd *
-pw_ent::getpwent (void)
-{
- if (state == rewound)
- setent (false);
- else
- clear_cache ();
- return (struct passwd *) getent ();
-}
+#endif
extern "C" void
-setpwent ()
-{
- pwent.setpwent ();
-}
-
-extern "C" struct passwd *
-getpwent (void)
+setpwent (void)
{
- return pwent.getpwent ();
+ _my_tls.locals.pw_pos = 0;
}
extern "C" void
endpwent (void)
{
- pwent.endpwent ();
+ _my_tls.locals.pw_pos = 0;
}
-/* *_filtered functions are called from mkpasswd */
-void *
-setpwent_filtered (int enums, PCWSTR enum_tdoms)
-{
- pw_ent *pw = new pw_ent;
- if (pw)
- pw->setpwent (enums, enum_tdoms);
- return (void *) pw;
-}
-
-void *
-getpwent_filtered (void *pw)
-{
- return (void *) ((pw_ent *) pw)->getpwent ();
-}
-
-void
-endpwent_filtered (void *pw)
-{
- ((pw_ent *) pw)->endpwent ();
-}
-
-#ifndef __x86_64__
-extern "C" struct passwd *
-getpwduid (__uid16_t)
-{
- return NULL;
-}
-#endif
-
extern "C" int
setpassent (int)
{
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 6a3a889a3..d8604817a 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2834,13 +2834,13 @@ restart:
This case is only recognized by the length of the
basename part. If it's 0, the incoming file is the
root of a drive. So we at least know it's a directory. */
- if (basename.Length)
- fileattr = FILE_ATTRIBUTE_DIRECTORY;
- else
- {
- fileattr = 0;
- set_error (geterrno_from_nt_status (status));
- }
+ if (basename.Length)
+ fileattr = FILE_ATTRIBUTE_DIRECTORY;
+ else
+ {
+ fileattr = 0;
+ set_error (geterrno_from_nt_status (status));
+ }
}
else
{
@@ -4695,6 +4695,142 @@ out:
return buf;
}
+int etc::curr_ix = 0;
+/* Note that the first elements of the below arrays are unused */
+bool etc::change_possible[MAX_ETC_FILES + 1];
+OBJECT_ATTRIBUTES etc::fn[MAX_ETC_FILES + 1];
+LARGE_INTEGER etc::last_modified[MAX_ETC_FILES + 1];
+
+int
+etc::init (int n, POBJECT_ATTRIBUTES attr)
+{
+ if (n > 0)
+ /* ok */;
+ else if (++curr_ix <= MAX_ETC_FILES)
+ n = curr_ix;
+ else
+ api_fatal ("internal error");
+
+ fn[n] = *attr;
+ change_possible[n] = false;
+ test_file_change (n);
+ paranoid_printf ("fn[%d] %S, curr_ix %d", n, fn[n].ObjectName, curr_ix);
+ return n;
+}
+
+bool
+etc::test_file_change (int n)
+{
+ NTSTATUS status;
+ FILE_NETWORK_OPEN_INFORMATION fnoi;
+ bool res;
+
+ status = NtQueryFullAttributesFile (&fn[n], &fnoi);
+ if (!NT_SUCCESS (status))
+ {
+ res = status != STATUS_OBJECT_NAME_NOT_FOUND;
+ memset (last_modified + n, 0, sizeof (last_modified[n]));
+ debug_printf ("NtQueryFullAttributesFile (%S) failed, %y",
+ fn[n].ObjectName, status);
+ }
+ else
+ {
+ res = CompareFileTime ((FILETIME *) &fnoi.LastWriteTime,
+ (FILETIME *) last_modified + n) > 0;
+ last_modified[n].QuadPart = fnoi.LastWriteTime.QuadPart;
+ }
+
+ paranoid_printf ("fn[%d] %S res %d", n, fn[n].ObjectName, res);
+ return res;
+}
+
+bool
+etc::dir_changed (int n)
+{
+ /* io MUST be static because NtNotifyChangeDirectoryFile works asynchronously.
+ It may write into io after the function has left, which may result in all
+ sorts of stack corruption. */
+ static IO_STATUS_BLOCK io NO_COPY;
+ static HANDLE changed_h NO_COPY;
+
+ if (!change_possible[n])
+ {
+ NTSTATUS status;
+
+ if (!changed_h)
+ {
+ OBJECT_ATTRIBUTES attr;
+
+ path_conv dir ("/etc");
+ status = NtOpenFile (&changed_h, SYNCHRONIZE | FILE_LIST_DIRECTORY,
+ dir.get_object_attr (attr, sec_none_nih), &io,
+ FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE);
+ if (!NT_SUCCESS (status))
+ {
+#ifdef DEBUGGING
+ system_printf ("NtOpenFile (%S) failed, %y",
+ dir.get_nt_native_path (), status);
+#endif
+ changed_h = INVALID_HANDLE_VALUE;
+ }
+ else
+ {
+ status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL,
+ NULL, &io, NULL, 0,
+ FILE_NOTIFY_CHANGE_LAST_WRITE
+ | FILE_NOTIFY_CHANGE_FILE_NAME,
+ FALSE);
+ if (!NT_SUCCESS (status))
+ {
+#ifdef DEBUGGING
+ system_printf ("NtNotifyChangeDirectoryFile (1) failed, %y",
+ status);
+#endif
+ NtClose (changed_h);
+ changed_h = INVALID_HANDLE_VALUE;
+ }
+ }
+ memset (change_possible, true, sizeof (change_possible));
+ }
+
+ if (changed_h == INVALID_HANDLE_VALUE)
+ change_possible[n] = true;
+ else if (WaitForSingleObject (changed_h, 0) == WAIT_OBJECT_0)
+ {
+ status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL,
+ NULL, &io, NULL, 0,
+ FILE_NOTIFY_CHANGE_LAST_WRITE
+ | FILE_NOTIFY_CHANGE_FILE_NAME,
+ FALSE);
+ if (!NT_SUCCESS (status))
+ {
+#ifdef DEBUGGING
+ system_printf ("NtNotifyChangeDirectoryFile (2) failed, %y",
+ status);
+#endif
+ NtClose (changed_h);
+ changed_h = INVALID_HANDLE_VALUE;
+ }
+ memset (change_possible, true, sizeof change_possible);
+ }
+ }
+
+ paranoid_printf ("fn[%d] %S change_possible %d",
+ n, fn[n].ObjectName, change_possible[n]);
+ return change_possible[n];
+}
+
+bool
+etc::file_changed (int n)
+{
+ bool res = false;
+ if (dir_changed (n) && test_file_change (n))
+ res = true;
+ change_possible[n] = false; /* Change is no longer possible */
+ paranoid_printf ("fn[%d] %S res %d", n, fn[n].ObjectName, res);
+ return res;
+}
+
/* No need to be reentrant or thread-safe according to SUSv3.
/ and \\ are treated equally. Leading drive specifiers are
kept intact as far as it makes sense. Everything else is
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 8d4525890..18b05261c 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -448,4 +448,21 @@ int normalize_win32_path (const char *, char *, char *&);
int normalize_posix_path (const char *, char *, char *&);
PUNICODE_STRING __reg3 get_nt_native_path (const char *, UNICODE_STRING&, bool);
+/* FIXME: Move to own include file eventually */
+
+#define MAX_ETC_FILES 2
+class etc
+{
+ friend class dtable;
+ static int curr_ix;
+ static bool change_possible[MAX_ETC_FILES + 1];
+ static OBJECT_ATTRIBUTES fn[MAX_ETC_FILES + 1];
+ static LARGE_INTEGER last_modified[MAX_ETC_FILES + 1];
+ static bool dir_changed (int);
+ static int init (int, POBJECT_ATTRIBUTES);
+ static bool file_changed (int);
+ static bool test_file_change (int);
+ friend class pwdgrp;
+};
+
int __reg3 symlink_worker (const char *, const char *, bool);
diff --git a/winsup/doc/path.xml b/winsup/cygwin/path.sgml
index 06a252bb0..79f97dff5 100644
--- a/winsup/doc/path.xml
+++ b/winsup/cygwin/path.sgml
@@ -1,14 +1,4 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-
-<sect1 id="func-cygwin-path">
-<title>Path conversion functions</title>
-
-<para>These functions are specific to Cygwin itself, and probably
-won't be found anywhere else. </para>
-
-<sect2 id="func-cygwin-conv-path">
+<sect1 id="func-cygwin-conv-path">
<title>cygwin_conv_path</title>
<funcsynopsis><funcprototype>
@@ -84,9 +74,9 @@ else
</programlisting>
</example>
-</sect2>
+</sect1>
-<sect2 id="func-cygwin-conv-path-list">
+<sect1 id="func-cygwin-conv-path-list">
<title>cygwin_conv_path_list</title>
<funcsynopsis><funcprototype>
@@ -111,9 +101,9 @@ convert it to the equivalent POSIX $PATH-style string (i.e. /foo:/bar).</para>
<para>See also <link linkend="func-cygwin-conv-path">cygwin_conv_path</link></para>
-</sect2>
+</sect1>
-<sect2 id="func-cygwin-create-path">
+<sect1 id="func-cygwin-create-path">
<title>cygwin_create_path</title>
<funcsynopsis><funcprototype>
@@ -140,9 +130,9 @@ errno can be set to the below value.</para>
<para>See also <link linkend="func-cygwin-conv-path">cygwin_conv_path</link></para>
-</sect2>
+</sect1>
-<sect2 id="func-cygwin-posix-path-list-p">
+<sect1 id="func-cygwin-posix-path-list-p">
<title>cygwin_posix_path_list_p</title>
<funcsynopsis><funcprototype>
@@ -159,9 +149,9 @@ true if the path is a POSIX path. Note that "_p" means "predicate", a
lisp term meaning that the function tells you something about the
parameter.</para>
-</sect2>
+</sect1>
-<sect2 id="func-cygwin-split-path">
+<sect1 id="func-cygwin-split-path">
<title>cygwin_split_path</title>
<funcsynopsis><funcprototype>
@@ -185,6 +175,4 @@ cygwin_split_path("c:/foo/bar.c", dir, file);
printf("dir=%s, file=%s\n", dir, file);
</programlisting>
</example>
-</sect2>
-
</sect1>
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 4518d6d51..5d9e74895 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -41,7 +41,7 @@ pinfo_basic::pinfo_basic ()
GetModuleFileNameW (NULL, progname, sizeof (progname) / sizeof (WCHAR));
/* Default uid/gid are needed very early to initialize shared user info. */
uid = ILLEGAL_UID;
- gid = ILLEGAL_GID;
+ gid = UNKNOWN_GID;
}
pinfo_basic myself_initial NO_COPY;
@@ -100,7 +100,7 @@ pinfo_init (char **envp, int envc)
myself->pgid = myself->sid = myself->pid;
myself->ctty = -1;
myself->uid = ILLEGAL_UID;
- myself->gid = ILLEGAL_GID;
+ myself->gid = UNKNOWN_GID;
environ_init (NULL, 0); /* call after myself has been set up */
myself->nice = winprio_to_nice (GetPriorityClass (GetCurrentProcess ()));
myself->ppid = 1; /* always set last */
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index 2b6f8a90a..17411a098 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -115,9 +115,8 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout)
So it looks like there's actually no good reason to
return POLLERR. */
fds[i].revents |= POLLIN;
- /* Handle failed connect. A failed connect implicitly sets
- POLLOUT, if requested, but it doesn't set POLLIN. */
- if ((fds[i].events & POLLIN)
+ /* Handle failed connect. */
+ if (FD_ISSET(fds[i].fd, write_fds)
&& (sock = cygheap->fdtab[fds[i].fd]->is_socket ())
&& sock->connect_state () == connect_failed)
fds[i].revents |= (POLLIN | POLLERR);
diff --git a/winsup/doc/posix.xml b/winsup/cygwin/posix.sgml
index 238153803..e8c97d601 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/cygwin/posix.sgml
@@ -1,10 +1,3 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-
-<chapter id="compatibility" xmlns:xi="http://www.w3.org/2001/XInclude">
-<title>Compatibility</title>
-
<sect1 id="std-susv4"><title>System interfaces compatible with the Single Unix Specification, Version 4:</title>
<para>Note that the core of the Single Unix Specification, Version 4 is
@@ -1569,5 +1562,3 @@ what works on Windows: Windows only supports user block quotas on NTFS, no
group quotas, no inode quotas, no time constraints.</para>
</sect1>
-
-</chapter>
diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h
index dfeef5680..fe3c3f2a1 100644
--- a/winsup/cygwin/pwdgrp.h
+++ b/winsup/cygwin/pwdgrp.h
@@ -1,6 +1,6 @@
/* pwdgrp.h
- Copyright 2001, 2002, 2003, 2014 Red Hat inc.
+ Copyright 2001, 2002, 2003 Red Hat inc.
Stuff common to pwd and grp handling.
@@ -10,84 +10,42 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
-#pragma once
-
-#include "sync.h"
-#include "ldap.h"
-#include "miscfuncs.h"
-
/* These functions are needed to allow searching and walking through
the passwd and group lists */
-extern struct passwd *internal_getpwsid (cygpsid &, cyg_ldap * = NULL);
-extern struct passwd *internal_getpwsid_from_db (cygpsid &sid);
-extern struct passwd *internal_getpwnam (const char *, cyg_ldap * = NULL);
-extern struct passwd *internal_getpwuid (uid_t, cyg_ldap * = NULL);
-extern struct group *internal_getgrsid (cygpsid &, cyg_ldap * = NULL);
-extern struct group *internal_getgrsid_from_db (cygpsid &sid);
-extern struct group *internal_getgrgid (gid_t, cyg_ldap * = NULL);
-extern struct group *internal_getgrnam (const char *, cyg_ldap * = NULL);
-
-extern int internal_getgroups (int, gid_t *, cyg_ldap *);
-
-/* These functions are called from mkpasswd/mkgroup via cygwin_internal. */
-void *setpwent_filtered (int enums, PCWSTR enum_tdoms);
-void *getpwent_filtered (void *gr);
-void endpwent_filtered (void *gr);
-void *setgrent_filtered (int enums, PCWSTR enum_tdoms);
-void *getgrent_filtered (void *gr);
-void endgrent_filtered (void *gr);
-
-enum fetch_user_arg_type_t {
- SID_arg,
- NAME_arg,
- ID_arg
-};
-
-struct fetch_user_arg_t
-{
- fetch_user_arg_type_t type;
- union {
- cygpsid *sid;
- const char *name;
- uint32_t id;
- };
- /* Only used in fetch_account_from_file/line. */
- size_t len;
-};
-
-struct pg_pwd
-{
- struct passwd p;
- cygsid sid;
- size_t len;
-};
-
-struct pg_grp
-{
- struct group g;
- cygsid sid;
- size_t len;
-};
+extern struct passwd *internal_getpwsid (cygpsid &);
+extern struct passwd *internal_getpwnam (const char *, bool = FALSE);
+extern struct passwd *internal_getpwuid (uid_t, bool = FALSE);
+extern struct group *internal_getgrsid (cygpsid &);
+extern struct group *internal_getgrgid (gid_t gid, bool = FALSE);
+extern struct group *internal_getgrnam (const char *, bool = FALSE);
+extern struct group *internal_getgrent (int);
+int internal_getgroups (int, gid_t *, cygpsid * = NULL);
+#include "sync.h"
+#include "cygtls.h"
class pwdgrp
{
- friend class pg_ent;
- friend class pw_ent;
- friend class gr_ent;
-
unsigned pwdgrp_buf_elem_size;
- void *pwdgrp_buf;
+ union
+ {
+ passwd **passwd_buf;
+ group **group_buf;
+ void **pwdgrp_buf;
+ };
+ void (pwdgrp::*read) ();
bool (pwdgrp::*parse) ();
- UNICODE_STRING path;
- OBJECT_ATTRIBUTES attr;
- LARGE_INTEGER last_modified;
- char *lptr;
- ULONG curr_lines;
- ULONG max_lines;
+ int etc_ix;
+ UNICODE_STRING upath;
+ PWCHAR path;
+ char *buf, *lptr;
+ int max_lines;
+ bool initialized;
static muto pglock;
bool parse_passwd ();
bool parse_group ();
+ void read_passwd ();
+ void read_group ();
char *add_line (char *);
char *raw_ptr () const {return lptr;}
char *next_str (char);
@@ -106,157 +64,21 @@ class pwdgrp
i = (int) x;
return res;
}
- void *add_account_post_fetch (char *line, bool lock);
- void *add_account_from_file (cygpsid &sid);
- void *add_account_from_file (const char *name);
- void *add_account_from_file (uint32_t id);
- void *add_account_from_windows (cygpsid &sid, cyg_ldap *pldap = NULL);
- void *add_account_from_windows (const char *name, cyg_ldap *pldap = NULL);
- void *add_account_from_windows (uint32_t id, cyg_ldap *pldap = NULL);
- void *add_account_from_cygserver (cygpsid &sid);
- void *add_account_from_cygserver (const char *name);
- void *add_account_from_cygserver (uint32_t id);
- char *fetch_account_from_line (fetch_user_arg_t &arg, const char *line);
- char *fetch_account_from_file (fetch_user_arg_t &arg);
- char *fetch_account_from_windows (fetch_user_arg_t &arg,
- cyg_ldap *pldap = NULL);
- char *fetch_account_from_cygserver (fetch_user_arg_t &arg);
-
-public:
- ULONG cached_users () const { return curr_lines; }
- ULONG cached_groups () const { return curr_lines; }
- POBJECT_ATTRIBUTES file_attr () { return &attr; }
- bool check_file ();
-
- void init_pwd ();
- bool is_passwd () const { return pwdgrp_buf_elem_size == sizeof (pg_pwd); }
- pg_pwd *passwd () const { return (pg_pwd *) pwdgrp_buf; };
- struct passwd *add_user_from_cygserver (cygpsid &sid)
- { return (struct passwd *) add_account_from_cygserver (sid); }
- struct passwd *add_user_from_cygserver (const char *name)
- { return (struct passwd *) add_account_from_cygserver (name); }
- struct passwd *add_user_from_cygserver (uint32_t id)
- { return (struct passwd *) add_account_from_cygserver (id); }
- struct passwd *add_user_from_file (cygpsid &sid)
- { return (struct passwd *) add_account_from_file (sid); }
- struct passwd *add_user_from_file (const char *name)
- { return (struct passwd *) add_account_from_file (name); }
- struct passwd *add_user_from_file (uint32_t id)
- { return (struct passwd *) add_account_from_file (id); }
- struct passwd *add_user_from_windows (cygpsid &sid, cyg_ldap *pldap = NULL)
- { return (struct passwd *) add_account_from_windows (sid, pldap); }
- struct passwd *add_user_from_windows (const char *name,
- cyg_ldap* pldap = NULL)
- { return (struct passwd *) add_account_from_windows (name, pldap); }
- struct passwd *add_user_from_windows (uint32_t id, cyg_ldap *pldap = NULL)
- { return (struct passwd *) add_account_from_windows (id, pldap); }
- struct passwd *find_user (cygpsid &sid);
- struct passwd *find_user (const char *name);
- struct passwd *find_user (uid_t uid);
-
- void init_grp ();
- bool is_group () const { return pwdgrp_buf_elem_size == sizeof (pg_grp); }
- pg_grp *group () const { return (pg_grp *) pwdgrp_buf; };
- struct group *add_group_from_cygserver (cygpsid &sid)
- { return (struct group *) add_account_from_cygserver (sid); }
- struct group *add_group_from_cygserver (const char *name)
- { return (struct group *) add_account_from_cygserver (name); }
- struct group *add_group_from_cygserver (uint32_t id)
- { return (struct group *) add_account_from_cygserver (id); }
- struct group *add_group_from_file (cygpsid &sid)
- { return (struct group *) add_account_from_file (sid); }
- struct group *add_group_from_file (const char *name)
- { return (struct group *) add_account_from_file (name); }
- struct group *add_group_from_file (uint32_t id)
- { return (struct group *) add_account_from_file (id); }
- struct group *add_group_from_windows (cygpsid &sid, cyg_ldap *pldap = NULL)
- { return (struct group *) add_account_from_windows (sid, pldap); }
- struct group *add_group_from_windows (const char *name,
- cyg_ldap *pldap = NULL)
- { return (struct group *) add_account_from_windows (name, pldap); }
- struct group *add_group_from_windows (uint32_t id, cyg_ldap *pldap = NULL)
- { return (struct group *) add_account_from_windows (id, pldap); }
- struct group *find_group (cygpsid &sid);
- struct group *find_group (const char *name);
- struct group *find_group (gid_t gid);
-};
-
-class pg_ent
-{
-protected:
- pwdgrp pg;
- bool group;
- pg_pwd pwd;
- pg_grp grp;
- NT_readline rl;
- cyg_ldap cldap;
- PCHAR buf;
- ULONG cnt;
- ULONG max;
- ULONG_PTR resume;
- int enums; /* ENUM_xxx values defined in sys/cygwin.h. */
- PCWSTR enum_tdoms;
- bool from_files;
- bool from_db;
- enum {
- rewound = 0,
- from_cache,
- from_file,
- from_builtin,
- from_local,
- from_sam,
- from_ad,
- finished
- } state;
-
- void clear_cache ();
- inline bool nss_db_enum_caches () const { return !!(enums & ENUM_CACHE); }
- inline bool nss_db_enum_files () const { return !!(enums & ENUM_FILES); }
- inline bool nss_db_enum_builtin () const { return !!(enums & ENUM_BUILTIN); }
- inline bool nss_db_enum_local () const { return !!(enums & ENUM_LOCAL); }
- inline bool nss_db_enum_primary () const { return !!(enums & ENUM_PRIMARY); }
- inline bool nss_db_enum_tdom (PWCHAR domain)
- {
- if (enums & ENUM_TDOMS_ALL)
- return true;
- if (!(enums & ENUM_TDOMS) || !enum_tdoms || !domain)
- return false;
- for (PCWSTR td = enum_tdoms; td && *td; td = wcschr (td, L'\0'))
- if (!wcscasecmp (td, domain))
- return true;
- return false;
- }
- virtual void *enumerate_caches () = 0;
- virtual void *enumerate_file ();
- virtual void *enumerate_builtin ();
- virtual void *enumerate_local () = 0;
- virtual void *enumerate_sam ();
- virtual void *enumerate_ad ();
public:
- void setent (bool _group, int _enums = 0, PCWSTR _enum_tdoms = NULL);
- void *getent ();
- void endent (bool _group);
-};
+ int curr_lines;
-class pw_ent : public pg_ent
-{
- void *enumerate_caches ();
- void *enumerate_local ();
-public:
- inline void setpwent (int _enums = 0, PCWSTR _enum_tdoms = NULL)
- { setent (false, _enums, _enum_tdoms); }
- struct passwd *getpwent ();
- inline void endpwent () { endent (false); }
-};
+ void load (const wchar_t *);
+ inline void refresh (bool check)
+ {
+ if (!check && initialized)
+ return;
+ if (pglock.acquire () == 1 &&
+ (!initialized || (check && etc::file_changed (etc_ix))))
+ (this->*read) ();
+ pglock.release ();
+ }
-class gr_ent : public pg_ent
-{
- void *enumerate_caches ();
- void *enumerate_local ();
-public:
- inline void setgrent (int _enums = 0, PCWSTR _enum_tdoms = NULL)
- { setent (true, _enums, _enum_tdoms); }
- struct group *getgrent ();
- inline void endgrent () { endent (true); }
+ pwdgrp (passwd *&pbuf);
+ pwdgrp (group *&gbuf);
};
diff --git a/winsup/cygwin/quotactl.cc b/winsup/cygwin/quotactl.cc
index 96c6134e8..fbc66eed3 100644
--- a/winsup/cygwin/quotactl.cc
+++ b/winsup/cygwin/quotactl.cc
@@ -17,6 +17,7 @@ details. */
#include "cygheap.h"
#include "ntdll.h"
#include "tls_pbuf.h"
+#include "pwdgrp.h"
#include <sys/mount.h>
#include <sys/quota.h>
diff --git a/winsup/cygwin/release/1.7.33 b/winsup/cygwin/release/1.7.33
index 28eabfbb3..0875e48a9 100644
--- a/winsup/cygwin/release/1.7.33
+++ b/winsup/cygwin/release/1.7.33
@@ -1,18 +1,6 @@
What's new:
-----------
-- Cygwin can now generate passwd/group entries directly from Windows
- user databases (local SAM or Active Directory), thus allowing to run
- Cygwin without having to create /etc/passwd and /etc/group files.
- Introduce /etc/nsswitch.conf file to configure passwd/group handling.
-
- For bordercase which require to use /etc/passwd and /etc/group files,
- change mkpasswd/mkgroup to generate passwd/group entries compatible
- with the entries read from SAM/AD.
-
-- Add -b/--remove-all option to setfacl to reduce the ACL to only the
- entries representing POSIX permission bits.
-
- /proc/cygdrive is a new symlink pointing to the current cygdrive prefix.
This can be utilized in scripts to access paths via cygdrive prefix, even
if the cygdrive prefix has been changed by the user.
@@ -29,19 +17,12 @@ What's new:
- New API: stime (SVr4).
-- Provide Cygwin documentation (PDFs and HTML) for offline usage in
- /usr/share/doc/cygwin-${version}.
-
What changed:
-------------
- New internal exception handling based on SEH on 64 bit Cygwin.
-- Revamp Solaris ACL implementation to more closely work like POSIX ACLs
- are supposed to work. Finally implement a CLASS_OBJ emulation. Update
- getfacl(1)/setfacl(1) accordingly.
-
- When exec'ing applications, check if $PATH exists and is non-empty. If not,
add PATH variable with Cygwin installation directory as content to Windows
environment to allow loading of Cygwin system DLLs.
@@ -52,9 +33,6 @@ What changed:
- Doug Lea malloc implementation update from 2.8.3 to the latest 2.8.6.
-- The xdr functions are no longer exported for newly built executables.
- Use libtirpc-devel instead.
-
- atexit is now exported as statically linked function from libcygwin.a.
This allows reliable access to the DSO handle of the caller for newly
built executables. The former atexit entry point into the DLL remains
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index 51f1c9964..2f7ac278d 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -1,7 +1,7 @@
/* sec_acl.cc: Sun compatible ACL functions.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011, 2012, 2014 Red Hat, Inc.
+ 2011, 2012 Red Hat, Inc.
Written by Corinna Vinschen <corinna@vinschen.de>
@@ -22,6 +22,7 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "ntdll.h"
+#include "pwdgrp.h"
#include "tls_pbuf.h"
static int
@@ -36,7 +37,6 @@ searchace (aclent_t *aclp, int nentries, int type, uid_t id = ILLEGAL_UID)
return -1;
}
-/* This function *requires* an acl list sorted with aclsort{32}. */
int
setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
bool &writable)
@@ -48,8 +48,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
return -1;
NTSTATUS status;
- PACL acl;
- BOOLEAN acl_exists, dummy;
+ BOOLEAN dummy;
/* Get owner SID. */
PSID owner_sid;
@@ -71,32 +70,9 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
}
cygsid group (group_sid);
- /* Search for NULL ACE and store state of SUID, SGID and VTX bits. */
- DWORD null_mask = 0;
- if (NT_SUCCESS (RtlGetDaclSecurityDescriptor (sd_ret, &acl_exists, &acl,
- &dummy)))
- for (USHORT i = 0; i < acl->AceCount; ++i)
- {
- ACCESS_ALLOWED_ACE *ace;
- if (NT_SUCCESS (RtlGetAce (acl, i, (PVOID *) &ace)))
- {
- cygpsid ace_sid ((PSID) &ace->SidStart);
- if (ace_sid == well_known_null_sid)
- {
- null_mask = ace->Mask;
- break;
- }
- }
- }
-
/* Initialize local security descriptor. */
SECURITY_DESCRIPTOR sd;
RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
-
- /* As in alloc_sd, set SE_DACL_PROTECTED to prevent the DACL from being
- modified by inheritable ACEs. */
- RtlSetControlSecurityDescriptor (&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
-
status = RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE);
if (!NT_SUCCESS (status))
{
@@ -111,7 +87,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
}
/* Fill access control list. */
- acl = (PACL) tp.w_get ();
+ PACL acl = (PACL) tp.w_get ();
size_t acl_len = sizeof (ACL);
int ace_off = 0;
@@ -119,102 +95,22 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
struct passwd *pw;
struct group *gr;
int pos;
- cyg_ldap cldap;
RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION);
writable = false;
- /* Pre-compute owner, group, and other permissions to allow creating
- matching deny ACEs as in alloc_sd. */
- DWORD owner_allow = 0, group_allow = 0, other_allow = 0;
- PDWORD allow;
- for (int i = 0; i < nentries; ++i)
- {
- switch (aclbufp[i].a_type)
- {
- case USER_OBJ:
- allow = &owner_allow;
- *allow = STANDARD_RIGHTS_ALL;
- break;
- case GROUP_OBJ:
- allow = &group_allow;
- break;
- case OTHER_OBJ:
- allow = &other_allow;
- break;
- default:
- continue;
- }
- *allow |= STANDARD_RIGHTS_READ | SYNCHRONIZE
- | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
- if (aclbufp[i].a_perm & S_IROTH)
- *allow |= FILE_GENERIC_READ;
- if (aclbufp[i].a_perm & S_IWOTH)
- {
- *allow |= FILE_GENERIC_WRITE;
- writable = true;
- }
- if (aclbufp[i].a_perm & S_IXOTH)
- *allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
- /* Keep S_ISVTX rule in sync with alloc_sd. */
- if (pc.isdir ()
- && (aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)
- && (aclbufp[i].a_type == USER_OBJ
- || !(null_mask & FILE_READ_DATA)))
- *allow |= FILE_DELETE_CHILD;
- aclbufp[i].a_type = 0;
- }
- bool isownergroup = (owner_sid == group_sid);
- DWORD owner_deny = ~owner_allow & (group_allow | other_allow);
- owner_deny &= ~(STANDARD_RIGHTS_READ
- | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES);
- DWORD group_deny = ~group_allow & other_allow;
- group_deny &= ~(STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES);
-
- /* Set deny ACE for owner. */
- if (owner_deny
- && !add_access_denied_ace (acl, ace_off++, owner_deny,
- owner_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set deny ACE for group here to respect the canonical order,
- if this does not impact owner */
- if (group_deny && !(group_deny & owner_allow) && !isownergroup
- && !add_access_denied_ace (acl, ace_off++, group_deny,
- group_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set allow ACE for owner. */
- if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
- owner_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set deny ACE for group, if still needed. */
- if (group_deny & owner_allow && !isownergroup
- && !add_access_denied_ace (acl, ace_off++, group_deny,
- group_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set allow ACE for group. */
- if (!isownergroup
- && !add_access_allowed_ace (acl, ace_off++, group_allow,
- group_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set allow ACE for everyone. */
- if (!add_access_allowed_ace (acl, ace_off++, other_allow,
- well_known_world_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* If a NULL ACE exists, copy it verbatim. */
- if (null_mask)
- if (!add_access_allowed_ace (acl, ace_off++, null_mask, well_known_null_sid,
- acl_len, NO_INHERITANCE))
- return -1;
for (int i = 0; i < nentries; ++i)
{
DWORD allow;
- /* Skip invalidated entries. */
- if (!aclbufp[i].a_type)
- continue;
-
- allow = STANDARD_RIGHTS_READ
- | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
+ /* Owner has more standard rights set. */
+ if ((aclbufp[i].a_type & ~ACL_DEFAULT) == USER_OBJ)
+ allow = STANDARD_RIGHTS_ALL
+ | (pc.fs_is_samba ()
+ ? 0 : (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES));
+ else
+ allow = STANDARD_RIGHTS_READ
+ | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
if (aclbufp[i].a_perm & S_IROTH)
allow |= FILE_GENERIC_READ;
if (aclbufp[i].a_perm & S_IWOTH)
@@ -224,10 +120,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
}
if (aclbufp[i].a_perm & S_IXOTH)
allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
- /* Keep S_ISVTX rule in sync with alloc_sd. */
- if (pc.isdir ()
- && (aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)
- && !(null_mask & FILE_READ_DATA))
+ if ((aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH))
allow |= FILE_DELETE_CHILD;
/* Set inherit property. */
DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)
@@ -240,7 +133,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
* inheritance bits is created.
*/
if (!(aclbufp[i].a_type & ACL_DEFAULT)
- && aclbufp[i].a_type & (USER|GROUP)
+ && aclbufp[i].a_type & (USER|GROUP|OTHER_OBJ)
&& (pos = searchace (aclbufp + i + 1, nentries - i - 1,
aclbufp[i].a_type | ACL_DEFAULT,
(aclbufp[i].a_type & (USER|GROUP))
@@ -248,11 +141,16 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
&& aclbufp[i].a_perm == aclbufp[i + 1 + pos].a_perm)
{
inheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
- /* invalidate the corresponding default entry. */
- aclbufp[i + 1 + pos].a_type = 0;
+ /* This invalidates the corresponding default entry. */
+ aclbufp[i + 1 + pos].a_type = USER|GROUP|ACL_DEFAULT;
}
switch (aclbufp[i].a_type)
{
+ case USER_OBJ:
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ owner, acl_len, inheritance))
+ return -1;
+ break;
case DEF_USER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_creator_owner_sid, acl_len, inheritance))
@@ -260,7 +158,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
break;
case USER:
case DEF_USER:
- if (!(pw = internal_getpwuid (aclbufp[i].a_id, &cldap))
+ if (!(pw = internal_getpwuid (aclbufp[i].a_id))
|| !sid.getfrompw (pw))
{
set_errno (EINVAL);
@@ -270,6 +168,11 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
sid, acl_len, inheritance))
return -1;
break;
+ case GROUP_OBJ:
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ group, acl_len, inheritance))
+ return -1;
+ break;
case DEF_GROUP_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_creator_group_sid, acl_len, inheritance))
@@ -277,7 +180,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
break;
case GROUP:
case DEF_GROUP:
- if (!(gr = internal_getgrgid (aclbufp[i].a_id, &cldap))
+ if (!(gr = internal_getgrgid (aclbufp[i].a_id))
|| !sid.getfromgr (gr))
{
set_errno (EINVAL);
@@ -287,11 +190,13 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
sid, acl_len, inheritance))
return -1;
break;
+ case OTHER_OBJ:
case DEF_OTHER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_world_sid,
acl_len, inheritance))
return -1;
+ break;
}
}
/* Set AclSize to computed value. */
@@ -378,7 +283,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
BOOLEAN dummy;
uid_t uid;
gid_t gid;
- cyg_ldap cldap;
status = RtlGetOwnerSecurityDescriptor (sd, (PSID *) &owner_sid, &dummy);
if (!NT_SUCCESS (status))
@@ -386,7 +290,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
__seterrno_from_nt_status (status);
return -1;
}
- uid = owner_sid.get_uid (&cldap);
+ uid = owner_sid.get_uid ();
status = RtlGetGroupSecurityDescriptor (sd, (PSID *) &group_sid, &dummy);
if (!NT_SUCCESS (status))
@@ -394,7 +298,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
__seterrno_from_nt_status (status);
return -1;
}
- gid = group_sid.get_gid (&cldap);
+ gid = group_sid.get_gid ();
aclent_t lacl[MAX_ACL_ENTRIES];
memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (aclent_t));
@@ -404,6 +308,9 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
lacl[1].a_id = gid;
lacl[2].a_type = OTHER_OBJ;
lacl[2].a_id = ILLEGAL_GID;
+ lacl[3].a_type = CLASS_OBJ;
+ lacl[3].a_id = ILLEGAL_GID;
+ lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
PACL acl;
BOOLEAN acl_exists;
@@ -416,11 +323,9 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
}
int pos, i, types_def = 0;
- int pgrp_pos = 1, def_pgrp_pos = -1;
- mode_t class_perm = 0, def_class_perm = 0;
if (!acl_exists || !acl)
- for (pos = 0; pos < 3; ++pos)
+ for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */
lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
else
{
@@ -435,11 +340,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
int id;
int type = 0;
- if (ace_sid == well_known_null_sid)
- {
- /* Simply ignore. */
- continue;
- }
if (ace_sid == well_known_world_sid)
{
type = OTHER_OBJ;
@@ -457,30 +357,25 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
}
else if (ace_sid == well_known_creator_group_sid)
{
- type = DEF_GROUP_OBJ;
+ type = GROUP_OBJ | ACL_DEFAULT;
types_def |= type;
id = ILLEGAL_GID;
}
else if (ace_sid == well_known_creator_owner_sid)
{
- type = DEF_USER_OBJ;
+ type = USER_OBJ | ACL_DEFAULT;
types_def |= type;
id = ILLEGAL_GID;
}
else
- id = ace_sid.get_id (TRUE, &type, &cldap);
+ id = ace_sid.get_id (true, &type);
if (!type)
continue;
if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE || type & ACL_DEFAULT))
{
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
- {
- getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
- /* Fix up CLASS_OBJ value. */
- if (type == USER || type == GROUP)
- class_perm |= lacl[pos].a_perm;
- }
+ getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
}
if ((ace->Header.AceFlags
& (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))
@@ -493,31 +388,13 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
type |= ACL_DEFAULT;
types_def |= type;
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
- {
- getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
- /* Fix up DEF_CLASS_OBJ value. */
- if (type == DEF_USER || type == DEF_GROUP)
- def_class_perm |= lacl[pos].a_perm;
- /* And note the position of the DEF_GROUP_OBJ entry. */
- else if (type == DEF_GROUP_OBJ)
- def_pgrp_pos = pos;
- }
+ getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
}
}
- /* If secondary user and group entries exist in the ACL, fake a matching
- CLASS_OBJ entry. The CLASS_OBJ permissions are the or'ed permissions
- of the primary group permissions and all secondary user and group
- permissions. */
- if (class_perm && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
- {
- lacl[pos].a_type = CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
- lacl[pos].a_perm = class_perm | lacl[pgrp_pos].a_perm;
- }
- /* Ensure that the default acl contains at least
- DEF_(USER|GROUP|OTHER)_OBJ entries. */
if (types_def && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
{
+ /* Ensure that the default acl contains at
+ least DEF_(USER|GROUP|OTHER)_OBJ entries. */
if (!(types_def & USER_OBJ))
{
lacl[pos].a_type = DEF_USER_OBJ;
@@ -530,8 +407,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
lacl[pos].a_type = DEF_GROUP_OBJ;
lacl[pos].a_id = gid;
lacl[pos].a_perm = lacl[1].a_perm;
- /* Note the position of the DEF_GROUP_OBJ entry. */
- def_pgrp_pos = pos;
pos++;
}
if (!(types_def & OTHER_OBJ) && pos < MAX_ACL_ENTRIES)
@@ -541,18 +416,13 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
lacl[pos].a_perm = lacl[2].a_perm;
pos++;
}
- }
- /* If secondary user default and group default entries exist in the ACL,
- fake a matching DEF_CLASS_OBJ entry. The DEF_CLASS_OBJ permissions are
- the or'ed permissions of the primary group default permissions and all
- secondary user and group default permissions. */
- if (def_class_perm && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
- {
- lacl[pos].a_type = DEF_CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
- lacl[pos].a_perm = def_class_perm;
- if (def_pgrp_pos >= 0)
- lacl[pos].a_perm |= lacl[def_pgrp_pos].a_perm;
+ /* Include DEF_CLASS_OBJ if any named default ace exists. */
+ if ((types_def & (USER|GROUP)) && pos < MAX_ACL_ENTRIES)
+ {
+ lacl[pos].a_type = DEF_CLASS_OBJ;
+ lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
+ }
}
}
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
@@ -628,7 +498,6 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
bool has_other_obj = false;
bool has_class_obj = false;
bool has_ug_objs __attribute__ ((unused)) = false;
- bool has_def_objs __attribute__ ((unused)) = false;
bool has_def_user_obj __attribute__ ((unused)) = false;
bool has_def_group_obj = false;
bool has_def_other_obj = false;
@@ -693,7 +562,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return USER_ERROR;
}
- has_def_objs = has_def_user_obj = true;
+ has_def_user_obj = true;
break;
case DEF_GROUP_OBJ:
if (has_def_group_obj)
@@ -702,7 +571,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return GRP_ERROR;
}
- has_def_objs = has_def_group_obj = true;
+ has_def_group_obj = true;
break;
case DEF_OTHER_OBJ:
if (has_def_other_obj)
@@ -711,7 +580,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return OTHER_ERROR;
}
- has_def_objs = has_def_other_obj = true;
+ has_def_other_obj = true;
break;
case DEF_CLASS_OBJ:
if (has_def_class_obj)
@@ -720,7 +589,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return CLASS_ERROR;
}
- has_def_objs = has_def_class_obj = true;
+ has_def_class_obj = true;
break;
case DEF_USER:
case DEF_GROUP:
@@ -731,7 +600,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos2;
return DUPLICATE_ERROR;
}
- has_def_objs = has_def_ug_objs = true;
+ has_def_ug_objs = true;
break;
default:
return ENTRY_ERROR;
@@ -739,10 +608,11 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
if (!has_user_obj
|| !has_group_obj
|| !has_other_obj
- || (has_def_objs
- && (!has_def_user_obj || !has_def_group_obj || !has_def_other_obj))
+#if 0
+ /* These checks are not ok yet since CLASS_OBJ isn't fully implemented. */
|| (has_ug_objs && !has_class_obj)
|| (has_def_ug_objs && !has_def_class_obj)
+#endif
)
{
if (which)
@@ -767,10 +637,7 @@ extern "C" int
aclsort32 (int nentries, int, aclent_t *aclbufp)
{
if (aclcheck32 (aclbufp, nentries, NULL))
- {
- set_errno (EINVAL);
- return -1;
- }
+ return -1;
if (!aclbufp || nentries < 1)
{
set_errno (EINVAL);
@@ -970,7 +837,6 @@ aclfromtext32 (char *acltextp, int *)
int pos = 0;
strcpy (buf, acltextp);
char *lasts;
- cyg_ldap cldap;
for (char *c = strtok_r (buf, ",", &lasts);
c;
c = strtok_r (NULL, ",", &lasts))
@@ -990,7 +856,7 @@ aclfromtext32 (char *acltextp, int *)
c += 5;
if (isalpha (*c))
{
- struct passwd *pw = internal_getpwnam (c, &cldap);
+ struct passwd *pw = internal_getpwnam (c);
if (!pw)
{
set_errno (EINVAL);
@@ -1018,7 +884,7 @@ aclfromtext32 (char *acltextp, int *)
c += 5;
if (isalpha (*c))
{
- struct group *gr = internal_getgrnam (c, &cldap);
+ struct group *gr = internal_getgrnam (c);
if (!gr)
{
set_errno (EINVAL);
diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc
index 3615588ef..2cdce8bd4 100644
--- a/winsup/cygwin/sec_auth.cc
+++ b/winsup/cygwin/sec_auth.cc
@@ -14,6 +14,7 @@ details. */
#include <wchar.h>
#include <wininet.h>
#include <ntsecapi.h>
+#include <dsgetdc.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
@@ -24,6 +25,7 @@ details. */
#include "tls_pbuf.h"
#include <lm.h>
#include <iptypes.h>
+#include "pwdgrp.h"
#include "cyglsa.h"
#include "cygserver_setpwd.h"
#include <cygwin/version.h>
@@ -219,27 +221,28 @@ lsa_close_policy (HANDLE lsa)
}
bool
-get_logon_server (PWCHAR domain, WCHAR *server, ULONG flags)
+get_logon_server (PWCHAR domain, WCHAR *server, bool rediscovery)
{
DWORD ret;
PDOMAIN_CONTROLLER_INFOW pci;
+ DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
/* Empty domain is interpreted as local system */
- if (cygheap->dom.init ()
- && (!domain[0]
- || !wcscasecmp (domain, cygheap->dom.account_flat_name ())))
+ if ((GetComputerNameW (server + 2, &size)) &&
+ (!wcscasecmp (domain, server + 2) || !domain[0]))
{
- wcpcpy (wcpcpy (server, L"\\\\"), cygheap->dom.account_flat_name ());
+ server[0] = server[1] = L'\\';
return true;
}
/* Try to get any available domain controller for this domain */
- ret = DsGetDcNameW (NULL, domain, NULL, NULL, flags, &pci);
+ ret = DsGetDcNameW (NULL, domain, NULL, NULL,
+ rediscovery ? DS_FORCE_REDISCOVERY : 0, &pci);
if (ret == ERROR_SUCCESS)
{
wcscpy (server, pci->DomainControllerName);
NetApiBufferFree (pci);
- debug_printf ("DC: server: %W", server);
+ debug_printf ("DC: rediscovery: %d, server: %W", rediscovery, server);
return true;
}
__seterrno_from_win_error (ret);
@@ -278,7 +281,7 @@ get_user_groups (WCHAR *logonserver, cygsidlist &grp_list,
for (DWORD i = 0; i < cnt; ++i)
{
cygsid gsid;
- DWORD glen = SECURITY_MAX_SID_SIZE;
+ DWORD glen = MAX_SID_LEN;
WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
DWORD dlen = sizeof (dom);
SID_NAME_USE use = SidTypeInvalid;
@@ -326,7 +329,7 @@ get_user_local_groups (PWCHAR logonserver, PWCHAR domain,
for (DWORD i = 0; i < cnt; ++i)
{
cygsid gsid;
- DWORD glen = SECURITY_MAX_SID_SIZE;
+ DWORD glen = MAX_SID_LEN;
WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
DWORD domlen = MAX_DOMAIN_NAME_LEN + 1;
@@ -362,7 +365,7 @@ get_user_local_groups (PWCHAR logonserver, PWCHAR domain,
if (bg_ptr)
{
wcscpy (bg_ptr, dg_ptr);
- glen = SECURITY_MAX_SID_SIZE;
+ glen = MAX_SID_LEN;
domlen = MAX_DOMAIN_NAME_LEN + 1;
if (LookupAccountNameW (NULL, builtin_grp, gsid, &glen,
dom, &domlen, &use))
@@ -395,6 +398,28 @@ sid_in_token_groups (PTOKEN_GROUPS grps, cygpsid sid)
}
static void
+get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
+{
+ struct group *gr;
+ cygsid gsid;
+
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ {
+ if (gr->gr_gid == pw->pw_gid)
+ goto found;
+ else if (gr->gr_mem)
+ for (int gi = 0; gr->gr_mem[gi]; ++gi)
+ if (strcasematch (pw->pw_name, gr->gr_mem[gi]))
+ goto found;
+ continue;
+ found:
+ if (gsid.getfromgr (gr))
+ grp_list += gsid;
+
+ }
+}
+
+static void
get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
LUID auth_luid, int &auth_pos)
{
@@ -455,6 +480,7 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
if (well_known_system_sid == usersid)
{
grp_list *= well_known_admins_sid;
+ get_unix_group_sidlist (pw, grp_list);
return true;
}
@@ -466,16 +492,12 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
__seterrno ();
return false;
}
- /* If the SID does NOT start with S-1-5-21, the domain is some builtin
- domain. The search for a logon server and fetching group accounts
- is moot. */
- if (sid_id_auth (usersid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (usersid, 0) == SECURITY_NT_NON_UNIQUE
- && get_logon_server (domain, server, DS_IS_FLAT_NAME))
- {
- get_user_groups (server, grp_list, user, domain);
- get_user_local_groups (server, domain, grp_list, user);
- }
+ if (get_logon_server (domain, server, false)
+ && !get_user_groups (server, grp_list, user, domain)
+ && get_logon_server (domain, server, true))
+ get_user_groups (server, grp_list, user, domain);
+ get_user_local_groups (server, domain, grp_list, user);
+ get_unix_group_sidlist (pw, grp_list);
return true;
}
@@ -683,7 +705,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
*pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
}
/* Verify usersid */
- cygsid tok_usersid (NO_SID);
+ cygsid tok_usersid = NO_SID;
status = NtQueryInformationToken (token, TokenUser, &tok_usersid,
sizeof tok_usersid, &size);
if (!NT_SUCCESS (status))
@@ -695,8 +717,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
is not well_known_null_sid, it must match pgrpsid */
if (intern && !groups.issetgroups ())
{
- const DWORD sd_buf_siz = SECURITY_MAX_SID_SIZE
- + sizeof (SECURITY_DESCRIPTOR);
+ const DWORD sd_buf_siz = MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR);
PSECURITY_DESCRIPTOR sd_buf = (PSECURITY_DESCRIPTOR) alloca (sd_buf_siz);
cygpsid gsid (NO_SID);
NTSTATUS status;
@@ -737,26 +758,35 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
if (groups.issetgroups ()) /* setgroups was called */
{
- cygpsid gsid;
+ cygsid gsid;
+ struct group *gr;
bool saw[groups.sgsids.count ()];
-
- /* Check that all groups in the setgroups () list are in the token.
- A token created through ADVAPI should be allowed to contain more
- groups than requested through setgroups(), especially since Vista
- and the addition of integrity groups. */
memset (saw, 0, sizeof(saw));
- for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
- {
- gsid = groups.sgsids.sids[gidx];
- if (sid_in_token_groups (my_grps, gsid))
- {
- int pos = groups.sgsids.position (gsid);
- if (pos >= 0)
- saw[pos] = true;
- else if (groups.pgsid == gsid)
- sawpg = true;
- }
- }
+
+ /* token groups found in /etc/group match the user.gsids ? */
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ if (gsid.getfromgr (gr) && sid_in_token_groups (my_grps, gsid))
+ {
+ int pos = groups.sgsids.position (gsid);
+ if (pos >= 0)
+ saw[pos] = true;
+ else if (groups.pgsid == gsid)
+ sawpg = true;
+#if 0
+ /* With this `else', verify_token returns false if we find
+ groups in the token, which are not in the group list set
+ with setgroups(). That's rather dangerous. What we're
+ really interested in is that all groups in the setgroups()
+ list are in the token. A token created through ADVAPI
+ should be allowed to contain more groups than requested
+ through setgroups(), esecially since Vista and the
+ addition of integrity groups. So we disable this statement
+ for now. */
+ else if (gsid != well_known_world_sid
+ && gsid != usersid)
+ goto done;
+#endif
+ }
/* user.sgsids groups must be in the token, except for builtin groups.
These can be different on domain member machines compared to
domain controllers, so these builtin groups may be validly missing
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index 946e78a8e..2d81cbd38 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -1,7 +1,7 @@
/* sec_helper.cc: NT security helper functions
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2011, 2012, 2013 Red Hat, Inc.
Written by Corinna Vinschen <corinna@vinschen.de>
@@ -22,8 +22,8 @@ details. */
#include "dtable.h"
#include "pinfo.h"
#include "cygheap.h"
+#include "pwdgrp.h"
#include "ntdll.h"
-#include "ldap.h"
/* General purpose security attribute objects for global use. */
static NO_COPY_RO SECURITY_DESCRIPTOR null_sdp =
@@ -66,10 +66,6 @@ MKSID (well_known_this_org_sid, "S-1-5-15",
SECURITY_NT_AUTHORITY, 1, 15);
MKSID (well_known_system_sid, "S-1-5-18",
SECURITY_NT_AUTHORITY, 1, SECURITY_LOCAL_SYSTEM_RID);
-MKSID (well_known_local_service_sid, "S-1-5-19",
- SECURITY_NT_AUTHORITY, 1, SECURITY_LOCAL_SERVICE_RID);
-MKSID (well_known_network_service_sid, "S-1-5-20",
- SECURITY_NT_AUTHORITY, 1, SECURITY_NETWORK_SERVICE_RID);
MKSID (well_known_builtin_sid, "S-1-5-32",
SECURITY_NT_AUTHORITY, 1, SECURITY_BUILTIN_DOMAIN_RID);
MKSID (well_known_admins_sid, "S-1-5-32-544",
@@ -78,11 +74,6 @@ MKSID (well_known_admins_sid, "S-1-5-32-544",
MKSID (well_known_users_sid, "S-1-5-32-545",
SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_USERS);
-MKSID (trusted_installer_sid,
- "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464",
- SECURITY_NT_AUTHORITY, SECURITY_SERVICE_ID_RID_COUNT,
- SECURITY_SERVICE_ID_BASE_RID, 956008885U, 3418522649U, 1831038044U,
- 1853292631U, 2271478464U);
MKSID (mandatory_medium_integrity_sid, "S-1-16-8192",
SECURITY_MANDATORY_LABEL_AUTHORITY, 1, SECURITY_MANDATORY_MEDIUM_RID);
MKSID (mandatory_high_integrity_sid, "S-1-16-12288",
@@ -102,7 +93,7 @@ cygpsid::operator== (const char *nsidstr) const
}
uid_t
-cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap)
+cygpsid::get_id (BOOL search_grp, int *type)
{
/* First try to get SID from group, then passwd */
uid_t id = ILLEGAL_UID;
@@ -112,27 +103,9 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap)
struct group *gr;
if (cygheap->user.groups.pgsid == psid)
id = myself->gid;
- else if (sid_id_auth (psid) == 22)
- {
- /* Samba UNIX group. Try to map to Cygwin gid. If there's no
- mapping in the cache, try to fetch it from the configured
- RFC 2307 domain (see last comment in cygheap_domain_info::init()
- for more information) and add it to the mapping cache. */
- gid_t gid = sid_sub_auth_rid (psid);
- gid_t map_gid = cygheap->ugid_cache.get_gid (gid);
- if (map_gid == ILLEGAL_GID)
- {
- if (pldap->open (cygheap->dom.get_rfc2307_domain ()) == NO_ERROR)
- map_gid = pldap->remap_gid (gid);
- if (map_gid == ILLEGAL_GID)
- map_gid = MAP_UNIX_TO_CYGWIN_ID (gid);
- cygheap->ugid_cache.add_gid (gid, map_gid);
- }
- id = (uid_t) map_gid;
- }
- else if ((gr = internal_getgrsid (*this, pldap)))
+ else if ((gr = internal_getgrsid (*this)))
id = gr->gr_gid;
- if ((gid_t) id != ILLEGAL_GID)
+ if (id != ILLEGAL_UID)
{
if (type)
*type = GROUP;
@@ -144,22 +117,7 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap)
struct passwd *pw;
if (*this == cygheap->user.sid ())
id = myself->uid;
- else if (sid_id_auth (psid) == 22)
- {
- /* Samba UNIX user. See comment above. */
- uid_t uid = sid_sub_auth_rid (psid);
- uid_t map_uid = cygheap->ugid_cache.get_uid (uid);
- if (map_uid == ILLEGAL_UID)
- {
- if (pldap->open (cygheap->dom.get_rfc2307_domain ()) == NO_ERROR)
- map_uid = pldap->remap_uid (uid);
- if (map_uid == ILLEGAL_UID)
- map_uid = MAP_UNIX_TO_CYGWIN_ID (uid);
- cygheap->ugid_cache.add_uid (uid, map_uid);
- }
- id = map_uid;
- }
- else if ((pw = internal_getpwsid (*this, pldap)))
+ else if ((pw = internal_getpwsid (*this)))
id = pw->pw_uid;
if (id != ILLEGAL_UID && type)
*type = USER;
@@ -168,7 +126,7 @@ cygpsid::get_id (BOOL search_grp, int *type, cyg_ldap *pldap)
}
PWCHAR
-cygpsid::pstring (PWCHAR nsidstr) const
+cygpsid::string (PWCHAR nsidstr) const
{
UNICODE_STRING sid;
@@ -176,19 +134,11 @@ cygpsid::pstring (PWCHAR nsidstr) const
return NULL;
RtlInitEmptyUnicodeString (&sid, nsidstr, 256);
RtlConvertSidToUnicodeString (&sid, psid, FALSE);
- return nsidstr + sid.Length / sizeof (WCHAR);
-}
-
-PWCHAR
-cygpsid::string (PWCHAR nsidstr) const
-{
- if (pstring (nsidstr))
- return nsidstr;
- return NULL;
+ return nsidstr;
}
char *
-cygpsid::pstring (char *nsidstr) const
+cygpsid::string (char *nsidstr) const
{
char *t;
DWORD i;
@@ -197,18 +147,10 @@ cygpsid::pstring (char *nsidstr) const
return NULL;
strcpy (nsidstr, "S-1-");
t = nsidstr + sizeof ("S-1-") - 1;
- t += __small_sprintf (t, "%u", sid_id_auth (psid));
- for (i = 0; i < sid_sub_auth_count (psid); ++i)
- t += __small_sprintf (t, "-%lu", sid_sub_auth (psid, i));
- return t;
-}
-
-char *
-cygpsid::string (char *nsidstr) const
-{
- if (pstring (nsidstr))
- return nsidstr;
- return NULL;
+ t += __small_sprintf (t, "%u", RtlIdentifierAuthoritySid (psid)->Value[5]);
+ for (i = 0; i < *RtlSubAuthorityCountSid (psid); ++i)
+ t += __small_sprintf (t, "-%lu", *RtlSubAuthoritySid (psid, i));
+ return nsidstr;
}
PSID
@@ -218,7 +160,7 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known)
SID_IDENTIFIER_AUTHORITY sid_auth = { SECURITY_NULL_SID_AUTHORITY };
# define SECURITY_NT_AUTH 5
- if (s > 255 || cnt < 1 || cnt > SID_MAX_SUB_AUTHORITIES)
+ if (s > 255 || cnt < 1 || cnt > 8)
{
psid = NO_SID;
return NULL;
@@ -226,9 +168,8 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known)
sid_auth.Value[5] = s;
set ();
RtlInitializeSid (psid, &sid_auth, cnt);
- PISID dsid = (PISID) psid;
for (i = 0; i < cnt; ++i)
- dsid->SubAuthority[i] = r[i];
+ memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
/* If the well_known flag isn't set explicitely, we check the SID
for being a well-known SID ourselves. That's necessary because this
cygsid is created from a SID string, usually from /etc/passwd or
@@ -244,34 +185,16 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known)
}
const PSID
-cygsid::getfromstr (PCWSTR nsidstr, bool well_known)
-{
- PWCHAR lasts;
- DWORD s, cnt = 0;
- DWORD r[SID_MAX_SUB_AUTHORITIES];
-
- if (nsidstr && !wcsncmp (nsidstr, L"S-1-", 4))
- {
- s = wcstoul (nsidstr + 4, &lasts, 10);
- while (cnt < SID_MAX_SUB_AUTHORITIES && *lasts == '-')
- r[cnt++] = wcstoul (lasts + 1, &lasts, 10);
- if (!*lasts)
- return get_sid (s, cnt, r, well_known);
- }
- return psid = NO_SID;
-}
-
-const PSID
cygsid::getfromstr (const char *nsidstr, bool well_known)
{
char *lasts;
DWORD s, cnt = 0;
- DWORD r[SID_MAX_SUB_AUTHORITIES];
+ DWORD r[8];
if (nsidstr && !strncmp (nsidstr, "S-1-", 4))
{
s = strtoul (nsidstr + 4, &lasts, 10);
- while (cnt < SID_MAX_SUB_AUTHORITIES && *lasts == '-')
+ while (cnt < 8 && *lasts == '-')
r[cnt++] = strtoul (lasts + 1, &lasts, 10);
if (!*lasts)
return get_sid (s, cnt, r, well_known);
@@ -338,24 +261,41 @@ cygsidlist::add (const PSID nsi, bool well_known)
bool
get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gidret)
{
- BOOL ret = false;
- cyg_ldap cldap;
+ struct passwd *pw;
+ struct group *gr = NULL;
+ bool ret = false;
owner_sid.debug_print ("get_sids_info: owner SID =");
group_sid.debug_print ("get_sids_info: group SID =");
- *uidret = owner_sid.get_uid (&cldap);
- *gidret = group_sid.get_gid (&cldap);
- if (*uidret == myself->uid)
+ if (group_sid == cygheap->user.groups.pgsid)
+ *gidret = myself->gid;
+ else if ((gr = internal_getgrsid (group_sid)))
+ *gidret = gr->gr_gid;
+ else
+ *gidret = ILLEGAL_GID;
+
+ if (owner_sid == cygheap->user.sid ())
{
+ *uidret = myself->uid;
if (*gidret == myself->gid)
- ret = TRUE;
+ ret = true;
else
- CheckTokenMembership (cygheap->user.issetuid ()
- ? cygheap->user.imp_token () : NULL,
- group_sid, &ret);
+ ret = (internal_getgroups (0, NULL, &group_sid) > 0);
+ }
+ else if ((pw = internal_getpwsid (owner_sid)))
+ {
+ *uidret = pw->pw_uid;
+ if (gr || (*gidret != ILLEGAL_GID
+ && (gr = internal_getgrgid (*gidret))))
+ for (int idx = 0; gr->gr_mem[idx]; ++idx)
+ if ((ret = strcasematch (pw->pw_name, gr->gr_mem[idx])))
+ break;
}
- return (bool) ret;
+ else
+ *uidret = ILLEGAL_UID;
+
+ return ret;
}
PSECURITY_DESCRIPTOR
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 4c46e05d9..606920da0 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -1,7 +1,7 @@
/* security.cc: NT file access control functions
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de
Completely rewritten by Corinna Vinschen <corinna@vinschen.de>
@@ -23,6 +23,7 @@ details. */
#include "pinfo.h"
#include "cygheap.h"
#include "ntdll.h"
+#include "pwdgrp.h"
#include "tls_pbuf.h"
#include <aclapi.h>
@@ -314,21 +315,6 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid,
*flags |= ((!(*anti & S_IXGRP)) ? S_IXGRP : 0)
| ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0);
}
- else if (flags == &allow)
- {
- /* Simplified computation of additional group permissions based on
- the CLASS_OBJ value. CLASS_OBJ represents the or'ed value of
- the primary group permissions and all secondary user and group
- permissions. FIXME: This only takes ACCESS_ALLOWED_ACEs into
- account. The computation with additional ACCESS_DENIED_ACE
- handling is much more complicated. */
- if (ace->Mask & FILE_READ_BITS)
- *flags |= S_IRGRP;
- if (ace->Mask & FILE_WRITE_BITS)
- *flags |= S_IWGRP;
- if (ace->Mask & FILE_EXEC_BITS)
- *flags |= S_IXGRP;
- }
}
*attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID);
if (owner_sid && group_sid && RtlEqualSid (owner_sid, group_sid)
@@ -1062,95 +1048,6 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping,
return ret;
}
-/* Samba override. Check security descriptor for Samba UNIX user and group
- accounts and check if we have an RFC 2307 mapping to a Windows account.
- Create a new security descriptor with all of the UNIX accounts with
- valid mapping replaced with their Windows counterpart. */
-static void
-convert_samba_sd (security_descriptor &sd_ret)
-{
- NTSTATUS status;
- BOOLEAN dummy;
- PSID sid;
- cygsid owner;
- cygsid group;
- SECURITY_DESCRIPTOR sd;
- cyg_ldap cldap;
- tmp_pathbuf tp;
- PACL acl, oacl;
- size_t acl_len;
- PACCESS_ALLOWED_ACE ace;
-
- if (!NT_SUCCESS (RtlGetOwnerSecurityDescriptor (sd_ret, &sid, &dummy)))
- return;
- owner = sid;
- if (!NT_SUCCESS (RtlGetGroupSecurityDescriptor (sd_ret, &sid, &dummy)))
- return;
- group = sid;
-
- if (sid_id_auth (owner) == 22)
- {
- struct passwd *pwd;
- uid_t uid = owner.get_uid (&cldap);
- if (uid < UNIX_POSIX_OFFSET && (pwd = internal_getpwuid (uid)))
- owner.getfrompw (pwd);
- }
- if (sid_id_auth (group) == 22)
- {
- struct group *grp;
- gid_t gid = group.get_gid (&cldap);
- if (gid < UNIX_POSIX_OFFSET && (grp = internal_getgrgid (gid)))
- group.getfromgr (grp);
- }
-
- if (!NT_SUCCESS (RtlGetDaclSecurityDescriptor (sd_ret, &dummy,
- &oacl, &dummy)))
- return;
- acl = (PACL) tp.w_get ();
- RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION);
- acl_len = sizeof (ACL);
-
- for (DWORD i = 0; i < oacl->AceCount; ++i)
- if (NT_SUCCESS (RtlGetAce (oacl, i, (PVOID *) &ace)))
- {
- cygsid ace_sid ((PSID) &ace->SidStart);
- if (sid_id_auth (ace_sid) == 22)
- {
- if (sid_sub_auth (ace_sid, 0) == 1) /* user */
- {
- struct passwd *pwd;
- uid_t uid = ace_sid.get_uid (&cldap);
- if (uid < UNIX_POSIX_OFFSET && (pwd = internal_getpwuid (uid)))
- ace_sid.getfrompw (pwd);
- }
- else /* group */
- {
- struct group *grp;
- gid_t gid = ace_sid.get_gid (&cldap);
- if (gid < UNIX_POSIX_OFFSET && (grp = internal_getgrgid (gid)))
- ace_sid.getfromgr (grp);
- }
- if (!add_access_allowed_ace (acl, i, ace->Mask, ace_sid, acl_len,
- ace->Header.AceFlags))
- return;
- }
- }
- acl->AclSize = acl_len;
-
- RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
- RtlSetControlSecurityDescriptor (&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
- RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE);
- RtlSetGroupSecurityDescriptor (&sd, group, FALSE);
-
- status = RtlSetDaclSecurityDescriptor (&sd, TRUE, acl, FALSE);
- if (!NT_SUCCESS (status))
- return;
- DWORD sd_size = 0;
- status = RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size);
- if (sd_size > 0 && sd_ret.malloc (sd_size))
- RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size);
-}
-
int
check_file_access (path_conv &pc, int flags, bool effective)
{
@@ -1164,12 +1061,7 @@ check_file_access (path_conv &pc, int flags, bool effective)
if (flags & X_OK)
desired |= FILE_EXECUTE;
if (!get_file_sd (pc.handle (), pc, sd, false))
- {
- /* Tweak Samba security descriptor as necessary. */
- if (pc.fs_is_samba ())
- convert_samba_sd (sd);
- ret = check_access (sd, file_mapping, desired, flags, effective);
- }
+ ret = check_access (sd, file_mapping, desired, flags, effective);
debug_printf ("flags %y, ret %d", flags, ret);
return ret;
}
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index eb3e0f1e5..940afc5d7 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -12,51 +12,18 @@ details. */
#pragma once
#include <accctrl.h>
-#include <dsgetdc.h>
/* Special file attribute set, for instance, in open() and mkdir() to
flag that a file has just been created. Used in alloc_sd, see there. */
#define S_JUSTCREATED 0x80000000
-/* UID/GID */
-void uinfo_init ();
-
-#define ILLEGAL_UID ((uid_t)-1)
-#define ILLEGAL_GID ((gid_t)-1)
-
-/* Offset for accounts in the primary domain of the machine. */
-#define PRIMARY_POSIX_OFFSET (0x00100000)
-
-/* Fake POSIX offsets used in scenarios in which the account has no permission
- to fetch the POSIX offset, or when the admins have set the offset to an
- unreasonable low value. The values are chosen in the hope that they won't
- collide with "real" offsets. */
-#define NOACCESS_POSIX_OFFSET (0xfe500000)
-#define UNUSABLE_POSIX_OFFSET (0xfea00000)
-
-/* For UNIX accounts not mapped to Windows accounts via winbind, Samba returns
- SIDs of the form S-1-22-x-y, with x == 1 for users and x == 2 for groups,
- and y == UNIX uid/gid. NFS returns no SIDs at all, but the plain UNIX
- uid/gid values.
-
- UNIX uid/gid values are mapped to Cygwin uid/gid values 0xff000000 +
- unix uid/gid. This *might* collide with a posix_offset of some trusted
- domain, but it's *very* unlikely. Define the mapping as macro. */
-#define UNIX_POSIX_OFFSET (0xff000000)
-#define UNIX_POSIX_MASK (0x00ffffff)
-#define MAP_UNIX_TO_CYGWIN_ID(id) (UNIX_POSIX_OFFSET \
- | ((id) & UNIX_POSIX_MASK))
-
-#ifndef __x86_64__
-#define ILLEGAL_UID16 ((__uid16_t)-1)
-#define ILLEGAL_GID16 ((__gid16_t)-1)
-#define uid16touid32(u16) ((u16)==ILLEGAL_UID16?ILLEGAL_UID:(uid_t)(u16))
-#define gid16togid32(g16) ((g16)==ILLEGAL_GID16?ILLEGAL_GID:(gid_t)(g16))
-#endif
+#define DEFAULT_UID DOMAIN_USER_RID_ADMIN
+#define UNKNOWN_UID 400 /* Non conflicting number */
+#define UNKNOWN_GID 401
+#define MAX_SID_LEN 40
#define MAX_DACL_LEN(n) (sizeof (ACL) \
- + (n) * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) \
- + SECURITY_MAX_SID_SIZE))
+ + (n) * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + MAX_SID_LEN))
#define SD_MIN_SIZE (sizeof (SECURITY_DESCRIPTOR) + MAX_DACL_LEN (1))
#define ACL_MAXIMUM_SIZE 65532 /* Yeah, right. 64K - sizeof (DWORD). */
#define SD_MAXIMUM_SIZE 65536
@@ -108,7 +75,7 @@ typedef struct {
BYTE Revision;
BYTE SubAuthorityCount;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
- DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
+ DWORD SubAuthority[8];
} DBGSID, *PDBGSID;
/* Macro to define variable length SID structures */
@@ -125,16 +92,6 @@ cygpsid NO_COPY name = (PSID) &name##_struct;
#define FILE_WRITE_BITS (FILE_WRITE_DATA | GENERIC_WRITE | GENERIC_ALL)
#define FILE_EXEC_BITS (FILE_EXECUTE | GENERIC_EXECUTE | GENERIC_ALL)
-/* Convenience macros. The Windows SID access functions are crude. */
-#define sid_id_auth(s) \
- (RtlIdentifierAuthoritySid (s)->Value[5])
-#define sid_sub_auth_count(s) \
- (*RtlSubAuthorityCountSid ((s)))
-#define sid_sub_auth(s,i) \
- (*RtlSubAuthoritySid ((s),(i)))
-#define sid_sub_auth_rid(s) \
- (*RtlSubAuthoritySid ((s), (*RtlSubAuthorityCountSid ((s)) - 1)))
-
#ifdef __cplusplus
extern "C"
{
@@ -147,8 +104,6 @@ extern "C"
}
#endif
-class cyg_ldap;
-
class cygpsid {
protected:
PSID psid;
@@ -157,13 +112,11 @@ public:
cygpsid (PSID nsid) { psid = nsid; }
operator PSID () const { return psid; }
const PSID operator= (PSID nsid) { return psid = nsid;}
- uid_t get_id (BOOL search_grp, int *type, cyg_ldap *pldap);
- int get_uid (cyg_ldap *pldap) { return get_id (FALSE, NULL, pldap); }
- int get_gid (cyg_ldap *pldap) { return get_id (TRUE, NULL, pldap); }
+ uid_t get_id (BOOL search_grp, int *type = NULL);
+ int get_uid () { return get_id (FALSE); }
+ int get_gid () { return get_id (TRUE); }
- PWCHAR pstring (PWCHAR nsidstr) const;
PWCHAR string (PWCHAR nsidstr) const;
- char *pstring (char *nsidstr) const;
char *string (char *nsidstr) const;
bool operator== (const PSID nsid) const
@@ -186,10 +139,9 @@ public:
};
class cygsid : public cygpsid {
- char sbuf[SECURITY_MAX_SID_SIZE];
+ char sbuf[MAX_SID_LEN];
bool well_known_sid;
- const PSID getfromstr (PCWSTR nsidstr, bool well_known);
const PSID getfromstr (const char *nsidstr, bool well_known);
PSID get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known);
@@ -200,7 +152,7 @@ class cygsid : public cygpsid {
else
{
psid = (PSID) sbuf;
- RtlCopySid (SECURITY_MAX_SID_SIZE, psid, nsid);
+ RtlCopySid (MAX_SID_LEN, psid, nsid);
well_known_sid = well_known;
}
return psid;
@@ -217,23 +169,18 @@ public:
{ return assign (nsid, nsid.well_known_sid); }
inline const PSID operator= (const PSID nsid)
{ return assign (nsid, false); }
- inline const PSID operator= (PCWSTR nsidstr)
- { return getfromstr (nsidstr, false); }
inline const PSID operator= (const char *nsidstr)
{ return getfromstr (nsidstr, false); }
inline const PSID operator*= (cygsid &nsid)
{ return assign (nsid, true); }
inline const PSID operator*= (const PSID nsid)
{ return assign (nsid, true); }
- inline const PSID operator*= (PCWSTR nsidstr)
- { return getfromstr (nsidstr, true); }
inline const PSID operator*= (const char *nsidstr)
{ return getfromstr (nsidstr, true); }
inline cygsid () : cygpsid ((PSID) sbuf), well_known_sid (false) {}
inline cygsid (const PSID nsid) { *this = nsid; }
inline cygsid (const char *nstrsid) { *this = nstrsid; }
- inline cygsid (cygsid &nsid) { *this = nsid; }
inline PSID set () { return psid = (PSID) sbuf; }
@@ -394,12 +341,9 @@ extern cygpsid well_known_service_sid;
extern cygpsid well_known_authenticated_users_sid;
extern cygpsid well_known_this_org_sid;
extern cygpsid well_known_system_sid;
-extern cygpsid well_known_local_service_sid;
-extern cygpsid well_known_network_service_sid;
extern cygpsid well_known_builtin_sid;
extern cygpsid well_known_admins_sid;
extern cygpsid well_known_users_sid;
-extern cygpsid trusted_installer_sid;
extern cygpsid mandatory_medium_integrity_sid;
extern cygpsid mandatory_high_integrity_sid;
extern cygpsid mandatory_system_integrity_sid;
@@ -470,7 +414,7 @@ bool get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw);
/* Extract U-domain\user field from passwd entry. */
void extract_nt_dom_user (const struct passwd *pw, PWCHAR domain, PWCHAR user);
/* Get default logonserver for a domain. */
-bool get_logon_server (PWCHAR domain, PWCHAR wserver, ULONG flags);
+bool get_logon_server (PWCHAR domain, PWCHAR wserver, bool rediscovery);
HANDLE lsa_open_policy (PWCHAR server, ACCESS_MASK access);
void lsa_close_policy (HANDLE lsa);
diff --git a/winsup/doc/logon-funcs.xml b/winsup/cygwin/security.sgml
index 9e32ad626..b286ef540 100644
--- a/winsup/doc/logon-funcs.xml
+++ b/winsup/cygwin/security.sgml
@@ -1,11 +1,4 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-
-<sect1 id="func-cygwin-login">
-<title>Helper functions to change user context</title>
-
-<sect2 id="func-cygwin-logon_user">
+<sect1 id="func-cygwin-logon_user">
<title>cygwin_logon_user</title>
<funcsynopsis><funcprototype>
@@ -15,21 +8,20 @@
<paramdef>const char *<parameter>password</parameter></paramdef>
</funcprototype></funcsynopsis>
-<para>Given a pointer to a passwd entry of a user and a cleartext password,
+<para>Given a pointer ot a passwd entry of a user and a cleartext password,
returns a HANDLE to an impersonation token for this user which can be used
in a subsequent call to <function>cygwin_set_impersonation_token</function>
to impersonate that user. This function can only be called from a process
which has the required NT user rights to perform a logon.</para>
-<para>See also the chapter
-<ulink url="../cygwin-ug-net/ntsec.html#ntsec-setuid-overview">Switching the user context</ulink>
-in the Cygwin User's guide.</para>
+<para>See also the chapter "New setuid concept" in the Cygwin user's guide.
+</para>
<para>See also <link linkend="func-cygwin-set-impersonation-token">cygwin_set_impersonation_token</link></para>
-</sect2>
+</sect1>
-<sect2 id="func-cygwin-set-impersonation-token">
+<sect1 id="func-cygwin-set-impersonation-token">
<title>cygwin_set_impersonation_token</title>
<funcsynopsis><funcprototype>
@@ -45,12 +37,9 @@ impersonation token for the next call to <function>setuid</function> or
<function>cygwin_logon_user</function> to impersonate users using
password authentication.</para>
-<para>See also the chapter
-<ulink url="../cygwin-ug-net/ntsec.html#ntsec-setuid-overview">Switching the user context</ulink>
-in the Cygwin User's guide.</para>
+<para>See also the chapter "New setuid concept" in the Cygwin user's guide.
+</para>
<para>See also <link linkend="func-cygwin-logon_user">cygwin_logon_user</link></para>
-</sect2>
-
</sect1>
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index c72cd0c76..75eb72637 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -473,6 +473,9 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
if (me->read_selected && me->read_ready)
{
UNIX_FD_SET (me->fd, readfds);
+ /* Special AF_LOCAL handling. */
+ if ((sock = me->fh->is_socket ()) && sock->connect_state () == connect_pending)
+ sock->connect_state (connected);
ready++;
}
if (me->write_selected && me->write_ready)
@@ -480,10 +483,16 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
UNIX_FD_SET (me->fd, writefds);
if (me->except_on_write && (sock = me->fh->is_socket ()))
{
- /* Set readfds entry in case of a failed connect. */
- if (!me->read_ready && me->read_selected
- && sock->connect_state () == connect_failed)
- UNIX_FD_SET (me->fd, readfds);
+ /* Special AF_LOCAL handling. */
+ if (!me->read_ready && sock->connect_state () == connect_pending
+ && sock->af_local_connect ())
+ {
+ if (me->read_selected)
+ UNIX_FD_SET (me->fd, readfds);
+ sock->connect_state (connect_failed);
+ }
+ else
+ sock->connect_state (connected);
}
ready++;
}
diff --git a/winsup/cygwin/setlsapwd.cc b/winsup/cygwin/setlsapwd.cc
index eb3b9e6bf..a906412ca 100644
--- a/winsup/cygwin/setlsapwd.cc
+++ b/winsup/cygwin/setlsapwd.cc
@@ -17,6 +17,7 @@ details. */
#include "cygheap.h"
#include "security.h"
#include "cygserver_setpwd.h"
+#include "pwdgrp.h"
#include "ntdll.h"
#include <ntsecapi.h>
#include <stdlib.h>
@@ -50,7 +51,7 @@ setlsapwd (const char *passwd, const char *username)
if (username)
{
cygsid psid;
- struct passwd *pw = internal_getpwnam (username);
+ struct passwd *pw = internal_getpwnam (username, false);
if (!pw || !psid.getfrompw (pw))
{
diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc
index 4510d02ab..2f5a45376 100644
--- a/winsup/cygwin/shared.cc
+++ b/winsup/cygwin/shared.cc
@@ -22,6 +22,7 @@ details. */
#include "shared_info_magic.h"
#include "registry.h"
#include "cygwin_version.h"
+#include "pwdgrp.h"
#include "spinlock.h"
#include <alloca.h>
#include <wchar.h>
@@ -343,8 +344,16 @@ shared_info::initialize ()
}
void
-memory_init ()
+memory_init (bool init_cygheap)
{
+ /* Initialize the Cygwin heap, if necessary */
+ if (init_cygheap)
+ {
+ cygheap_init ();
+ cygheap->user.init ();
+ cygheap->init_installation_root (); /* Requires user.init! */
+ }
+
shared_info::create (); /* Initialize global shared memory */
user_info::create (false); /* Initialize per-user shared memory */
/* Initialize tty list session stuff. Doesn't really belong here but
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index 90b386fe6..6733b3636 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -75,7 +75,7 @@ enum shared_locations
};
-void memory_init ();
+void __reg1 memory_init (bool);
void __stdcall shared_destroy ();
#define shared_align_past(p) \
diff --git a/winsup/cygwin/stackdump.sgml b/winsup/cygwin/stackdump.sgml
new file mode 100644
index 000000000..1969e2e6f
--- /dev/null
+++ b/winsup/cygwin/stackdump.sgml
@@ -0,0 +1,13 @@
+<sect1 id="func-cygwin-stackdump">
+<title>cygwin_stackdump</title>
+
+<funcsynopsis><funcprototype>
+<funcdef>extern "C" void
+<function>cygwin_stackdump</function></funcdef>
+<void />
+</funcprototype></funcsynopsis>
+
+<para> Outputs a stackdump to stderr from the called location.
+</para>
+
+</sect1>
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 933bfe464..544169d78 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -58,6 +58,7 @@ details. */
#include "pinfo.h"
#include "shared_info.h"
#include "cygheap.h"
+#include "pwdgrp.h"
#include "registry.h"
#include "environ.h"
#include "tls_pbuf.h"
diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h
index 572dfb7b7..402638e59 100644
--- a/winsup/cygwin/tlsoffsets.h
+++ b/winsup/cygwin/tlsoffsets.h
@@ -3,115 +3,115 @@
//; $tls::start_offset = -12700;
//; $tls::locals = -12700;
//; $tls::plocals = 0;
-//; $tls::local_clib = -10980;
-//; $tls::plocal_clib = 1720;
-//; $tls::__dontuse = -10980;
-//; $tls::p__dontuse = 1720;
-//; $tls::func = -9892;
-//; $tls::pfunc = 2808;
-//; $tls::saved_errno = -9888;
-//; $tls::psaved_errno = 2812;
-//; $tls::sa_flags = -9884;
-//; $tls::psa_flags = 2816;
-//; $tls::oldmask = -9880;
-//; $tls::poldmask = 2820;
-//; $tls::deltamask = -9876;
-//; $tls::pdeltamask = 2824;
-//; $tls::errno_addr = -9872;
-//; $tls::perrno_addr = 2828;
-//; $tls::sigmask = -9868;
-//; $tls::psigmask = 2832;
-//; $tls::sigwait_mask = -9864;
-//; $tls::psigwait_mask = 2836;
-//; $tls::sigwait_info = -9860;
-//; $tls::psigwait_info = 2840;
-//; $tls::signal_arrived = -9856;
-//; $tls::psignal_arrived = 2844;
-//; $tls::will_wait_for_signal = -9852;
-//; $tls::pwill_wait_for_signal = 2848;
-//; $tls::thread_context = -9848;
-//; $tls::pthread_context = 2852;
-//; $tls::thread_id = -9636;
-//; $tls::pthread_id = 3064;
-//; $tls::infodata = -9632;
-//; $tls::pinfodata = 3068;
-//; $tls::tid = -9484;
-//; $tls::ptid = 3216;
-//; $tls::_ctinfo = -9480;
-//; $tls::p_ctinfo = 3220;
-//; $tls::andreas = -9476;
-//; $tls::pandreas = 3224;
-//; $tls::wq = -9472;
-//; $tls::pwq = 3228;
-//; $tls::sig = -9444;
-//; $tls::psig = 3256;
-//; $tls::incyg = -9440;
-//; $tls::pincyg = 3260;
-//; $tls::spinning = -9436;
-//; $tls::pspinning = 3264;
-//; $tls::stacklock = -9432;
-//; $tls::pstacklock = 3268;
-//; $tls::stackptr = -9428;
-//; $tls::pstackptr = 3272;
-//; $tls::stack = -9424;
-//; $tls::pstack = 3276;
-//; $tls::initialized = -8400;
-//; $tls::pinitialized = 4300;
+//; $tls::local_clib = -10940;
+//; $tls::plocal_clib = 1760;
+//; $tls::__dontuse = -10940;
+//; $tls::p__dontuse = 1760;
+//; $tls::func = -9852;
+//; $tls::pfunc = 2848;
+//; $tls::saved_errno = -9848;
+//; $tls::psaved_errno = 2852;
+//; $tls::sa_flags = -9844;
+//; $tls::psa_flags = 2856;
+//; $tls::oldmask = -9840;
+//; $tls::poldmask = 2860;
+//; $tls::deltamask = -9836;
+//; $tls::pdeltamask = 2864;
+//; $tls::errno_addr = -9832;
+//; $tls::perrno_addr = 2868;
+//; $tls::sigmask = -9828;
+//; $tls::psigmask = 2872;
+//; $tls::sigwait_mask = -9824;
+//; $tls::psigwait_mask = 2876;
+//; $tls::sigwait_info = -9820;
+//; $tls::psigwait_info = 2880;
+//; $tls::signal_arrived = -9816;
+//; $tls::psignal_arrived = 2884;
+//; $tls::will_wait_for_signal = -9812;
+//; $tls::pwill_wait_for_signal = 2888;
+//; $tls::thread_context = -9808;
+//; $tls::pthread_context = 2892;
+//; $tls::thread_id = -9596;
+//; $tls::pthread_id = 3104;
+//; $tls::infodata = -9592;
+//; $tls::pinfodata = 3108;
+//; $tls::tid = -9444;
+//; $tls::ptid = 3256;
+//; $tls::_ctinfo = -9440;
+//; $tls::p_ctinfo = 3260;
+//; $tls::andreas = -9436;
+//; $tls::pandreas = 3264;
+//; $tls::wq = -9432;
+//; $tls::pwq = 3268;
+//; $tls::sig = -9404;
+//; $tls::psig = 3296;
+//; $tls::incyg = -9400;
+//; $tls::pincyg = 3300;
+//; $tls::spinning = -9396;
+//; $tls::pspinning = 3304;
+//; $tls::stacklock = -9392;
+//; $tls::pstacklock = 3308;
+//; $tls::stackptr = -9388;
+//; $tls::pstackptr = 3312;
+//; $tls::stack = -9384;
+//; $tls::pstack = 3316;
+//; $tls::initialized = -8360;
+//; $tls::pinitialized = 4340;
//; __DATA__
#define tls_locals (-12700)
#define tls_plocals (0)
-#define tls_local_clib (-10980)
-#define tls_plocal_clib (1720)
-#define tls___dontuse (-10980)
-#define tls_p__dontuse (1720)
-#define tls_func (-9892)
-#define tls_pfunc (2808)
-#define tls_saved_errno (-9888)
-#define tls_psaved_errno (2812)
-#define tls_sa_flags (-9884)
-#define tls_psa_flags (2816)
-#define tls_oldmask (-9880)
-#define tls_poldmask (2820)
-#define tls_deltamask (-9876)
-#define tls_pdeltamask (2824)
-#define tls_errno_addr (-9872)
-#define tls_perrno_addr (2828)
-#define tls_sigmask (-9868)
-#define tls_psigmask (2832)
-#define tls_sigwait_mask (-9864)
-#define tls_psigwait_mask (2836)
-#define tls_sigwait_info (-9860)
-#define tls_psigwait_info (2840)
-#define tls_signal_arrived (-9856)
-#define tls_psignal_arrived (2844)
-#define tls_will_wait_for_signal (-9852)
-#define tls_pwill_wait_for_signal (2848)
-#define tls_thread_context (-9848)
-#define tls_pthread_context (2852)
-#define tls_thread_id (-9636)
-#define tls_pthread_id (3064)
-#define tls_infodata (-9632)
-#define tls_pinfodata (3068)
-#define tls_tid (-9484)
-#define tls_ptid (3216)
-#define tls__ctinfo (-9480)
-#define tls_p_ctinfo (3220)
-#define tls_andreas (-9476)
-#define tls_pandreas (3224)
-#define tls_wq (-9472)
-#define tls_pwq (3228)
-#define tls_sig (-9444)
-#define tls_psig (3256)
-#define tls_incyg (-9440)
-#define tls_pincyg (3260)
-#define tls_spinning (-9436)
-#define tls_pspinning (3264)
-#define tls_stacklock (-9432)
-#define tls_pstacklock (3268)
-#define tls_stackptr (-9428)
-#define tls_pstackptr (3272)
-#define tls_stack (-9424)
-#define tls_pstack (3276)
-#define tls_initialized (-8400)
-#define tls_pinitialized (4300)
+#define tls_local_clib (-10940)
+#define tls_plocal_clib (1760)
+#define tls___dontuse (-10940)
+#define tls_p__dontuse (1760)
+#define tls_func (-9852)
+#define tls_pfunc (2848)
+#define tls_saved_errno (-9848)
+#define tls_psaved_errno (2852)
+#define tls_sa_flags (-9844)
+#define tls_psa_flags (2856)
+#define tls_oldmask (-9840)
+#define tls_poldmask (2860)
+#define tls_deltamask (-9836)
+#define tls_pdeltamask (2864)
+#define tls_errno_addr (-9832)
+#define tls_perrno_addr (2868)
+#define tls_sigmask (-9828)
+#define tls_psigmask (2872)
+#define tls_sigwait_mask (-9824)
+#define tls_psigwait_mask (2876)
+#define tls_sigwait_info (-9820)
+#define tls_psigwait_info (2880)
+#define tls_signal_arrived (-9816)
+#define tls_psignal_arrived (2884)
+#define tls_will_wait_for_signal (-9812)
+#define tls_pwill_wait_for_signal (2888)
+#define tls_thread_context (-9808)
+#define tls_pthread_context (2892)
+#define tls_thread_id (-9596)
+#define tls_pthread_id (3104)
+#define tls_infodata (-9592)
+#define tls_pinfodata (3108)
+#define tls_tid (-9444)
+#define tls_ptid (3256)
+#define tls__ctinfo (-9440)
+#define tls_p_ctinfo (3260)
+#define tls_andreas (-9436)
+#define tls_pandreas (3264)
+#define tls_wq (-9432)
+#define tls_pwq (3268)
+#define tls_sig (-9404)
+#define tls_psig (3296)
+#define tls_incyg (-9400)
+#define tls_pincyg (3300)
+#define tls_spinning (-9396)
+#define tls_pspinning (3304)
+#define tls_stacklock (-9392)
+#define tls_pstacklock (3308)
+#define tls_stackptr (-9388)
+#define tls_pstackptr (3312)
+#define tls_stack (-9384)
+#define tls_pstack (3316)
+#define tls_initialized (-8360)
+#define tls_pinitialized (4340)
diff --git a/winsup/cygwin/tlsoffsets64.h b/winsup/cygwin/tlsoffsets64.h
index 991280663..7df2c988b 100644
--- a/winsup/cygwin/tlsoffsets64.h
+++ b/winsup/cygwin/tlsoffsets64.h
@@ -3,115 +3,115 @@
//; $tls::start_offset = -12800;
//; $tls::locals = -12800;
//; $tls::plocals = 0;
-//; $tls::local_clib = -10624;
-//; $tls::plocal_clib = 2176;
-//; $tls::__dontuse = -10624;
-//; $tls::p__dontuse = 2176;
-//; $tls::func = -8736;
-//; $tls::pfunc = 4064;
-//; $tls::saved_errno = -8728;
-//; $tls::psaved_errno = 4072;
-//; $tls::sa_flags = -8724;
-//; $tls::psa_flags = 4076;
-//; $tls::oldmask = -8720;
-//; $tls::poldmask = 4080;
-//; $tls::deltamask = -8712;
-//; $tls::pdeltamask = 4088;
-//; $tls::errno_addr = -8704;
-//; $tls::perrno_addr = 4096;
-//; $tls::sigmask = -8696;
-//; $tls::psigmask = 4104;
-//; $tls::sigwait_mask = -8688;
-//; $tls::psigwait_mask = 4112;
-//; $tls::sigwait_info = -8680;
-//; $tls::psigwait_info = 4120;
-//; $tls::signal_arrived = -8672;
-//; $tls::psignal_arrived = 4128;
-//; $tls::will_wait_for_signal = -8664;
-//; $tls::pwill_wait_for_signal = 4136;
-//; $tls::thread_context = -8656;
-//; $tls::pthread_context = 4144;
-//; $tls::thread_id = -7824;
-//; $tls::pthread_id = 4976;
-//; $tls::infodata = -7820;
-//; $tls::pinfodata = 4980;
-//; $tls::tid = -7672;
-//; $tls::ptid = 5128;
-//; $tls::_ctinfo = -7664;
-//; $tls::p_ctinfo = 5136;
-//; $tls::andreas = -7656;
-//; $tls::pandreas = 5144;
-//; $tls::wq = -7648;
-//; $tls::pwq = 5152;
-//; $tls::sig = -7600;
-//; $tls::psig = 5200;
-//; $tls::incyg = -7596;
-//; $tls::pincyg = 5204;
-//; $tls::spinning = -7592;
-//; $tls::pspinning = 5208;
-//; $tls::stacklock = -7588;
-//; $tls::pstacklock = 5212;
-//; $tls::stackptr = -7584;
-//; $tls::pstackptr = 5216;
-//; $tls::stack = -7576;
-//; $tls::pstack = 5224;
-//; $tls::initialized = -5528;
-//; $tls::pinitialized = 7272;
+//; $tls::local_clib = -10560;
+//; $tls::plocal_clib = 2240;
+//; $tls::__dontuse = -10560;
+//; $tls::p__dontuse = 2240;
+//; $tls::func = -8672;
+//; $tls::pfunc = 4128;
+//; $tls::saved_errno = -8664;
+//; $tls::psaved_errno = 4136;
+//; $tls::sa_flags = -8660;
+//; $tls::psa_flags = 4140;
+//; $tls::oldmask = -8656;
+//; $tls::poldmask = 4144;
+//; $tls::deltamask = -8648;
+//; $tls::pdeltamask = 4152;
+//; $tls::errno_addr = -8640;
+//; $tls::perrno_addr = 4160;
+//; $tls::sigmask = -8632;
+//; $tls::psigmask = 4168;
+//; $tls::sigwait_mask = -8624;
+//; $tls::psigwait_mask = 4176;
+//; $tls::sigwait_info = -8616;
+//; $tls::psigwait_info = 4184;
+//; $tls::signal_arrived = -8608;
+//; $tls::psignal_arrived = 4192;
+//; $tls::will_wait_for_signal = -8600;
+//; $tls::pwill_wait_for_signal = 4200;
+//; $tls::thread_context = -8592;
+//; $tls::pthread_context = 4208;
+//; $tls::thread_id = -7760;
+//; $tls::pthread_id = 5040;
+//; $tls::infodata = -7756;
+//; $tls::pinfodata = 5044;
+//; $tls::tid = -7608;
+//; $tls::ptid = 5192;
+//; $tls::_ctinfo = -7600;
+//; $tls::p_ctinfo = 5200;
+//; $tls::andreas = -7592;
+//; $tls::pandreas = 5208;
+//; $tls::wq = -7584;
+//; $tls::pwq = 5216;
+//; $tls::sig = -7536;
+//; $tls::psig = 5264;
+//; $tls::incyg = -7532;
+//; $tls::pincyg = 5268;
+//; $tls::spinning = -7528;
+//; $tls::pspinning = 5272;
+//; $tls::stacklock = -7524;
+//; $tls::pstacklock = 5276;
+//; $tls::stackptr = -7520;
+//; $tls::pstackptr = 5280;
+//; $tls::stack = -7512;
+//; $tls::pstack = 5288;
+//; $tls::initialized = -5464;
+//; $tls::pinitialized = 7336;
//; __DATA__
#define tls_locals (-12800)
#define tls_plocals (0)
-#define tls_local_clib (-10624)
-#define tls_plocal_clib (2176)
-#define tls___dontuse (-10624)
-#define tls_p__dontuse (2176)
-#define tls_func (-8736)
-#define tls_pfunc (4064)
-#define tls_saved_errno (-8728)
-#define tls_psaved_errno (4072)
-#define tls_sa_flags (-8724)
-#define tls_psa_flags (4076)
-#define tls_oldmask (-8720)
-#define tls_poldmask (4080)
-#define tls_deltamask (-8712)
-#define tls_pdeltamask (4088)
-#define tls_errno_addr (-8704)
-#define tls_perrno_addr (4096)
-#define tls_sigmask (-8696)
-#define tls_psigmask (4104)
-#define tls_sigwait_mask (-8688)
-#define tls_psigwait_mask (4112)
-#define tls_sigwait_info (-8680)
-#define tls_psigwait_info (4120)
-#define tls_signal_arrived (-8672)
-#define tls_psignal_arrived (4128)
-#define tls_will_wait_for_signal (-8664)
-#define tls_pwill_wait_for_signal (4136)
-#define tls_thread_context (-8656)
-#define tls_pthread_context (4144)
-#define tls_thread_id (-7824)
-#define tls_pthread_id (4976)
-#define tls_infodata (-7820)
-#define tls_pinfodata (4980)
-#define tls_tid (-7672)
-#define tls_ptid (5128)
-#define tls__ctinfo (-7664)
-#define tls_p_ctinfo (5136)
-#define tls_andreas (-7656)
-#define tls_pandreas (5144)
-#define tls_wq (-7648)
-#define tls_pwq (5152)
-#define tls_sig (-7600)
-#define tls_psig (5200)
-#define tls_incyg (-7596)
-#define tls_pincyg (5204)
-#define tls_spinning (-7592)
-#define tls_pspinning (5208)
-#define tls_stacklock (-7588)
-#define tls_pstacklock (5212)
-#define tls_stackptr (-7584)
-#define tls_pstackptr (5216)
-#define tls_stack (-7576)
-#define tls_pstack (5224)
-#define tls_initialized (-5528)
-#define tls_pinitialized (7272)
+#define tls_local_clib (-10560)
+#define tls_plocal_clib (2240)
+#define tls___dontuse (-10560)
+#define tls_p__dontuse (2240)
+#define tls_func (-8672)
+#define tls_pfunc (4128)
+#define tls_saved_errno (-8664)
+#define tls_psaved_errno (4136)
+#define tls_sa_flags (-8660)
+#define tls_psa_flags (4140)
+#define tls_oldmask (-8656)
+#define tls_poldmask (4144)
+#define tls_deltamask (-8648)
+#define tls_pdeltamask (4152)
+#define tls_errno_addr (-8640)
+#define tls_perrno_addr (4160)
+#define tls_sigmask (-8632)
+#define tls_psigmask (4168)
+#define tls_sigwait_mask (-8624)
+#define tls_psigwait_mask (4176)
+#define tls_sigwait_info (-8616)
+#define tls_psigwait_info (4184)
+#define tls_signal_arrived (-8608)
+#define tls_psignal_arrived (4192)
+#define tls_will_wait_for_signal (-8600)
+#define tls_pwill_wait_for_signal (4200)
+#define tls_thread_context (-8592)
+#define tls_pthread_context (4208)
+#define tls_thread_id (-7760)
+#define tls_pthread_id (5040)
+#define tls_infodata (-7756)
+#define tls_pinfodata (5044)
+#define tls_tid (-7608)
+#define tls_ptid (5192)
+#define tls__ctinfo (-7600)
+#define tls_p_ctinfo (5200)
+#define tls_andreas (-7592)
+#define tls_pandreas (5208)
+#define tls_wq (-7584)
+#define tls_pwq (5216)
+#define tls_sig (-7536)
+#define tls_psig (5264)
+#define tls_incyg (-7532)
+#define tls_pincyg (5268)
+#define tls_spinning (-7528)
+#define tls_pspinning (5272)
+#define tls_stacklock (-7524)
+#define tls_pstacklock (5276)
+#define tls_stackptr (-7520)
+#define tls_pstackptr (5280)
+#define tls_stack (-7512)
+#define tls_pstack (5288)
+#define tls_initialized (-5464)
+#define tls_pinitialized (7336)
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 8b9266f9d..bb75850a0 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -1,7 +1,7 @@
/* uinfo.cc: user info (uid, gid, etc...)
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011, 2012, 2014 Red Hat, Inc.
+ 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
@@ -10,14 +10,12 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
-#include <iptypes.h>
-#include <lm.h>
-#include <ntsecapi.h>
-#include <wininet.h>
#include <unistd.h>
+#include <wininet.h>
#include <stdlib.h>
-#include <stdio.h>
#include <wchar.h>
+#include <lm.h>
+#include <iptypes.h>
#include <sys/cygwin.h>
#include "cygerrno.h"
#include "pinfo.h"
@@ -29,11 +27,9 @@ details. */
#include "registry.h"
#include "child_info.h"
#include "environ.h"
+#include "pwdgrp.h"
#include "tls_pbuf.h"
-#include "miscfuncs.h"
#include "ntdll.h"
-#include "ldap.h"
-#include "cygserver_pwdgrp.h"
/* Initialize the part of cygheap_user that does not depend on files.
The information is used in shared.cc for the user shared.
@@ -85,7 +81,7 @@ cygheap_user::init ()
status = NtSetInformationToken (hProcToken, TokenOwner, &effec_cygsid,
sizeof (cygsid));
if (!NT_SUCCESS (status))
- debug_printf ("NtSetInformationToken (TokenOwner), %y", status);
+ debug_printf ("NtSetInformationToken(TokenOwner), %y", status);
/* Standard way to build a security descriptor with the usual DACL */
PSECURITY_ATTRIBUTES sa_buf = (PSECURITY_ATTRIBUTES) alloca (1024);
@@ -116,63 +112,41 @@ cygheap_user::init ()
void
internal_getlogin (cygheap_user &user)
{
- struct passwd *pwd;
- struct group *pgrp, *grp, *grp2;
- cyg_ldap cldap;
-
- /* Fetch (and potentially generate) passwd and group entries for the user
- and the primary group in the token. */
- pwd = internal_getpwsid (user.sid (), &cldap);
- pgrp = internal_getgrsid (user.groups.pgsid, &cldap);
- if (!cygheap->pg.nss_cygserver_caching ())
- internal_getgroups (0, NULL, &cldap);
- if (!pwd)
- debug_printf ("user not found in passwd DB");
+ struct passwd *pw = NULL;
+
+ cygpsid psid = user.sid ();
+ pw = internal_getpwsid (psid);
+
+ if (!pw && !(pw = internal_getpwnam (user.name ()))
+ && !(pw = internal_getpwuid (DEFAULT_UID)))
+ debug_printf ("user not found in augmented /etc/passwd");
else
{
cygsid gsid;
- user.set_name (pwd->pw_name);
- myself->uid = pwd->pw_uid;
- myself->gid = pwd->pw_gid;
- /* If the primary group in the passwd DB is different from the primary
- group in the user token, we have to find the SID of that group and
- try to override the token primary group. */
- if (!pgrp || myself->gid != pgrp->gr_gid)
+ myself->uid = pw->pw_uid;
+ myself->gid = pw->pw_gid;
+ user.set_name (pw->pw_name);
+ if (gsid.getfromgr (internal_getgrgid (pw->pw_gid)))
{
- if (gsid.getfromgr (grp = internal_getgrgid (pwd->pw_gid, &cldap)))
+ if (gsid != user.groups.pgsid)
{
- /* We might have a group file with a group entry for the current
- user's primary group, but the current user has no entry in
- passwd. If so, pw_gid is taken from windows and might
- disagree with gr_gid from the group file. Overwrite it. */
- if ((grp2 = internal_getgrsid (gsid, &cldap)) && grp2 != grp)
- myself->gid = pwd->pw_gid = grp2->gr_gid;
/* Set primary group to the group in /etc/passwd. */
- if (gsid != user.groups.pgsid)
- {
- NTSTATUS status = NtSetInformationToken (hProcToken,
- TokenPrimaryGroup,
- &gsid, sizeof gsid);
- if (!NT_SUCCESS (status))
- {
- debug_printf ("NtSetInformationToken (TokenPrimaryGroup),"
- " %y", status);
- /* Revert the primary group setting and override the
- setting in the passwd entry. */
- if (pgrp)
- myself->gid = pwd->pw_gid = pgrp->gr_gid;
- }
- else
- user.groups.pgsid = gsid;
- clear_procimptoken ();
- }
+ NTSTATUS status = NtSetInformationToken (hProcToken,
+ TokenPrimaryGroup,
+ &gsid, sizeof gsid);
+ if (!NT_SUCCESS (status))
+ debug_printf ("NtSetInformationToken (TokenPrimaryGroup), %y",
+ status);
+ else
+ user.groups.pgsid = gsid;
+ clear_procimptoken ();
}
- else
- debug_printf ("group not found in group DB");
}
+ else
+ debug_printf ("gsid not found in augmented /etc/group");
}
- cygheap->user.ontherange (CH_HOME, pwd);
+ cygheap->user.ontherange (CH_HOME, pw);
}
void
@@ -339,7 +313,7 @@ cygheap_user::ontherange (homebodies what, struct passwd *pw)
{
if (pw && pw->pw_dir && *pw->pw_dir)
{
- debug_printf ("Set HOME (from account db) to %s", pw->pw_dir);
+ debug_printf ("Set HOME (from /etc/passwd) to %s", pw->pw_dir);
setenv ("HOME", pw->pw_dir, 1);
}
else
@@ -446,7 +420,7 @@ cygheap_user::env_logsrv (const char *name, size_t namelen)
WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3];
sys_mbstowcs (wdomain, MAX_DOMAIN_NAME_LEN + 1, mydomain);
cfree_and_set (plogsrv, almost_null);
- if (get_logon_server (wdomain, wlogsrv, DS_IS_FLAT_NAME))
+ if (get_logon_server (wdomain, wlogsrv, false))
sys_wcstombs_alloc (&plogsrv, HEAP_STR, wlogsrv);
return plogsrv;
}
@@ -556,13 +530,21 @@ pwdgrp::add_line (char *eptr)
{
if (eptr)
{
+ lptr = eptr;
+ eptr = strchr (lptr, '\n');
+ if (eptr)
+ {
+ if (eptr > lptr && eptr[-1] == '\r')
+ eptr[-1] = '\0';
+ else
+ *eptr = '\0';
+ eptr++;
+ }
if (curr_lines >= max_lines)
{
max_lines += 10;
- pwdgrp_buf = crealloc_abort (pwdgrp_buf,
- max_lines * pwdgrp_buf_elem_size);
+ *pwdgrp_buf = realloc (*pwdgrp_buf, max_lines * pwdgrp_buf_elem_size);
}
- lptr = eptr;
if ((this->*parse) ())
curr_lines++;
}
@@ -570,1460 +552,82 @@ pwdgrp::add_line (char *eptr)
}
void
-cygheap_pwdgrp::init ()
-{
- pwd_cache.cygserver.init_pwd ();
- pwd_cache.file.init_pwd ();
- pwd_cache.win.init_pwd ();
- grp_cache.cygserver.init_grp ();
- grp_cache.file.init_grp ();
- grp_cache.win.init_grp ();
- /* Default settings:
-
- passwd: files db
- group: files db
- db_prefix: auto DISABLED
- db_separator: + DISABLED
- db_enum: cache builtin
- */
- pwd_src = (NSS_FILES | NSS_DB);
- grp_src = (NSS_FILES | NSS_DB);
- prefix = NSS_AUTO;
- separator[0] = L'+';
- enums = (ENUM_CACHE | ENUM_BUILTIN);
- enum_tdoms = NULL;
- caching = true; /* INTERNAL ONLY */
-}
-
-/* The /etc/nsswitch.conf file is read exactly once by the root process of a
- process tree. We can't afford methodical changes during the lifetime of a
- process tree. */
-void
-cygheap_pwdgrp::nss_init_line (const char *line)
-{
- const char *c = line + strspn (line, " \t");
- switch (*c)
- {
- case 'p':
- case 'g':
- {
- int *src = NULL;
- if (!strncmp (c, "passwd:", 7))
- {
- src = &pwd_src;
- c += 7;
- }
- else if (!strncmp (c, "group:", 6))
- {
- src = &grp_src;
- c += 6;
- }
- if (src)
- {
- *src = 0;
- while (*c)
- {
- c += strspn (c, " \t");
- if (!*c || *c == '#')
- break;
- if (!strncmp (c, "files", 5) && strchr (" \t", c[5]))
- {
- *src |= NSS_FILES;
- c += 5;
- }
- else if (!strncmp (c, "db", 2) && strchr (" \t", c[2]))
- {
- *src |= NSS_DB;
- c += 2;
- }
- else
- {
- c += strcspn (c, " \t");
- debug_printf ("Invalid nsswitch.conf content: %s", line);
- }
- }
- if (*src == 0)
- *src = (NSS_FILES | NSS_DB);
- }
- }
- break;
- case 'd':
- if (strncmp (c, "db_", 3))
- {
- debug_printf ("Invalid nsswitch.conf content: %s", line);
- break;
- }
- c += 3;
-#if 0 /* Disable setting prefix and separator from nsswitch.conf for now.
- Remove if nobody complains too loudly. */
- if (!strncmp (c, "prefix:", 7))
- {
- c += 7;
- c += strspn (c, " \t");
- if (!strncmp (c, "auto", 4) && strchr (" \t", c[4]))
- prefix = NSS_AUTO;
- else if (!strncmp (c, "primary", 7) && strchr (" \t", c[7]))
- prefix = NSS_PRIMARY;
- else if (!strncmp (c, "always", 6) && strchr (" \t", c[6]))
- prefix = NSS_ALWAYS;
- else
- debug_printf ("Invalid nsswitch.conf content: %s", line);
- }
- else if (!strncmp (c, "separator:", 10))
- {
- c += 10;
- c += strspn (c, " \t");
- if ((unsigned char) *c <= 0x7f && *c != ':' && strchr (" \t", c[1]))
- separator[0] = (unsigned char) *c;
- else
- debug_printf ("Invalid nsswitch.conf content: %s", line);
- }
- else
-#endif
- if (!strncmp (c, "enum:", 5))
- {
- tmp_pathbuf tp;
- char *tdoms = tp.c_get ();
- char *td = tdoms;
- int new_enums = ENUM_NONE;
-
- td[0] = '\0';
- c += 5;
- c += strspn (c, " \t");
- while (!strchr (" \t", *c))
- {
- const char *e = c + strcspn (c, " \t");
- if (!strncmp (c, "none", 4) && strchr (" \t", c[4]))
- new_enums = ENUM_NONE;
- else if (!strncmp (c, "builtin", 7) && strchr (" \t", c[7]))
- new_enums |= ENUM_BUILTIN;
- else if (!strncmp (c, "cache", 5) && strchr (" \t", c[5]))
- new_enums |= ENUM_CACHE;
- else if (!strncmp (c, "files", 5) && strchr (" \t", c[5]))
- new_enums |= ENUM_FILES;
- else if (!strncmp (c, "local", 5) && strchr (" \t", c[5]))
- new_enums |= ENUM_LOCAL;
- else if (!strncmp (c, "primary", 7) && strchr (" \t", c[7]))
- new_enums |= ENUM_PRIMARY;
- else if (!strncmp (c, "alltrusted", 10) && strchr (" \t", c[10]))
- new_enums |= ENUM_TDOMS | ENUM_TDOMS_ALL;
- else if (!strncmp (c, "all", 3) && strchr (" \t", c[3]))
- new_enums |= ENUM_ALL;
- else
- {
- td = stpcpy (stpncpy (td, c, e - c), " ");
- new_enums |= ENUM_TDOMS;
- }
- c = e;
- c += strspn (c, " \t");
- }
- if ((new_enums & (ENUM_TDOMS | ENUM_TDOMS_ALL)) == ENUM_TDOMS)
- {
- if (td > tdoms)
- {
- PWCHAR spc;
- sys_mbstowcs_alloc (&enum_tdoms, HEAP_BUF, tdoms);
- /* Convert string to REG_MULTI_SZ-style. */
- while ((spc = wcsrchr (enum_tdoms, L' ')))
- *spc = L'\0';
- }
- else
- new_enums &= ~(ENUM_TDOMS | ENUM_TDOMS_ALL);
- }
- enums = new_enums;
- }
- break;
- case '\0':
- case '#':
- break;
- default:
- debug_printf ("Invalid nsswitch.conf content: %s", line);
- break;
- }
-}
-
-void
-cygheap_pwdgrp::_nss_init ()
+pwdgrp::load (const wchar_t *rel_path)
{
- UNICODE_STRING path;
- OBJECT_ATTRIBUTES attr;
- NT_readline rl;
- tmp_pathbuf tp;
- char *buf = tp.c_get ();
-
- PCWSTR rel_path = L"\\etc\\nsswitch.conf";
- path.Length = (wcslen (cygheap->installation_root) + wcslen (rel_path))
- * sizeof (WCHAR);
- path.MaximumLength = path.Length + sizeof (WCHAR);
- path.Buffer = (PWCHAR) alloca (path.MaximumLength);
- wcpcpy (wcpcpy (path.Buffer, cygheap->installation_root), rel_path);
- InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE,
- NULL, NULL);
- if (rl.init (&attr, buf, NT_MAX_PATH))
- while ((buf = rl.gets ()))
- nss_init_line (buf);
- nss_inited = true;
-}
-
-/* Override the ParentIndex value of the PDS_DOMAIN_TRUSTSW entry with the
- PosixOffset. */
-#define PosixOffset ParentIndex
+ static const char failed[] = "failed";
+ static const char succeeded[] = "succeeded";
+ const char *res = failed;
+ HANDLE fh = NULL;
-bool
-cygheap_domain_info::init ()
-{
- HANDLE lsa;
NTSTATUS status;
- ULONG ret;
- /* We *have* to copy the information. Apart from our wish to have the
- stuff in the cygheap, even when not calling LsaFreeMemory on the result,
- the data will be overwritten later. From what I gather, the information
- is, in fact, stored on the stack. */
- PPOLICY_DNS_DOMAIN_INFO pdom;
- PPOLICY_ACCOUNT_DOMAIN_INFO adom;
- PDS_DOMAIN_TRUSTSW td;
- ULONG tdom_cnt;
-
- if (adom_name)
- return true;
- lsa = lsa_open_policy (NULL, POLICY_VIEW_LOCAL_INFORMATION);
- if (!lsa)
- {
- system_printf ("lsa_open_policy(NULL) failed");
- return false;
- }
- /* Fetch primary domain information from local LSA. */
- status = LsaQueryInformationPolicy (lsa, PolicyDnsDomainInformation,
- (PVOID *) &pdom);
- if (status != STATUS_SUCCESS)
- {
- system_printf ("LsaQueryInformationPolicy(Primary) %y", status);
- return false;
- }
- /* Copy primary domain info to cygheap. */
- pdom_name = cwcsdup (pdom->Name.Buffer);
- pdom_dns_name = pdom->DnsDomainName.Length
- ? cwcsdup (pdom->DnsDomainName.Buffer) : NULL;
- pdom_sid = pdom->Sid;
- LsaFreeMemory (pdom);
- /* Fetch account domain information from local LSA. */
- status = LsaQueryInformationPolicy (lsa, PolicyAccountDomainInformation,
- (PVOID *) &adom);
- if (status != STATUS_SUCCESS)
- {
- system_printf ("LsaQueryInformationPolicy(Account) %y", status);
- return false;
- }
- /* Copy account domain info to cygheap. If we're running on a DC the account
- domain is identical to the primary domain. This leads to confusion when
- trying to compute the uid/gid values. Therefore we invalidate the account
- domain name if we're running on a DC. */
- adom_sid = adom->DomainSid;
- adom_name = cwcsdup (pdom_sid == adom_sid ? L"@" : adom->DomainName.Buffer);
- LsaFreeMemory (adom);
- lsa_close_policy (lsa);
- if (cygheap->dom.member_machine ())
- {
- ret = DsEnumerateDomainTrustsW (NULL, DS_DOMAIN_DIRECT_INBOUND
- | DS_DOMAIN_DIRECT_OUTBOUND
- | DS_DOMAIN_IN_FOREST,
- &td, &tdom_cnt);
- if (ret != ERROR_SUCCESS)
- {
- SetLastError (ret);
- debug_printf ("DsEnumerateDomainTrusts: %E");
- return true;
- }
- if (tdom_cnt == 0)
- {
- return true;
- }
- /* Copy trusted domain info to cygheap, setting PosixOffset on the fly. */
- tdom = (PDS_DOMAIN_TRUSTSW)
- cmalloc_abort (HEAP_BUF, tdom_cnt * sizeof (DS_DOMAIN_TRUSTSW));
- memcpy (tdom, td, tdom_cnt * sizeof (DS_DOMAIN_TRUSTSW));
- for (ULONG idx = 0; idx < tdom_cnt; ++idx)
- {
- /* Copy... */
- tdom[idx].NetbiosDomainName = cwcsdup (td[idx].NetbiosDomainName);
- /* DnsDomainName as well as DomainSid can be NULL. The reason is
- usually a domain of type TRUST_TYPE_DOWNLEVEL. This can be an
- old pre-AD domain, or a Netware domain, etc. If DnsDomainName
- is NULL, just set it to NetbiosDomainName. This simplifies
- subsequent code which doesn't have to check for a NULL pointer. */
- tdom[idx].DnsDomainName = td[idx].DnsDomainName
- ? cwcsdup (td[idx].DnsDomainName)
- : tdom[idx].NetbiosDomainName;
- if (td[idx].DomainSid)
- {
- ULONG len = RtlLengthSid (td[idx].DomainSid);
- tdom[idx].DomainSid = cmalloc_abort(HEAP_BUF, len);
- RtlCopySid (len, tdom[idx].DomainSid, td[idx].DomainSid);
- }
- /* ...and set PosixOffset to 0. This */
- tdom[idx].PosixOffset = 0;
- }
- NetApiBufferFree (td);
- tdom_count = tdom_cnt;
- }
- /* If we have Microsoft Client for NFS installed, we make use of a name
- mapping server. This can be either Active Directory to map uids/gids
- directly to Windows SIDs, or an AD LDS or other RFC 2307 compatible
- identity store. The name of the mapping domain can be fetched from the
- registry key created by the NFS client installation and entered by the
- user via nfsadmin or the "Services For NFS" MMC snap-in.
-
- Reference:
- http://blogs.technet.com/b/filecab/archive/2012/10/09/nfs-identity-mapping-in-windows-server-2012.aspx
- Note that we neither support UNMP nor local passwd/group file mapping,
- nor UUUA.
-
- This function returns the mapping server from the aforementioned registry
- key, or, if none is configured, NULL, which will be resolved to the
- primary domain of the machine by the ldap_init function.
-
- The latter is useful to get an RFC 2307 mapping for Samba UNIX accounts,
- even if no NFS name mapping is configured on the machine. Fortunately,
- the posixAccount and posixGroup schemas are already available in the
- Active Directory default setup since Windows Server 2003 R2. */
- reg_key reg (HKEY_LOCAL_MACHINE, KEY_READ | KEY_WOW64_64KEY,
- L"SOFTWARE", L"Microsoft", L"ServicesForNFS", NULL);
- if (!reg.error ())
- {
- DWORD rfc2307 = reg.get_dword (L"Rfc2307", 0);
- if (rfc2307)
- {
- rfc2307_domain_buf = (PWCHAR) ccalloc_abort (HEAP_STR, 257,
- sizeof (WCHAR));
- reg.get_string (L"Rfc2307Domain", rfc2307_domain_buf, 257, L"");
- if (!rfc2307_domain_buf[0])
- {
- cfree (rfc2307_domain_buf);
- rfc2307_domain_buf = NULL;
- }
- }
- }
- return true;
-}
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ FILE_STANDARD_INFORMATION fsi;
-/* Per session, so it changes potentially when switching the user context. */
-static cygsid logon_sid ("");
+ if (buf)
+ free (buf);
+ buf = NULL;
+ curr_lines = 0;
-static void
-get_logon_sid ()
-{
- if (PSID (logon_sid) == NO_SID)
+ if (!path &&
+ !(path = (PWCHAR) malloc ((wcslen (cygheap->installation_root)
+ + wcslen (rel_path) + 1) * sizeof (WCHAR))))
{
- NTSTATUS status;
- ULONG size;
- tmp_pathbuf tp;
- PTOKEN_GROUPS groups = (PTOKEN_GROUPS) tp.c_get ();
-
- status = NtQueryInformationToken (hProcToken, TokenGroups, groups,
- NT_MAX_PATH, &size);
- if (!NT_SUCCESS (status))
- debug_printf ("NtQueryInformationToken() %y", status);
- else
- {
- for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
- if (groups->Groups[pg].Attributes & SE_GROUP_LOGON_ID)
- {
- logon_sid = groups->Groups[pg].Sid;
- break;
- }
- }
+ paranoid_printf ("malloc (%W) failed", rel_path);
+ goto out;
}
-}
-
-void *
-pwdgrp::add_account_post_fetch (char *line, bool lock)
-{
- if (line)
- {
- void *ret;
- if (lock)
- pglock.init ("pglock")->acquire ();
- add_line (line);
- ret = ((char *) pwdgrp_buf) + (curr_lines - 1) * pwdgrp_buf_elem_size;
- if (lock)
- pglock.release ();
- return ret;
- }
- return NULL;
-}
-
-void *
-pwdgrp::add_account_from_file (cygpsid &sid)
-{
- if (!path.MaximumLength)
- return NULL;
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = fetch_account_from_file (arg);
- return (struct passwd *) add_account_post_fetch (line, true);
-}
+ wcpcpy (wcpcpy (path, cygheap->installation_root), rel_path);
+ RtlInitUnicodeString (&upath, path);
-void *
-pwdgrp::add_account_from_file (const char *name)
-{
- if (!path.MaximumLength)
- return NULL;
- fetch_user_arg_t arg;
- arg.type = NAME_arg;
- arg.name = name;
- char *line = fetch_account_from_file (arg);
- return (struct passwd *) add_account_post_fetch (line, true);
-}
+ InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+ etc_ix = etc::init (etc_ix, &attr);
-void *
-pwdgrp::add_account_from_file (uint32_t id)
-{
- if (!path.MaximumLength)
- return NULL;
- fetch_user_arg_t arg;
- arg.type = ID_arg;
- arg.id = id;
- char *line = fetch_account_from_file (arg);
- return (struct passwd *) add_account_post_fetch (line, true);
-}
+ paranoid_printf ("%S", &upath);
-void *
-pwdgrp::add_account_from_windows (cygpsid &sid, cyg_ldap *pldap)
-{
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = fetch_account_from_windows (arg, pldap);
- if (!line)
- return NULL;
- return add_account_post_fetch (line, true);
-}
-
-void *
-pwdgrp::add_account_from_windows (const char *name, cyg_ldap *pldap)
-{
- fetch_user_arg_t arg;
- arg.type = NAME_arg;
- arg.name = name;
- char *line = fetch_account_from_windows (arg, pldap);
- if (!line)
- return NULL;
- return add_account_post_fetch (line, true);
-}
-
-void *
-pwdgrp::add_account_from_windows (uint32_t id, cyg_ldap *pldap)
-{
- fetch_user_arg_t arg;
- arg.type = ID_arg;
- arg.id = id;
- char *line = fetch_account_from_windows (arg, pldap);
- if (!line)
- return NULL;
- return add_account_post_fetch (line, true);
-}
-
-/* Check if file exists and if it has been written to since last checked.
- If file has been changed, invalidate the current cache.
-
- If the file doesn't exist when this function is called the first time,
- by the first Cygwin process in a process tree, the file will never be
- visited again by any process in this process tree. This is important,
- because we cannot allow a change of UID/GID values for the lifetime
- of a process tree.
-
- If the file gets deleted or unreadable, the file cache will stay in
- place, but we won't try to read new accounts from the file.
-
- The return code indicates to the calling function if the file exists. */
-bool
-pwdgrp::check_file ()
-{
- FILE_BASIC_INFORMATION fbi;
- NTSTATUS status;
-
- if (!path.Buffer)
- {
- PCWSTR rel_path = is_group () ? L"\\etc\\group" : L"\\etc\\passwd";
- path.Length = (wcslen (cygheap->installation_root) + wcslen (rel_path))
- * sizeof (WCHAR);
- path.MaximumLength = path.Length + sizeof (WCHAR);
- path.Buffer = (PWCHAR) cmalloc_abort (HEAP_BUF, path.MaximumLength);
- wcpcpy (wcpcpy (path.Buffer, cygheap->installation_root), rel_path);
- InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE,
- NULL, NULL);
- }
- else if (path.MaximumLength == 0) /* Indicates that the file doesn't exist. */
- return false;
- status = NtQueryAttributesFile (&attr, &fbi);
+ status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
{
- if (last_modified.QuadPart)
- last_modified.QuadPart = 0LL;
- else
- path.MaximumLength = 0;
- return false;
- }
- if (fbi.LastWriteTime.QuadPart > last_modified.QuadPart)
- {
- last_modified.QuadPart = fbi.LastWriteTime.QuadPart;
- if (curr_lines > 0)
- {
- pglock.init ("pglock")->acquire ();
- int curr = curr_lines;
- curr_lines = 0;
- for (int i = 0; i < curr; ++i)
- cfree (is_group () ? this->group ()[i].g.gr_name
- : this->passwd ()[i].p.pw_name);
- pglock.release ();
- }
- }
- return true;
-}
-
-char *
-pwdgrp::fetch_account_from_line (fetch_user_arg_t &arg, const char *line)
-{
- char *p, *e;
-
- switch (arg.type)
- {
- case SID_arg:
- /* Ignore fields, just scan for SID string. */
- if (!(p = strstr (line, arg.name)) || p[arg.len] != ':')
- return NULL;
- break;
- case NAME_arg:
- /* First field is always name. */
- if (!strncasematch (line, arg.name, arg.len) || line[arg.len] != ':')
- return NULL;
- break;
- case ID_arg:
- /* Skip to third field. */
- if (!(p = strchr (line, ':')) || !(p = strchr (p + 1, ':')))
- return NULL;
- if (strtoul (p + 1, &e, 10) != arg.id || !e || *e != ':')
- return NULL;
- break;
- }
- return cstrdup (line);
-}
-
-char *
-pwdgrp::fetch_account_from_file (fetch_user_arg_t &arg)
-{
- NT_readline rl;
- tmp_pathbuf tp;
- char *buf = tp.c_get ();
- char str[128];
- char *ret = NULL;
-
- /* Create search string. */
- switch (arg.type)
- {
- case SID_arg:
- /* Override SID with SID string. */
- arg.sid->string (str);
- arg.name = str;
- /*FALLTHRU*/
- case NAME_arg:
- arg.len = strlen (arg.name);
- break;
- case ID_arg:
- break;
- }
- if (rl.init (&attr, buf, NT_MAX_PATH))
- while ((buf = rl.gets ()))
- if ((ret = fetch_account_from_line (arg, buf)))
- return ret;
- return NULL;
-}
-
-static ULONG
-fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, cyg_ldap *cldap)
-{
- uint32_t id_val = UINT32_MAX;
-
- if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY) && td->DomainSid)
- {
- if (cldap->open (NULL) == NO_ERROR)
- id_val = cldap->fetch_posix_offset_for_domain (td->DnsDomainName);
- if (id_val < PRIMARY_POSIX_OFFSET)
- {
- /* If the offset is less than the primay domain offset, we're bound
- to suffer collisions with system and local accounts. Move offset
- to a fixed replacement fake offset. This may result in collisions
- between other domains all of which were moved to this replacement
- offset, but we can't fix all problems caused by careless admins. */
- id_val = UNUSABLE_POSIX_OFFSET;
- }
- else if (id_val == UINT32_MAX)
- {
- /* We're probably running under a local account, so we're not allowed
- to fetch any information from AD beyond the most obvious. Fake a
- reasonable posix offset as above and hope for the best. */
- id_val = NOACCESS_POSIX_OFFSET;
- }
- td->PosixOffset = id_val;
- }
- return td->PosixOffset;
-}
-
-/* Helper function to replace colons with semicolons in pw_gecos field. */
-static PWCHAR
-colon_to_semicolon (PWCHAR str)
-{
- PWCHAR cp = str;
- while ((cp = wcschr (cp, L':')) != NULL)
- *cp++ = L';';
- return str;
-}
-
-/* CV 2014-05-08: USER_INFO_24 is not yet defined in Mingw64, but will be in
- the next release. For the time being, define the structure here with
- another name which won't collide with the upcoming correct definition
- in lmaccess.h. */
-struct cyg_USER_INFO_24
-{
- BOOL usri24_internet_identity;
- DWORD usri24_flags;
- LPWSTR usri24_internet_provider_name;
- LPWSTR usri24_internet_principal_name;
- PSID usri24_user_sid;
-};
-
-char *
-pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
-{
- /* Used in LookupAccount calls. */
- WCHAR namebuf[UNLEN + 1], *name = namebuf;
- WCHAR dom[DNLEN + 1] = L"";
- cygsid csid;
- DWORD nlen = UNLEN + 1;
- DWORD dlen = DNLEN + 1;
- DWORD slen = SECURITY_MAX_SID_SIZE;
- cygpsid sid (NO_SID);
- SID_NAME_USE acc_type;
- BOOL ret = false;
- /* Cygwin user name style. */
- bool fully_qualified_name = false;
- /* Computed stuff. */
- uid_t uid = ILLEGAL_UID;
- gid_t gid = ILLEGAL_GID;
- bool is_domain_account = true;
- PCWSTR domain = NULL;
- PWCHAR shell = NULL;
- PWCHAR home = NULL;
- PWCHAR gecos = NULL;
- /* Temporary stuff. */
- PWCHAR p;
- WCHAR sidstr[128];
- ULONG posix_offset = 0;
- uint32_t id_val;
- cyg_ldap loc_ldap;
- cyg_ldap *cldap = pldap ?: &loc_ldap;
-
- /* Initialize */
- if (!cygheap->dom.init ())
- return NULL;
-
- switch (arg.type)
- {
- case SID_arg:
- sid = *arg.sid;
- ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type);
- if (!ret
- && cygheap->dom.member_machine ()
- && sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (sid, 0) == SECURITY_BUILTIN_DOMAIN_RID)
- {
- /* LookupAccountSid called on a non-DC cannot resolve aliases which
- are not defined in the local SAM. If we encounter an alias which
- can't be resolved, and if we're a domain member machine, ask a DC.
- Do *not* use LookupAccountSidW. It can take ages when called on a
- DC for some weird reason. Use LDAP instead. */
- PWCHAR val;
-
- if (cldap->open (NULL) == NO_ERROR
- && cldap->fetch_ad_account (sid, is_group ())
- && (val = cldap->get_group_name ()))
- {
- wcpcpy (name, val);
- wcpcpy (dom, L"BUILTIN");
- acc_type = SidTypeAlias;
- ret = true;
- }
- }
- if (!ret)
- debug_printf ("LookupAccountSid(%W), %E", sid.string (sidstr));
- break;
- case NAME_arg:
- bool fq_name;
-
- fq_name = false;
- /* Copy over to wchar for search. */
- sys_mbstowcs (name, UNLEN + 1, arg.name);
- /* Replace domain separator char with backslash and make sure p is NULL
- or points to the backslash. */
- if ((p = wcschr (name, cygheap->pg.nss_separator ()[0])))
- {
- fq_name = true;
- *p = L'\\';
- }
- sid = csid;
- ret = LookupAccountNameW (NULL, name, sid, &slen, dom, &dlen, &acc_type);
- /* If this is a name-only S-1-5-21 account *and* it's a machine account
- on a domain member machine, then we found the wrong one. Another
- weird, but perfectly valid case is, if the group name is identical
- to the domain name. Try again with domain name prepended. */
- if (ret
- && !fq_name
- && sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (sid, 0) == SECURITY_NT_NON_UNIQUE
- && cygheap->dom.member_machine ()
- && (wcscasecmp (dom, cygheap->dom.account_flat_name ()) == 0
- || acc_type == SidTypeDomain))
- {
- p = wcpcpy (name, cygheap->dom.primary_flat_name ());
- *p = L'\\';
- sys_mbstowcs (p + 1, UNLEN + 1, arg.name);
- slen = SECURITY_MAX_SID_SIZE;
- dlen = DNLEN + 1;
- sid = csid;
- ret = LookupAccountNameW (NULL, name, sid, &slen, dom, &dlen,
- &acc_type);
- }
- if (!ret)
- {
- debug_printf ("LookupAccountNameW (%W), %E", name);
- return NULL;
- }
- /* We can skip the backslash in the rest of this function. */
- if (p)
- name = p + 1;
- /* Last but not least, some validity checks on the name style. */
- if (!fq_name)
- {
- /* name_only only if db_prefix is auto. */
- if (!cygheap->pg.nss_prefix_auto ())
- {
- debug_printf ("Invalid account name <%s> (name only/"
- "db_prefix not auto)", arg.name);
- return NULL;
- }
- /* name_only account is either builtin or primary domain, or
- account domain on non-domain machines. */
- if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (sid, 0) == SECURITY_NT_NON_UNIQUE)
- {
- if (cygheap->dom.member_machine ())
- {
- if (wcscasecmp (dom, cygheap->dom.primary_flat_name ()) != 0)
- {
- debug_printf ("Invalid account name <%s> (name only/"
- "non primary on domain machine)", arg.name);
- return NULL;
- }
- }
- else if (wcscasecmp (dom, cygheap->dom.account_flat_name ()) != 0)
- {
- debug_printf ("Invalid account name <%s> (name only/"
- "non machine on non-domain machine)", arg.name);
- return NULL;
- }
- }
- }
- else
- {
- /* All is well if db_prefix is always. */
- if (cygheap->pg.nss_prefix_always ())
- break;
- /* Otherwise, no fully_qualified for builtin accounts. */
- if (sid_id_auth (sid) != 5 /* SECURITY_NT_AUTHORITY */
- || sid_sub_auth (sid, 0) != SECURITY_NT_NON_UNIQUE)
- {
- debug_printf ("Invalid account name <%s> (fully qualified/"
- "not NON_UNIQUE)", arg.name);
- return NULL;
- }
- /* All is well if db_prefix is primary. */
- if (cygheap->pg.nss_prefix_primary ())
- break;
- /* Domain member and domain == primary domain? */
- if (cygheap->dom.member_machine ())
- {
- if (!wcscasecmp (dom, cygheap->dom.primary_flat_name ()))
- {
- debug_printf ("Invalid account name <%s> (fully qualified/"
- "primary domain account)", arg.name);
- return NULL;
- }
- }
- /* Not domain member and domain == account domain? */
- else if (!wcscasecmp (dom, cygheap->dom.account_flat_name ()))
- {
- debug_printf ("Invalid account name <%s> (fully qualified/"
- "local account)", arg.name);
- return NULL;
- }
- }
- break;
- case ID_arg:
- /* Construct SID from ID using the SFU rules, just like the code below
- goes the opposite route. */
-#ifndef INTERIX_COMPATIBLE
- /* Except for Builtin and Alias groups in the SECURITY_NT_AUTHORITY.
- We create uid/gid values compatible with the old values generated
- by mkpasswd/mkgroup. */
- if (arg.id < 0x200)
- __small_swprintf (sidstr, L"S-1-5-%u", arg.id & 0x1ff);
- else if (arg.id == 0x3e8) /* Special case "Other Organization" */
- wcpcpy (sidstr, L"S-1-5-1000");
- else if (arg.id <= 0x7ff)
- __small_swprintf (sidstr, L"S-1-5-32-%u", arg.id & 0x7ff);
- else
-#endif
- if (arg.id == 0xffe)
- {
- /* OtherSession != Logon SID. */
- get_logon_sid ();
- /* LookupAccountSidW will fail. */
- sid = csid = logon_sid;
- sid_sub_auth_rid (sid) = 0;
- break;
- }
- else if (arg.id == 0xfff)
- {
- /* CurrentSession == Logon SID. */
- get_logon_sid ();
- /* LookupAccountSidW will fail. */
- sid = logon_sid;
- break;
- }
- else if (arg.id < 0x10000)
- {
- /* Nothing. */
- debug_printf ("Invalid POSIX id %u", arg.id);
- return NULL;
- }
- else if (arg.id < 0x20000)
- {
- /* Well-Known Group */
- arg.id -= 0x10000;
- /* SECURITY_APP_PACKAGE_AUTHORITY */
- if (arg.id >= 0xf20 && arg.id <= 0xf3f)
- __small_swprintf (sidstr, L"S-1-15-%u-%u", (arg.id >> 4) & 0xf,
- arg.id & 0xf);
- else
- __small_swprintf (sidstr, L"S-1-%u-%u", arg.id >> 8, arg.id & 0xff);
- }
- else if (arg.id >= 0x30000 && arg.id < 0x40000)
- {
- /* Account domain user or group. */
- PWCHAR s = cygheap->dom.account_sid ().pstring (sidstr);
- __small_swprintf (s, L"-%u", arg.id & 0xffff);
- }
- else if (arg.id < 0x60000)
- {
- /* Builtin Alias */
- __small_swprintf (sidstr, L"S-1-5-%u-%u",
- arg.id >> 12, arg.id & 0xffff);
- }
- else if (arg.id < 0x70000)
- {
- /* Mandatory Label. */
- __small_swprintf (sidstr, L"S-1-16-%u", arg.id & 0xffff);
- }
- else if (arg.id < 0x80000)
- {
- /* Identity assertion SIDs. */
- __small_swprintf (sidstr, L"S-1-18-%u", arg.id & 0xffff);
- }
- else if (arg.id < PRIMARY_POSIX_OFFSET)
- {
- /* Nothing. */
- debug_printf ("Invalid POSIX id %u", arg.id);
- return NULL;
- }
- else if (arg.id == ILLEGAL_UID)
- {
- /* Just some fake. */
- sid = csid = "S-1-99-0";
- break;
- }
- else if (arg.id >= UNIX_POSIX_OFFSET)
- {
- /* UNIX (unknown NFS or Samba) user account. */
- __small_swprintf (sidstr, L"S-1-22-%u-%u",
- is_group () ? 2 : 1, arg.id & UNIX_POSIX_MASK);
- /* LookupAccountSidW will fail. */
- sid = csid = sidstr;
- break;
- }
- else
- {
- /* Some trusted domain? */
- PDS_DOMAIN_TRUSTSW td = NULL, this_td = NULL;
-
- for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
- {
- fetch_posix_offset (td, &loc_ldap);
- if (td->PosixOffset > posix_offset && td->PosixOffset <= arg.id)
- posix_offset = (this_td = td)->PosixOffset;
- }
- if (this_td)
- {
- cygpsid tsid (this_td->DomainSid);
- PWCHAR s = tsid.pstring (sidstr);
- __small_swprintf (s, L"-%u", arg.id - posix_offset);
- }
- else
- {
- /* Primary domain */
- PWCHAR s = cygheap->dom.primary_sid ().pstring (sidstr);
- __small_swprintf (s, L"-%u", arg.id - PRIMARY_POSIX_OFFSET);
- }
- posix_offset = 0;
- }
- sid = csid = sidstr;
- ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type);
- if (!ret)
- {
- debug_printf ("LookupAccountSidW (%W), %E", sidstr);
- return NULL;
- }
- break;
- }
- if (ret)
- {
- /* Builtin account? SYSTEM, for instance, is returned as SidTypeUser,
- if a process is running as LocalSystem service.
- Microsoft Account? These show up in the user's group list, using the
- undocumented security authority 11. Even though this is officially a
- user account, it only matters as part of the group list, so we convert
- it to a well-known group here. */
- if (acc_type == SidTypeUser
- && (sid_sub_auth_count (sid) <= 3 || sid_id_auth (sid) == 11))
- acc_type = SidTypeWellKnownGroup;
- switch (acc_type)
- {
- case SidTypeUser:
- /* Don't allow users as group. While this is technically possible,
- it doesn't make sense in a POSIX scenario. It *is* used for
- Microsoft Accounts, but those are converted to well-known groups
- above. */
- if (is_group ())
- return NULL;
- /*FALLTHRU*/
- case SidTypeGroup:
- case SidTypeAlias:
- /* Predefined alias? */
- if (acc_type == SidTypeAlias
- && sid_sub_auth (sid, 0) != SECURITY_NT_NON_UNIQUE)
- {
-#ifdef INTERIX_COMPATIBLE
- posix_offset = 0x30000;
- uid = 0x1000 * sid_sub_auth (sid, 0)
- + (sid_sub_auth_rid (sid) & 0xffff);
-#else
- posix_offset = 0;
-#endif
- fully_qualified_name = cygheap->pg.nss_prefix_always ();
- is_domain_account = false;
- }
- /* Account domain account? */
- else if (!wcscasecmp (dom, cygheap->dom.account_flat_name ()))
- {
- posix_offset = 0x30000;
- if (cygheap->dom.member_machine ()
- || !cygheap->pg.nss_prefix_auto ())
- fully_qualified_name = true;
- is_domain_account = false;
- }
- /* Domain member machine? */
- else if (cygheap->dom.member_machine ())
- {
- /* Primary domain account? */
- if (!wcscasecmp (dom, cygheap->dom.primary_flat_name ()))
- {
- posix_offset = PRIMARY_POSIX_OFFSET;
- /* In theory domain should have been set to
- cygheap->dom.primary_dns_name (), but it turns out that
- not setting the domain here has advantages. We open the
- ldap connection to NULL (== some DC of our primary domain)
- anyway. So the domain is only used later on. So, don't
- set domain here to non-NULL, unless you're sure you have
- also changed subsequent assumptions that domain is NULL
- if it's a primary domain account. */
- if (!cygheap->pg.nss_prefix_auto ())
- fully_qualified_name = true;
- }
- else
- {
- /* No, fetch POSIX offset. */
- PDS_DOMAIN_TRUSTSW td = NULL;
-
- fully_qualified_name = true;
- for (ULONG idx = 0;
- (td = cygheap->dom.trusted_domain (idx));
- ++idx)
- if (!wcscasecmp (dom, td->NetbiosDomainName))
- {
- domain = td->DnsDomainName;
- posix_offset =
- fetch_posix_offset (td, &loc_ldap);
- break;
- }
-
- if (!domain)
- {
- debug_printf ("Unknown domain %W", dom);
- return NULL;
- }
- }
- }
- /* If the domain returned by LookupAccountSid is not our machine
- name, and if our machine is no domain member, we lose. We have
- nobody to ask for the POSIX offset. */
- else
- {
- debug_printf ("Unknown domain %W", dom);
- return NULL;
- }
- /* Generate values. */
- if (uid == ILLEGAL_UID)
- uid = posix_offset + sid_sub_auth_rid (sid);
-
- /* We only care for extended user information if we're creating a
- passwd entry and the account is a user or alias. */
- if (is_group () || acc_type == SidTypeGroup)
- break;
-
- if (acc_type == SidTypeUser)
- {
- /* Default primary group. If the sid is the current user, fetch
- the default group from the current user token, otherwise make
- the educated guess that the user is in group "Domain Users"
- or "None". */
- if (sid == cygheap->user.sid ())
- gid = posix_offset
- + sid_sub_auth_rid (cygheap->user.groups.pgsid);
- else
- gid = posix_offset + DOMAIN_GROUP_RID_USERS;
- }
-
- if (is_domain_account)
- {
- /* Use LDAP to fetch domain account infos. */
- if (cldap->open (NULL) != NO_ERROR)
- break;
- if (cldap->fetch_ad_account (sid, is_group (), domain))
- {
- PWCHAR val;
-
- if ((id_val = cldap->get_primary_gid ()) != ILLEGAL_GID)
- gid = posix_offset + id_val;
- if ((val = cldap->get_gecos ()))
- gecos = colon_to_semicolon (
- wcscpy ((PWCHAR) alloca ((wcslen (val) + 1)
- * sizeof (WCHAR)), val));
- if ((val = cldap->get_home ()))
- home = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1)
- * sizeof (WCHAR)), val);
- if ((val = cldap->get_shell ()))
- shell = wcscpy ((PWCHAR) alloca ((wcslen (val) + 1)
- * sizeof (WCHAR)), val);
- /* Check and, if necessary, add unix<->windows id mapping on
- the fly, unless we're called from getpwent. */
- if (!pldap)
- {
- id_val = cldap->get_unix_uid ();
- if (id_val != ILLEGAL_UID
- && cygheap->ugid_cache.get_uid (id_val)
- == ILLEGAL_UID)
- cygheap->ugid_cache.add_uid (id_val, uid);
- }
- }
- }
- /* Otherwise check account domain (local SAM).*/
- else
- {
- NET_API_STATUS nas;
- PUSER_INFO_4 ui;
- PLOCALGROUP_INFO_1 gi;
- PCWSTR comment;
- PWCHAR pgrp = NULL;
- PWCHAR uxid = NULL;
- struct {
- PCWSTR str;
- size_t len;
- PWCHAR *tgt;
- bool group;
- } search[] = {
- { L"unix=\"", 6, &uxid, true },
- { L"home=\"", 6, &home, false },
- { L"shell=\"", 7, &shell, false },
- { L"group=\"", 7, &pgrp, false },
- { NULL, 0, NULL }
- };
- PWCHAR s, e;
-
- if (acc_type == SidTypeUser)
- {
- nas = NetUserGetInfo (NULL, name, 4, (PBYTE *) &ui);
- if (nas != NERR_Success)
- {
- debug_printf ("NetUserGetInfo(%W) %u", name, nas);
- break;
- }
- /* Set comment variable for below attribute loop. */
- comment = ui->usri4_comment;
- /* Logging in with a Microsoft Account, the user's primary
- group SID is the user's SID. Security sensitive tools
- expecting tight file permissions choke on that. We need
- an explicit primary group which is not identical to the
- user account. Unfortunately, while the default primary
- group of the account in SAM is still "None", "None" is not
- in the user token group list. So, what we do here is to
- use "Users" as a sane default primary group instead. */
- if (wincap.has_microsoft_accounts ())
- {
- struct cyg_USER_INFO_24 *ui24;
- nas = NetUserGetInfo (NULL, name, 24, (PBYTE *) &ui24);
- if (nas == NERR_Success)
- {
- if (ui24->usri24_internet_identity)
- gid = DOMAIN_ALIAS_RID_USERS;
- NetApiBufferFree (ui24);
- }
- }
- }
- else /* acc_type == SidTypeAlias */
- {
- nas = NetLocalGroupGetInfo (NULL, name, 1, (PBYTE *) &gi);
- if (nas != NERR_Success)
- {
- debug_printf ("NetLocalGroupGetInfo(%W) %u", name, nas);
- break;
- }
- /* Set comment variable for below attribute loop. */
- comment = gi->lgrpi1_comment;
- }
- /* Local SAM accounts have only a handful attributes
- available to home users. Therefore, fetch additional
- passwd/group attributes from the "Description" field
- in XML short style. */
- if ((s = wcsstr (comment, L"<cygwin "))
- && (e = wcsstr (s + 8, L"/>")))
- {
- s += 8;
- *e = L'\0';
- while (*s)
- {
- bool found = false;
-
- while (*s == L' ')
- ++s;
- for (size_t i = 0; search[i].str; ++i)
- if ((acc_type == SidTypeUser || search[i].group)
- && !wcsncmp (s, search[i].str, search[i].len))
- {
- s += search[i].len;
- if ((e = wcschr (s, L'"'))
- && (i > 0 || wcsncmp (name, s, e - s)))
- {
- *search[i].tgt =
- (PWCHAR) alloca ((e - s + 1)
- * sizeof (WCHAR));
- *wcpncpy (*search[i].tgt, s, e - s) = L'\0';
- s = e + 1;
- found = true;
- }
- else
- break;
- }
- if (!found)
- break;
- }
- }
- if (acc_type == SidTypeUser)
- NetApiBufferFree (ui);
- else
- NetApiBufferFree (gi);
- if (pgrp)
- {
- /* Set primary group from the "Description" field. Prepend
- account domain if this is a domain member machine or the
- db_prefix setting requires it. */
- char gname[2 * (DNLEN + UNLEN) + 2], *gp = gname;
- struct group *gr;
-
- if (cygheap->dom.member_machine ()
- || !cygheap->pg.nss_prefix_auto ())
- {
- gp = gname
- + sys_wcstombs (gname, sizeof gname,
- cygheap->dom.account_flat_name ());
- *gp++ = cygheap->pg.nss_separator ()[0];
- }
- sys_wcstombs (gp, sizeof gname - (gp - gname), pgrp);
- if ((gr = internal_getgrnam (gname, cldap)))
- gid = gr->gr_gid;
- }
- if (!pldap && uxid && ((id_val = wcstoul (uxid, &e, 10)), !*e))
- {
- if (acc_type == SidTypeUser)
- {
- if (cygheap->ugid_cache.get_uid (id_val) == ILLEGAL_UID)
- cygheap->ugid_cache.add_uid (id_val, uid);
- }
- else if (cygheap->ugid_cache.get_gid (id_val) == ILLEGAL_GID)
- cygheap->ugid_cache.add_gid (id_val, uid);
- }
- }
- break;
- case SidTypeWellKnownGroup:
- fully_qualified_name = (cygheap->pg.nss_prefix_always ()
- /* Microsoft Account */
- || sid_id_auth (sid) == 11);
-#ifdef INTERIX_COMPATIBLE
- if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth_count (sid) > 1)
- {
- uid = 0x1000 * sid_sub_auth (sid, 0)
- + (sid_sub_auth_rid (sid) & 0xffff);
- fully_qualified_name = true;
- }
- else
- uid = 0x10000 + 0x100 * sid_id_auth (sid)
- + (sid_sub_auth_rid (sid) & 0xff);
-#else
- if (sid_id_auth (sid) == 15 /* SECURITY_APP_PACKAGE_AUTHORITY */)
- uid = 0x10000 + 0x100 * sid_id_auth (sid)
- + 0x10 * sid_sub_auth (sid, 0)
- + (sid_sub_auth_rid (sid) & 0xf);
- else if (sid_id_auth (sid) != 5 /* SECURITY_NT_AUTHORITY */)
- uid = 0x10000 + 0x100 * sid_id_auth (sid)
- + (sid_sub_auth_rid (sid) & 0xff);
- else if (sid_sub_auth (sid, 0) < SECURITY_PACKAGE_BASE_RID
- || sid_sub_auth (sid, 0) > SECURITY_MAX_BASE_RID)
- uid = sid_sub_auth_rid (sid) & 0x7ff;
- else
- {
- uid = 0x1000 * sid_sub_auth (sid, 0)
- + (sid_sub_auth_rid (sid) & 0xffff);
- }
-#endif
- /* Special case for "NULL SID", S-1-0-0 and "Everyone", S-1-1-0.
- Never return "NULL SID" or Everyone as user or group. */
- if (uid == 0x10000 || uid == 0x10100)
- return NULL;
- break;
- case SidTypeLabel:
- uid = 0x60000 + sid_sub_auth_rid (sid);
- fully_qualified_name = cygheap->pg.nss_prefix_always ();
- break;
- default:
- return NULL;
- }
- }
- else if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (sid, 0) == SECURITY_LOGON_IDS_RID)
- {
- /* Logon ID. Mine or other? */
- get_logon_sid ();
- if (PSID (logon_sid) == NO_SID)
- return NULL;
- if (RtlEqualSid (sid, logon_sid))
- {
- uid = 0xfff;
- wcpcpy (name = namebuf, L"CurrentSession");
- }
- else
- {
- uid = 0xffe;
- wcpcpy (name = namebuf, L"OtherSession");
- }
- acc_type = SidTypeUnknown;
- }
- else if (sid_id_auth (sid) == 18)
- {
- /* Authentication assertion SIDs.
-
- Available when using a 2012R2 DC, but not supported by
- LookupAccountXXX on pre Windows 8/2012 machines */
- uid = 0x11200 + sid_sub_auth_rid (sid);
- wcpcpy (name = namebuf, sid_sub_auth_rid (sid) == 1
- ? (PWCHAR) L"Authentication authority asserted identity"
- : (PWCHAR) L"Service asserted identity");
- fully_qualified_name = false;
- acc_type = SidTypeUnknown;
+ paranoid_printf ("NtOpenFile(%S) failed, status %y", &upath, status);
+ goto out;
}
- else if (sid_id_auth (sid) == 22)
+ status = NtQueryInformationFile (fh, &io, &fsi, sizeof fsi,
+ FileStandardInformation);
+ if (!NT_SUCCESS (status))
{
- /* Samba UNIX Users/Groups
-
- This *might* collide with a posix_offset of some trusted domain.
- It's just very unlikely. */
- uid = MAP_UNIX_TO_CYGWIN_ID (sid_sub_auth_rid (sid));
- /* Unfortunately we have no access to the file server from here,
- so we can't generate correct user names. */
- p = wcpcpy (dom, L"Unix_");
- wcpcpy (p, sid_sub_auth (sid, 0) == 1 ? L"User" : L"Group");
- __small_swprintf (name = namebuf, L"%d", uid & UNIX_POSIX_MASK);
- fully_qualified_name = true;
- acc_type = SidTypeUnknown;
+ paranoid_printf ("NtQueryInformationFile(%S) failed, status %y",
+ &upath, status);
+ goto out;
}
- else
+ /* FIXME: Should we test for HighPart set? If so, the
+ passwd or group file is way beyond what we can handle. */
+ /* FIXME 2: It's still ugly that we keep the file in memory.
+ Big organizations have naturally large passwd files. */
+ buf = (char *) malloc (fsi.EndOfFile.LowPart + 1);
+ if (!buf)
{
- if (cygheap->dom.member_machine ()
- && sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (sid, 0) == SECURITY_NT_NON_UNIQUE)
- {
- /* Check if we know the domain. If so, create a passwd/group
- entry with domain prefix and RID as username. */
- PDS_DOMAIN_TRUSTSW td = NULL;
-
- sid_sub_auth_count (sid) = sid_sub_auth_count (sid) - 1;
- if (RtlEqualSid (sid, cygheap->dom.primary_sid ()))
- {
- domain = cygheap->dom.primary_flat_name ();
- posix_offset = PRIMARY_POSIX_OFFSET;
- }
- else
- for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
- if (td->DomainSid && RtlEqualSid (sid, td->DomainSid))
- {
- domain = td->NetbiosDomainName;
- posix_offset = fetch_posix_offset (td, &loc_ldap);
- break;
- }
- }
- if (domain)
- {
- sid_sub_auth_count (sid) = sid_sub_auth_count (sid) + 1;
- wcscpy (dom, domain);
- __small_swprintf (name = namebuf, L"%W(%u)",
- is_group () ? L"Group" : L"User",
- sid_sub_auth_rid (sid));
- uid = posix_offset + sid_sub_auth_rid (sid);
- }
- else
- {
- wcpcpy (dom, L"Unknown");
- wcpcpy (name = namebuf, is_group () ? L"Group" : L"User");
- }
- fully_qualified_name = true;
- acc_type = SidTypeUnknown;
+ paranoid_printf ("malloc (%u) failed", fsi.EndOfFile.LowPart);
+ goto out;
}
-
- tmp_pathbuf tp;
- PWCHAR linebuf = tp.w_get ();
- char *line = NULL;
-
- WCHAR posix_name[UNLEN + 1 + DNLEN + 1];
- p = posix_name;
- if (gid == ILLEGAL_GID)
- gid = uid;
- if (fully_qualified_name)
- p = wcpcpy (wcpcpy (p, dom), cygheap->pg.nss_separator ());
- wcpcpy (p, name);
-
- if (is_group ())
- __small_swprintf (linebuf, L"%W:%W:%u:",
- posix_name, sid.string (sidstr), uid);
- /* For non-users, create a passwd entry which doesn't allow interactive
- logon. Unless it's the SYSTEM account. This conveniently allows to
- logon interactively as SYSTEM for debugging purposes. */
- else if (acc_type != SidTypeUser && sid != well_known_system_sid)
- __small_swprintf (linebuf, L"%W:*:%u:%u:,%W:/:/sbin/nologin",
- posix_name, uid, gid, sid.string (sidstr));
- else
- __small_swprintf (linebuf, L"%W:*:%u:%u:%W%WU-%W\\%W,%W:%W%W:%W",
- posix_name, uid, gid,
- gecos ?: L"", gecos ? L"," : L"",
- dom, name,
- sid.string (sidstr),
- home ? L"" : L"/home/", home ?: name,
- shell ?: L"/bin/bash");
- sys_wcstombs_alloc (&line, HEAP_BUF, linebuf);
- debug_printf ("line: <%s>", line);
- return line;
-}
-
-client_request_pwdgrp::client_request_pwdgrp (fetch_user_arg_t &arg, bool group)
- : client_request (CYGSERVER_REQUEST_PWDGRP, &_parameters, sizeof (_parameters))
-{
- size_t len = 0;
- char *p;
-
- _parameters.in.group = group;
- _parameters.in.type = arg.type;
- switch (arg.type)
- {
- case SID_arg:
- RtlCopySid (sizeof (DBGSID), (PSID) &_parameters.in.arg.sid, *arg.sid);
- len = RtlLengthSid (*arg.sid);
- break;
- case NAME_arg:
- p = stpcpy (_parameters.in.arg.name, arg.name);
- len = p - _parameters.in.arg.name + 1;
- break;
- case ID_arg:
- _parameters.in.arg.id = arg.id;
- len = sizeof (uint32_t);
- }
- msglen (__builtin_offsetof (struct _pwdgrp_param_t::_pwdgrp_in_t, arg) + len);
-}
-
-char *
-pwdgrp::fetch_account_from_cygserver (fetch_user_arg_t &arg)
-{
- client_request_pwdgrp request (arg, is_group ());
- if (request.make_request () == -1 || request.error_code ())
+ status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, fsi.EndOfFile.LowPart,
+ NULL, NULL);
+ if (!NT_SUCCESS (status))
{
- /* Cygserver not running? Don't try again. This will automatically
- avoid an endless loop in cygserver itself. */
- if (request.error_code () == ENOSYS)
- cygheap->pg.nss_disable_cygserver_caching ();
- return NULL;
- }
- if (!request.line ())
- return NULL;
- return cstrdup (request.line ());
-}
-
-void *
-pwdgrp::add_account_from_cygserver (cygpsid &sid)
-{
- /* No, Everyone is no group in terms of POSIX. */
- if (sid_id_auth (sid) == 1 /* SECURITY_WORLD_SID_AUTHORITY */
- && sid_sub_auth (sid, 0) == SECURITY_WORLD_RID)
- return NULL;
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = fetch_account_from_cygserver (arg);
- return add_account_post_fetch (line, true);
-}
-
-void *
-pwdgrp::add_account_from_cygserver (const char *name)
-{
- fetch_user_arg_t arg;
- arg.type = NAME_arg;
- arg.name = name;
- char *line = fetch_account_from_cygserver (arg);
- return add_account_post_fetch (line, true);
-}
-
-void *
-pwdgrp::add_account_from_cygserver (uint32_t id)
-{
- fetch_user_arg_t arg;
- arg.type = ID_arg;
- arg.id = id;
- char *line = fetch_account_from_cygserver (arg);
- return add_account_post_fetch (line, true);
+ paranoid_printf ("NtReadFile(%S) failed, status %y", &upath, status);
+ free (buf);
+ goto out;
+ }
+ buf[fsi.EndOfFile.LowPart] = '\0';
+ for (char *eptr = buf; (eptr = add_line (eptr)); )
+ continue;
+ debug_printf ("%W curr_lines %d", rel_path, curr_lines);
+ res = succeeded;
+
+out:
+ if (fh)
+ NtClose (fh);
+ debug_printf ("%W load %s", rel_path, res);
+ initialized = true;
}
diff --git a/winsup/cygwin/uname.cc b/winsup/cygwin/uname.cc
index b586e6374..2990a01da 100644
--- a/winsup/cygwin/uname.cc
+++ b/winsup/cygwin/uname.cc
@@ -45,7 +45,12 @@ uname (struct utsname *name)
cygwin_version.dll_major / 1000,
cygwin_version.dll_major % 1000,
cygwin_version.dll_minor,
+#if 0
snp ? "s" : "",
+#else
+ /* Add a hint to allow to recognize updates */
+ "-2",
+#endif
cygwin_version.api_major,
cygwin_version.api_minor,
cygwin_version.shared_data,
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index f6faa03b6..cdbb1c37e 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -2,7 +2,7 @@
capability class to the appropriate values.
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
- 2012, 2013, 2014 Red Hat, Inc.
+ 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -49,7 +49,6 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_pipe_reject_remote_clients:false,
terminate_thread_frees_stack:false,
has_precise_system_time:false,
- has_microsoft_accounts:false,
};
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -78,7 +77,6 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_pipe_reject_remote_clients:false,
terminate_thread_frees_stack:false,
has_precise_system_time:false,
- has_microsoft_accounts:false,
};
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -107,7 +105,6 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_pipe_reject_remote_clients:true,
terminate_thread_frees_stack:true,
has_precise_system_time:false,
- has_microsoft_accounts:false,
};
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -136,7 +133,6 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_pipe_reject_remote_clients:true,
terminate_thread_frees_stack:true,
has_precise_system_time:false,
- has_microsoft_accounts:false,
};
wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -165,7 +161,6 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_pipe_reject_remote_clients:true,
terminate_thread_frees_stack:true,
has_precise_system_time:true,
- has_microsoft_accounts:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 43c72b648..98fef2656 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -1,7 +1,7 @@
/* wincap.h: Header for OS capability class.
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
- 2012, 2013, 2014 Red Hat, Inc.
+ 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -39,7 +39,6 @@ struct wincaps
unsigned has_pipe_reject_remote_clients : 1;
unsigned terminate_thread_frees_stack : 1;
unsigned has_precise_system_time : 1;
- unsigned has_microsoft_accounts : 1;
};
class wincapc
@@ -90,7 +89,6 @@ public:
bool IMPLEMENT (has_pipe_reject_remote_clients)
bool IMPLEMENT (terminate_thread_frees_stack)
bool IMPLEMENT (has_precise_system_time)
- bool IMPLEMENT (has_microsoft_accounts)
#undef IMPLEMENT
};
diff --git a/winsup/cygwin/winlean.h b/winsup/cygwin/winlean.h
index 63cebdb96..64e689dd4 100644
--- a/winsup/cygwin/winlean.h
+++ b/winsup/cygwin/winlean.h
@@ -1,6 +1,6 @@
/* winlean.h - Standard "lean" windows include
- Copyright 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ Copyright 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 2be96f8ef..99b3e0763 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -177,8 +177,20 @@ void __reg1 do_exit (int) __attribute__ ((noreturn));
/* libstdc++ malloc operator wrapper support. */
extern struct per_process_cxx_malloc default_cygwin_cxx_malloc;
+/* UID/GID */
+void uinfo_init ();
+
+#define ILLEGAL_UID ((uid_t)-1)
+#define ILLEGAL_GID ((gid_t)-1)
#define ILLEGAL_SEEK ((off_t)-1)
+#ifndef __x86_64__
+#define ILLEGAL_UID16 ((__uid16_t)-1)
+#define ILLEGAL_GID16 ((__gid16_t)-1)
+#define uid16touid32(u16) ((u16)==ILLEGAL_UID16?ILLEGAL_UID:(uid_t)(u16))
+#define gid16togid32(g16) ((g16)==ILLEGAL_GID16?ILLEGAL_GID:(gid_t)(g16))
+#endif
+
/* Convert LARGE_INTEGER into long long */
#define get_ll(pl) (((long long) (pl).HighPart << 32) | (pl).LowPart)
@@ -290,17 +302,6 @@ extern "C" char _data_start__, _data_end__, _bss_start__, _bss_end__;
extern "C" void (*__CTOR_LIST__) (void);
extern "C" void (*__DTOR_LIST__) (void);
-#ifdef NEEDED
-/* This was inexplicably needed after updating a toolchain.
- The need disappeared when updating further but I'm keeping
- it around temporarily in case the issue crops up again.
- This manifests as SEGVs in one of the Interlocked functions below
- in kernel32.dll. */
-#define InterlockedDecrement _InterlockedDecrement
-#define InterlockedExchange _InterlockedExchange
-#define InterlockedIncrement _InterlockedIncrement
-#endif /*NEEDED*/
-
#ifndef NO_GLOBALS_H
#define _RDATA /* See globals.h */
#include "globals.h"
diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog
index 41ce35cc7..4deed1e4f 100644
--- a/winsup/doc/ChangeLog
+++ b/winsup/doc/ChangeLog
@@ -1,76 +1,16 @@
-2014-11-07 Corinna Vinschen <corinna@vinschen.de>
-
- * utils.xml (mkpasswd): Change /etc/group to /etc/passwd.
-
2014-11-05 Corinna Vinschen <corinna@vinschen.de>
- * new-features.xml (ov-new1.7.33): Document xdr and atexit.
-
-2014-10-30 David Rothenberger <daveroth@acm.org>
-
- * ntsec.xml: Fix typo.
-
-2014-10-29 Dave Habermann <dahabermann@dow.com>
-
- * ntsec.xml (ntsec-mapping-caching): Describe service dependencies
- in terms of cygserver.
-
-2014-10-28 Corinna Vinschen <corinna@vinschen.de>
-
- * xidepend: Make PDF file dependent on the same input files as the
- HTML file of the same name to trigger automatic rebuild of PDFs on
- source file changes as well.
+ * new-features.xml (ov-new1.7.33): Document atexit.
2014-10-28 Corinna Vinschen <corinna@vinschen.de>
* cygwinenv.xml: Change default setting of dosfilewarning.
* new-features.xml (ov-new1.7.33): Document aforementioned change.
-2014-10-28 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml: Fix Solaris doc URLs.
-
-2014-10-28 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml: Try to make an expression less ambiguous.
-
-2014-10-27 Luke Kendall <luke.kendall@cisra.canon.com.au>
- Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml: More language fixes.
-
2014-10-27 Corinna Vinschen <corinna@vinschen.de>
* new-features.xml (ov-new1.7.33): Document empty $PATH handling.
-2014-10-27 Corinna Vinschen <corinna@vinschen.de>
-
- * new-features.xml (ov-new1.7.33): Fix paragraph order.
-
-2014-10-27 Corinna Vinschen <corinna@vinschen.de>
-
- * highlights.xml: Rearrange itemizedlist markup slightly.
- * new-features.xml (ov-new1.7.33): Add setfacl -b option.
- * utils.xml (setfacl): Ditto.
-
-2014-10-24 Luke Kendall <luke.kendall@cisra.canon.com.au>
-
- * ntsec.xml: More language and typo fixes.
-
-2014-10-23 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml: Fix language.
-
-2014-10-22 Corinna Vinschen <corinna@vinschen.de>
-
- * Makefile.in: Create install targets.
- (cygwin-ug-net/cygwin-ug-net.pdf): Create subdir to allow building PDF
- even if subdir is missing.
- (cygwin-api/cygwin-api.pdf): Ditto.
- * configure.ac: Add AC_PROG_INSTALL rule.
- * configure: Regenerate.
- * new-features.xml (ov-new1.7.33): Add installation of docs.
-
2014-10-22 Corinna Vinschen <corinna@vinschen.de>
* posix.xml (std-gnu): Add ffsl, ffsll, quotactl.
@@ -89,80 +29,11 @@
* new-features.xml (ov-new1.7.33): Update to current state.
-2014-09-05 Corinna Vinschen <corinna@vinschen.de>
-
- * pathnames.xml (cygdrive): Add /proc/cygdrive description.
-
-2014-09-03 Corinna Vinschen <corinna@vinschen.de>
-
- * utils.xml (setfacl): Align documentation to help text in setfacl.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml (ntsec-common): Drop outdated comment about underdeveloped
- Solaris ACL API support.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * utils.xml (setfacl): Drop outdated note that default ACEs are not
- taken into account.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml: Disable description of db_prefix and db_separator settings.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * utils.xml (getfacl): Document additional suid/sgid/vtx flag printing.
-
-2014-08-15 Corinna Vinschen <corinna@vinschen.de>
-
- * configure.ac: Convert to new AC_INIT style.
- * configure: Regenerate.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * cygwin-api.xml: Include misc-funcs.xml.
- * misc-funcs.xml: New file.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * cygwin-api.xml: Move chapter tags from path.xml back here.
- Include logon-funcs.xml.
- * logon-funcs.xml: Moved from ../cygwin here and converted to XML.
- * path.xml: Drop chapter tags. Create subsections.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * Makefile.in: Throughout use parenthesis instead of braces where
- appropriate.
- (DBXDIRS): Remove.
- (XSLTPROC): Define for symmetry. Use throughout.
- (clean): Drop removing cygwin-api.xml and doctool.*.
- (cygwin-api.xml): Drop rule.
- (doctool): Drop rule.
- (Makefile.dep): Add dependency to cygwin-api.xml.
- * cygwin-api.in.xml: Rename to cygwin-api.xml. Convert includes to
- XML XInclude style.
- * doctool.c: Remove.
- * doctool.txt: Remove.
- * faq-programming.xml: Drop reference to local utils.xml file.
- * path.xml: Moved from ../cygwin and converted to XML.
- * posix.xml: Ditto.
- * using.xml: Drop relative path from utils.xml include.
- * utils.xml: Moved from ../utils.
-
2014-08-13 Corinna Vinschen <corinna@vinschen.de>
* new-features.xml (ov-new1.7.33): Add new section.
(ov-new1.7.32): Reflect intermediate 1.7.32 release.
-2014-08-06 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml (ntsec-mapping): Drop plus-prepended builtin accounts as
- default setting. Add short explanation in db_prefix: always mode.
- Fix a type. Drop a paragraph with redundant information.
-
2014-08-03 Yaakov Selkowitz <yselkowitz@cygwin.com>
* faq-what.xml (faq.what.who): Remove mention of retired setup
@@ -172,32 +43,6 @@
* faq-what.xml (faq.what.who): CGF has retired.
-2014-07-30 Corinna Vinschen <corinna@vinschen.de>
-
- * ntsec.xml: Small improvments.
-
-2014-07-30 Corinna Vinschen <corinna@vinschen.de>
-
- * new-features.xml: (ov-new1.7): Change section title.
-
-2014-07-30 Corinna Vinschen <corinna@vinschen.de>
-
- * new-features.xml: (ov-new1.7.1): Add new section. Move old 1.7
- sections into section level 3.
-
-2014-07-30 Corinna Vinschen <corinna@vinschen.de>
-
- * cygwin.xsl: Allow 3 section levels in TOC.
- * new-features.xml: (ov-new1.7.32): Add new section.
- * ntsec.xml: Rename top-level section to reflect extension of topics.
- Remove old /etc/passwd, /etc/group considerations. Add new sections
- explaining Windows to POSIX account mapping. Make setuid sections
- third level sections.
- * pathnames.xml: Note new method of account mapping for fstab.d/$USER.
- * faq-setup.xml: Rework references to /etc/passwd and /etc/group to
- reflect changes to account handling.
- * faq-using.xml: Ditto.
-
2014-07-21 Corinna Vinschen <corinna@vinschen.de>
* new-features.xml: (ov-new1.7.31): Add new section.
diff --git a/winsup/doc/Makefile.in b/winsup/doc/Makefile.in
index 21fd5ad30..8bc583149 100644
--- a/winsup/doc/Makefile.in
+++ b/winsup/doc/Makefile.in
@@ -1,6 +1,6 @@
# -*- Makefile -*- for winsup/doc
# Copyright (c) 1998-2000, 2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010,
-# 2013, 2014 Red Hat, Inc.
+# 2013 Red Hat, Inc.
#
# This file is part of Cygwin.
#
@@ -12,32 +12,22 @@ SHELL = @SHELL@
srcdir = @srcdir@
VPATH = @srcdir@
-datarootdir:=@datarootdir@
-docdir = @docdir@
-htmldir = @htmldir@
-
-override INSTALL:=@INSTALL@
-override INSTALL_DATA:=@INSTALL_DATA@
-
-MKDIRP:=$(INSTALL) -m 755 -d
+DBXDIRS = -d $(srcdir) -d $(srcdir)/../utils -d $(srcdir)/../cygwin
CC:=@CC@
CC_FOR_TARGET:=@CC@
-XSLTPROC:=xsltproc --xinclude
XMLTO:=xmlto --skip-validation --with-dblatex
include $(srcdir)/../Makefile.common
-FAQ_SOURCES:= $(wildcard $(srcdir)/faq*.xml)
+FAQ_SOURCES:= $(wildcard ${srcdir}/faq*.xml)
.SUFFIXES: .html .body
.html.body:
$(srcdir)/bodysnatcher.pl $<
-.PHONY: all clean install install-all install-pdf install-html tarball
-
all: Makefile Makefile.dep \
cygwin-ug-net/cygwin-ug-net.html \
cygwin-ug-net/cygwin-ug-net-nochunks.html.gz \
@@ -46,54 +36,46 @@ all: Makefile Makefile.dep \
cygwin-ug-net/cygwin-ug-net.pdf \
cygwin-api/cygwin-api.pdf
-Makefile: $(srcdir)/Makefile.in
+Makefile: ${srcdir}/Makefile.in
/bin/sh ./config.status
clean:
rm -f Makefile.dep
+ rm -f doctool.exe doctool.o
+ rm -f cygwin-api.xml
rm -f *.html *.html.gz
rm -Rf cygwin-api cygwin-ug cygwin-ug-net faq
-install: install-all
-
-install-all: install-pdf install-html
-
-install-pdf: cygwin-ug-net/cygwin-ug-net.pdf cygwin-api/cygwin-api.pdf
- @$(MKDIRP) $(DESTDIR)$(docdir)
- $(INSTALL_DATA) $^ $(DESTDIR)$(docdir)
-
-install-html: cygwin-ug-net/cygwin-ug-net.html cygwin-api/cygwin-api.html
- @$(MKDIRP) $(DESTDIR)$(htmldir)/cygwin-ug-net
- $(INSTALL_DATA) cygwin-ug-net/*.html $(DESTDIR)$(htmldir)/cygwin-ug-net
- $(INSTALL_DATA) cygwin-ug-net/cygwin-ug-net.html $(DESTDIR)$(htmldir)/cygwin-ug-net/index.html
- @$(MKDIRP) $(DESTDIR)$(htmldir)/cygwin-api
- $(INSTALL_DATA) cygwin-api/*.html $(DESTDIR)$(htmldir)/cygwin-api
- $(INSTALL_DATA) cygwin-api/cygwin-api.html $(DESTDIR)$(htmldir)/cygwin-api/index.html
+install: all
cygwin-ug-net/cygwin-ug-net-nochunks.html.gz : cygwin-ug-net.xml
- -$(XMLTO) html-nochunks -m $(srcdir)/cygwin.xsl $<
+ -${XMLTO} html-nochunks -m $(srcdir)/cygwin.xsl $<
-cp cygwin-ug-net.html cygwin-ug-net/cygwin-ug-net-nochunks.html
-rm -f cygwin-ug-net/cygwin-ug-net-nochunks.html.gz
-gzip cygwin-ug-net/cygwin-ug-net-nochunks.html
cygwin-ug-net/cygwin-ug-net.html : cygwin-ug-net.xml cygwin.xsl
- -$(XMLTO) html -o cygwin-ug-net/ -m $(srcdir)/cygwin.xsl $<
+ -${XMLTO} html -o cygwin-ug-net/ -m $(srcdir)/cygwin.xsl $<
cygwin-ug-net/cygwin-ug-net.pdf : cygwin-ug-net.xml fo.xsl
- @$(MKDIRP) cygwin-ug-net
- -$(XSLTPROC) $(srcdir)/fo.xsl $< | fop -q -fo - $@
+ -xsltproc --xinclude $(srcdir)/fo.xsl $< | fop -q -fo - $@
cygwin-api/cygwin-api.html : cygwin-api.xml cygwin.xsl
- -$(XMLTO) html -o cygwin-api/ -m $(srcdir)/cygwin.xsl $<
+ -${XMLTO} html -o cygwin-api/ -m $(srcdir)/cygwin.xsl $<
cygwin-api/cygwin-api.pdf : cygwin-api.xml fo.xsl
- @$(MKDIRP) cygwin-api
- -$(XSLTPROC) $(srcdir)/fo.xsl $< | fop -q -fo - $@
+ -xsltproc --xinclude $(srcdir)/fo.xsl $< | fop -q -fo - $@
+
+cygwin-api.xml : cygwin-api.in.xml doctool Makefile.in
+ -./doctool -m $(DBXDIRS) -s $(srcdir) -o $@ $<
faq/faq.html : $(FAQ_SOURCES)
- -$(XMLTO) html -o faq -m $(srcdir)/cygwin.xsl $(srcdir)/faq.xml
+ -${XMLTO} html -o faq -m $(srcdir)/cygwin.xsl $(srcdir)/faq.xml
-sed -i 's;</a><a name="id[0-9]*"></a>;</a>;g' faq/faq.html
+doctool : doctool.c
+ gcc -g $< -o $@
+
TBFILES = cygwin-ug-net.dvi cygwin-ug-net.rtf cygwin-ug-net.ps \
cygwin-ug-net.pdf cygwin-ug-net.xml \
cygwin-api.dvi cygwin-api.rtf cygwin-api.ps \
@@ -105,7 +87,7 @@ tarball : cygwin-docs.tar.bz2
cygwin-docs.tar.bz2 : $(TBFILES) $(TBDEPS)
find $(TBFILES) $(TBDIRS) \! -type d | sort | tar -T - -cf - | bzip2 > cygwin-docs.tar.bz2
-Makefile.dep: cygwin-ug-net.xml cygwin-api.xml
+Makefile.dep: cygwin-ug-net.xml
cd $(srcdir) && ./xidepend $^ > "${CURDIR}/$@"
-include Makefile.dep
diff --git a/winsup/doc/configure b/winsup/doc/configure
index a484c8de8..996722fc1 100755
--- a/winsup/doc/configure
+++ b/winsup/doc/configure
@@ -1,8 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Cygwin Documentation 0.
-#
-# Report bugs to <cygwin@cygwin.com>.
+# Generated by GNU Autoconf 2.69.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -265,11 +263,10 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and cygwin@cygwin.com
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
exit 1
fi
@@ -577,14 +574,14 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME='Cygwin Documentation'
-PACKAGE_TARNAME='cygwin'
-PACKAGE_VERSION='0'
-PACKAGE_STRING='Cygwin Documentation 0'
-PACKAGE_BUGREPORT='cygwin@cygwin.com'
-PACKAGE_URL='https://cygwin.com'
-
-ac_unique_file="cygwin-api.xml"
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="cygwin-api.in.xml"
ac_no_link=no
ac_subst_vars='LTLIBOBJS
LIBOBJS
@@ -608,9 +605,6 @@ build_os
build_vendor
build_cpu
build
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
target_alias
host_alias
build_alias
@@ -701,7 +695,7 @@ sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
@@ -1201,7 +1195,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Cygwin Documentation 0 to adapt to many kinds of systems.
+\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1249,7 +1243,7 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/cygwin]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
@@ -1266,9 +1260,7 @@ _ACEOF
fi
if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of Cygwin Documentation 0:";;
- esac
+
cat <<\_ACEOF
Some influential environment variables:
@@ -1283,8 +1275,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Documentation home page: <https://cygwin.com>.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1347,7 +1338,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Cygwin Documentation configure 0
+configure
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1402,7 +1393,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Cygwin Documentation $as_me 0, which was
+It was created by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1750,7 +1741,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_aux_dir=
for ac_dir in ../.. "$srcdir"/../..; do
if test -f "$ac_dir/install-sh"; then
@@ -1781,99 +1771,6 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
-if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- rm -rf conftest.one conftest.two conftest.dir
- echo one > conftest.one
- echo two > conftest.two
- mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
- test -s conftest.one && test -s conftest.two &&
- test -s conftest.dir/conftest.one &&
- test -s conftest.dir/conftest.two
- then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- fi
- done
- done
- ;;
-esac
-
- done
-IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- INSTALL=$ac_install_sh
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
@@ -3494,7 +3391,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Cygwin Documentation $as_me 0, which was
+This file was extended by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -3541,14 +3438,13 @@ Usage: $0 [OPTION]... [TAG]...
Configuration files:
$config_files
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Documentation home page: <https://cygwin.com>."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Cygwin Documentation config.status 0
+config.status
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -3558,7 +3454,6 @@ gives unlimited permission to copy, distribute and modify it."
ac_pwd='$ac_pwd'
srcdir='$srcdir'
-INSTALL='$INSTALL'
test -n "\$AWK" || AWK=awk
_ACEOF
@@ -3994,10 +3889,6 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
# CONFIG_FILE
#
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
- esac
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
@@ -4051,7 +3942,6 @@ s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-s&@INSTALL@&$ac_INSTALL&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
diff --git a/winsup/doc/configure.ac b/winsup/doc/configure.ac
index 30439b8c6..ea5d61074 100644
--- a/winsup/doc/configure.ac
+++ b/winsup/doc/configure.ac
@@ -1,5 +1,5 @@
-dnl Autoconf configure script for winsup/doc
-dnl Copyright 1997, 1998, 1999, 2000, 2001, 2006, 2012, 2013, 2014 Red Hat, Inc.
+dnl Autoconf configure script for winsup/regexp
+dnl Copyright 1997,1998,1999,2000,2001 Red Hat, Inc.
dnl
dnl This file is part of Cygwin.
dnl
@@ -9,13 +9,10 @@ dnl details.
dnl Process this file with autoconf to produce a configure script.
-AC_PREREQ([2.59])
-AC_INIT([Cygwin Documentation], 0,
- cygwin@cygwin.com, cygwin, https://cygwin.com)
-AC_CONFIG_SRCDIR(cygwin-api.xml)
+AC_PREREQ(2.59)
+AC_INIT(cygwin-api.in.xml)
AC_CONFIG_AUX_DIR(../..)
-AC_PROG_INSTALL
AC_NO_EXECUTABLES
AC_CANONICAL_SYSTEM
diff --git a/winsup/doc/cygwin-api.in.xml b/winsup/doc/cygwin-api.in.xml
new file mode 100644
index 000000000..3fee468dc
--- /dev/null
+++ b/winsup/doc/cygwin-api.in.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
+ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+
+<book id="cygwin-api" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <bookinfo>
+ <date>1998-08-31</date>
+ <title>Cygwin API Reference</title>
+DOCTOOL-INSERT-legal
+ </bookinfo>
+
+ <toc></toc>
+
+<chapter id="compatibility"><title>Compatibility</title>
+DOCTOOL-INSERT-std-susv4
+DOCTOOL-INSERT-std-bsd
+DOCTOOL-INSERT-std-gnu
+DOCTOOL-INSERT-std-solaris
+DOCTOOL-INSERT-std-deprec
+DOCTOOL-INSERT-std-notimpl
+DOCTOOL-INSERT-std-notes
+</chapter>
+
+<chapter id="cygwin-functions"><title>Cygwin Functions</title>
+
+<para>These functions are specific to Cygwin itself, and probably
+won't be found anywhere else. </para>
+
+DOCTOOL-INSERT-func-
+
+</chapter>
+
+</book>
diff --git a/winsup/doc/cygwin-api.xml b/winsup/doc/cygwin-api.xml
deleted file mode 100644
index ac98c0033..000000000
--- a/winsup/doc/cygwin-api.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-
-<book id="cygwin-api" xmlns:xi="http://www.w3.org/2001/XInclude">
-
- <bookinfo>
- <date>1998-08-31</date>
- <title>Cygwin API Reference</title>
- <xi:include href="legal.xml"/>
- </bookinfo>
-
- <toc></toc>
-
- <xi:include href="posix.xml"/>
-
- <chapter id="cygwin-functions" xmlns:xi="http://www.w3.org/2001/XInclude">
- <title>Cygwin Functions</title>
-
- <xi:include href="path.xml"/>
- <xi:include href="logon-funcs.xml"/>
- <xi:include href="misc-funcs.xml"/>
-
- </chapter>
-
-</book>
diff --git a/winsup/doc/cygwin.xsl b/winsup/doc/cygwin.xsl
index 157f6f2ed..23512934a 100644
--- a/winsup/doc/cygwin.xsl
+++ b/winsup/doc/cygwin.xsl
@@ -8,6 +8,5 @@
<xsl:param name="html.stylesheet" select="'docbook.css'"/>
<xsl:param name="use.id.as.filename" select="1" />
<xsl:param name="root.filename" select="@id" />
-<xsl:param name="toc.section.depth" select="3" />
</xsl:stylesheet>
diff --git a/winsup/doc/doctool.c b/winsup/doc/doctool.c
new file mode 100644
index 000000000..0a5060c76
--- /dev/null
+++ b/winsup/doc/doctool.c
@@ -0,0 +1,622 @@
+/* doctool.c
+
+ Copyright 1998,1999,2000,2001,2006 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. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utime.h>
+
+/* Building native in a cross-built directory is tricky. Be careful,
+and beware that you don't have the full portability stuff available to
+you (like libiberty) */
+
+/*****************************************************************************/
+
+/* The list of extensions that may contain SGML snippets. We check
+ both cases in case the file system isn't case sensitive enough. */
+
+struct {
+ char *upper;
+ char *lower;
+ int is_sgml;
+} extensions[] = {
+ { ".C", ".c", 0 },
+ { ".CC", ".cc", 0 },
+ { ".H", ".h", 0 },
+ { ".SGML", ".sgml", 1 },
+ { 0, 0, 0 }
+};
+
+/*****************************************************************************/
+
+void
+show_help()
+{
+ printf("Usage: doctool [-m] [-i] [-d dir] [-o outfile] [-s prefix] \\\n");
+ printf(" [-b book_id] infile\n");
+ printf(" -m means to adjust Makefile to include new dependencies\n");
+ printf(" -i means to include internal snippets\n");
+ printf(" -d means to recursively scan directory for snippets\n");
+ printf(" -o means to output to file (else stdout)\n");
+ printf(" -s means to suppress source dir prefix\n");
+ printf(" -b means to change the <book id=\"book_id\">\n");
+ printf("\n");
+ printf("doctool looks for DOCTOOL-START and DOCTOOL-END lines in source,\n");
+ printf("saves <foo id=\"bar\"> blocks, and looks for DOCTOOL-INSERT-bar\n");
+ printf("commands to insert selected sections. IDs starting with int-\n");
+ printf("are internal only, add- are added at the end of relevant sections\n");
+ printf("or add-int- for both. Inserted sections are chosen by prefix,\n");
+ printf("and sorted when inserted.\n");
+ exit(1);
+}
+
+/*****************************************************************************/
+
+typedef struct Section {
+ struct Section *next;
+ struct OneFile *file;
+ char *name;
+ char internal;
+ char addend;
+ char used;
+ char **lines;
+ int num_lines;
+ int max_lines;
+} Section;
+
+typedef struct OneFile {
+ struct OneFile *next;
+ char *filename;
+ int enable_scan;
+ int used;
+ Section *sections;
+} OneFile;
+
+OneFile *file_list = 0;
+
+char *output_name = 0;
+FILE *output_file = 0;
+
+char *source_dir_prefix = "";
+char *book_id = 0;
+
+int internal_flag = 0;
+
+/*****************************************************************************/
+
+char *
+has_string(char *line, char *string)
+{
+ int i;
+ while (*line)
+ {
+ for (i=0; line[i]; i++)
+ {
+ if (!string[i])
+ return line;
+ if (line[i] != string[i])
+ break;
+ }
+ line++;
+ }
+ return 0;
+}
+
+int
+starts_with(char *line, char *string)
+{
+ int i=0;
+ while (1)
+ {
+ if (!string[i])
+ return 1;
+ if (!line[i] || line[i] != string[i])
+ return 0;
+ i++;
+ }
+}
+
+/*****************************************************************************/
+
+#ifdef S_ISLNK
+#define STAT lstat
+#else
+#define STAT stat
+#endif
+
+void
+scan_directory(dirname)
+ char *dirname;
+{
+ struct stat st;
+ char *name;
+ struct dirent *de;
+ DIR *dir = opendir(dirname);
+ if (!dir)
+ return;
+ while (de = readdir(dir))
+ {
+ if (strcmp(de->d_name, ".") == 0
+ || strcmp(de->d_name, "..") == 0)
+ continue;
+
+ name = (char *)malloc(strlen(dirname)+strlen(de->d_name)+3);
+ strcpy(name, dirname);
+ strcat(name, "/");
+ strcat(name, de->d_name);
+
+ STAT(name, &st);
+
+ if (S_ISDIR(st.st_mode) && strcmp(de->d_name, "CVS") != 0)
+ {
+ scan_directory(name);
+ }
+
+ else if (S_ISREG(st.st_mode))
+ {
+ char *dot = strrchr(de->d_name, '.');
+ int i;
+
+ if (dot)
+ {
+ for (i=0; extensions[i].upper; i++)
+ if (strcmp(dot, extensions[i].upper) == 0
+ || strcmp(dot, extensions[i].lower) == 0)
+ {
+ OneFile *one = (OneFile *)malloc(sizeof(OneFile));
+ one->next = file_list;
+ file_list = one;
+ one->filename = name;
+ one->enable_scan = ! extensions[i].is_sgml;
+ one->used = 0;
+ one->sections = 0;
+ }
+ }
+ }
+ }
+ closedir (dir);
+}
+
+/*****************************************************************************/
+
+void
+scan_file(OneFile *one)
+{
+ FILE *f = fopen(one->filename, "r");
+ int enabled = ! one->enable_scan;
+ char line[1000], *tag=0, *id=0, *tmp;
+ int taglen = 0;
+ Section *section = 0;
+ Section **prev_section_ptr = &(one->sections);
+
+ if (!f)
+ {
+ perror(one->filename);
+ return;
+ }
+
+ while (fgets(line, 1000, f))
+ {
+ if (one->enable_scan)
+ {
+ /* source files have comment-embedded docs, check for them */
+ if (has_string(line, "DOCTOOL-START"))
+ enabled = 1;
+ if (has_string(line, "DOCTOOL-END"))
+ enabled = 0;
+ }
+ if (!enabled)
+ continue;
+
+ /* DOCTOOL-START
+
+<sect1 id="dt-tags">
+this is the doctool tags section.
+</sect1>
+
+ DOCTOOL-END */
+
+ if (!tag && line[0] == '<')
+ {
+ tag = (char *)malloc(strlen(line)+1);
+ id = (char *)malloc(strlen(line)+1);
+ if (sscanf(line, "<%s id=\"%[^\"]\">", tag, id) == 2)
+ {
+ if (strcmp(tag, "book") == 0 || strcmp(tag, "BOOK") == 0)
+ {
+ /* Don't want to "scan" these */
+ return;
+ }
+ taglen = strlen(tag);
+ section = (Section *)malloc(sizeof(Section));
+ /* We want chunks within single files to appear in that order */
+ section->next = 0;
+ section->file = one;
+ *prev_section_ptr = section;
+ prev_section_ptr = &(section->next);
+ section->internal = 0;
+ section->addend = 0;
+ section->used = 0;
+ section->name = id;
+ if (starts_with(section->name, "add-"))
+ {
+ section->addend = 1;
+ section->name += 4;
+ }
+ if (starts_with(section->name, "int-"))
+ {
+ section->internal = 1;
+ section->name += 4;
+ }
+ section->lines = (char **)malloc(10*sizeof(char *));
+ section->num_lines = 0;
+ section->max_lines = 10;
+ }
+ else
+ {
+ free(tag);
+ free(id);
+ tag = id = 0;
+ }
+ }
+
+ if (tag && section)
+ {
+ if (section->num_lines >= section->max_lines)
+ {
+ section->max_lines += 10;
+ section->lines = (char **)realloc(section->lines,
+ section->max_lines * sizeof (char *));
+ }
+ section->lines[section->num_lines] = (char *)malloc(strlen(line)+1);
+ strcpy(section->lines[section->num_lines], line);
+ section->num_lines++;
+
+ if (line[0] == '<' && line[1] == '/'
+ && memcmp(line+2, tag, taglen) == 0
+ && (isspace(line[2+taglen]) || line[2+taglen] == '>'))
+ {
+ /* last line! */
+ tag = 0;
+ }
+ }
+ }
+ fclose(f);
+}
+
+/*****************************************************************************/
+
+Section **
+enumerate_matching_sections(char *name_prefix, int internal, int addend, int *count_ret)
+{
+ Section **rv = (Section **)malloc(12*sizeof(Section *));
+ int count = 0, max=10, prefix_len = strlen(name_prefix);
+ OneFile *one;
+ int wildcard = 0;
+
+ if (name_prefix[strlen(name_prefix)-1] == '-')
+ wildcard = 1;
+
+ for (one=file_list; one; one=one->next)
+ {
+ Section *s;
+ for (s=one->sections; s; s=s->next)
+ {
+ int matches = 0;
+ if (wildcard)
+ {
+ if (starts_with(s->name, name_prefix))
+ matches = 1;
+ }
+ else
+ {
+ if (strcmp(s->name, name_prefix) == 0)
+ matches = 1;
+ }
+ if (s->internal <= internal
+ && s->addend == addend
+ && matches
+ && ! s->used)
+ {
+ s->used = 1;
+ if (count >= max)
+ {
+ max += 10;
+ rv = (Section **)realloc(rv, max*sizeof(Section *));
+ }
+ rv[count++] = s;
+ rv[count] = 0;
+ }
+ }
+ }
+ if (count_ret)
+ *count_ret = count;
+ return rv;
+}
+
+/*****************************************************************************/
+
+#define ID_CHARS "~@$%&()_-+[]{}:."
+
+void include_section(char *name, int addend);
+
+char *
+unprefix(char *fn)
+{
+ int l = strlen(source_dir_prefix);
+ if (memcmp(fn, source_dir_prefix, l) == 0)
+ {
+ fn += l;
+ while (*fn == '/' || *fn == '\\')
+ fn++;
+ return fn;
+ }
+ return fn;
+}
+
+void
+parse_line(char *line, char *filename)
+{
+ char *cmd = has_string(line, "DOCTOOL-INSERT-");
+ char *sname, *send, *id, *save;
+ if (!cmd)
+ {
+ if (book_id
+ && (starts_with(line, "<book") || starts_with(line, "<BOOK")))
+ {
+ cmd = strchr(line, '>');
+ if (cmd)
+ {
+ cmd++;
+ fprintf(output_file, "<book id=\"%s\">", book_id);
+ fputs(cmd, output_file);
+ return;
+ }
+ }
+ fputs(line, output_file);
+ return;
+ }
+ if (cmd != line)
+ fwrite(line, cmd-line, 1, output_file);
+ save = (char *)malloc(strlen(line)+1);
+ strcpy(save, line);
+ line = save;
+
+ sname = cmd + 15; /* strlen("DOCTOOL-INSERT-") */
+ for (send = sname;
+ *send && isalnum(*send) || strchr(ID_CHARS, *send);
+ send++);
+ id = (char *)malloc(send-sname+2);
+ memcpy(id, sname, send-sname);
+ id[send-sname] = 0;
+ include_section(id, 0);
+
+ fprintf(output_file, "<!-- %s -->\n", unprefix(filename));
+
+ fputs(send, output_file);
+ free(save);
+}
+
+int
+section_sort(const void *va, const void *vb)
+{
+ Section *a = *(Section **)va;
+ Section *b = *(Section **)vb;
+ int rv = strcmp(a->name, b->name);
+ if (rv)
+ return rv;
+ return a->internal - b->internal;
+}
+
+void
+include_section(char *name, int addend)
+{
+ Section **sections, *s;
+ int count, i, l;
+
+ sections = enumerate_matching_sections(name, internal_flag, addend, &count);
+
+ qsort(sections, count, sizeof(sections[0]), section_sort);
+ for (i=0; i<count; i++)
+ {
+ s = sections[i];
+ s->file->used = 1;
+ fprintf(output_file, "<!-- %s -->\n", unprefix(s->file->filename));
+ for (l=addend; l<s->num_lines-1; l++)
+ parse_line(s->lines[l], s->file->filename);
+ if (!addend)
+ {
+ include_section(s->name, 1);
+ parse_line(s->lines[l], s->file->filename);
+ }
+ }
+
+ free(sections);
+}
+
+void
+parse_sgml(FILE *in, char *input_name)
+{
+ static char line[1000];
+ while (fgets(line, 1000, in))
+ {
+ parse_line(line, input_name);
+ }
+}
+
+/*****************************************************************************/
+
+void
+fix_makefile(char *output_name)
+{
+ FILE *in, *out;
+ char line[1000];
+ int oname_len = strlen(output_name);
+ OneFile *one;
+ int used_something = 0;
+ struct stat st;
+ struct utimbuf times;
+
+ stat("Makefile", &st);
+
+ in = fopen("Makefile", "r");
+ if (!in)
+ {
+ perror("Makefile");
+ return;
+ }
+
+ out = fopen("Makefile.new", "w");
+ if (!out)
+ {
+ perror("Makefile.new");
+ return;
+ }
+
+ while (fgets(line, 1000, in))
+ {
+ if (starts_with(line, output_name)
+ && strcmp(line+oname_len, ": \\\n") == 0)
+ {
+ /* this is the old dependency */
+ while (fgets(line, 1000, in))
+ {
+ if (strcmp(line+strlen(line)-2, "\\\n"))
+ break;
+ }
+ }
+ else
+ fputs(line, out);
+ }
+ fclose(in);
+
+ for (one=file_list; one; one=one->next)
+ if (one->used)
+ {
+ used_something = 1;
+ break;
+ }
+
+ if (used_something)
+ {
+ fprintf(out, "%s:", output_name);
+ for (one=file_list; one; one=one->next)
+ if (one->used)
+ fprintf(out, " \\\n\t%s", one->filename);
+ fprintf(out, "\n");
+ }
+
+ fclose(out);
+
+ times.actime = st.st_atime;
+ times.modtime = st.st_mtime;
+ utime("Makefile.new", &times);
+
+ if (rename("Makefile", "Makefile.old"))
+ return;
+ if (rename("Makefile.new", "Makefile"))
+ rename("Makefile.old", "Makefile");
+}
+
+/*****************************************************************************/
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ OneFile *one;
+ FILE *input_file;
+ int fix_makefile_flag = 0;
+
+ while (argc > 1 && argv[1][0] == '-')
+ {
+ if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
+ {
+ show_help();
+ }
+ else if (strcmp(argv[1], "-i") == 0)
+ {
+ internal_flag = 1;
+ }
+ else if (strcmp(argv[1], "-m") == 0)
+ {
+ fix_makefile_flag = 1;
+ }
+ else if (strcmp(argv[1], "-d") == 0 && argc > 2)
+ {
+ scan_directory(argv[2]);
+ argc--;
+ argv++;
+ }
+ else if (strcmp(argv[1], "-o") == 0 && argc > 2)
+ {
+ output_name = argv[2];
+ argc--;
+ argv++;
+ }
+ else if (strcmp(argv[1], "-s") == 0 && argc > 2)
+ {
+ source_dir_prefix = argv[2];
+ argc--;
+ argv++;
+ }
+ else if (strcmp(argv[1], "-b") == 0 && argc > 2)
+ {
+ book_id = argv[2];
+ argc--;
+ argv++;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ for (one=file_list; one; one=one->next)
+ {
+ scan_file(one);
+ }
+
+ input_file = fopen(argv[1], "r");
+ if (!input_file)
+ {
+ perror(argv[1]);
+ return 1;
+ }
+
+ if (output_name)
+ {
+ output_file = fopen(output_name, "w");
+ if (!output_file)
+ {
+ perror(output_name);
+ return 1;
+ }
+ }
+ else
+ {
+ output_file = stdout;
+ output_name = "<stdout>";
+ }
+
+ parse_sgml(input_file, argv[1]);
+
+ if (output_file != stdout)
+ fclose(output_file);
+
+ if (fix_makefile_flag)
+ fix_makefile(output_name);
+
+ return 0;
+}
diff --git a/winsup/doc/doctool.txt b/winsup/doc/doctool.txt
new file mode 100644
index 000000000..c89e39243
--- /dev/null
+++ b/winsup/doc/doctool.txt
@@ -0,0 +1,146 @@
+Doctool
+
+DJ Delorie <dj@cygnus.com>
+
+These are the instructions for using doctool. Yes, I should have
+written them *in* DocBook, but hey, I was in a hurry.
+
+OK, doctool is a program that gathers snippets of a docbook document and
+puts them all together in the right order. There are three
+places that it gets snippets from:
+
+1. The document that you tell it you want "finished"
+
+2. blocks of SGML in *.sgml files
+
+3. comments in source code
+
+The first of these is the template file, which is to say, it's a
+normal SGML file (sort of). This file is the first one read, and
+includes such things as your <book> tags etc. It contains commands to
+doctool to tell it where to put the other parts.
+
+The second, the *.sgml files, contain one or more blocks of SGML.
+To work with doctool, each of these snippets must begin and end
+with matching tags, must have an id="" attribute, and the start/end
+tags must begin at the beginning of the line. For example:
+
+<foo id="frob-45">
+ stuff goes here
+</foo>
+<bar id="frob-48">
+ stuff goes here
+</bar>
+
+In this example, the file contains two snippets, one marked by "foo"
+and one barked by "bar", with id's "from-45" and "from-48". Note that
+I made up the foo and bar tags. You'd usually use a <sect1> tag or
+something useful like that. Stuff outside the blocks is ignored.
+
+The third is simply an encapsulation of the second in comments, like this:
+
+/* DOCTOOL-START
+<foo id="frob-45">
+ stuff goes here
+</foo>
+DOCTOOL-END */
+
+The DOCTOOL-START and DOCTOOL-END things are special. Doctool uses
+those to know which parts of which comments are useful, and which
+parts are the useless source code stuff ;-)
+
+
+OK, so now we've got all these snippets of SGML floating around. What
+do we do with them? Well, inside the template document (#1 in our
+list up there) you'd put text snippets that said "ok, put them
+here". Each text snippet looks like this:
+
+DOCTOOL-INSERT-frob-
+
+Note that the "frob-" part tells doctool to pull in all the snippets
+with IDs that start with "frob-", in alphabetical (well, asciibetical
+at the moment) order. So, by saying "DOCTOOL-INSERT-frob-" you'd get
+all the "frob-*" snippets, like "frob-45" and "frob-48".
+
+If you just said DOCTOOL-INSERT-frob, it inserts the snippet named
+"frob" and no others.
+
+Note that no snippet will ever be inserted more than once, no matter
+how many DOCTOOL-INSERTs you have.
+
+There's two other tricks doctool has. If it finds a snippet with an ID
+like "int-*" (i.e. int-frob-45) that means that snippet of documentation
+is for the "internal" version only. The "int-" is discarded, and if
+the -i option is given to doctool, this snippet is treated as if the
+int- wasn't there. Without the -i, the int-* snippets are ignored
+completely.
+
+If a snippet has "add-" on it, like "add-frob-45", that's an addendum.
+Each time a snippet named without the add- is found, doctool looks for
+an addendum with exactly that same name (i.e. frob-45 looks for
+add-frob-45). If it finds any, it puts them just before the last line
+of the non-add snippet (so that it's *inside* the main snippet's
+block, not after it). Example:
+
+<sect1 id="frob-45">
+ some text
+</sect1>
+<sect1 id="add-frob-45">
+ more text
+</sect1>
+
+This would yield:
+
+<sect1 id="frob-45">
+ some text
+ more text
+</sect1>
+
+You should use the same outermost tags as the main snippet, but only
+because it sets the proper nesting rules for what's enclosed.
+
+You can use add- and int- at the same time, but always do add-int- and
+not int-add- (i.e. "add-int-frob-45").
+
+
+OK, now for doctool command line options.
+
+-m tells doctool to "fix" the Makefile (not makefile) to include the
+extra dependencies needed by the file you're generating. You need to
+manually include dependencies on the Makefile itself and the template
+file; doctool only includes the snippet files (sources etc) that it
+actually pulled content from. Note: this isn't perfect! Someone can
+come along and add a new snippet to a source file, and doctool would
+never know. Sometimes, it's best to just rebuild the docs all the
+time.
+
+-i means to include snippets with the "int-" prefix on their IDs. Use
+with -b to make internal and public versions from the same sources.
+
+"-d dir" tells doctool to scan all the files in that directory (and
+subdirectories, recursively) for files that might contain snippets of
+SGML. These include *.c, *.cc, *.h, and *.sgml. The idea is that
+most of the documentation would be in a *.sgml file named after the
+source (i.e. foo.c -> foo.sgml) but some commentary within the source
+might be useful in the docs as well. SGML files (*.sgml) do not need
+the DOCTOOL-START/END tags but the others do.
+
+-o sets the output file. Without -o, the file goes to stdout (ick).
+
+-s tells doctool to supress a "source directory prefix". What this
+means is that, in the generated output doctool puts comments that say
+where each snippet comes from (for debugging), which includes the full
+path sometimes, but if you use -s, you can tell doctool to cut off
+that prefix. For example,
+/usr/people/dj/src/cygnus/latest/devo/winsup/foo.c might get shortened
+to winsup/foo.c if you gave "-s
+/usr/people/dj/src/cygnus/latest/devo/". Cygnus makefiles could
+just use -s $(srcdir) most of the time.
+
+-b changes the ID for the <book> tag. db2html uses the <book> tag's
+ID as the default subdirectory name and/or html file name to create
+the book with. You'd need this to generate two books (internal vs
+public) from the same source.
+
+The only other thing you'd add to the command line is the ONE template
+file you want to pull in.
diff --git a/winsup/doc/faq-programming.xml b/winsup/doc/faq-programming.xml
index 4332d2b75..47e278220 100644
--- a/winsup/doc/faq-programming.xml
+++ b/winsup/doc/faq-programming.xml
@@ -937,7 +937,8 @@ info would not be compatible with gdb).
<para>Yes. You can use the <literal>strace.exe</literal> utility to run other cygwin
programs with various debug and trace messages enabled. For information
-on using <literal>strace</literal>, see the Cygwin User's Guide.
+on using <literal>strace</literal>, see the Cygwin User's Guide or the file
+<literal>winsup/utils/utils.sgml</literal> in the Cygwin sources.
</para>
</answer></qandaentry>
diff --git a/winsup/doc/faq-setup.xml b/winsup/doc/faq-setup.xml
index b8ec06195..d2a0f1cc0 100644
--- a/winsup/doc/faq-setup.xml
+++ b/winsup/doc/faq-setup.xml
@@ -377,9 +377,8 @@ you are much better off if you can avoid the problem entirely.
run mkpasswd.
</para>
</listitem>
-<listitem><para>If you already have an /etc/passwd file, you can simply edit
-your Cygwin user name (first field). It's also a good idea to avoid spaces in
-the home directory.
+<listitem><para>You can simply edit the /etc/passwd file and change the Cygwin user name
+(first field). It's also a good idea to avoid spaces in the home directory.
</para>
</listitem>
</orderedlist>
@@ -397,7 +396,7 @@ in order of decreasing priority:
<listitem><para><literal>HOME</literal> from the Windows environment, translated to POSIX form.
</para>
</listitem>
-<listitem><para>The pw_home field from the passwd entry as returned by <command>getent passwd</command>.
+<listitem><para>The entry in /etc/passwd
</para>
</listitem>
<listitem><para>/home/USERNAME
@@ -405,7 +404,8 @@ in order of decreasing priority:
</listitem>
</orderedlist>
-<para>When using Cygwin from the network (telnet, ssh,...), <literal>HOME</literal> is taken from the passwd entry.
+<para>When using Cygwin from the network (telnet, ssh,...), <literal>HOME</literal> is set
+from /etc/passwd.
</para>
<para>If your <literal>HOME</literal> is set to a value such as /cygdrive/c, it is likely
that it was set in Windows. Start a DOS Command Window and type
@@ -413,9 +413,8 @@ that it was set in Windows. Start a DOS Command Window and type
</para>
<para>Access to shared drives is often restricted when starting from the network,
thus Domain users may wish to have a different <literal>HOME</literal> in the
-Windows environment (on shared drive) than in Cygwin (on local drive).
-Note that ssh only considers the account information as retrieved by
-getpwnam(3), disregarding <literal>HOME</literal>.
+Windows environment (on shared drive) than in /etc/passwd (on local drive).
+Note that ssh only considers /etc/passwd, disregarding <literal>HOME</literal>.
</para>
</answer></qandaentry>
diff --git a/winsup/doc/faq-using.xml b/winsup/doc/faq-using.xml
index 1b83ef950..19e381624 100644
--- a/winsup/doc/faq-using.xml
+++ b/winsup/doc/faq-using.xml
@@ -137,7 +137,7 @@ as such.
<para>Your .bashrc is read from your home directory specified by the HOME
environment variable. It uses /.bashrc if HOME is not set. So you need
-to set HOME (and the home dir in your passwd account information) correctly.
+to set HOME (and the home dir in your /etc/passwd entry) correctly.
</para>
</answer></qandaentry>
@@ -265,6 +265,12 @@ must create the whatis database. Just run the command
<question><para>Why doesn't <literal>chmod</literal> work?</para></question>
<answer>
+<para>The most common case is that your <literal>/etc/passwd</literal>
+or <literal>/etc/group</literal> files are not properly set up. If
+<literal>ls -l</literal> shows a group of <literal>mkpasswd</literal>
+or <literal>mkgroup</literal>, you need to run one or both of those
+commands.
+</para>
<para>If you're using FAT32 instead of NTFS, <literal>chmod</literal>
will fail since FAT32 does not provide any permission information.
You should really consider converting the drive to NTFS with
@@ -1026,6 +1032,19 @@ sure you're running bash elevated.
</para>
<para>
+If "cyg_server" is not already in <literal>/etc/passwd</literal>, add it
+using <literal>mkpasswd</literal>. Make sure all domain accounts which are
+supposed to be able to logon via ssh are in <literal>/etc/passwd</literal>.
+Also make sure that all important domain groups are in
+<literal>/etc/group</literal>. If in doubt, call
+</para>
+
+<screen>
+ $ mkpasswd -l -d your_domain > /etc/passwd
+ $ mkgroup -l -d your_domain > /etc/group
+</screen>
+
+<para>
Then run ssh-host-config. Answer all questions so that "cyg_server" is
used to run the service. When done, check ownership of
<literal>/var/empty</literal> and all <literal>/etc/ssh*</literal>
diff --git a/winsup/doc/highlights.xml b/winsup/doc/highlights.xml
index 76eb3fb1c..5de789a8c 100644
--- a/winsup/doc/highlights.xml
+++ b/winsup/doc/highlights.xml
@@ -245,9 +245,8 @@ support for cloning address space between processes and several
features actively undermine a reliable <literal>fork</literal>
implementation. Three issues are especially prevalent:</para>
-<itemizedlist mark="bullet">
-
-<listitem><para>DLL base address collisions. Unlike *nix shared
+<para><itemizedlist>
+<listitem>DLL base address collisions. Unlike *nix shared
libraries, which use "position-independent code", Windows shared
libraries assume a fixed base address. Whenever the hard-wired
address ranges of two DLLs collide (which occurs quite often), the
@@ -260,18 +259,18 @@ statically-linked dlls (dependencies known at compile time) are
resolved before <literal>cygwin1.dll</literal> initializes and
cannot be fixed afterward. This problem can only be solved by
removing the base address conflicts which cause the problem,
-usually using the <literal>rebaseall</literal> tool.</para></listitem>
+usually using the <literal>rebaseall</literal> tool.</listitem>
-<listitem><para>Address space layout randomization (ASLR). Starting with
+<listitem>Address space layout randomization (ASLR). Starting with
Vista, Windows implements ASLR, which means that thread stacks,
heap, memory-mapped files, and statically-linked dlls are placed
at different (random) locations in each process. This behaviour
interferes with a proper <literal>fork</literal>, and if an
unmovable object (process heap or system dll) ends up at the wrong
location, Cygwin can do nothing to compensate (though it will
-retry a few times automatically).</para></listitem>
+retry a few times automatically).</listitem>
-<listitem><para>DLL injection by
+<listitem>DLL injection by
<ulink url="http://cygwin.com/faq/faq.html#faq.using.bloda">
BLODA</ulink>. Badly-behaved applications which
inject dlls into other processes often manage to clobber important
@@ -280,9 +279,7 @@ collisions which rebasing cannot fix. The only way to resolve this
problem is to remove (usually uninstall) the offending app. See
<xref linkend="cygwinenv-implemented-options"></xref> for the
<literal>detect_bloda</literal> option, which may be able to identify the
-BLODA.</para></listitem>
-
-</itemizedlist>
+BLODA.</listitem></itemizedlist></para>
<para>In summary, current Windows implementations make it
impossible to implement a perfectly reliable fork, and occasional
diff --git a/winsup/doc/misc-funcs.xml b/winsup/doc/misc-funcs.xml
deleted file mode 100644
index 06776d9e7..000000000
--- a/winsup/doc/misc-funcs.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding='UTF-8'?>
-<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-
-<sect1 id="func-cygwin-misc">
-<title>Miscellaneous functions</title>
-
-<sect2 id="func-cygwin-attach-handle-to-fd">
-<title>cygwin_attach_handle_to_fd</title>
-
-<funcsynopsis><funcprototype>
-<funcdef>extern "C" int
-<function>cygwin_attach_handle_to_fd</function></funcdef>
-<paramdef>char *<parameter>name</parameter></paramdef>
-<paramdef>int <parameter>fd</parameter></paramdef>
-<paramdef>HANDLE <parameter>handle</parameter></paramdef>
-<paramdef>int <parameter>bin</parameter></paramdef>
-<paramdef>int <parameter>access</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>This function can be used to turn a Win32 "handle" into a
-posix-style file handle. <parameter>fd</parameter> may be -1 to
-make cygwin allocate a handle; the actual handle is returned
-in all cases.</para>
-
-<para>Even after using function, Cygwin doesn't know anything about the
-underlying file or device. It just tries to supply the typical file
-functions on a "best-effort" basis. Use with care. Don't expect too
-much.</para>
-
-</sect2>
-
-<sect2 id="func-cygwin-internal">
-<title>cygwin_internal</title>
-
-<funcsynopsis><funcprototype>
-<funcdef>extern "C" DWORD
-<function>cygwin_internal</function></funcdef>
-<paramdef>cygwin_getinfo_types <parameter>t</parameter></paramdef>
-<paramdef><parameter>...</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>This function gives you access to various internal data and functions.
-It takes two arguments. The first argument is a type from the 'cygwin_getinfo_types'
-enum. The second is an optional pointer.</para>
-<para>Stay away unless you know what you're doing.</para>
-
-</sect2>
-
-<sect2 id="func-cygwin-stackdump">
-<title>cygwin_stackdump</title>
-
-<funcsynopsis><funcprototype>
-<funcdef>extern "C" void
-<function>cygwin_stackdump</function></funcdef>
-<void />
-</funcprototype></funcsynopsis>
-
-<para> Outputs a stackdump to stderr from the called location.
-</para>
-
-</sect2>
-
-</sect1>
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index 05aa6c4e0..fdee13f59 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -9,28 +9,6 @@
<itemizedlist mark="bullet">
<listitem><para>
-Cygwin can now generate passwd/group entries directly from Windows user
-databases (local SAM or Active Directory), thus allowing to run Cygwin
-without having to create /etc/passwd and /etc/group files. Introduce
-/etc/nsswitch.conf file to configure passwd/group handling.
-</para>
-
-<para>
-For bordercase which require to use /etc/passwd and /etc/group files,
-change mkpasswd/mkgroup to generate passwd/group entries compatible with
-the entries read from SAM/AD.
-</para>
-
-<para>For a description of this exciting new feature see
-<xref linkend="ntsec"></xref>.
-</para></listitem>
-
-<listitem><para>
-Add -b/--remove-all option to setfacl to reduce the ACL to only the entries
-representing POSIX permission bits.
-</para></listitem>
-
-<listitem><para>
/proc/cygdrive is a new symlink pointing to the current cygdrive prefix.
This can be utilized in scripts to access paths via cygdrive prefix,
even if the cygdrive prefix has been changed by the user.
@@ -66,12 +44,6 @@ New internal exception handling based on SEH on 64 bit Cygwin.
</para></listitem>
<listitem><para>
-Revamp Solaris ACL implementation to more closely work like POSIX ACLs
-are supposed to work. Finally implement a CLASS_OBJ emulation. Update
-getfacl(1)/setfacl(1) accordingly.
-</para></listitem>
-
-<listitem><para>
When exec'ing applications, check if $PATH exists and is non-empty. If
not, add PATH variable with Cygwin installation directory as content to
Windows environment to allow loading of Cygwin system DLLs.
@@ -90,11 +62,6 @@ Doug Lea malloc implementation update from 2.8.3 to the latest 2.8.6.
</para></listitem>
<listitem><para>
-The xdr functions are no longer exported for newly built executables.
-Use libtirpc-devel instead.
-</para></listitem>
-
-<listitem><para>
atexit(3) is now exported as statically linked function from libcygwin.a.
This allows reliable access to the DSO handle of the caller for newly
built executables. The former atexit entry point into the DLL remains
diff --git a/winsup/doc/ntsec.xml b/winsup/doc/ntsec.xml
index 2649398af..72cf7bb89 100644
--- a/winsup/doc/ntsec.xml
+++ b/winsup/doc/ntsec.xml
@@ -2,12 +2,12 @@
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<sect1 id="ntsec"><title>POSIX accounts, permission, and security</title>
+<sect1 id="ntsec"><title>Using Windows security in Cygwin</title>
<para>This section discusses how the Windows security model is
-utilized in Cygwin to implement POSIX account information, POSIX-like
-permissions, and how the Windows authentication model is used to allow
-cygwin applications to switch users in a POSIX-like fashion.</para>
+utilized in Cygwin to implement POSIX-like permissions, as well as how
+the Windows authentication model is used to allow cygwin applications
+to switch users in a POSIX-like fashion.</para>
<para>The setting of POSIX-like file and directory permissions is
controlled by the <link linkend="mount-table">mount</link> option
@@ -23,7 +23,7 @@ discussed here, but assumed to be understood by the reader. If you
don't know the POSIX security model, search the web for beginner
documentation.</para>
-<sect2 id="ntsec-common"><title>Brief overview of Windows security</title>
+<sect2 id="ntsec-common"><title>Overview</title>
<para>In the Windows security model, almost any "object" is securable.
"Objects" are files, processes, threads, semaphores, etc.</para>
@@ -117,22 +117,13 @@ treat these SIDs as identifying two separate accounts. One is
"FOO\johndoe", the other one is "BAR\johndoe" or "johndoe@bar.local".
Different SID, different account. Full stop. </para>
-<para>Starting with Cygwin 1.7.33, Cygwin uses an automatic, internal
-translation from Windows SID to POSIX UID/GID. This mechanism, which is
-the preferred method for the SID&lt;=&gt;UID/GID mapping, is described in
-detail in <xref linkend="ntsec-mapping"></xref>.</para>
-
-<para>Prior to Cygwin 1.7.33, the last part of the SID, the so called
-"Relative IDentifier" (RID), was by default used as UID and/or GID
-when you created the <filename>/etc/passwd</filename> and
-<filename>/etc/group</filename> files using the
-<command><link linkend="mkpasswd">mkpasswd</link></command> and
-<command><link linkend="mkgroup">mkgroup</link></command> tools.
-These tools as well as reading accounts from <filename>/etc/passwd</filename>
-and <filename>/etc/group</filename> files is still present in recent
-versions of Cygwin, but you should switch to the aforementioned
-automatic translation, unless you have very specific needs. Again,
-see <xref linkend="ntsec-mapping"></xref> for the details.</para>
+<para>The last part of the SID, the so called "Relative IDentifier" (RID),
+is by default used as UID and/or GID under Cygwin when you create the
+<filename>/etc/passwd</filename> and <filename>/etc/group</filename>
+files using the <command><link linkend="mkpasswd">mkpasswd</link></command> and <command><link linkend="mkgroup">mkgroup</link></command>
+tools. Domain account UIDs and GIDs are offset by 10000 by default
+which might be a bit low for very big organizations. Fortunately there's
+an option in both tools to change the offset...</para>
<para>Do you still remember the SIDs with special meaning? In offical
notation they are called "well-known SIDs". For example, POSIX has no GID
@@ -216,1413 +207,214 @@ from the permission to change object data, and even changing object data
can be separated into different permission bits for different kind of
data. But there's a problem with the definition of a "correct" ACL
which disallows mapping of certain POSIX permissions cleanly. See
-<xref linkend="ntsec-files"></xref>.</para>
+<xref linkend="ntsec-mapping"></xref>.</para>
<para>POSIX is able to create only three different permissions? Not quite.
Newer operating systems and file systems on POSIX systems also provide
access control lists. Two different APIs exist for accessing these
-ACLs, the Solaris API and the POSIX API. Cygwin implements the original
-Solaris API to access Windows ACLs in a Unixy way. Online man pages for the
-Solaris ACL API can be found on
-<ulink url="http://docs.oracle.com">http://docs.oracle.com</ulink>.
-For an overview see <ulink url="http://docs.oracle.com/cd/E23824_01/html/821-1474/acl-5.html#scrolltoc">acl(5)</ulink>.</para>
+ACLs, the Solaris API and the POSIX API. Cygwin implements the Solaris
+API to access Windows ACLs in a Unixy way. At the time of writing this
+document, the Cygwin implementation of the Solaris API isn't quite up
+to speed. For instance, it doesn't handle access denied ACEs gracefully.
+So, use with care. Online man pages for the Solaris ACL API can be
+found on <ulink url="http://docs.sun.com">http://docs.sun.com</ulink>.</para>
</sect2>
-<sect2 id="ntsec-mapping"><title id="ntsec-mapping.title">Mapping Windows accounts to POSIX accounts</title>
-
-<para>
-For as long as Cygwin has existed, it has stored user and group information in
-<filename>/etc/passwd</filename> and <filename>/etc/group</filename> files.
-Under the assumption that these files would never be too large, the first
-process in a process tree, as well as every execing process within the tree
-would parse them into structures in memory. Thus every Cygwin process would
-contain an expanded copy of the full information from
-<filename>/etc/passwd</filename> and <filename>/etc/group</filename>.
-</para>
-
-<para>
-This approach has a few downsides. One of them is that the idea that these
-files will always be small, is flawed. Another one is that reading the entire
-file is most of the time entirely useless, since most processes only
-need information on their own user and the primary group. Last but not
-least, the passwd and group files have to be maintained separately from
-the already existing Windows user databases, the local SAM and Active
-Directory.
-</para>
-
-<para>
-On the other hand, we have to have this mapping between Windows SIDs and
-POSIX uid/gid values, so we need a mechanism to convert SIDs to uid/gid
-values and vice versa.
-</para>
-
-<para>
-Microsoft "Services for UNIX" (SFU) (deprecated since Windows 8/Server 2012)
-never used passwd/group files. Rather, SFU used a fixed, computational mapping
-between SIDs and POSIX uid/gid which even has Active Directory support. It
-allows us to generate uid/gid values from SIDs and vice versa. The mechanism is
-documented, albeit in a confusing way and spread over multiple MSDN articles.
-</para>
-
-<para>
-Starting with Cygwin 1.7.33, Cygwin utilizes an approach inspired by the
-mapping method as implemented by SFU, with a few differences for backward
-compatibility and to handle some border cases differently.
-</para>
-
-<sect3 id="ntsec-mapping-how"><title id="ntsec-mapping-how.title">Mapping Windows SIDs to POSIX uid/gid values</title>
-
-<para>
-The following description assumes you're comfortable with the concept of
-Windows SIDs and RIDs. For a brief introduction, see
-<xref linkend="ntsec-common"></xref>.
-</para>
-
-<para>
-Cygwin's mapping between SIDs and uid/gid values works in two ways.
-</para>
-
-<itemizedlist spacing="compact">
-<listitem><para>Read <filename>/etc/passwd<filename> and
-</filename>/etc/group</filename> files if they exist, just as in the olden
-days, mainly for backward compatibility.</para></listitem>
-<listitem><para>If no files are present, or if an entry is missing in the files,
-ask Windows.</para></listitem>
-</itemizedlist>
-
-<para>
-At least, that's the default behaviour now. It will be configurable
-using a file <filename>/etc/nsswitch.conf</filename>, which is discussed in
-<xref linkend="ntsec-mapping-nsswitch"></xref>. Let's explore the default
-for now.
-</para>
-
-<para>
-If the passwd or group files are present, they will be scanned on demand as
-soon as a mapping from SIDs to uid/gid or account names is required. The new
-mechanism will never read the entire file into memory, but only scan for
-the requested entry and cache this one in memory.
-</para>
-
-<para>
-If no entry is found, or no passwd or group file was present, Cygwin
-will ask the OS.
-</para>
-
-<note>
-<para>
-If the first process in a Cygwin process tree determines that no
-<filename>/etc/passwd</filename> or <filename>/etc/group</filename> file is
-present, no other process in the entire process tree will try to read the files
-later on. This is done for self-preservation. It's rather bad if the uid
-or gid of a user changes during the lifetime of a process tree.
-</para>
-
-<para>
-For the same reason, if you delete the <filename>/etc/passwd</filename>
-or <filename>/etc/group</filename> file, this will be ignored. The passwd
-and group records read from the files will persist in memory until either a
-new <filename>/etc/passwd</filename> or <filename>/etc/group</filename>
-is created, or you exit all processes in the current process tree.
-</para>
-
-<para>
-See the note in <xref linkend="ntsec-mapping-nsswitch"></xref> for some
-comprehensive examples.
-</para>
-</note>
-
-<para>
-So if we've drawn a blank reading the files, we're going to ask the OS.
-First thing, we ask the local machine for the SID or the username. The
-OS functions
-<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379166%28v=vs.85%29.aspx">LookupAccountSid</ulink>
-and
-<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379159%28v=vs.85%29.aspx">LookupAccountName</ulink>
-are pretty intelligent. They have all the stuff built in to ask for any
-account of the local machine, the Active Directory domain of the machine,
-the Global Catalog of the forest of the domain, as well as any trusted
-domain of our forest for the information. One OS call and we're
-practically done...
-</para>
-
-<para>
-Except, the calls only return the mapping between SID, account name and the
-account's domain. We don't have a mapping to POSIX uid/gid and we're missing
-information on the user's home dir and login shell.
-</para>
-
-<para>
-Let's discuss the SID&lt;=&gt;uid/gid mapping first. Here's how it works.
-</para>
-
-<itemizedlist spacing="compact">
-
-<listitem>
-<para>
-<ulink url="http://msdn.microsoft.com/en-us/library/aa379649.aspx">Well-known
-SIDs</ulink>
-in the NT_AUTHORITY domain of the S-1-5-RID type, or aliases of the
-S-1-5-32-RID type are mapped to the uid/gid value RID. Examples:
-</para>
-
-<screen>
- "SYSTEM" S-1-5-18 &lt;=&gt; uid/gid: 18
- "Users" S-1-5-32-545 &lt;=&gt; uid/gid: 545
-</screen>
-</listitem>
-
-<listitem>
-<para>
-Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
-</para>
-
-<screen>
- S-1-5-X-RID &lt;=&gt; uid/gid: 0x1000 * X + RID
-</screen>
-
-<para>Example:</para>
-
-<screen>
- "NTLM Authentication" S-1-5-64-10 &lt;=&gt; uid/gid: 0x4000A == 262154
-</screen>
-</listitem>
-
-<listitem><para>
-Other well-known SIDs:
-</para>
-
-<screen>
- S-1-X-Y &lt;=&gt; uid/gid: 0x10000 + 0x100 * X + Y
-</screen>
-
-<para>Example:</para>
-
-<screen>
- "LOCAL" S-1-2-0 &lt;=&gt; uid/gid: 0x10200 == 66048
- "Creator Group" S-1-3-1 &lt;=&gt; uid/gid: 0x10301 == 66305
-</screen>
-</listitem>
-
-<listitem>
-<para>
-Logon SIDs: The LogonSid of the current user's session is converted to the
-fixed uid 0xfff == 4095 and named "CurrentSession". Any other LogonSid is
-converted to the fixed uid 0xffe == 4094 and named "OtherSession".
-</para>
-</listitem>
-
-<listitem>
-<para>
-Mandatory Labels:
-</para>
-
-<screen>
- S-1-16-RID &lt;=&gt; uid/gid: 0x60000 + RID
-</screen>
-
-<para>Example:</para>
-
-<screen>
- "Medium Mandatory Level" S-1-16-8192 &lt;=&gt; uid/gid: 0x62000 == 401408
-</screen>
-</listitem>
-
-<listitem>
-<para>
-Accounts from the local machine's user DB (SAM):
-</para>
-
-<screen>
- S-1-5-21-X-Y-Z-RID &lt;=&gt; uid/gid: 0x30000 + RID
-</screen>
-
-<para>Example:</para>
-
-<screen>
- "Administrator" S-1-5-21-X-Y-Z-500 &lt;=&gt; uid/gid: 0x301f4 == 197108
-</screen>
-</listitem>
-
-<listitem>
-<para>
-Accounts from the machine's primary domain:
-</para>
-
-<screen>
- S-1-5-21-X-Y-Z-RID &lt;=&gt; uid/gid: 0x100000 + RID
-</screen>
-
-<para>Example:</para>
-
-<screen>
- "Domain Users" S-1-5-21-X-Y-Z-513 &lt;=&gt; uid/gid: 0x100201 == 1049089
-</screen>
-</listitem>
-
-<listitem>
-<para>
-Accounts from a trusted domain of the machine's primary domain:
-</para>
-
-<screen>
- S-1-5-21-X-Y-Z-RID &lt;=&gt; uid/gid: trustPosixOffset(domain) + RID
-</screen>
-
-<para>
-<literal>trustPosixOffset</literal>? This needs a bit of explanation. This
-value exists in Windows domains already since before Active Directory days.
-What happens is this. If you create a domain trust between two domains, a
-trustedDomain entry will be added to both databases. It describes how
-<emphasis>this</emphasis> domain trusts the <emphasis>other</emphasis> domain.
-One attribute of a trust is a 32 bit value called
-<literal>trustPosixOffset</literal> For each new trust,
-<literal>trustPosixOffset</literal> will get some automatic value. In recent
-AD domain implementations, the first trusted domain will get
-<literal>trustPosixOffset</literal> set to 0x80000000. Following domains will
-get lower values. Unfortunately the domain admins are allowed to set the
-<literal>trustPosixOffset</literal> value for each trusted domain to some
-arbitrary 32 bit value, no matter what the other
-<literal>trustPosixOffset</literal> are set to, thus allowing any kind of
-collisions between the <literal>trustPosixOffset</literal> values of domains.
-That's not exactly helpful, but as the user of this value, we have to
-<emphasis>trust</emphasis> the domain admins to set
-<literal>trustPosixOffset</literal> to sensible values, or to keep it at the
-system chosen defaults.
-</para>
-
-<para>
-So, for the first (or only) trusted domain of your domain, the automatic offset
-is 0x80000000. An example for a user of that trusted domain is
-</para>
-
-<screen>
- S-1-5-21-X-Y-Z-1234 &lt;=&gt; uid/gid 0x800004d2 == 2147484882
-</screen>
-
-<para>
-There's one problem with this approach. Assuming you're running in the context
-of a local SAM user on a domain member machine. Local users don't have the
-right to fetch this kind of domain information from the DC, they'll get
-permission denied. In this case Cygwin will fake a sensible
-<literal>trustPosixOffset</literal> value.
-</para>
-
-<para>
-Another problem is if the AD administrators chose an unreasonably small
-<literal>trustPosixOffset</literal> value. Anything below the hexadecimal
-value 0x100000 (the POSIX offset of the primary domain) is bound to produce
-collisions with system accounts as well as local accounts. The right thing
-to do in this case is to notify your administrator of the problem and to ask
-for moving the offset to a more reasonable value. However, to reduce the
-probability for collisions, Cygwin overrides this offset with a sensible
-fixed replacement offset.
-</para>
-</listitem>
-
-<listitem>
-<para>
-Local accounts from another machine in the network:
-</para>
-
-<para>
-There's no SID&lt;=&gt;uid/gid mapping implemented for this case. The problem
-is, there's no way to generate a bijective mapping. There's no central place
-which keeps an analogue of the <literal>trustPosixOffset</literal>, and there's
-the additional problem that the
-<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379166%28v=vs.85%29.aspx">LookupAccountSid</ulink>
-and
-<ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379159%28v=vs.85%29.aspx">LookupAccountName</ulink>
-functions cannnot resolve the SIDs, unless they know the name of the machine
-this SID comes from. And even then it will probably suffer a
-<literal>Permission denied</literal> error when trying to ask the machine
-for its local account.
-</para>
-</listitem>
-
-</itemizedlist>
-
-<para>
-Now we have a semi-bijective mapping between SIDs and POSIX uid/gid values,
-but given that we have potentially users and groups in different domains having
-the same name, how do we uniquely distinguish between them by name? Well, we
-can do that by making their names unique in a per-machine way. Dependent on
-the domain membership of the account, and dependent of the machine being a
-domain member or not, the user and group names will be generated using a domain
-prefix and a separator character between domain and account name.
-The <!-- default --> separator character is the plus sign, <literal>+</literal>.
-</para>
-
-<itemizedlist spacing="compact">
-
-<listitem>
-<para>
-Well-known and builtin accounts will be named as in Windows:
-</para>
-
-<screen>
- "SYSTEM", "LOCAL", "Medium Mandatory Level", ...
-</screen>
-</listitem>
-
-<listitem>
-<para>
-If the machine is not a domain member machine, only local accounts can be resolved
-into names, so for ease of use, just the account names are used as Cygwin
-user/group names:
-</para>
-
-<screen>
- "corinna", "bigfoot", "None", ...
-</screen>
-</listitem>
-
-<listitem>
-<para>
-If the machine is a domain member machine, all accounts from the primary domain
-of the machine are mapped to Cygwin names without domain prefix:
-</para>
-
-<screen>
- "corinna", "bigfoot", "Domain Users", ...
-</screen>
-
-<para>
-while accounts from other domains are prepended by their domain:
-</para>
-
-<screen>
- "DOMAIN1+corinna", "DOMAIN2+bigfoot", "DOMAIN3+Domain Users", ...
-</screen>
-</listitem>
-
-<listitem>
-<para>
-Local machine accounts of a domain member machine get a Cygwin user name the
-same way as accounts from another domain: The local machine name gets
-prepended:
-</para>
-
-<screen>
- "MYMACHINE+corinna", "MYMACHINE+bigfoot", "MYMACHINE+None", ...
-</screen>
-</listitem>
-
-<listitem>
-<para>
-If LookupAccountSid fails, Cygwin checks the accounts against the known trusted
-domains. If the account is from one of the trusted domains, an artificial
-account name is created. It consists of the domain name, and a special name
-created from the account RID:
-</para>
-
-<screen>
- "MY_DOM+User(1234)", "MY_DOM+Group(5678)"
-</screen>
-
-<para>
-Otherwise we know nothing about this SID, so it will be mapped to the
-fake accounts <literal>Unknown+User</literal>/<literal>Unknown+Group</literal>
-with uid/gid -1.
-</para>
-</listitem>
-
-</itemizedlist>
-
-</sect3>
-
-<sect3 id="ntsec-mapping-passwdinfo"><title id="ntsec-mapping-passwdinfo.title">Cygwin user names, home dirs, login shells</title>
-
-<para>
-Obviously, if you don't maintain <filename>passwd</filename> and
-<filename>group</filename> files, you need to have a way to maintain the other
-fields of a passwd entry as well. Three things come to mind:
-</para>
+<sect2 id="ntsec-files"><title id="ntsec-files.title">File permissions</title>
-<itemizedlist spacing="compact">
+<para>On NTFS and if the <literal>noacl</literal> mount option is not
+specified for a mount point, Cygwin sets file permissions as in POSIX.
+Basically this is done by defining a SD with the matching owner and group
+SIDs, and a DACL which contains ACEs for the owner, the group and for
+"Everyone", which represents what POSIX calls "others".</para>
-<listitem>
-<para>
-You want to use a Cygwin username different from your Windows username.
-</para>
+<para>To use Windows security correctly, Cygwin depends on the files
+<filename>/etc/passwd</filename> and <filename>/etc/group</filename>.
+These files define the translation between the Cygwin uid/gid and the
+Windows SID. The SID is stored in the pw_gecos field in
+<filename>/etc/passwd</filename>, and in the gr_passwd field in
+<filename>/etc/group</filename>. Since the pw_gecos field can contain
+more information than just a SID, there are some rules for the layout.
+It's required that the SID is the last entry of the pw_gecos field,
+assuming that the entries in pw_gecos are comma-separated. The
+commands <command>mkpasswd</command> and <command>mkgroup</command>
+usually do this for you.</para>
+
+<para>Another interesting entry in the pw_gecos field (which is also
+usually created by running <command>mkpasswd</command>) is the Windows user
+name entry. It takes the form "U-domain\username" and is sometimes used
+by services to authenticate a user. Logging in through
+<command>telnet</command> is a common scenario.</para>
+
+<para>A typical snippet from <filename>/etc/passwd</filename>:</para>
+
+<example id="ntsec-passwd">
+<title>/etc/passwd:</title>
+<screen>
+SYSTEM:*:18:544:,S-1-5-18::
+Administrators:*:544:544:,S-1-5-32-544::
+Administrator:unused:500:513:U-FOO\Administrator,S-1-5-21-790525478-115176313-839522115-500:/home/Administrator:/bin/bash
+corinna:unused:11001:11125:U-BAR\corinna,S-1-5-21-2913048732-1697188782-3448811101-1001:/home/corinna:/bin/tcsh
+</screen>
+</example>
+
+<para>The SYSTEM entry is usually needed by services. The Administrators
+entry (Huh? A group in /etc/passwd?) is only here to allow
+<command>ls</command> and similar commands to print some file ownerships
+correctly. Windows doesn't care if the owner of a file is a user or a
+group. In older versions of Windows NT the default ownership for files
+created by an administrator account was set to the group Administrators
+instead of to the creating user account. This has changed, but you can
+still switch to this setting on newer systems. So it's convenient to
+have the Administrators group in
+<filename>/etc/passwd</filename>.</para>
+
+<para>The really interesting entries are the next two. The Administrator
+entry is for the local administrator, the corinna entry matches the corinna
+account in the domain BAR. The information given in the pw_gecos field
+are all we need to exactly identify an account, and to have a two way
+translation, from Windows account name/SID to Cygwin account name uid and
+vice versa. Having this complete information allows us to choose a Cygwin
+user name and uid which doesn't have to match the Windows account at all. As
+long as the pw_gecos information is available, we're on the safe side:</para>
+
+<example id="ntsec-passwd-tweaked">
+<title>/etc/passwd, tweaked:</title>
+<screen>
+root:unused:0:513:U-FOO\Administrator,S-1-5-21-790525478-115176313-839522115-500:/home/Administrator:/bin/bash
+thursday_next:unused:11001:11125:U-BAR\corinna,S-1-5-21-2913048732-1697188782-3448811101-1001:/home/corinna:/bin/tcsh
+</screen>
+</example>
+
+<para> The above <filename>/etc/passwd</filename> will still work fine.
+You can now login via <command>ssh</command> as the user "root", and
+Cygwin dutifully translates "root" into the Windows user
+"FOO\Administrator" and files owned by FOO\Administrator are shown to
+have the uid 0 when calling <command>ls -ln</command>. All you do you're
+actually doing as Administrator. Files created as root will be owned by
+FOO\Administrator. And the domain user BAR\corinna can now happily
+pretend to be Thursday Next, but will wake up sooner or later finding
+out she's still actually the domain user BAR\corinna...</para>
+
+<para>Do I have to mention that you can also rename groups in
+<filename>/etc/group</filename>? As long as the SID is present and correct,
+all is well. This allows you to, for instance, rename the "Administrators"
+group to "root" as well:</para>
+
+<example id="ntsec-group-tweaked">
+<title>/etc/group, tweaked:</title>
+<screen>
+root:S-1-5-32-544:544:
+</screen>
+</example>
+
+<para>Last but not least, you can also change the primary group of a user
+in <filename>/etc/passwd</filename>. The only requirement is that the user
+is actually a member of the new primary group in Windows. For instance,
+normal users in a domain environment are members in the group "Domain Users",
+which in turn belongs to the well-known group "Users". So, if it's
+more convenient in your environment for the user's primary group to be
+"Users", just set the user's primary group in <filename>/etc/passwd</filename>
+to the Cygwin uid of "Users" (see in <filename>/etc/group</filename>,
+default 545) and let the user create files with a default group ownership
+of "Users".</para>
<note><para>
-Note: This is only supported via <filename>/etc/passwd</filename> and
-<filename>/etc/group</filename> files. A Cygwin username maintained in
-the Windows user databases would require very costly (read: slow) search
-operations.
+If you wish to make these kind of changes to /etc/passwd and /etc/group,
+do so only if you feel comfortable with the concepts. Otherwise, do not
+be surprised if things break in either subtle or surprising ways! If you
+do screw things up, revert to copies of <filename>/etc/passwd</filename>
+and <filename>/etc/group</filename> files created by
+<command>mkpasswd</command> and <command>mkgroup</command>. (Make
+backup copies of these files before modifying them.) Especially, don't
+change the UID or the name of the user SYSTEM. It may mostly work, but
+some Cygwin applications running as a local service under that account
+could suddenly start behaving strangely.
</para></note>
-</listitem>
-
-<listitem>
-<para>
-You want a home dir different from the default <filename>/home/$USER</filename>.
-</para>
-</listitem>
-
-<listitem>
-<para>
-You want to specify a different login shell than <filename>/bin/bash</filename>.
-</para>
-</listitem>
-
-</itemizedlist>
-
-<para>
-How this is done depends on your account being a domain account or a
-local account. Let's start with the default. Assuming your Windows
-account name is <literal>bigfoot</literal> and your domain is
-<literal>MY_DOM</literal>. Your default passwd entry <!-- in absence of
-anything I'll describe below -->looks like this:
-</para>
-
-<screen>
- bigfoot:*:&lt;uid&gt;:&lt;gid&gt;:U-MY_DOM\bigfoot,S-1-5-....:/home/bigfoot:/bin/bash
-</screen>
-
-<para>
-or, if your account is from a different domain than the primary domain of
-the machine:
-</para>
-
-<screen>
- MY_DOM+bigfoot:*:&lt;uid&gt;:&lt;gid&gt;:U-MY_DOM\bigfoot,S-1-5-....:/home/bigfoot:/bin/bash
-</screen>
-
-<para>
-Yes, the default homedir is still /home/bigfoot.
-</para>
-
-<para>
-If your account is a domain account:
-</para>
-
-<itemizedlist spacing="compact">
-
-<listitem>
-<para>
-Either create an <filename>/etc/passwd</filename> and/or
-<filename>/etc/group</filename> file with entries for your account and tweak
-that,
-</para>
-</listitem>
-
-<listitem>
-<para>
-or Cygwin will utilize the
-<literal>posixAccount</literal>/<literal>posixGroup</literal> attributes per
-<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>. These
-attributes are by default available in Active Directory since Windows Server
-2003 R2. They are <literal>not set</literal>, unless utilized by the
-(deprecated since Server 2012 R2) Active Directory "Server for NIS" feature.
-The user attributes utilized by Cygwin are:
-</para>
-
-<segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>unixHomeDirectory</literal></seg>
- <seg>If set, will be used as Cygwin home directory.</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>loginShell</literal></seg>
- <seg>If set, will be used as Cygwin login shell.</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>gecos</literal></seg>
- <seg>Content will be added to the pw_gecos field.</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>uidNumber</literal></seg>
- <seg>See <xref linkend="ntsec-mapping-nfs"></xref>.</seg>
- </seglistitem>
- <seglistitem>
- <seg>The group attributes utilized by Cygwin are:</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>gidNumber</literal></seg>
- <seg>See <xref linkend="ntsec-mapping-nfs"></xref>.</seg>
- </seglistitem>
-</segmentedlist>
-
-<para>
-Apart from power shell scripting or inventing new CLI tools, these attributes
-can be changed using the <literal>Attribute Editor</literal> tab in the user
-properties dialog of the <literal>Active Directory Users and Computers</literal>
-MMC snap-in. Alternatively, if the <literal>Server for NIS</literal>
-administration feature has been installed, there will be a
-<literal>UNIX Attributes</literal> tab which contains the required fields,
-except for the gecos field, which isn't really important anyway. Last resort
-is <literal>ADSI Edit</literal>.
-</para>
-
-<para>
-The primary group of a user is always the Windows primary group set in
-Active Directory and can't be changed.
-</para>
-</listitem>
-
-</itemizedlist>
-
-<para>
-If your machine is not a domain member machine or your account is a
-local account for some reason:
-</para>
-
-<itemizedlist spacing="compact">
-
-<listitem>
-<para>
-Either create an <filename>/etc/passwd</filename> and/or
-<filename>/etc/group</filename> file with entries for your account and tweak
-that,
-</para>
-</listitem>
-
-<listitem>
-<para>
-or enter the information into the comment field of your local user entry.
-In the <literal>Local Users and Groups</literal> MMC snap-in it's called
-<literal>Description</literal>.
-</para>
-
-<para>
-You can utilize this field even if you're running a "home edition" of
-Windows, using the command line. The <command>net user</command> command
-allows to set all values in the SAM, even if the GUI is crippled.
-</para>
-
-<para>
-A Cygwin SAM comment entry looks like this:
-</para>
-
-<screen>
-&lt;cygwin key="value" key="value" [...] /&gt;
-</screen>
-
-<para>
-The supported keys are:
-</para>
-
-<segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>home="value"</literal></seg>
- <seg>Sets the Cygwin home dir to value.</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>shell="value"</literal></seg>
- <seg>Sets the Cygwin login shell to value.</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>group="value"</literal></seg>
- <seg>Sets the Cygwin primary group of the account to value, provided that
- the user *is* already a member of that group. This allows to override
- the default "None" primary group for local accounts. One nice idea
- here is, for instance group="Users".</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>unix="value"</literal></seg>
- <seg>Sets the NFS/Samba uid of the user to the decimal value.
- See <xref linkend="ntsec-mapping-nfs"></xref>.</seg>
- </seglistitem>
-</segmentedlist>
-
-<para>
-The &lt;cygwin .../&gt; string can start at any point in the comment, but
-you have to follow the rules:
-</para>
-
-<itemizedlist spacing="compact">
-<listitem>
-It starts with "&lt;cygwin " and ends with "/&gt;".
-</listitem>
-<listitem>
-The "cygwin" string and the key names have to be lowercase.
-</listitem>
-<listitem>
-No spaces between key and "value", just the equal sign.
-</listitem>
-<listitem>
-The value must be placed within double quotes and it must not contain a double
-quote itself. The double quotes are required for the decimal values as well!
-</listitem>
-</itemizedlist>
-
-<para>
-CMD example:
-</para>
-
-<screen>
-net user corinna /comment:"&lt;cygwin home=\"/home/foo\"/&gt;"
-</screen>
-
-<para>
-Bash example (use single quotes):
-</para>
-
-<screen>
-net user corinna /comment:'&lt;cygwin home="/home/foo"/&gt;'
-</screen>
-
-<para>
-For changing group comments, use the `net localgroup' command. The supported
-key/value pair for groups are:
-</para>
-
-<segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>unix="value"</literal></seg>
- <seg>Sets the NFS/Samba gid of the group to the decimal value.
- See <xref linkend="ntsec-mapping-nfs"></xref>.</seg>
- </seglistitem>
-</segmentedlist>
-
-</listitem>
-
-</itemizedlist>
-
-</sect3>
-
-<sect3 id="ntsec-mapping-caching"><title id="ntsec-mapping-caching.title">Caching account information</title>
-
-<para>
-The information fetched from the Windows account database or the
-<filename>/etc/passwd</filename> and <filename>/etc/group</filename> files is
-cached by the process. The cached information is inherited by Cygwin child
-processes. A Cygwin process invoked from a Windows command, such as CMD.exe,
-will start a new Cygwin process tree and the caching starts from scratch
-(unless <command><link linkend="using-cygserver">cygserver</link></command> is
-running, but read on).
-</para>
-
-<para>
-While usually working fine, this has some drawbacks. Consider a shell calling
-<command>id</command>. <command>id</command> fetches all group information
-from the current token and caches them. Unfortunately <command>id</command>
-doesn't start any child processes, so the information is lost as soon as
-<command>id</command> exits.
-</para>
-
-<para>
-But there's another caching mechanism available. If
-<command><link linkend="using-cygserver">cygserver</link></command> is running
-it will provide passwd and group entry caching for all processes in every Cygwin
-process tree started after
-<command><link linkend="using-cygserver">cygserver</link></command>. So, if
-you start a Cygwin Terminal and
-<command><link linkend="using-cygserver">cygserver</link></command> is running
-at the time, <command>mintty</command>, the shell, and all child processes will
-use <command><link linkend="using-cygserver">cygserver</link></command> caching.
-If you start a Cygwin Terminal and
-<command><link linkend="using-cygserver">cygserver</link></command> is not
-running at the time, none of the processes started inside this terminal window
-will use <command><link linkend="using-cygserver">cygserver</link></command>
-caching.
-</para>
-<para>
-The advantage of
-<command><link linkend="using-cygserver">cygserver</link></command> caching is
-that it's system-wide and, as long as
-<command><link linkend="using-cygserver">cygserver</link></command> is running,
-unforgetful. Every Cygwin process on the system will have the
-<command><link linkend="using-cygserver">cygserver</link></command> cache at
-its service. Additionally, all information requested from
-<command><link linkend="using-cygserver">cygserver</link></command> once, will
-be cached inside the process itself and, again, propagated to child processes.
-</para>
-
-<para>
-If you automatically start Cygwin processes as Windows services at system
-startup, you may wish to consider starting
-<command><link linkend="using-cygserver">cygserver</link></command> first in
-order to take advantage of this system-wide caching. To assure that
-<command><link linkend="using-cygserver">cygserver</link></command> has started
-prior to starting <command>sshd</command> or other Cygwin processes, you may
-wish to create service startup dependencies.
-<command><link linkend="using-cygserver">Cygserver</link></command> should
-probably wait for Windows TCPIP and AFD services before it starts, and then
-other Cygwin process should start after
-<command><link linkend="using-cygserver">cygserver</link></command>. Example
-Windows commands to accomplish this (after the services already exist) are
-shown below. You will need an administrative prompt to run the
-<command>sc config</command> commands.
-</para>
-
-<screen>
- # Delay Cygserver until TCPIP and AFD have started
- # Note the (odd) required space character after "depend="
-
- sc config cygserver depend= tcpip/afd
-
- # Delay sshd until after Cygserver has started
- # Again note the (odd) required space character after "depend="
-
- sc config sshd depend= cygserver
-
- # View the Cygserver service details
-
- sc qc cygserver
-</screen>
-
-<para>
-Note that this <command>sc config</command> command
-<emphasis>replaces</emphasis> any existing dependencies. The above changes
-will not impact the running instance, only future instances.
-</para>
-
-<screen>
- # To remove all dependencies from the cygserver service
-
- sc config cygserver depend= /
-</screen>
-
-</sect3>
-
-<sect3 id="ntsec-mapping-nfs"><title id="ntsec-mapping-nfs.title">NFS account mapping</title>
-
-<para>
-Microsoft's NFS client does not map the uid/gid values on the NFS shares
-to SIDs. There's no such thing as a (fake) security descriptor returned
-to the application. Rather, via an undocumented API an application can
-fetch <ulink url="https://tools.ietf.org/html/rfc1813">RFC 1813</ulink>
-compatible NFSv3 stat information from the share. This is what Cygwin is
-using to show stat information for files on NFS shares.
-</para>
-
-<para>
-The problem is, while all other information in this stat record, like
-timestamps, file size etc., can be used by Cygwin, Cygwin had no way to
-map the values of the st_uid and st_gid members to a Windows SID for a
-long time. So it just faked the file owner info and claimed that it's
-you.
-</para>
-
-<para>
-However, SFU has, over time, developed multiple methods to map UNIX
-uid/gid values on NFS shares to Windows SIDs. You'll find the full
-documentation of the mapping methods in
-<ulink url="http://blogs.technet.com/b/filecab/archive/2012/10/09/nfs-identity-mapping-in-windows-server-2012.aspx">NFS Identity Mapping in Windows Server 2012</ulink>
-</para>
-
-<para>
-Cygwin now utilizes the
-<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>
-mapping for this purpose. This is most of the time provided by an AD domain,
-but it could also be a standalone LDAP mapping server. Per
-<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>, the uid is
-in the attribute <literal>uidNumber</literal>. For groups, the gid is in the
-<literal>gidNumber</literal> attribute.
-</para>
-
-<para>
-When Cygwin stat()s files on an NFS share, it asks the mapping server via
-LDAP in two different ways, depending on the role of the mapping server.
-</para>
+</sect2>
+<sect2 id="ntsec-ids"><title id="ntsec-ids.title">Special values of user and group ids</title>
+
+<para>If the current user is not present in
+<filename>/etc/passwd</filename>, that user's uid is set to a
+special value of 400. The user name for the current user will always be
+shown correctly. If another user (or a Windows group, treated as a
+user) is not present in <filename>/etc/passwd</filename>, the uid of
+that user will have a special value of -1 (which would be shown by
+<command>ls</command> as 65535). The user name shown in this case will
+be '????????'.</para>
+
+<para>If the current user is not present in
+<filename>/etc/passwd</filename>, that user's login gid is set to a
+special value of 401. The gid 401 is shown as 'mkpasswd',
+indicating the command that should be run to alleviate the
+situation.</para>
+
+<para>If another user is not present in
+<filename>/etc/passwd</filename>, that user's login gid is set to a
+special value of -1. If the user is present in
+<filename>/etc/passwd</filename>, but that user's group is not in
+<filename>/etc/group</filename> and is not the login group of that user,
+the gid is set to a special value of -1. The name of this group
+(id -1) will be shown as '????????'.</para>
+
+<para>If the current user is present in
+<filename>/etc/passwd</filename>, but that user's login group is not
+present in <filename>/etc/group</filename>, the group name will be shown
+as 'mkgroup', again indicating the appropriate command.</para>
+
+<para>A special case is if the current user's primary group SID is noted
+in the user's <filename>/etc/passwd</filename> entry using another group
+id than the group entry of the same group SID in
+<filename>/etc/group</filename>. This should be noted and corrected.
+The group name printed in this case is
+'passwd/group_GID_clash(PPP/GGG)', with PPP being the gid as noted
+in <filename>/etc/passwd</filename> and GGG the gid as noted in
+<filename>/etc/group</filename>.</para>
+
+<para>To summarize:</para>
<itemizedlist spacing="compact">
-<listitem>
-If the server is an AD domain controller, it asks for an account with
-<literal>uidNumber</literal> attribute == <literal>st_uid</literal> field of
-the stat record returned by NFS. If an account matches, AD returns the
-Windows SID, so we have an immediate mapping from UNIX uid to a Windows SID,
-if the user account has a valid <literal>uidNumber</literal> attribute. For
-groups, the method is the same, just that Cygwin asks for a group with
-<literal>gidNumber</literal> attribute == <literal>st_gid</literal> field of the
-stat record.
-</listitem>
+<listitem><para>If the current user doesn't show up in
+<filename>/etc/passwd</filename>, it's <emphasis>group</emphasis> will
+be named 'mkpasswd'.</para></listitem>
-<listitem>
-If the server is a standalone LDAP mapping server Cygwin asks for the
-same <literal>uidNumber</literal>/<literal>gidNumber</literal> attributes, but
-it can't expect that the LDAP server knows anything about Windows SIDs.
-Rather, the mapping server returns the account name. Cygwin then asks the
-DC for an account with this name, and if that succeeds, we have a mapping
-between UNIX uid/gid and Windows SIDs.
+<listitem><para>Otherwise, if the login group of the current user isn't
+in <filename>/etc/group</filename>, it will be named 'mkgroup'.</para>
</listitem>
-</itemizedlist>
-
-<para>
-The mapping will be cached for the lifetime of the process, and inherited
-by child processes.
-</para>
-
-</sect3>
-
-<sect3 id="ntsec-mapping-samba"><title id="ntsec-mapping-samba.title">Samba account mapping</title>
-
-<para>
-A fully set up Samba with domain integration is running winbindd to
-map Window SIDs to artificially created UNIX uids and gids, and this
-mapping is transparent within the domain, so Cygwin doesn't have to do
-anything special.
-</para>
-
-<para>
-However, setting up winbindd isn't for everybody, and it fails to map
-Windows accounts to already existing UNIX users or groups. In contrast
-to NFS, Samba returns security descriptors, but unmapped UNIX accounts
-get special SIDs:
-</para>
-
-<itemizedlist spacing="compact">
-
-<listitem>
-A UNIX user account with uid X is mapped to the Windows SID S-1-22-1-X.
+<listitem><para>Otherwise a group not in <filename>/etc/group</filename>
+will be shown as '????????' and a user not in
+<filename>/etc/passwd</filename> will be shown as "????????".</para>
</listitem>
-<listitem>
-A UNIX group account with gid X is mapped to SID S-1-22-2-X.
-</listitem>
+<listitem><para>If different group ids are used for a group with the same
+SID, the group name is shown as 'passwd/group_GID_clash(PPP/GGG)' with
+PPP and GGG being the different group ids.</para></listitem>
</itemizedlist>
<para>
-As you can see, even though we have SIDs, they just reflect the actual
-uid/gid values on the UNIX box in the RID value. It's only marginally
-different from the NFS method, so why not just use the same method as
-for NFS?
-</para>
-
-<para>
-That's what Cygwin will do. If it encounters a S-1-22-x-y SID, it
-will perform the same
-<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>
-mapping as for NFS shares.
-</para>
-
-<para>
-For home users without any Windows domain or LDAP server per
-<ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>,
-but with a Linux machine running Samba, just add this information to
-your SAM account. Assuming the uid of your Linux user account is 505
-and the gid of your primary group is, say, 100, just add the values to
-your SAM user and group accounts. The following example assumes you
-didn't already add something else to the comment field.
-</para>
-
-<para>
-To your user's SAM comment (remember: called <literal>Description</literal>
-in the GUI),
-add:
-</para>
-
-<screen>
- &lt;cygwin group="Users" unix="505"/&gt;
-</screen>
-
-<para>
-To the user's group SAM comment add:
-</para>
-
-<screen>
- &lt;cygwin unix="100"/&gt;
-</screen>
-
-<para>
-This should be sufficient to work on your Samba share and to see
-all files owned by your Linux user account as your files.
-</para>
-
-</sect3>
-
-<sect3 id="ntsec-mapping-nsswitch"><title id="ntsec-mapping-nsswitch.title">The <filename>/etc/nsswitch.conf</filename> file</title>
-
-<para>
-Last, but not least, let's talk about the way to configure how the
-mapping works on your machine. On Linux and some other UNIXy OSes, we
-have a file called
-<ulink url="http://linux.die.net/man/5/nsswitch.conf">/etc/nsswitch.conf</ulink>.
-One part of it is to specify how the passwd and group entries are generated.
-That's what Cygwin now provides as well.
-</para>
-
-<para>
-The <filename>/etc/nsswitch.conf</filename> file is optional. If you don't
-have one, Cygwin uses sensible defaults.
+Note that, since the special user and group names are just indicators,
+nothing prevents you from actually having a user named `mkpasswd' in
+<filename>/etc/passwd</filename> (or a group named `mkgroup' in
+<filename>/etc/group</filename>). If you do that, however, be aware of
+the possible confusion.
</para>
-<note>
-<para>
-The <filename>/etc/nsswitch.conf</filename> file is read exactly once by
-the first process of a Cygwin process tree. If there was no
-<filename>/etc/nsswitch.conf</filename> file when this first process started,
-then no other process in the running Cygwin process tree will try to read the
-file.
-</para>
-
-<para>
-If you create or change <filename>/etc/nsswitch.conf</filename>, you have to
-restart all Cygwin processes that need to see the change. If the process
-you want to see the change is a child of another process, you need to restart
-all of that process's parents, too.
-</para>
-
-<para>
-For example, if you run <command>vim</command> inside the default Cygwin
-Terminal, <command>vim</command> is a child of your shell, which is a child
-of <command>mintty</command>. If you edit
-<filename>/etc/nsswitch.conf</filename> in that <command>vim</command>
-instance, your shell won't immediately see the change, nor will
-<command>vim</command> if you restart it from that same shell instance.
-This is because both are getting their nsswitch information from their
-ancestor, <command>mintty</command>. You have to start a fresh terminal
-window for the change to take effect.
-</para>
-
-<para>
-By contrast, if you leave that Cygwin Terminal window open after making the
-change to <filename>/etc/nsswitch.conf</filename>, then restart a Cygwin
-service like <command>cron</command>, <command>cron</command> will see the
-change, because it is not a child of <command>mintty</command> or any other
-Cygwin process. (Technically, it is a child of <command>cygrunsrv</command>,
-but that instance also restarts when you restart the service.)
-</para>
-
-<para>
-The reason we point all this out is that the requirements for restarting
-things are not quite as stringent as when you replace
-<filename>cygwin1.dll</filename>. If you have three process trees, you have
-three independent copies of the nsswitch information. If you start a fresh
-process tree, it will see the changes. As long as any process in an existing
-process tree remains running, all processes in that tree will continue to use
-the old information.
-</para>
-</note>
-
-<para>
-So, what settings can we perform with <filename>/etc/nsswitch.conf</filename>?
-To explain, lets have a look into an <filename>/etc/nsswitch.conf</filename>
-file set up to all default values:
-</para>
-
-<screen>
- # /etc/nsswitch.conf
- passwd: files db
- group: files db
-<!--
- db_prefix: auto
- db_separator: + -->
- db_enum: cache builtin
-</screen>
-
-<para>
-The first line, starting with a hash <literal>#</literal> is a comment.
-The hash character starts a comment, just as in shell scripts. Everything
-up to the end of the line is ignored. So this:
-</para>
-
-<screen>
- foo: bar # baz
-</screen>
-
-<para>
-means, set "foo" to value "bar", ignore everything after the hash.
-</para>
-
-<para>
-The other lines define the available settings. The first word up to a
-colon is a keyword. Note that the colon <emphasis>must</emphasis> follow
-immediately after the keyword. This is a valid line:
-</para>
-
-<screen>
- foo: bar
-</screen>
-
-<para>
-This is not valid:
-</para>
-
-<screen>
- foo : bar
-</screen>
-
-<para>
-Apart from this restriction, the reminder of the line can have as
-many spaces and TABs as you like.
-</para>
-
-<para>
-Now let's have a look at the available keywords and settings.
-</para>
-
-<para>
-The two lines starting with the keywords <literal>passwd:</literal> and
-<literal>group:</literal> define where Cygwin gets its passwd and group
-information from. <literal>files</literal> means, fetch the information
-from the corresponding file in the /etc directory. <literal>db</literal>
-means, fetch the information from the Windows account databases, the SAM
-for local accounts, Active Directory for domain account. Examples:
-</para>
-
-<screen>
- passwd: files
-</screen>
-
-<para>
-Read passwd entries only from /etc/passwd.
-</para>
-
-<screen>
- group: db
-</screen>
-
-<para>
-Read group entries only from SAM/AD.
-</para>
-
-<screen>
- group: files # db
-</screen>
-
-<para>
-Read group entries only from <filename>/etc/group</filename>
-(<literal>db</literal> is only a comment).
-</para>
-
-<screen>
- passwd: files db
-</screen>
-
-<para>
-Read passwd entries from <filename>/etc/passwd</filename>. If a user account
-isn't found, try to find it in SAM or AD. This is the default for both,
-passwd and group information.
-</para>
-
-<screen>
- group: db files
-</screen>
-
-<para>
-This is a valid entry, but the order will be ignored by Cygwin. If both
-settings, <literal>files</literal> and <literal>db</literal> are specified,
-Cygwin will always try the files first, then the db.
-</para>
-
-<para>
-The remaining entries define certain aspects of the Windows account
-database search. Right now, only one entry is valid:
-</para>
-
-<itemizedlist spacing="compact">
-
-<!--
-<listitem>
-<para>
-<literal>db_prefix:</literal> determines how the Cygwin user or group name
-is created. The recognized values are:
-</para>
-
-<variablelist>
- <varlistentry>
- <term><literal>auto</literal></term>
- <listitem>
- <para>
- This is the default. If your account is from the primary domain of your
- machine, or if your machine is a standalone machine (not a domain member),
- your Cygwin account name is just the Windows account name.
- </para>
-
- <para>
- If your account is from another domain, or if you're logged in as
- local user on a domain machine, the Cygwin username will be the
- combination of Windows domainname and username, with the separator
- char in between:
- </para>
-
- <segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>MY_DOM+username</literal></seg>
- <seg>(foreign domain)</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>MACHINE+username</literal></seg>
- <seg>(local account)</seg>
- </seglistitem>
- </segmentedlist>
-
- <para>
- Builtin accounts are simply used as is:
- </para>
-
- <segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>LOCAL</literal></seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>Users</literal></seg>
- </seglistitem>
- </segmentedlist>
-
- <para>
- Unknown accounts on NFS or Samba shares (that is, accounts which cannot be
- mapped to Windows user accounts via
- <ulink url="https://tools.ietf.org/html/rfc2307">RFC 2307</ulink>) get a
- Cygwin account name consisting of the artificial domains
- <literal>Unix_User</literal> or <literal>Unix_Group</literal> and the
- uid/gid value, for instance:
- </para>
-
- <segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>Unix_User+0</literal></seg>
- <seg>(root)</seg>
- </seglistitem>
- <seglistitem>
- <seg><literal>Unix_Group+10</literal></seg>
- <seg>(wheel)</seg>
- </seglistitem>
- </segmentedlist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>primary</literal></term>
- <listitem>
- <para>
- Like <literal>auto</literal>, but primary domain accounts will be
- prepended by the domainname as well.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>always</literal></term>
- <listitem>
- <para>
- All accounts, even the builtin accounts, will have the domain name
- prepended:
- </para>
-
- <segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>BUILTIN+Users</literal></seg>
- </seglistitem>
- </segmentedlist>
-
- <para>
- A special case are builtin accounts which have an emtpy domain name.
- These will be prependend by just the separator character in
- <literal>always</literal> mode:
- </para>
-
- <segmentedlist><?dbhtml list-presentation="table"?>
- <seglistitem>
- <seg><literal>+LOCAL</literal></seg>
- </seglistitem>
- </segmentedlist>
- </listitem>
- </varlistentry>
-</variablelist>
-
-</listitem>
-
-<listitem>
-<para>
-<literal>db_separator:</literal> defines the spearator char used to prepend the
-domain name to the user or group name. The default is the plus character
-<literal>+</literal>.
-</para>
-
-<screen>
- MY_DOM+username
-</screen>
-
-<para>
-With <literal>db_separator:</literal>, you can define any ASCII char except
-space, tab, carriage return, line feed, and the colon, as separator char.
-Example:
-</para>
-
-<screen>
- db_separator: \
-</screen>
-
-<para>
-This results in usernames with the backslash as separator:
-</para>
-
-<screen>
- MY_DOM\username
-</screen>
-
-</listitem>
--->
-<listitem>
-<para>
-<literal>db_enum:</literal> defines the depth of a database search, if an
-application calls one of the enumeration functions
-<ulink url="http://linux.die.net/man/3/getpwent">getpwent</ulink>
-or <ulink url="http://linux.die.net/man/3/getgrent">getgrent</ulink>.
-The problem with these functions is, they neither allow to define how many
-entries will be enumerated when calling them in a loop, nor do they
-allow to add some filter criteria. They were designed back in the days,
-when only <filename>/etc/passwd</filename> and <filename>/etc/group</filename>
-files existed and the number of user accounts on a typical UNIX system was
-seldomly a three-digit number.
-</para>
-
-<para>
-These days, with user and group databases sometimes going in the
-six-digit range, they are a potential burden. For that reason, Cygwin
-does not enumerate all user or group accounts by default, but rather
-just a very small list, consisting only of the accounts cached in memory
-by the current process, as well as a handful of predefined builtin
-accounts.
-</para>
-
-<para>
-<literal>db_enum:</literal> allows to specify the accounts to enumerate in a
-fine-grained manner. It takes a list of sources as argument:
-</para>
-
-<screen>
- db_enum: source1 source2 ...
-</screen>
-
-<para>
-The recognized sources are the following:
-</para>
-
-<variablelist>
- <varlistentry>
- <term><literal>none</literal></term>
- <listitem>No output from
- <function>getpwent</function>/<function>getgrent</function>
- at all.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>all</literal></term>
- <listitem>The opposite. Enumerates accounts from all known sources, including
- all trusted domains.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>cache</literal></term>
- <listitem>Enumerate all accounts currently cached in memory.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>builtin</literal></term>
- <listitem>Enumerate the predefined builtin accounts for backward compatibility.
- These are five passwd accounts (SYSTEM, LocalService, NetworkService,
- Administrators, TrustedInstaller) and two group accounts (SYSTEM and
- TrustedInstaller).</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>files</literal></term>
- <listitem>Enumerate the accounts from <filename>/etc/passwd</filename> or
- <filename>/etc/group</filename>.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>local</literal></term>
- <listitem>Enumerate all accounts from the local SAM.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>primary</literal></term>
- <listitem>Enumerate all accounts from the primary domain.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>alltrusted</literal></term>
- <listitem>Enumerate all accounts from all trusted domains.</listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>some.domain</literal></term>
- <listitem>Enumerate all accounts from the trusted domain some.domain. The
- trusted domain can be given as Netbios flat name (MY_DOMAIN) or as
- dns domain name (my_domain.corp). In contrast to the aforementioned
- fixed source keywords, distinct domain names are caseinsensitive.
- Only domains which are actually trusted domains are enumerated.
- Unknown domains are simply ignored.</listitem>
- </varlistentry>
-</variablelist>
-
-<para>
-Please note that <function>getpwent</function>/<function>getgrent</function>
-do <emphasis>not</emphasis> test if an account was already listed from another
-source, so an account can easily show up twice or three times. Such a test
-would be rather tricky, nor does the Linux implementation perform such test.
-Here are a few examples for <filename>/etc/nsswitch.conf</filename>:
-</para>
-
-<screen>
- db_enum: none
-</screen>
-
-<para>
-No output from <function>getpwent</function>/<function>getgrent</function>
-at all. The first call to the function immediately returns a NULL pointer.
-</para>
-
-<screen>
- db_enum: cache files
-</screen>
-
-<para>
-Enumerate all accounts cached by the current process, plus all entries
-from either the /etc/passwd or /etc/group file.
-</para>
-
-<screen>
- db_enum: cache local primary
-</screen>
-
-<para>
-Enumerate all accounts cached by the current process, all accounts from the SAM
-of the local machine, and all accounts from the primary domain of the machine.
-</para>
-
-<screen>
- db_enum: local primary alltrusted
-</screen>
-
-<para>
-Enumerate the accounts from the machine's SAM, from the primary domain of the
-machine, and from all trusted domains.
-</para>
-
-<screen>
- db_enum: primary domain1.corp sub.domain.corp domain2.net
-</screen>
-
-<para>
-Enumerate the accounts from the primary domain and from the domains
-domain1.corp, sub.domain.corp and domain2.net.
-</para>
-
-<screen>
- db_enum: all
-</screen>
-
-<para>
-Enumerate everything and the kitchen sink.
-</para>
-
-</listitem>
-
-</itemizedlist>
-
-</sect3>
-
-
</sect2>
-<sect2 id="ntsec-files"><title id="ntsec-files.title">File permissions</title>
-<para>On NTFS and if the <literal>noacl</literal> mount option is not
-specified for a mount point, Cygwin sets file permissions as on POSIX
-systems. Basically this is done by defining a Security Descriptor with the
-matching owner and group SIDs, and a DACL which contains ACEs for the owner,
-the group and for "Everyone", which represents what POSIX calls "others".</para>
+<sect2 id="ntsec-mapping"><title id="ntsec-mapping.title">The POSIX permission mapping leak</title>
-<para>There's just one problem when trying to map the POSIX permission model
-onto the Windows permission model.</para>
+<para>As promised earlier, here's the problem when trying to map the
+POSIX permission model onto the Windows permission model.</para>
-<para>There's a leak in the definition of a "correct" ACL which disallows a
-certain POSIX permission setting. The official documentation explains in short
-the following:</para>
+<para>There's a leak in the definition of a "correct" ACL which
+disallows a certain POSIX permission setting. The official
+documentation explains in short the following:</para>
<itemizedlist spacing="compact">
<listitem><para>The requested permissions are checked against all
@@ -1709,7 +501,7 @@ OthersAllow: 110
</screen>
<para>Again: This works on all existing versions of Windows NT, at the
-time of writing from at least Windows XP up to Server 2012 R2. Only
+time of writing from at least Windows XP up to Server 2012. Only
the GUIs aren't able (or willing) to deal with that order.</para>
</sect2>
@@ -1742,7 +534,9 @@ inherits the access token from its parent process. Every thread can
get its own access token, which allows, for instance, to define threads
with restricted permissions.</para>
-<sect3 id="ntsec-logonuser"><title id="ntsec-logonuser.title">Switching the user context with password authentication</title>
+</sect2>
+
+<sect2 id="ntsec-logonuser"><title id="ntsec-logonuser.title">Switching the user context with password authentication</title>
<para>To switch the user context, the process has to request such an access
token for the new user. This is typically done by calling the Win32 API
@@ -1818,9 +612,9 @@ example:</para>
</screen>
-</sect3>
+</sect2>
-<sect3 id="ntsec-nopasswd1"><title id="ntsec-nopasswd1.title">Switching the user context without password, Method 1: Create a token from scratch</title>
+<sect2 id="ntsec-nopasswd1"><title id="ntsec-nopasswd1.title">Switching the user context without password, Method 1: Create a token from scratch</title>
<para>An unfortunate aspect of the implementation of
<command>set(e)uid</command> is the fact that the calling process
@@ -1908,9 +702,9 @@ path as in</para>
bash$ grep foo //server/share/foofile
</screen>
-</sect3>
+</sect2>
-<sect3 id="ntsec-nopasswd2"><title id="ntsec-nopasswd2.title">Switching the user context without password, Method 2: LSA authentication package</title>
+<sect2 id="ntsec-nopasswd2"><title id="ntsec-nopasswd2.title">Switching the user context without password, Method 2: LSA authentication package</title>
<para>We're looking for another way to switch the user context without
having to provide the password. Another technique is to create an
@@ -1955,9 +749,9 @@ inconvenience compared to that...</para>
<para>Nevertheless, this is already a lot better than what we get by
using <command>NtCreateToken</command>, isn't it?</para>
-</sect3>
+</sect2>
-<sect3 id="ntsec-nopasswd3"><title id="ntsec-nopasswd3.title">Switching the user context without password, Method 3: With password</title>
+<sect2 id="ntsec-nopasswd3"><title id="ntsec-nopasswd3.title">Switching the user context without password, Method 3: With password</title>
<para>Ok, so we have solved almost any problem, except for the network
access problem. Not being able to access network shares without
@@ -2030,9 +824,9 @@ safely use this method.</para>
<para>In all other cases, don't use this method. You have been warned.</para>
-</sect3>
+</sect2>
-<sect3 id="ntsec-setuid-impl"><title id="ntsec-setuid-impl.title">Switching the user context, how does it all fit together?</title>
+<sect2 id="ntsec-setuid-impl"><title id="ntsec-setuid-impl.title">Switching the user context, how does it all fit together?</title>
<para>Now we learned about four different ways to switch the user
context using the <command>set(e)uid</command> system call, but
@@ -2090,8 +884,6 @@ fails and returns -1, setting errno to EPERM.</para>
</listitem>
</itemizedlist>
-</sect3>
-
</sect2>
</sect1>
diff --git a/winsup/doc/pathnames.xml b/winsup/doc/pathnames.xml
index 412c98f43..3647253e2 100644
--- a/winsup/doc/pathnames.xml
+++ b/winsup/doc/pathnames.xml
@@ -44,9 +44,7 @@ all users. Sometimes there's a requirement to have user specific
mount points. The Cygwin DLL supports user specific fstab files.
These are stored in the directory <filename>/etc/fstab.d</filename>
and the name of the file is the Cygwin username of the user, as it's
-created from the Windows account database or stored in the
-<filename>/etc/passwd</filename> file (see
-<xref linkend="ntsec-mapping"></xref>). The structure of the
+stored in the <filename>/etc/passwd</filename> file. The structure of the
user specific file is identical to the system-wide
<filename>fstab</filename> file.</para>
@@ -355,25 +353,6 @@ the cygdrive prefix, use a distinct path prefix:</para>
D: /mnt/d somefs text 0 0
</screen>
-<para>To simplify scripting, Cygwin also provides a
-<filename>/proc/cygdrive</filename> symlink, which allows to use a fixed path
-in scripts, even if the actual cygdrive prefix has been changed, or is different
-between different users. So, in scripts, conveniently use the
-<filename>/proc/cygdrive</filename> symlink to successfully access files
-independently from the current cygdrive prefix:</para>
-
-<screen>
- $ mount -p
- Prefix Type Flags
- /mnt user binmode
- $ cat &gt; x.sh &lt;&lt;EOF
- cd /proc/cygdrive/c/Windows/System32/Drivers/etc
- ls -l hosts
- EOF
- $ sh -c ./x.sh
- -rwxrwx---+ 1 SYSTEM SYSTEM 826 Sep 4 22:43 hosts
-</screen>
-
</sect2>
<sect2 id="pathnames-symlinks"><title>Symbolic links</title>
diff --git a/winsup/doc/using.xml b/winsup/doc/using.xml
index 3ec26707b..1795acccd 100644
--- a/winsup/doc/using.xml
+++ b/winsup/doc/using.xml
@@ -16,6 +16,6 @@ knowledge of standard UNIX commands.</para>
<xi:include href="cygwinenv.xml"/>
<xi:include href="ntsec.xml"/>
<xi:include href="cygserver.xml"/>
- <xi:include href="utils.xml"/>
+ <xi:include href="../utils/utils.xml"/>
<xi:include href="effectively.xml"/>
</chapter>
diff --git a/winsup/doc/xidepend b/winsup/doc/xidepend
index d3b233a57..2a1fc831d 100755
--- a/winsup/doc/xidepend
+++ b/winsup/doc/xidepend
@@ -15,7 +15,7 @@ do
then
# This file uses XIncludes. Let's chase its deps recursively.
base=`basename "$f" .xml`
- if [ $subproc -eq 0 ] ; then echo -n "$base/$base.html $base/$base.pdf:" ; fi
+ if [ $subproc -eq 0 ] ; then echo -n "$base/$base.html:" ; fi
deps=`grep 'xi:include.*href' "$f" | cut -f2 -d\" | tr '\n' ' '`
echo -n " $deps"
diff --git a/winsup/lsaauth/ChangeLog b/winsup/lsaauth/ChangeLog
index 81e3ab1aa..020e972f0 100644
--- a/winsup/lsaauth/ChangeLog
+++ b/winsup/lsaauth/ChangeLog
@@ -1,8 +1,3 @@
-2014-08-15 Corinna Vinschen <corinna@vinschen.de>
-
- * configure.ac: Convert to new AC_INIT style.
- * configure: Regenerate.
-
2013-12-03 Christopher Faylor <me.cygwin2013@cgf.cx>
* configure.ac: Back out stupid change.
diff --git a/winsup/lsaauth/configure b/winsup/lsaauth/configure
index b83cc3364..6073a2d61 100755
--- a/winsup/lsaauth/configure
+++ b/winsup/lsaauth/configure
@@ -1,8 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Cygwin Lsaauth 0.
-#
-# Report bugs to <cygwin@cygwin.com>.
+# Generated by GNU Autoconf 2.69.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -265,11 +263,10 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and cygwin@cygwin.com
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
exit 1
fi
@@ -577,12 +574,12 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME='Cygwin Lsaauth'
-PACKAGE_TARNAME='cygwin'
-PACKAGE_VERSION='0'
-PACKAGE_STRING='Cygwin Lsaauth 0'
-PACKAGE_BUGREPORT='cygwin@cygwin.com'
-PACKAGE_URL='https://cygwin.com'
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
ac_unique_file="Makefile.in"
ac_no_link=no
@@ -702,7 +699,7 @@ sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
@@ -1202,7 +1199,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Cygwin Lsaauth 0 to adapt to many kinds of systems.
+\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1250,7 +1247,7 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/cygwin]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
@@ -1272,9 +1269,7 @@ _ACEOF
fi
if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of Cygwin Lsaauth 0:";;
- esac
+
cat <<\_ACEOF
Some influential environment variables:
@@ -1289,8 +1284,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Lsaauth home page: <https://cygwin.com>.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1353,7 +1347,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Cygwin Lsaauth configure 0
+configure
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1408,7 +1402,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Cygwin Lsaauth $as_me 0, which was
+It was created by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1757,7 +1751,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_aux_dir=
for ac_dir in ../.. "$srcdir"/../..; do
if test -f "$ac_dir/install-sh"; then
@@ -3603,7 +3596,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Cygwin Lsaauth $as_me 0, which was
+This file was extended by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -3650,14 +3643,13 @@ Usage: $0 [OPTION]... [TAG]...
Configuration files:
$config_files
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Lsaauth home page: <https://cygwin.com>."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Cygwin Lsaauth config.status 0
+config.status
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/winsup/lsaauth/configure.ac b/winsup/lsaauth/configure.ac
index 2bcb43cc4..fe2e30bf0 100644
--- a/winsup/lsaauth/configure.ac
+++ b/winsup/lsaauth/configure.ac
@@ -1,21 +1,22 @@
-dnl Autoconf configure script for Cygwin utilities.
-dnl Copyright 2006, 2008, 2012, 2013, 2014 Red Hat, Inc.
+dnl Copyright (c) 2006, Red Hat, Inc.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
dnl
-dnl This file is part of Cygwin.
-dnl
-dnl This software is a copyrighted work licensed under the terms of the
-dnl Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-dnl details.
+dnl A copy of the GNU General Public License can be found at
+dnl http://www.gnu.org/
dnl
dnl Written by Christopher Faylor <cgf@redhat.com>
dnl Changed for lsa subdir by Corinna Vinschen <corinna@vinschen.de>
+dnl Autoconf configure script for Cygwin utilities.
+dnl
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([Cygwin Lsaauth], 0,
- cygwin@cygwin.com, cygwin, https://cygwin.com)
-AC_CONFIG_SRCDIR(Makefile.in)
+AC_INIT(Makefile.in)
AC_CONFIG_AUX_DIR(../..)
diff --git a/winsup/testsuite/ChangeLog b/winsup/testsuite/ChangeLog
index e9cff49a0..262971ea0 100644
--- a/winsup/testsuite/ChangeLog
+++ b/winsup/testsuite/ChangeLog
@@ -1,8 +1,3 @@
-2014-08-15 Corinna Vinschen <corinna@vinschen.de>
-
- * configure.ac: Convert to new AC_INIT style.
- * configure: Regenerate.
-
2012-11-26 Christopher Faylor <me.cygwin2012@cgf.cx>
* configure.ac: Rename from configure.in.
diff --git a/winsup/testsuite/configure b/winsup/testsuite/configure
index da4616582..f0767845a 100644
--- a/winsup/testsuite/configure
+++ b/winsup/testsuite/configure
@@ -1,11 +1,11 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Cygwin Testsuite 0.
+# Generated by GNU Autoconf 2.68.
#
-# Report bugs to <cygwin@cygwin.com>.
#
-#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -134,31 +134,6 @@ export LANGUAGE
# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-# Use a proper internal environment variable to ensure we don't fall
- # into an infinite loop, continuously re-executing ourselves.
- if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
- _as_can_reexec=no; export _as_can_reexec;
- # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
- *v*x* | *x*v* ) as_opts=-vx ;;
- *v* ) as_opts=-v ;;
- *x* ) as_opts=-x ;;
- * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
- fi
- # We don't want this to propagate to other subprocesses.
- { _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
@@ -192,8 +167,7 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
else
exitcode=1; echo positional parameters were not saved.
fi
-test x\$exitcode = x0 || exit 1
-test -x / || exit 1"
+test x\$exitcode = x0 || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -237,25 +211,21 @@ IFS=$as_save_IFS
if test "x$CONFIG_SHELL" != x; then :
- export CONFIG_SHELL
- # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
- *v*x* | *x*v* ) as_opts=-vx ;;
- *v* ) as_opts=-v ;;
- *x* ) as_opts=-x ;;
- * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-exit 255
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
fi
if test x$as_have_required = xno; then :
@@ -265,11 +235,10 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and cygwin@cygwin.com
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
exit 1
fi
@@ -358,14 +327,6 @@ $as_echo X"$as_dir" |
} # as_fn_mkdir_p
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
- test -f "$1" && test -x "$1"
-} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -487,10 +448,6 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
chmod +x "$as_me.lineno" ||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
- # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
- # already done that, so ensure we don't try to do so again and fall
- # in an infinite loop. This has already happened in practice.
- _as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
@@ -525,16 +482,16 @@ if (echo >conf$$.file) 2>/dev/null; then
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -pR'.
+ # In both cases, we have to default to `cp -p'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -pR'
+ as_ln_s='cp -p'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
- as_ln_s='cp -pR'
+ as_ln_s='cp -p'
fi
else
- as_ln_s='cp -pR'
+ as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
@@ -546,8 +503,28 @@ else
as_mkdir_p=false
fi
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -577,12 +554,12 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME='Cygwin Testsuite'
-PACKAGE_TARNAME='cygwin'
-PACKAGE_VERSION='0'
-PACKAGE_STRING='Cygwin Testsuite 0'
-PACKAGE_BUGREPORT='cygwin@cygwin.com'
-PACKAGE_URL='https://cygwin.com'
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
ac_unique_file="Makefile.in"
ac_subst_vars='LTLIBOBJS
@@ -687,7 +664,7 @@ sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
@@ -1102,6 +1079,8 @@ target=$target_alias
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
@@ -1187,7 +1166,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Cygwin Testsuite 0 to adapt to many kinds of systems.
+\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1235,7 +1214,7 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/cygwin]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
@@ -1247,9 +1226,7 @@ _ACEOF
fi
if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of Cygwin Testsuite 0:";;
- esac
+
cat <<\_ACEOF
Some influential environment variables:
@@ -1265,8 +1242,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Testsuite home page: <https://cygwin.com>.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1329,10 +1305,10 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Cygwin Testsuite configure 0
-generated by GNU Autoconf 2.69
+configure
+generated by GNU Autoconf 2.68
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1421,8 +1397,8 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Cygwin Testsuite $as_me 0, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+It was created by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -1680,7 +1656,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;}
|| { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
done
@@ -1770,7 +1746,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -1793,7 +1768,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -1833,7 +1808,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -1886,7 +1861,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -1927,7 +1902,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
@@ -1985,7 +1960,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2029,7 +2004,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2072,7 +2047,7 @@ fi
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -2187,7 +2162,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -2230,7 +2205,7 @@ else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -2289,7 +2264,7 @@ $as_echo "$ac_try_echo"; } >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
fi
fi
@@ -2341,7 +2316,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
@@ -2475,7 +2450,8 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
#include <stdio.h>
-struct stat;
+#include <sys/types.h>
+#include <sys/stat.h>
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -2688,7 +2664,7 @@ else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
+See \`config.log' for more details" "$LINENO" 5 ; }
fi
ac_ext=c
@@ -2714,7 +2690,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_AR="${ac_tool_prefix}ar"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2754,7 +2730,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_AR="ar"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -3235,16 +3211,16 @@ if (echo >conf$$.file) 2>/dev/null; then
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -pR'.
+ # In both cases, we have to default to `cp -p'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -pR'
+ as_ln_s='cp -p'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
- as_ln_s='cp -pR'
+ as_ln_s='cp -p'
fi
else
- as_ln_s='cp -pR'
+ as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
@@ -3304,16 +3280,28 @@ else
as_mkdir_p=false
fi
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
- test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -3334,8 +3322,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Cygwin Testsuite $as_me 0, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -3381,18 +3369,17 @@ Usage: $0 [OPTION]... [TAG]...
Configuration files:
$config_files
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Testsuite home page: <https://cygwin.com>."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Cygwin Testsuite config.status 0
-configured by $0, generated by GNU Autoconf 2.69,
+config.status
+configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -3469,7 +3456,7 @@ fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
- set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
\$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
@@ -3500,7 +3487,7 @@ do
case $ac_config_target in
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
esac
done
@@ -3708,7 +3695,7 @@ do
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
- :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
@@ -3736,7 +3723,7 @@ do
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
- as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
@@ -3763,7 +3750,7 @@ $as_echo "$as_me: creating $ac_file" >&6;}
case $ac_tag in
*:-:* | *:-) cat >"$ac_tmp/stdin" \
- || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
diff --git a/winsup/testsuite/configure.ac b/winsup/testsuite/configure.ac
index dc7cd2133..37190f9d9 100755
--- a/winsup/testsuite/configure.ac
+++ b/winsup/testsuite/configure.ac
@@ -1,5 +1,5 @@
dnl Autoconf configure script for Cygwin's testsuite.
-dnl Copyright 2000, 2006, 2012 Red Hat, Inc.
+dnl Copyright 2000 Red Hat, Inc.
dnl
dnl This file is part of Cygwin.
dnl
@@ -10,9 +10,7 @@ dnl
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([Cygwin Testsuite], 0,
- cygwin@cygwin.com, cygwin, https://cygwin.com)
-AC_CONFIG_SRCDIR(Makefile.in)
+AC_INIT(Makefile.in)
AC_PROG_CC
AC_PROG_CPP
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
index 09dc0bf31..8559de18d 100644
--- a/winsup/utils/ChangeLog
+++ b/winsup/utils/ChangeLog
@@ -1,87 +1,9 @@
-2014-11-10 Corinna Vinschen <corinna@vinschen.de>
-
- * cygcheck.cc (dump_sysinfo): Handle Windows 10/Server 2014(?).
-
-2014-11-03 Corinna Vinschen <corinna@vinschen.de>
-
- * mkgroup.c (enum_local_groups): Don't generate leading separator char
- for builtin accounts.
-
-2014-10-29 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (setfacl): Fix bracketing in expression.
-
-2014-10-27 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (usage): Add -b to require options.
-
-2014-10-27 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (action_t): Add DeleteAll value.
- (delacl): New function to remove all ACL entries not representing POSIX
- permissions.
- (setfacl): Rearrange conditional expression into switch statement.
- Add DeleteAll case.
- (usage): Add and describe -b option.
- (longopts): Add --remove-all option.
- (opts): Add -b option.
- (main): Handle -b option.
-
2014-10-21 Corinna Vinschen <corinna@vinschen.de>
* cygcheck.cc (CYGLSA64_DLL): Remove unused macro.
(dump_sysinfo): If COMSPEC isn't set in the MSVCRT environment, set it.
Explain why.
-2014-09-03 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (addmissing): New function to add missing acl entries to
- a modified acl per the rules set by aclcheck.
- (setfacl): Call addmissing unless action is Delete.
-
-2014-09-03 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (getaclentry): Fix previous fix again. Allow lone 'm' as
- well as any lone default entry if action is Delete. Fix comments.
- (usage): Align usage text.
-
-2014-09-03 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (getaclentry): Fix return value in case of a lone 'm' if
- action is Delete. Drop requirement for a trailing colon if action is
- Delete.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * setfacl.c (usage): Drop outdated note that default ACEs are not
- taken into account.
-
-2014-08-31 Corinna Vinschen <corinna@vinschen.de>
-
- * getfacl.c (usage): Add flags description.
- (main): Print suid/sgid/vtx flags if available.
-
-2014-08-15 Corinna Vinschen <corinna@vinschen.de>
-
- * configure.ac: Convert to new AC_INIT style.
- * configure: Regenerate.
-
-2014-08-14 Corinna Vinschen <corinna@vinschen.de>
-
- * utils.xml: Move to ../doc.
-
-2014-08-06 Corinna Vinschen <corinna@vinschen.de>
-
- * passwd.c (usage): Rename DAYS to MINDAYS and MAXDAYS.
- * utils.xml (passwd): Ditto.
-
-2014-07-29 Corinna Vinschen <corinna@vinschen.de>
-
- * mkgroup.c (usage): Move info message that this /etc/group isn't really
- required anymore more to the top of the usage output.
- * mkpasswd.c (usage): Ditto for /etc/passwd. Drop old text from output.
- * utils.xml: Fix accordingly.
-
2014-06-16 Corinna Vinschen <corinna@vinschen.de>
* passwd.c (main): Fix typo in error output.
@@ -104,40 +26,6 @@
* minidumper.cc (minidump): Fix copy and paste error in checking
result of OpenProcess().
-2014-02-24 Corinna Vinschen <corinna@vinschen.de>
-
- * mkgroup.c (domlist_t): Drop id_offset.
- (get_dcname): Remove.
- (current_group): Remove.
- (enum_unix_groups): Simplify. Change space to underscore in domain
- name.
- (enum_local_groups): Simplify to accommodate the fact that it's only
- called for foreign machines.
- (enum_groups): Ditto.
- (print_special_by_sid): Remove.
- (print_special_by_name): Remove.
- (usage): Align to new code.
- (fetch_primary_domain): Remove.
- (main): Use cygwin_internal CW_SETENT, CW_GETENT and CW_ENDENT method.
- Call enum_local_groups, enum_groups, and enum_unix_groups only for
- foreign machines.
- * mkpasswd.c (get_dcname): Remove.
- (current_user): Remove.
- (enum_unix_users): Simplify. Change space to underscore in domain name.
- (enum_users): Simplify to accommodate the fact that it's only
- called for foreign machines.
- (print_special_by_sid): Remove.
- (usage): Align to new code.
- (longopts): Add -b/--no-builtin option.
- (opts): Add -b option.
- (print_special_by_name): Remove.
- (enum_std_accounts): Remove.
- (fetch_primary_domain): Remove.
- (main): Use cygwin_internal CW_SETENT, CW_GETENT and CW_ENDENT method.
- Call enum_users and enum_unix_users only for foreign machines.
- * utils.xml (mkgroup): Align documentation to new usage.
- (mkpasswd): Ditto.
-
2014-02-23 Jon TURNEY <jon.turney@dronecode.org.uk>
* minidumper.cc (minidump): Fix -t option argument handling.
diff --git a/winsup/utils/configure b/winsup/utils/configure
index 5cf181edd..7e524e279 100755
--- a/winsup/utils/configure
+++ b/winsup/utils/configure
@@ -1,8 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Cygwin Utils 0.
-#
-# Report bugs to <cygwin@cygwin.com>.
+# Generated by GNU Autoconf 2.69.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -265,11 +263,10 @@ fi
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and cygwin@cygwin.com
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
fi
exit 1
fi
@@ -577,12 +574,12 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME='Cygwin Utils'
-PACKAGE_TARNAME='cygwin'
-PACKAGE_VERSION='0'
-PACKAGE_STRING='Cygwin Utils 0'
-PACKAGE_BUGREPORT='cygwin@cygwin.com'
-PACKAGE_URL='https://cygwin.com'
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
ac_unique_file="mount.cc"
ac_no_link=no
@@ -716,7 +713,7 @@ sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+docdir='${datarootdir}/doc/${PACKAGE}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
@@ -1216,7 +1213,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures Cygwin Utils 0 to adapt to many kinds of systems.
+\`configure' configures this package to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1264,7 +1261,7 @@ Fine tuning of the installation directories:
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/cygwin]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
@@ -1286,9 +1283,7 @@ _ACEOF
fi
if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of Cygwin Utils 0:";;
- esac
+
cat <<\_ACEOF
Optional Packages:
@@ -1312,8 +1307,7 @@ Some influential environment variables:
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Utils home page: <https://cygwin.com>.
+Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
@@ -1376,7 +1370,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-Cygwin Utils configure 0
+configure
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1469,7 +1463,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by Cygwin Utils $as_me 0, which was
+It was created by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -1817,7 +1811,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
ac_aux_dir=
for ac_dir in ../.. "$srcdir"/../..; do
if test -f "$ac_dir/install-sh"; then
@@ -3860,7 +3853,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by Cygwin Utils $as_me 0, which was
+This file was extended by $as_me, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -3907,14 +3900,13 @@ Usage: $0 [OPTION]... [TAG]...
Configuration files:
$config_files
-Report bugs to <cygwin@cygwin.com>.
-Cygwin Utils home page: <https://cygwin.com>."
+Report bugs to the package provider."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-Cygwin Utils config.status 0
+config.status
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/winsup/utils/configure.ac b/winsup/utils/configure.ac
index d90c3fc6f..5f517c0d0 100644
--- a/winsup/utils/configure.ac
+++ b/winsup/utils/configure.ac
@@ -1,6 +1,5 @@
dnl Autoconf configure script for Cygwin utilities.
-dnl Copyright 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2006, 2008, 2012, 2013,
-dnl 2014 Red Hat, Inc.
+dnl Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
dnl
dnl This file is part of Cygwin.
dnl
@@ -11,9 +10,7 @@ dnl details.
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT([Cygwin Utils], 0,
- cygwin@cygwin.com, cygwin, https://cygwin.com)
-AC_CONFIG_SRCDIR(mount.cc)
+AC_INIT(mount.cc)
AC_CONFIG_AUX_DIR(../..)
AC_NO_EXECUTABLES
diff --git a/winsup/utils/cygcheck.cc b/winsup/utils/cygcheck.cc
index 5d823e9a3..cc400519e 100644
--- a/winsup/utils/cygcheck.cc
+++ b/winsup/utils/cygcheck.cc
@@ -1480,13 +1480,10 @@ dump_sysinfo ()
? "8" : "2012");
break;
case 3:
- strcpy (osname, osversion.wProductType == VER_NT_WORKSTATION
- ? "8.1" : "2012 R2");
- break;
- case 4:
default:
+ osversion.dwMinorVersion = 3;
strcpy (osname, osversion.wProductType == VER_NT_WORKSTATION
- ? "10" : "2014");
+ ? "8.1" : "2012 R2");
break;
}
DWORD prod;
diff --git a/winsup/utils/getfacl.c b/winsup/utils/getfacl.c
index ed1adfce7..cbde4668a 100644
--- a/winsup/utils/getfacl.c
+++ b/winsup/utils/getfacl.c
@@ -1,6 +1,6 @@
/* getfacl.c
- Copyright 2000, 2001, 2002, 2003, 2004, 2009, 2011, 2014 Red Hat Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2009, 2011 Red Hat Inc.
Written by Corinna Vinschen <vinschen@redhat.com>
@@ -87,15 +87,13 @@ usage (FILE * stream)
"For directories getfacl displays additionally the default ACL.\n"
"\n"
"With no options specified, getfacl displays the filename, the\n"
- "owner, the group, the setuid (s), setgid (s), and sticky (t)\n"
- "bits if available, and both the ACL and the default ACL, if it\n"
+ "owner, the group, and both the ACL and the default ACL, if it\n"
"exists.\n"
"\n"
"The format for ACL output is as follows:\n"
" # file: filename\n"
" # owner: name or uid\n"
" # group: name or uid\n"
- " # flags: sst\n"
" user::perm\n"
" user:name or uid:perm\n"
" group::perm\n"
@@ -198,10 +196,6 @@ main (int argc, char **argv)
printf ("# owner: %s\n", username (st.st_uid));
printf ("# group: %s\n", groupname (st.st_gid));
}
- if (st.st_mode & (S_ISUID | S_ISGID | S_ISVTX))
- printf ("# flags: %c%c%c\n", (st.st_mode & S_ISUID) ? 's' : '-',
- (st.st_mode & S_ISGID) ? 's' : '-',
- (st.st_mode & S_ISVTX) ? 't' : '-');
for (i = 0; i < num_acls; ++i)
{
if (acls[i].a_type & ACL_DEFAULT)
diff --git a/winsup/utils/mkgroup.c b/winsup/utils/mkgroup.c
index 8894b315f..05f5910b0 100644
--- a/winsup/utils/mkgroup.c
+++ b/winsup/utils/mkgroup.c
@@ -1,7 +1,7 @@
/* mkgroup.c:
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -21,7 +21,6 @@
#include <inttypes.h>
#include <getopt.h>
#include <io.h>
-#include <grp.h>
#include <sys/fcntl.h>
#include <sys/cygwin.h>
#include <cygwin/version.h>
@@ -30,7 +29,9 @@
#include <wininet.h>
#include <iptypes.h>
#include <ntsecapi.h>
+#include <dsgetdc.h>
#include <ntdef.h>
+#include "loadlib.h"
#define print_win_error(x) _print_win_error(x, __LINE__)
@@ -46,7 +47,9 @@ SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY};
typedef struct
{
char *str;
+ DWORD id_offset;
BOOL domain;
+ BOOL with_dom;
} domlist_t;
static void
@@ -67,6 +70,31 @@ _print_win_error (DWORD code, int line)
line, (unsigned int) code);
}
+static PWCHAR
+get_dcname (char *domain)
+{
+ static WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ DWORD rc;
+ WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1];
+ PDOMAIN_CONTROLLER_INFOW pdci = NULL;
+
+ if (domain)
+ {
+ mbstowcs (domain_name, domain, strlen (domain) + 1);
+ rc = DsGetDcNameW (NULL, domain_name, NULL, NULL, 0, &pdci);
+ }
+ else
+ rc = DsGetDcNameW (NULL, NULL, NULL, NULL, 0, &pdci);
+ if (rc != ERROR_SUCCESS)
+ {
+ print_win_error (rc);
+ return (PWCHAR) -1;
+ }
+ wcscpy (server, pdci->DomainControllerName);
+ NetApiBufferFree (pdci);
+ return server;
+}
+
static char *
put_sid (PSID psid)
{
@@ -121,10 +149,40 @@ fetch_current_pgrp_sid ()
}
static void
-enum_unix_groups (domlist_t *mach, const char *sep, DWORD id_offset,
+current_group (const char *sep, DWORD id_offset)
+{
+ WCHAR grp[GNLEN + 1];
+ WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
+ DWORD glen = GNLEN + 1;
+ DWORD dlen = MAX_DOMAIN_NAME_LEN + 1;
+ int gid;
+ SID_NAME_USE acc_type;
+
+ if (!curr_pgrp.psid
+ || !LookupAccountSidW (NULL, curr_pgrp.psid, grp, &glen, dom, &dlen,
+ &acc_type))
+ {
+ print_win_error (GetLastError ());
+ return;
+ }
+ gid = *GetSidSubAuthority (curr_pgrp.psid,
+ *GetSidSubAuthorityCount(curr_pgrp.psid) - 1);
+ printf ("%ls%s%ls:%s:%" PRIu32 ":\n",
+ sep ? dom : L"",
+ sep ?: "",
+ grp,
+ put_sid (curr_pgrp.psid),
+ (unsigned int) (id_offset + gid));
+}
+
+static void
+enum_unix_groups (domlist_t *dom_or_machine, const char *sep, DWORD id_offset,
char *unix_grp_list)
{
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ PWCHAR servername = NULL;
+ char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL;
+ BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE;
SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } };
char *gstr, *grp_list;
WCHAR grp[GNLEN + sizeof ("Unix Group\\") + 1];
@@ -134,13 +192,17 @@ enum_unix_groups (domlist_t *mach, const char *sep, DWORD id_offset,
char psid_buffer[MAX_SID_LEN];
SID_NAME_USE acc_type;
- int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
+ if (!d_or_m)
+ return;
+
+ int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
{
fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
- program_invocation_short_name, mach->str);
+ program_invocation_short_name, d_or_m);
return;
}
+ servername = machine;
if (!AllocateAndInitializeSid (&auth, 2, 2, 0, 0, 0, 0, 0, 0, 0, &psid))
return;
@@ -160,15 +222,15 @@ enum_unix_groups (domlist_t *mach, const char *sep, DWORD id_offset,
if (ret < 1 || ret >= GNLEN + 1)
fprintf (stderr, "%s: Invalid group name '%s'. Skipping...\n",
program_invocation_short_name, gstr);
- else if (LookupAccountNameW (machine, grp,
+ else if (LookupAccountNameW (servername, grp,
psid = (PSID) psid_buffer,
(sidlen = MAX_SID_LEN, &sidlen),
dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type))
printf ("%s%s%ls:%s:%" PRIu32 ":\n",
- "Unix_Group",
- sep,
+ with_dom ? "Unix Group" : "",
+ with_dom ? sep : "",
p,
put_sid (psid),
(unsigned int) (id_offset +
@@ -197,15 +259,15 @@ enum_unix_groups (domlist_t *mach, const char *sep, DWORD id_offset,
{
*GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1)
= start;
- if (LookupAccountSidW (machine, psid,
+ if (LookupAccountSidW (servername, psid,
grp, (glen = GNLEN + 1, &glen),
dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type)
&& !iswdigit (grp[0]))
printf ("%s%s%ls:%s:%" PRIu32 ":\n",
- "Unix_Group",
- sep,
+ with_dom ? "Unix Group" : "",
+ with_dom ? sep : "",
grp,
put_sid (psid),
(unsigned int) (id_offset + start));
@@ -218,11 +280,14 @@ enum_unix_groups (domlist_t *mach, const char *sep, DWORD id_offset,
}
static int
-enum_local_groups (domlist_t *mach, const char *sep,
+enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
DWORD id_offset, char *disp_groupname, int print_builtin,
int print_current)
{
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ PWCHAR servername = NULL;
+ char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL;
+ BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE;
LOCALGROUP_INFO_0 *buffer;
DWORD entriesread = 0;
DWORD totalentries = 0;
@@ -230,12 +295,22 @@ enum_local_groups (domlist_t *mach, const char *sep,
WCHAR gname[GNLEN + 1];
DWORD rc;
- int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
- if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
+ if (domain)
{
- fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
- program_invocation_short_name, mach->str);
- return 1;
+ servername = get_dcname (d_or_m);
+ if (servername == (PWCHAR) -1)
+ return 1;
+ }
+ else if (d_or_m)
+ {
+ int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
+ if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
+ {
+ fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
+ program_invocation_short_name, d_or_m);
+ return 1;
+ }
+ servername = machine;
}
do
@@ -245,7 +320,7 @@ enum_local_groups (domlist_t *mach, const char *sep,
if (disp_groupname)
{
mbstowcs (gname, disp_groupname, GNLEN + 1);
- rc = NetLocalGroupGetInfo (machine, gname, 0, (void *) &buffer);
+ rc = NetLocalGroupGetInfo (servername, gname, 0, (void *) &buffer);
if (rc == ERROR_SUCCESS)
entriesread = 1;
/* Allow further searching for the group and avoid annoying
@@ -255,7 +330,7 @@ enum_local_groups (domlist_t *mach, const char *sep,
return 0;
}
else
- rc = NetLocalGroupEnum (machine, 0, (void *) &buffer,
+ rc = NetLocalGroupEnum (servername, 0, (void *) &buffer,
MAX_PREFERRED_LENGTH, &entriesread,
&totalentries, &resume_handle);
switch (rc)
@@ -285,7 +360,7 @@ enum_local_groups (domlist_t *mach, const char *sep,
PDBGSID pdsid;
BOOL is_builtin = FALSE;
- if (!LookupAccountNameW (machine, buffer[i].lgrpi0_name, psid,
+ if (!LookupAccountNameW (servername, buffer[i].lgrpi0_name, psid,
&sid_length, domain_name, &domname_len,
&acc_type))
{
@@ -302,7 +377,7 @@ enum_local_groups (domlist_t *mach, const char *sep,
wcscat (domname, buffer[i].lgrpi0_name);
sid_length = MAX_SID_LEN;
domname_len = MAX_DOMAIN_NAME_LEN + 1;
- if (!LookupAccountNameW (machine, domname,
+ if (!LookupAccountNameW (servername, domname,
psid, &sid_length,
domain_name, &domname_len,
&acc_type))
@@ -340,8 +415,8 @@ enum_local_groups (domlist_t *mach, const char *sep,
gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1);
printf ("%ls%s%ls:%s:%" PRIu32 ":\n",
- !is_builtin ? domain_name : L"",
- !is_builtin ? sep : "",
+ with_dom && !is_builtin ? domain_name : L"",
+ with_dom && !is_builtin ? sep : "",
buffer[i].lgrpi0_name,
put_sid (psid),
(unsigned int) (gid + (is_builtin ? 0 : id_offset)));
@@ -361,10 +436,13 @@ skip_group:
}
static void
-enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
- char *disp_groupname, int print_current)
+enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
+ DWORD id_offset, char *disp_groupname, int print_current)
{
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ PWCHAR servername = NULL;
+ char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL;
+ BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE;
GROUP_INFO_2 *buffer;
DWORD entriesread = 0;
DWORD totalentries = 0;
@@ -372,12 +450,22 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
WCHAR gname[GNLEN + 1];
DWORD rc;
- int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
- if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
+ if (domain)
{
- fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
- program_invocation_short_name, mach->str);
- return;
+ servername = get_dcname (d_or_m);
+ if (servername == (PWCHAR) -1)
+ return;
+ }
+ else if (d_or_m)
+ {
+ int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
+ if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
+ {
+ fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
+ program_invocation_short_name, d_or_m);
+ return;
+ }
+ servername = machine;
}
do
@@ -387,7 +475,8 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
if (disp_groupname != NULL)
{
mbstowcs (gname, disp_groupname, GNLEN + 1);
- rc = NetGroupGetInfo (machine, (LPWSTR) & gname, 2, (void *) &buffer);
+ rc = NetGroupGetInfo (servername, (LPWSTR) & gname, 2,
+ (void *) &buffer);
entriesread=1;
/* Avoid annoying error messages just because the group hasn't been
found. */
@@ -395,8 +484,9 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
return;
}
else
- rc = NetGroupEnum (machine, 2, (void *) & buffer, MAX_PREFERRED_LENGTH,
- &entriesread, &totalentries, &resume_handle);
+ rc = NetGroupEnum (servername, 2, (void *) & buffer,
+ MAX_PREFERRED_LENGTH, &entriesread, &totalentries,
+ &resume_handle);
switch (rc)
{
case ERROR_ACCESS_DENIED:
@@ -422,7 +512,7 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
SID_NAME_USE acc_type;
int gid = buffer[i].grpi2_group_id;
- if (!LookupAccountNameW (machine, buffer[i].grpi2_name,
+ if (!LookupAccountNameW (servername, buffer[i].grpi2_name,
psid, &sid_length,
domain_name, &domname_len,
&acc_type))
@@ -435,13 +525,16 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
{
WCHAR domname[MAX_DOMAIN_NAME_LEN + GNLEN + 2];
- wcscpy (domname, machine);
+ wcscpy (domname, domain || !servername
+ ? domain_name : servername);
wcscat (domname, L"\\");
wcscat (domname, buffer[i].grpi2_name);
sid_length = MAX_SID_LEN;
domname_len = MAX_DOMAIN_NAME_LEN + 1;
- if (!LookupAccountNameW (machine, domname, psid, &sid_length,
- domain_name, &domname_len, &acc_type))
+ if (!LookupAccountNameW (servername, domname,
+ psid, &sid_length,
+ domain_name, &domname_len,
+ &acc_type))
{
print_win_error (GetLastError ());
fprintf(stderr, " (%ls)\n", domname);
@@ -454,8 +547,8 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
got_curr_pgrp = TRUE;
printf ("%ls%s%ls:%s:%" PRIu32 ":\n",
- domain_name,
- sep,
+ with_dom ? domain_name : L"",
+ with_dom ? sep : "",
buffer[i].grpi2_name,
put_sid (psid),
(unsigned int) (id_offset + gid));
@@ -467,42 +560,107 @@ enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
while (rc == ERROR_MORE_DATA);
}
+static void
+print_special_by_sid (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt,
+ DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4,
+ DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8)
+{
+ WCHAR grp[GNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1];
+ DWORD glen, dlen, rid;
+ PSID psid;
+ SID_NAME_USE acc_type;
+
+ if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4,
+ sub5, sub6, sub7, sub8, &psid))
+ {
+ if (LookupAccountSidW (NULL, psid,
+ grp, (glen = GNLEN + 1, &glen),
+ dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
+ &acc_type))
+ {
+ if (sub8)
+ rid = sub8;
+ else if (sub7)
+ rid = sub7;
+ else if (sub6)
+ rid = sub6;
+ else if (sub5)
+ rid = sub5;
+ else if (sub4)
+ rid = sub4;
+ else if (sub3)
+ rid = sub3;
+ else if (sub2)
+ rid = sub2;
+ else
+ rid = sub1;
+ printf ("%ls:%s:%" PRIu32 ":\n", grp, put_sid (psid),
+ (unsigned int) rid);
+ }
+ FreeSid (psid);
+ }
+}
+
+static void
+print_special_by_name (PCWSTR name, gid_t gid)
+{
+ DWORD size = 256, dom_size = 256;
+ PSID sid = (PSID) alloca (size);
+ WCHAR dom[dom_size];
+ SID_NAME_USE use;
+
+ PWCHAR name_only = wcschr (name, L'\\');
+ if (name_only)
+ ++name_only;
+
+ if (LookupAccountNameW (NULL, name, sid, &size, dom, &dom_size, &use))
+ printf ("%ls:%s:%lu:\n",
+ name_only ?: name, put_sid (sid), (unsigned long) gid);
+}
+
static int
usage (FILE * stream)
{
fprintf (stream,
"Usage: %s [OPTION]...\n"
"\n"
-"Write /etc/group-like output to stdout\n"
-"\n"
-"Don't use this command to generate a local /etc/group file, unless you\n"
-"really need one. See the Cygwin User's Guide for more information.\n"
+"Print /etc/group file to stdout\n"
"\n"
"Options:\n"
"\n"
-" -l,--local [machine] print local groups of \"machine\"\n"
+" -l,--local [machine[,offset]]\n"
+" print local groups with gid offset offset\n"
" (from local machine if no machine specified)\n"
-" -d,--domain [domain] print domain groups\n"
+" -L,--Local [machine[,offset]]\n"
+" ditto, but generate groupname with machine prefix\n"
+" -d,--domain [domain[,offset]]\n"
+" print domain groups with gid offset offset\n"
" (from current domain if no domain specified)\n"
+" -D,--Domain [domain[,offset]]\n"
+" ditto, but generate groupname with machine prefix\n"
" -c,--current print current group\n"
-" -S,--separator char for -l use character char as domain\\group\n"
-" separator in groupname instead of default '%s'\n"
-" -o,--id-offset offset change the default offset (0x10000) added to\n"
-" gids of foreign machine accounts.\n"
+" -C,--Current ditto, but generate groupname with machine or\n"
+" domain prefix\n"
+" -S,--separator char for -L, -D, -C use character char as domain\\group\n"
+" separator in groupname instead of the default '\\'\n"
+" -o,--id-offset offset change the default offset (10000) added to gids\n"
+" in domain or foreign server accounts.\n"
" -g,--group groupname only return information for the specified group\n"
-" one of -l, -d must be specified, too\n"
+" one of -l, -L, -d, -D must be specified, too\n"
" -b,--no-builtin don't print BUILTIN groups\n"
-" -U,--unix grouplist print UNIX groups when using -l on a UNIX Samba\n"
-" server. grouplist is a comma-separated list of\n"
-" groupnames or gid ranges (root,-25,50-100).\n"
+" -U,--unix grouplist additionally print UNIX groups when using -l or -L\n"
+" on a UNIX Samba server\n"
+" grouplist is a comma-separated list of groupnames\n"
+" or gid ranges (root,-25,50-100).\n"
" (enumerating large ranges can take a long time!)\n"
+" -s,--no-sids (ignored)\n"
+" -u,--users (ignored)\n"
" -h,--help print this message\n"
" -v,--version print version information and exit\n"
"\n"
"Default is to print local groups on stand-alone machines, plus domain\n"
"groups on domain controllers and domain member machines.\n"
-"\n", program_invocation_short_name,
- (const char *) cygwin_internal (CW_GETNSSSEP));
+"\n", program_invocation_short_name);
return 1;
}
@@ -541,20 +699,44 @@ print_version ()
strrchr (__DATE__, ' ') + 1);
}
+static PPOLICY_PRIMARY_DOMAIN_INFO p_dom;
+
+static BOOL
+fetch_primary_domain ()
+{
+ NTSTATUS status;
+ LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 };
+ LSA_HANDLE lsa;
+
+ if (!p_dom)
+ {
+ status = LsaOpenPolicy (NULL, &oa, POLICY_EXECUTE, &lsa);
+ if (!NT_SUCCESS (status))
+ return FALSE;
+ status = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation,
+ (PVOID *) ((void *) &p_dom));
+ LsaClose (lsa);
+ if (!NT_SUCCESS (status))
+ return FALSE;
+ }
+ return !!p_dom->Sid;
+}
+
int
main (int argc, char **argv)
{
int print_domlist = 0;
domlist_t domlist[32];
- char *opt, *p;
+ char *opt, *p, *ep;
int print_current = 0;
+ int print_system = 0;
int print_builtin = 1;
char *print_unix = NULL;
- const char *sep_char = (const char *) cygwin_internal (CW_GETNSSSEP);
- DWORD id_offset = 0x10000, off;
+ const char *sep_char = "\\";
+ DWORD id_offset = 10000, off;
int c, i;
char *disp_groupname = NULL;
- //BOOL in_domain;
+ BOOL in_domain;
int optional_args = 0;
if (!isatty (1))
@@ -564,21 +746,22 @@ main (int argc, char **argv)
setlocale (LC_CTYPE, "");
if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
setlocale (LC_CTYPE, "en_US.UTF-8");
+ in_domain = fetch_primary_domain ();
fetch_current_pgrp_sid ();
if (argc == 1)
{
- int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN;
- uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums, NULL);
- if (ticket)
+ print_special_by_sid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0);
+ if (in_domain)
{
- struct group *grp;
-
- while ((grp = (struct group *) cygwin_internal (CW_GETENT, TRUE,
- ticket)))
- printf ("%s:%s:%u:\n", grp->gr_name, grp->gr_passwd, grp->gr_gid);
- cygwin_internal (CW_ENDENT, TRUE, ticket);
+ if (!enum_local_groups (TRUE, NULL, sep_char, id_offset,
+ disp_groupname, print_builtin, 0))
+ enum_groups (TRUE, NULL, sep_char, id_offset, disp_groupname, 0);
}
+ else if (!enum_local_groups (FALSE, NULL, sep_char, 0, disp_groupname,
+ print_builtin, 0))
+ enum_groups (FALSE, NULL, sep_char, 0, disp_groupname, 0);
return 0;
}
@@ -614,12 +797,17 @@ main (int argc, char **argv)
program_invocation_short_name,
domlist[i].domain ? "domain" : "machine",
domlist[i].str);
- break;
+ goto skip;
}
- domlist[print_domlist].str = opt;
+ if (!(domlist[print_domlist].str = opt))
+ print_system = 1;
+ domlist[print_domlist].id_offset = UINT32_MAX;
if (opt && (p = strchr (opt, ',')))
{
- if (p == opt)
+ if (p == opt
+ || !isdigit ((unsigned char) p[1])
+ || (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10)
+ , *ep))
{
fprintf (stderr, "%s: Malformed machine,offset string '%s'. "
"Skipping...\n", program_invocation_short_name, opt);
@@ -627,27 +815,15 @@ main (int argc, char **argv)
}
*p = '\0';
}
- if ((c == 'l' || c == 'L') && opt)
- {
- char cname[1024];
- DWORD csize = sizeof cname;
-
- /* Check if machine name is local machine. Keep it simple. */
- if (GetComputerNameExA (strchr (opt, '.')
- ? ComputerNameDnsFullyQualified
- : ComputerNameNetBIOS,
- cname, &csize)
- && strcasecmp (opt, cname) == 0)
- domlist[print_domlist].str = NULL;
- }
- ++print_domlist;
+ domlist[print_domlist++].with_dom = (c == 'D' || c == 'L');
+skip:
break;
case 'S':
sep_char = optarg;
if (strlen (sep_char) > 1)
{
- fprintf (stderr, "%s: Only one ASCII character allowed as "
- "domain\\user separator character.\n",
+ fprintf (stderr, "%s: Only one character allowed as domain\\user "
+ "separator character.\n",
program_invocation_short_name);
return 1;
}
@@ -662,6 +838,8 @@ main (int argc, char **argv)
print_unix = optarg;
break;
case 'c':
+ sep_char = NULL;
+ /*FALLTHRU*/
case 'C':
print_current = 1;
break;
@@ -698,77 +876,34 @@ main (int argc, char **argv)
exit (1);
}
- struct group *pgrp = NULL;
- if (print_current)
- pgrp = (struct group *) cygwin_internal (CW_GETGRSID, TRUE, curr_pgrp.psid);
-
- int enums = ENUM_NONE;
- WCHAR tdoms[print_domlist * 258];
- PWCHAR t = tdoms;
- if (!disp_groupname && print_builtin && print_domlist)
- enums |= ENUM_BUILTIN;
- for (i = 0; i < print_domlist; ++i)
- {
- if (domlist[i].domain)
- {
- if (domlist[i].str)
- {
- enums |= ENUM_TDOMS;
- t += mbstowcs (t, domlist[i].str, 257);
- *t++ = L'\0';
- }
- else
- enums |= ENUM_PRIMARY;
- }
- else if (!domlist[i].str)
- enums |= ENUM_LOCAL;
- }
- if (t > tdoms)
- *t++ = L'\0';
- if (enums)
+ /* Get 'system' group */
+ if (!disp_groupname && print_system && print_builtin && print_domlist)
{
- uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums,
- t > tdoms ? tdoms : NULL);
- if (ticket)
- {
- struct group *grp;
- const char *nss_sep = (const char *) cygwin_internal (CW_GETNSSSEP);
-
- while ((grp = (struct group *)
- cygwin_internal (CW_GETENT, TRUE, ticket)))
- {
- if (disp_groupname
- && strcasecmp (disp_groupname, grp->gr_name) != 0
- && (!(p = strchr (grp->gr_name, nss_sep[0]))
- || strcasecmp (disp_groupname, p + 1) != 0))
- continue;
- printf ("%s:%s:%u:\n", grp->gr_name, grp->gr_passwd,
- grp->gr_gid);
- if (pgrp && !strcmp (grp->gr_passwd, pgrp->gr_passwd))
- got_curr_pgrp = TRUE;
- }
- cygwin_internal (CW_ENDENT, TRUE, ticket);
- }
+ print_special_by_sid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0);
+ print_special_by_name (L"NT SERVICE\\TrustedInstaller", -2);
}
- if (print_current && !got_curr_pgrp)
- printf ("%s:%s:%u:\n", pgrp->gr_name, pgrp->gr_passwd, pgrp->gr_gid);
-
- off = 0xfd000000;
+ off = id_offset;
for (i = 0; i < print_domlist; ++i)
{
- if (domlist[i].domain || !domlist[i].str)
- continue;
- if (!enum_local_groups (domlist + i, sep_char, off, disp_groupname,
- print_builtin, print_current))
+ DWORD my_off = (domlist[i].domain || domlist[i].str)
+ ? domlist[i].id_offset != UINT_MAX
+ ? domlist[i].id_offset : off : 0;
+ if (!enum_local_groups (domlist[i].domain, domlist + i, sep_char,
+ my_off, disp_groupname, print_builtin, print_current))
{
- enum_groups (domlist + i, sep_char, off, disp_groupname,
- print_current);
if (!domlist[i].domain && domlist[i].str && print_unix)
- enum_unix_groups (domlist + i, sep_char, 0xff000000, print_unix);
- off += id_offset;
+ enum_unix_groups (domlist + i, sep_char, my_off, print_unix);
+ enum_groups (domlist[i].domain, domlist + i, sep_char, my_off,
+ disp_groupname, print_current);
+ if (my_off)
+ off += id_offset;
}
}
+ if (print_current && !got_curr_pgrp)
+ current_group (sep_char, off);
+
return 0;
}
diff --git a/winsup/utils/mkpasswd.c b/winsup/utils/mkpasswd.c
index 5ff33d8a1..d080dbd70 100644
--- a/winsup/utils/mkpasswd.c
+++ b/winsup/utils/mkpasswd.c
@@ -1,7 +1,7 @@
/* mkpasswd.c:
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2009,
- 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
+ 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
@@ -21,7 +21,6 @@
#include <inttypes.h>
#include <getopt.h>
#include <io.h>
-#include <pwd.h>
#include <sys/fcntl.h>
#include <sys/cygwin.h>
#include <cygwin/version.h>
@@ -32,6 +31,7 @@
#include <ntsecapi.h>
#include <dsgetdc.h>
#include <ntdef.h>
+#include "loadlib.h"
#define print_win_error(x) _print_win_error(x, __LINE__)
@@ -47,7 +47,9 @@ SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY};
typedef struct
{
char *str;
+ DWORD id_offset;
BOOL domain;
+ BOOL with_dom;
} domlist_t;
static void
@@ -68,6 +70,31 @@ _print_win_error(DWORD code, int line)
line, (unsigned int) code);
}
+static PWCHAR
+get_dcname (char *domain)
+{
+ static WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ DWORD rc;
+ WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1];
+ PDOMAIN_CONTROLLER_INFOW pdci = NULL;
+
+ if (domain)
+ {
+ mbstowcs (domain_name, domain, strlen (domain) + 1);
+ rc = DsGetDcNameW (NULL, domain_name, NULL, NULL, 0, &pdci);
+ }
+ else
+ rc = DsGetDcNameW (NULL, NULL, NULL, NULL, 0, &pdci);
+ if (rc != ERROR_SUCCESS)
+ {
+ print_win_error (rc);
+ return (PWCHAR) -1;
+ }
+ wcscpy (server, pdci->DomainControllerName);
+ NetApiBufferFree (pdci);
+ return server;
+}
+
static char *
put_sid (PSID sid)
{
@@ -123,10 +150,72 @@ fetch_current_user_sid ()
}
static void
-enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
+current_user (const char *sep, const char *passed_home_path, DWORD id_offset,
+ const char *disp_username)
+{
+ WCHAR user[UNLEN + 1];
+ WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
+ DWORD ulen = UNLEN + 1;
+ DWORD dlen = MAX_DOMAIN_NAME_LEN + 1;
+ SID_NAME_USE acc_type;
+ int uid, gid;
+ char homedir_psx[PATH_MAX] = {0};
+
+ if (!curr_user.psid || !curr_pgrp.psid
+ || !LookupAccountSidW (NULL, curr_user.psid, user, &ulen, dom, &dlen,
+ &acc_type))
+ {
+ print_win_error (GetLastError ());
+ return;
+ }
+
+ uid = *GetSidSubAuthority (curr_user.psid,
+ *GetSidSubAuthorityCount(curr_user.psid) - 1);
+ gid = *GetSidSubAuthority (curr_pgrp.psid,
+ *GetSidSubAuthorityCount(curr_pgrp.psid) - 1);
+ if (passed_home_path[0] == '\0')
+ {
+ char *envhome = getenv ("HOME");
+
+ /* If $HOME exists and is non-empty, just copy it over to homedir_psx.
+ Otherwise, generate a new path of the form "/home/$USER". */
+ if (envhome && envhome[0] != '\0')
+ strncat (homedir_psx, envhome, sizeof (homedir_psx) - 1);
+ else
+ {
+ wcstombs (stpncpy (homedir_psx, "/home/", sizeof (homedir_psx)),
+ user, sizeof (homedir_psx) - 6);
+ homedir_psx[PATH_MAX - 1] = '\0';
+ }
+ }
+ else
+ {
+ char *p = stpncpy (homedir_psx, passed_home_path, sizeof (homedir_psx));
+ wcstombs (p, user, sizeof (homedir_psx) - (p - homedir_psx));
+ homedir_psx[PATH_MAX - 1] = '\0';
+ }
+
+ printf ("%ls%s%ls:unused:%" PRIu32 ":%" PRIu32
+ ":U-%ls\\%ls,%s:%s:/bin/bash\n",
+ sep ? dom : L"",
+ sep ?: "",
+ user,
+ (unsigned int) (id_offset + uid),
+ (unsigned int) (id_offset + gid),
+ dom,
+ user,
+ put_sid (curr_user.psid),
+ homedir_psx);
+}
+
+static void
+enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset,
char *unix_user_list)
{
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ PWCHAR servername = NULL;
+ char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL;
+ BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE;
SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } };
char *ustr, *user_list;
WCHAR user[UNLEN + sizeof ("Unix User\\") + 1];
@@ -136,13 +225,17 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
char psid_buffer[MAX_SID_LEN];
SID_NAME_USE acc_type;
- int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
+ if (!d_or_m)
+ return;
+
+ int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
{
fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
- program_invocation_short_name, mach->str);
+ program_invocation_short_name, d_or_m);
return;
}
+ servername = machine;
if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid))
return;
@@ -162,15 +255,15 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
if (ret < 1 || ret >= UNLEN + 1)
fprintf (stderr, "%s: Invalid user name '%s'. Skipping...\n",
program_invocation_short_name, ustr);
- else if (LookupAccountNameW (machine, user,
+ else if (LookupAccountNameW (servername, user,
psid = (PSID) psid_buffer,
(sidlen = MAX_SID_LEN, &sidlen),
dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type))
printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n",
- "Unix_User",
- sep,
+ with_dom ? "Unix User" : "",
+ with_dom ? sep : "",
user + 10,
(unsigned int) (id_offset +
*GetSidSubAuthority (psid,
@@ -199,15 +292,15 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
{
*GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1)
= start;
- if (LookupAccountSidW (machine, psid,
+ if (LookupAccountSidW (servername, psid,
user, (ulen = GNLEN + 1, &ulen),
dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type)
&& !iswdigit (user[0]))
printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n",
- "Unix_User",
- sep,
+ with_dom ? "Unix User" : "",
+ with_dom ? sep : "",
user,
(unsigned int) (id_offset + start),
put_sid (psid));
@@ -220,23 +313,36 @@ enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset,
}
static int
-enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
- DWORD id_offset, char *disp_username, int print_current)
+enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep,
+ const char *passed_home_path, DWORD id_offset, char *disp_username,
+ int print_current)
{
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ PWCHAR servername = NULL;
+ char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL;
+ BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE;
USER_INFO_3 *buffer;
DWORD entriesread = 0;
DWORD totalentries = 0;
DWORD resume_handle = 0;
DWORD rc;
WCHAR uni_name[UNLEN + 1];
-
- int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
- if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
+ if (domain)
{
- fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
- program_invocation_short_name, mach->str);
- return 1;
+ servername = get_dcname (d_or_m);
+ if (servername == (PWCHAR) -1)
+ return 1;
+ }
+ else if (d_or_m)
+ {
+ int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
+ if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
+ {
+ fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
+ program_invocation_short_name, d_or_m);
+ return 1;
+ }
+ servername = machine;
}
do
@@ -246,7 +352,7 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
if (disp_username != NULL)
{
mbstowcs (uni_name, disp_username, UNLEN + 1);
- rc = NetUserGetInfo (machine, (LPWSTR) &uni_name, 3,
+ rc = NetUserGetInfo (servername, (LPWSTR) &uni_name, 3,
(void *) &buffer);
entriesread = 1;
/* Avoid annoying error messages just because the user hasn't been
@@ -255,7 +361,7 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
return 0;
}
else
- rc = NetUserEnum (machine, 3, FILTER_NORMAL_ACCOUNT,
+ rc = NetUserEnum (servername, 3, FILTER_NORMAL_ACCOUNT,
(void *) &buffer, MAX_PREFERRED_LENGTH,
&entriesread, &totalentries, &resume_handle);
switch (rc)
@@ -301,7 +407,7 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
stpcpy (homedir_psx, passed_home_path),
PATH_MAX - strlen (passed_home_path));
- if (!LookupAccountNameW (machine, buffer[i].usri3_name,
+ if (!LookupAccountNameW (servername, buffer[i].usri3_name,
psid, &sid_length, domain_name,
&domname_len, &acc_type))
{
@@ -313,12 +419,13 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
{
WCHAR domname[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
- wcscpy (domname, machine);
+ wcscpy (domname, domain || !servername
+ ? domain_name : servername);
wcscat (domname, L"\\");
wcscat (domname, buffer[i].usri3_name);
sid_length = MAX_SID_LEN;
domname_len = sizeof (domname);
- if (!LookupAccountNameW (machine, domname, psid,
+ if (!LookupAccountNameW (servername, domname, psid,
&sid_length, domain_name,
&domname_len, &acc_type))
{
@@ -334,8 +441,8 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
printf ("%ls%s%ls:unused:%" PRIu32 ":%" PRIu32
":%ls%sU-%ls\\%ls,%s:%s:/bin/bash\n",
- domain_name,
- sep,
+ with_dom ? domain_name : L"",
+ with_dom ? sep : "",
buffer[i].usri3_name,
(unsigned int) (id_offset + uid),
(unsigned int) (id_offset + gid),
@@ -356,49 +463,98 @@ enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
return 0;
}
+static void
+print_special_by_sid (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt,
+ DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4,
+ DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8)
+{
+ WCHAR user[UNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1];
+ DWORD len, len2, rid;
+ PSID sid;
+ SID_NAME_USE acc_type;
+
+ if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4,
+ sub5, sub6, sub7, sub8, &sid))
+ {
+ if (LookupAccountSidW (NULL, sid,
+ user, (len = UNLEN + 1, &len),
+ dom, (len2 = MAX_DOMAIN_NAME_LEN + 1, &len2),
+ &acc_type))
+ {
+ if (sub8)
+ rid = sub8;
+ else if (sub7)
+ rid = sub7;
+ else if (sub6)
+ rid = sub6;
+ else if (sub5)
+ rid = sub5;
+ else if (sub4)
+ rid = sub4;
+ else if (sub3)
+ rid = sub3;
+ else if (sub2)
+ rid = sub2;
+ else
+ rid = sub1;
+ printf ("%ls:*:%" PRIu32 ":%" PRIu32 ":,%s::\n",
+ user, (unsigned int) rid,
+ (unsigned int) (rid == 18 ? 544 : rid), /* SYSTEM hack */
+ put_sid (sid));
+ }
+ FreeSid (sid);
+ }
+}
+
static int
usage (FILE * stream)
{
fprintf (stream,
"Usage: %s [OPTIONS]...\n"
"\n"
-"Write /etc/passwd-like output to stdout\n"
-"\n"
-"Don't use this command to generate a local /etc/passwd file, unless you\n"
-"really need one. See the Cygwin User's Guide for more information.\n"
+"Print /etc/passwd file to stdout\n"
"\n"
"Options:\n"
"\n"
-" -l,--local [machine] print local user accounts of \"machine\"\n"
+" -l,--local [machine[,offset]]\n"
+" print local user accounts with uid offset offset\n"
" (from local machine if no machine specified)\n"
-" -d,--domain [domain] print domain accounts\n"
+" -L,--Local [machine[,offset]]\n"
+" ditto, but generate username with machine prefix\n"
+" -d,--domain [domain[,offset]]\n"
+" print domain accounts with uid offset offset\n"
" (from current domain if no domain specified)\n"
+" -D,--Domain [domain[,offset]]\n"
+" ditto, but generate username with domain prefix\n"
" -c,--current print current user\n"
-" -S,--separator char for -l use character char as domain\\user\n"
-" separator in username instead of the default '%s'\n"
-" -o,--id-offset offset change the default offset (0x10000) added to uids\n"
-" of foreign local machine accounts. Use with -l.\n"
+" -C,--Current ditto, but generate username with machine or\n"
+" domain prefix\n"
+" -S,--separator char for -L, -D, -C use character char as domain\\user\n"
+" separator in username instead of the default '\\'\n"
+" -o,--id-offset offset change the default offset (10000) added to uids\n"
+" in domain or foreign server accounts.\n"
" -u,--username username only return information for the specified user\n"
-" one of -l, -d must be specified, too\n"
-" -b,--no-builtin don't print BUILTIN users\n"
+" one of -l, -L, -d, -D must be specified, too\n"
" -p,--path-to-home path use specified path instead of user account home dir\n"
" or /home prefix\n"
-" -U,--unix userlist print UNIX users when using -l on a UNIX Samba\n"
-" server. userlist is a comma-separated list of\n"
-" usernames or uid ranges (root,-25,50-100).\n"
+" -U,--unix userlist additionally print UNIX users when using -l or -L\n"
+" on a UNIX Samba server\n"
+" userlist is a comma-separated list of usernames\n"
+" or uid ranges (root,-25,50-100).\n"
" (enumerating large ranges can take a long time!)\n"
+" -s,--no-sids (ignored)\n"
+" -m,--no-mount (ignored)\n"
+" -g,--local-groups (ignored)\n"
" -h,--help displays this message\n"
" -V,--version version information and exit\n"
"\n"
"Default is to print local accounts on stand-alone machines, domain accounts\n"
"on domain controllers and domain member machines.\n"
-"\n", program_invocation_short_name,
- (const char *) cygwin_internal (CW_GETNSSSEP));
+"\n", program_invocation_short_name);
return 1;
}
static struct option longopts[] = {
- {"no-builtin", no_argument, NULL, 'b'},
{"current", no_argument, NULL, 'c'},
{"Current", no_argument, NULL, 'C'},
{"domain", optional_argument, NULL, 'd'},
@@ -418,7 +574,7 @@ static struct option longopts[] = {
{0, no_argument, NULL, 0}
};
-static char opts[] = "bcCd::D::ghl::L::mo:sS:p:u:U:V";
+static char opts[] = "cCd::D::ghl::L::mo:sS:p:u:U:V";
static void
print_version ()
@@ -434,6 +590,66 @@ print_version ()
strrchr (__DATE__, ' ') + 1);
}
+static void
+print_special_by_name (PCWSTR name, uid_t uid, gid_t gid)
+{
+ DWORD size = 256, dom_size = 256;
+ PSID sid = (PSID) alloca (size);
+ WCHAR dom[dom_size];
+ SID_NAME_USE use;
+
+ PWCHAR name_only = wcschr (name, L'\\');
+ if (name_only)
+ ++name_only;
+
+ if (LookupAccountNameW (NULL, name, sid, &size, dom, &dom_size, &use))
+ printf ("%ls:*:%lu:%lu:U-%ls%s%ls,%s::\n",
+ name_only ?: name,
+ (unsigned long) uid,
+ (unsigned long) gid,
+ name_only ? dom : L"",
+ name_only ? "\\" : "",
+ name_only ?: name,
+ put_sid (sid));
+}
+
+static void
+enum_std_accounts ()
+{
+ /* Generate service starter account entries. */
+ printf ("SYSTEM:*:18:544:,S-1-5-18::\n");
+ printf ("LocalService:*:19:544:U-NT AUTHORITY\\LocalService,S-1-5-19::\n");
+ printf ("NetworkService:*:20:544:U-NT AUTHORITY\\NetworkService,S-1-5-20::\n");
+ /* Get 'administrators' group (has localized name). */
+ print_special_by_sid (&sid_nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0);
+ /* Fetch "TrustedInstaller" account starting with Vista. */
+ print_special_by_name (L"NT SERVICE\\TrustedInstaller", -2, -2);
+}
+
+static PPOLICY_PRIMARY_DOMAIN_INFO p_dom;
+
+static BOOL
+fetch_primary_domain ()
+{
+ NTSTATUS status;
+ LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 };
+ LSA_HANDLE lsa;
+
+ if (!p_dom)
+ {
+ status = LsaOpenPolicy (NULL, &oa, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
+ if (!NT_SUCCESS (status))
+ return FALSE;
+ status = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation,
+ (PVOID *) ((void *) &p_dom));
+ LsaClose (lsa);
+ if (!NT_SUCCESS (status))
+ return FALSE;
+ }
+ return !!p_dom->Sid;
+}
+
int
main (int argc, char **argv)
{
@@ -441,14 +657,13 @@ main (int argc, char **argv)
domlist_t domlist[32];
char *opt, *p, *ep;
int print_current = 0;
- int print_builtin = 1;
char *print_unix = NULL;
- const char *nss_sep = (const char *) cygwin_internal (CW_GETNSSSEP);
- const char *sep_char = nss_sep;
- DWORD id_offset = 0x10000, off;
+ const char *sep_char = "\\";
+ DWORD id_offset = 10000, off;
int c, i;
char *disp_username = NULL;
char passed_home_path[PATH_MAX];
+ BOOL in_domain;
int optional_args = 0;
passed_home_path[0] = '\0';
@@ -459,23 +674,18 @@ main (int argc, char **argv)
setlocale (LC_CTYPE, "");
if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
setlocale (LC_CTYPE, "en_US.UTF-8");
+ in_domain = fetch_primary_domain ();
fetch_current_user_sid ();
if (argc == 1)
{
- int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN;
- uintptr_t ticket = cygwin_internal (CW_SETENT, FALSE, enums, NULL);
- if (ticket)
- {
- struct passwd *pwd;
-
- while ((pwd = (struct passwd *) cygwin_internal (CW_GETENT, FALSE,
- ticket)))
- printf ("%s:%s:%u:%u:%s:%s:%s\n", pwd->pw_name, pwd->pw_passwd,
- pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
- pwd->pw_shell);
- cygwin_internal (CW_ENDENT, FALSE, ticket);
- }
+ enum_std_accounts ();
+ if (in_domain)
+ enum_users (TRUE, NULL, sep_char, passed_home_path, 10000,
+ disp_username, 0);
+ else
+ enum_users (FALSE, NULL, sep_char, passed_home_path, 0,
+ disp_username, 0);
return 0;
}
@@ -511,40 +721,32 @@ main (int argc, char **argv)
program_invocation_short_name,
domlist[i].domain ? "domain" : "machine",
domlist[i].str);
- break;
+ goto skip;
}
domlist[print_domlist].str = opt;
+ domlist[print_domlist].id_offset = UINT32_MAX;
if (opt && (p = strchr (opt, ',')))
{
- if (p == opt)
+ if (p == opt
+ || !isdigit ((unsigned char) p[1])
+ || (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10)
+ , *ep))
{
- fprintf (stderr, "%s: Malformed domain string '%s'. "
+ fprintf (stderr, "%s: Malformed domain,offset string '%s'. "
"Skipping...\n", program_invocation_short_name, opt);
break;
}
*p = '\0';
}
- if ((c == 'l' || c == 'L') && opt)
- {
- char cname[1024];
- DWORD csize = sizeof cname;
-
- /* Check if machine name is local machine. Keep it simple. */
- if (GetComputerNameExA (strchr (opt, '.')
- ? ComputerNameDnsFullyQualified
- : ComputerNameNetBIOS,
- cname, &csize)
- && strcasecmp (opt, cname) == 0)
- domlist[print_domlist].str = NULL;
- }
- ++print_domlist;
+ domlist[print_domlist++].with_dom = (c == 'D' || c == 'L');
+skip:
break;
case 'S':
sep_char = optarg;
if (strlen (sep_char) > 1)
{
- fprintf (stderr, "%s: Only one ASCII character allowed as "
- "domain\\user separator character.\n",
+ fprintf (stderr, "%s: Only one character allowed as domain\\user "
+ "separator character.\n",
program_invocation_short_name);
return 1;
}
@@ -559,14 +761,19 @@ main (int argc, char **argv)
print_unix = optarg;
break;
case 'c':
+ sep_char = NULL;
+ /*FALLTHRU*/
case 'C':
print_current = 1;
break;
case 'o':
id_offset = strtoul (optarg, &ep, 10);
- break;
- case 'b':
- print_builtin = 0;
+ if (*ep)
+ {
+ fprintf (stderr, "%s: Malformed offset '%s'. "
+ "Skipping...\n", program_invocation_short_name, optarg);
+ return 1;
+ }
break;
case 'p':
if (optarg[0] != '/')
@@ -607,91 +814,24 @@ main (int argc, char **argv)
exit (1);
}
- struct passwd *ppwd = NULL;
- const char *ppwd_sid = NULL;
- if (print_current)
- {
- ppwd = (struct passwd *) cygwin_internal (CW_GETPWSID, TRUE,
- curr_user.psid);
- if (ppwd)
- ppwd_sid = strrchr (ppwd->pw_gecos, ',');
- }
-
- int enums = ENUM_NONE;
- WCHAR tdoms[print_domlist * 258];
- PWCHAR t = tdoms;
- if (!disp_username && print_builtin && print_domlist)
- enums |= ENUM_BUILTIN;
+ off = id_offset;
for (i = 0; i < print_domlist; ++i)
{
- if (domlist[i].domain)
- {
- if (domlist[i].str)
- {
- enums |= ENUM_TDOMS;
- t += mbstowcs (t, domlist[i].str, 257);
- *t++ = L'\0';
- }
- else
- enums |= ENUM_PRIMARY;
- }
- else if (!domlist[i].str)
- enums |= ENUM_LOCAL;
- }
- if (t > tdoms)
- *t++ = L'\0';
- if (enums)
- {
- uintptr_t ticket = cygwin_internal (CW_SETENT, FALSE, enums,
- t > tdoms ? tdoms : NULL);
- if (ticket)
- {
- struct passwd *pwd;
-
- while ((pwd = (struct passwd *)
- cygwin_internal (CW_GETENT, FALSE, ticket)))
- {
- p = NULL;
- if (disp_username
- && strcasecmp (disp_username, pwd->pw_name) != 0
- && (!(p = strchr (pwd->pw_name, nss_sep[0]))
- || strcasecmp (disp_username, p + 1) != 0))
- continue;
- printf ("%s:%s:%u:%u:%s:%s%s:%s\n", pwd->pw_name, pwd->pw_passwd,
- pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos,
- passed_home_path[0] ? passed_home_path : "",
- passed_home_path[0] ? (p ? p + 1 : pwd->pw_name)
- : pwd->pw_dir,
- pwd->pw_shell);
- const char *pwd_sid = strrchr (pwd->pw_gecos, ',');
- if (ppwd && ppwd_sid && pwd_sid && !strcmp (pwd_sid, ppwd_sid))
- got_curr_user = TRUE;
- }
- cygwin_internal (CW_ENDENT, FALSE, ticket);
- }
+ DWORD my_off = (domlist[i].domain || domlist[i].str)
+ ? domlist[i].id_offset != UINT_MAX
+ ? domlist[i].id_offset : off : 0;
+ if (!domlist[i].domain && domlist[i].str && print_unix)
+ enum_unix_users (domlist + i, sep_char, my_off, print_unix);
+ if (!my_off && !disp_username)
+ enum_std_accounts ();
+ enum_users (domlist[i].domain, domlist + i, sep_char, passed_home_path,
+ my_off, disp_username, print_current);
+ if (my_off)
+ off += id_offset;
}
if (print_current && !got_curr_user)
- {
- p = strchr (ppwd->pw_name, nss_sep[0]);
- printf ("%s:%s:%u:%u:%s:%s%s:%s\n", ppwd->pw_name, ppwd->pw_passwd,
- ppwd->pw_uid, ppwd->pw_gid, ppwd->pw_gecos,
- passed_home_path[0] ? passed_home_path : "",
- passed_home_path[0] ? (p ? p + 1 : ppwd->pw_name) : ppwd->pw_dir,
- ppwd->pw_shell);
- }
-
- off = 0xfd000000;
- for (i = 0; i < print_domlist; ++i)
- {
- if (domlist[i].domain || !domlist[i].str)
- continue;
- enum_users (domlist + i, sep_char, passed_home_path, off, disp_username,
- print_current);
- if (!domlist[i].domain && domlist[i].str && print_unix)
- enum_unix_users (domlist + i, sep_char, 0xff000000, print_unix);
- off += id_offset;
- }
+ current_user (sep_char, passed_home_path, off, disp_username);
return 0;
}
diff --git a/winsup/utils/passwd.c b/winsup/utils/passwd.c
index 2046849a1..991935a2a 100644
--- a/winsup/utils/passwd.c
+++ b/winsup/utils/passwd.c
@@ -1,7 +1,7 @@
/* passwd.c: Changing passwords and managing account information
Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2011, 2012,
- 2013, 2014 Red Hat, Inc.
+ 2013 Red Hat, Inc.
Written by Corinna Vinschen <corinna.vinschen@cityweb.de>
@@ -84,7 +84,7 @@ EvalRet (int ret, const char *user)
return 0;
case ERROR_ACCESS_DENIED:
- if (!user)
+ if (! user)
eprint (0, "You may not change password expiry information.");
else
eprint (0, "You may not change the password for %s.", user);
@@ -153,7 +153,7 @@ ChangePW (const char *user, const char *oldpwd, const char *pwd, int justcheck,
mbstowcs (name, user, UNLEN + 1);
mbstowcs (pass, pwd, 512);
- if (!oldpwd)
+ if (! oldpwd)
{
USER_INFO_1003 ui;
@@ -167,8 +167,10 @@ ChangePW (const char *user, const char *oldpwd, const char *pwd, int justcheck,
}
if (justcheck && ret != ERROR_INVALID_PASSWORD)
return 0;
- if (!EvalRet (ret, user) && !justcheck)
- eprint (0, "Password changed.");
+ if (! EvalRet (ret, user) && ! justcheck)
+ {
+ eprint (0, "Password changed.");
+ }
return ret;
}
@@ -191,7 +193,7 @@ PrintPW (PUSER_INFO_3 ui, LPCWSTR server)
(ui->usri3_password_expired) ? "yes\n" : "no\n");
printf ("Latest password change : %s", ctime(&t));
ret = NetUserModalsGet (server, 0, (void *) &mi);
- if (!ret)
+ if (! ret)
{
if (mi->usrmod0_max_passwd_age == TIMEQ_FOREVER)
mi->usrmod0_max_passwd_age = 0;
@@ -220,7 +222,7 @@ SetModals (int xarg, int narg, int iarg, int Larg, LPCWSTR server)
PUSER_MODALS_INFO_0 mi;
ret = NetUserModalsGet (server, 0, (void *) &mi);
- if (!ret)
+ if (! ret)
{
if (xarg == 0)
mi->usrmod0_max_passwd_age = TIMEQ_FOREVER;
@@ -275,8 +277,8 @@ usage (FILE * stream, int status)
"System operations:\n"
" -i, --inactive NUM set NUM of days before inactive accounts are disabled\n"
" (inactive accounts are those with expired passwords).\n"
- " -n, --minage MINDAYS set system minimum password age to MINDAYS days.\n"
- " -x, --maxage MAXDAYS set system maximum password age to MAXDAYS days.\n"
+ " -n, --minage DAYS set system minimum password age to DAYS days.\n"
+ " -x, --maxage DAYS set system maximum password age to DAYS days.\n"
" -L, --length LEN set system minimum password length to LEN.\n"
"\n"
"Other options:\n"
@@ -591,7 +593,7 @@ main (int argc, char **argv)
}
ui = GetPW (user, 1, server);
- if (!ui)
+ if (! ui)
return 1;
if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt)
@@ -634,6 +636,9 @@ main (int argc, char **argv)
if (!caller_is_admin () && !myself)
return eprint (0, "You may not change the password for %s.", user);
+ eprint (0, "Enter the new password (minimum of 5, maximum of 8 characters).");
+ eprint (0, "Please use a combination of upper and lower case letters and numbers.");
+
oldpwd[0] = '\0';
if (!caller_is_admin ())
{
@@ -647,11 +652,11 @@ main (int argc, char **argv)
strcpy (newpwd, getpass ("New password: "));
if (strcmp (newpwd, getpass ("Re-enter new password: ")))
eprint (0, "Password is not identical.");
- else if (!ChangePW (user, *oldpwd ? oldpwd : NULL, newpwd, 0, server))
+ else if (! ChangePW (user, *oldpwd ? oldpwd : NULL, newpwd, 0, server))
ret = 1;
- if (!ret && cnt < 2)
+ if (! ret && cnt < 2)
eprint (0, "Try again.");
}
- while (!ret && ++cnt < 3);
- return !ret;
+ while (! ret && ++cnt < 3);
+ return ! ret;
}
diff --git a/winsup/utils/setfacl.c b/winsup/utils/setfacl.c
index 9051fb355..66739c043 100644
--- a/winsup/utils/setfacl.c
+++ b/winsup/utils/setfacl.c
@@ -1,7 +1,6 @@
/* setfacl.c
- Copyright 2000, 2001, 2002, 2003, 2006, 2008, 2009, 2010, 2011, 2014
- Red Hat Inc.
+ Copyright 2000, 2001, 2002, 2003, 2006, 2008, 2009, 2010, 2011 Red Hat Inc.
Written by Corinna Vinschen <vinschen@redhat.com>
@@ -48,7 +47,6 @@ typedef enum {
Modify,
Delete,
ModNDel,
- DeleteAll,
SetFromFile
} action_t;
@@ -109,22 +107,16 @@ getaclentry (action_t action, char *c, aclent_t *ace)
return FALSE;
/* Skip to next field. */
c = c2;
- if (!*c)
- {
- /* Nothing follows. This is only valid if action is Delete and the
- type is CLASS_OBJ, or if ACL_DEFAULT is set. */
- if (action != Delete
- || (!(ace->a_type & (CLASS_OBJ | ACL_DEFAULT))))
- return FALSE;
- }
- else if (!(ace->a_type & (USER_OBJ | GROUP_OBJ)))
+ if (!*c && action != Delete)
+ return FALSE;
+ /* If this is a user or group entry, check if next char is a colon char.
+ If so, skip it, otherwise it's the name of a user or group. */
+ if (!(ace->a_type & (USER_OBJ | GROUP_OBJ)))
{
/* Mask and other entries may contain an extra colon. */
if (*c == ':')
++c;
}
- /* If this is a user or group entry, check if next char is a colon char.
- If so, skip it, otherwise it's the name of a user or group. */
else if (*c == ':')
++c;
else if (*c)
@@ -138,6 +130,8 @@ getaclentry (action_t action, char *c, aclent_t *ace)
*c2++ = '\0';
else if (action != Delete)
return FALSE;
+ else if (!(ace->a_type & ACL_DEFAULT))
+ return FALSE;
/* Fetch user/group id. */
if (isdigit ((unsigned char) *c))
{
@@ -268,130 +262,26 @@ modacl (aclent_t *tgt, int tcnt, aclent_t *src, int scnt)
}
int
-addmissing (aclent_t *tgt, int tcnt)
-{
- int t;
- int types = 0, def_types = 0;
- int perm = 0, def_perm = 0;
-
- /* Check if we have all the required entries now. */
- for (t = 0; t < tcnt; ++t)
- if (tgt[t].a_type & ACL_DEFAULT)
- {
- def_types |= tgt[t].a_type;
- if (tgt[t].a_type & (USER | GROUP | GROUP_OBJ))
- def_perm |= tgt[t].a_perm;
- }
- else
- {
- types |= tgt[t].a_type;
- if (tgt[t].a_type & (USER | GROUP | GROUP_OBJ))
- perm |= tgt[t].a_perm;
- }
- /* Add missing CLASS_OBJ */
- if ((types & (USER | GROUP)) && !(types & CLASS_OBJ))
- {
- tgt[tcnt].a_type = CLASS_OBJ;
- tgt[tcnt].a_id = (uid_t) -1;
- tgt[tcnt++].a_perm = perm;
- }
- if (def_types)
- {
- /* Add missing default entries. */
- if (!(def_types & USER_OBJ) && tcnt < MAX_ACL_ENTRIES)
- {
- t = searchace (tgt, tcnt, USER_OBJ, -1);
- tgt[tcnt].a_type = DEF_USER_OBJ;
- tgt[tcnt].a_id = (uid_t) -1;
- tgt[tcnt++].a_perm = t >= 0 ? tgt[t].a_perm : S_IRWXO;
- }
- if (!(def_types & GROUP_OBJ) && tcnt < MAX_ACL_ENTRIES)
- {
- t = searchace (tgt, tcnt, GROUP_OBJ, -1);
- tgt[tcnt].a_type = DEF_GROUP_OBJ;
- tgt[tcnt].a_id = (uid_t) -1;
- tgt[tcnt].a_perm = t >= 0 ? tgt[t].a_perm : (S_IROTH | S_IXOTH);
- def_perm |= tgt[tcnt++].a_perm;
- }
- if (!(def_types & OTHER_OBJ) && tcnt < MAX_ACL_ENTRIES)
- {
- t = searchace (tgt, tcnt, OTHER_OBJ, -1);
- tgt[tcnt].a_type = DEF_OTHER_OBJ;
- tgt[tcnt].a_id = (uid_t) -1;
- tgt[tcnt++].a_perm = t >= 0 ? tgt[t].a_perm : (S_IROTH | S_IXOTH);
- }
- /* Add missing DEF_CLASS_OBJ */
- if ((def_types & (USER | GROUP)) && !(def_types & CLASS_OBJ))
- {
- tgt[tcnt].a_type = DEF_CLASS_OBJ;
- tgt[tcnt].a_id = (uid_t) -1;
- tgt[tcnt++].a_perm = def_perm;
- }
- }
- return tcnt;
-}
-
-int
-delacl (aclent_t *tgt, int tcnt)
-{
- int t;
-
- /* Remove all extended ACL entries. */
- for (t = 0; t < tcnt; ++t)
- if (tgt[t].a_type & (USER | GROUP | CLASS_OBJ))
- {
- --tcnt;
- if (t < tcnt)
- memmove (&tgt[t], &tgt[t + 1], (tcnt - t) * sizeof (aclent_t));
- --t;
- }
- return tcnt;
-}
-
-int
-setfacl (action_t action, const char *path, aclent_t *acls, int cnt)
+setfacl (action_t action, char *path, aclent_t *acls, int cnt)
{
aclent_t lacl[MAX_ACL_ENTRIES];
int lcnt;
memset (lacl, 0, sizeof lacl);
- switch (action)
+ if (action == Set)
{
- case Set:
if (acl (path, SETACL, cnt, acls))
{
perror (prog_name);
return 2;
}
- break;
- case Delete:
- if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0
- || (lcnt = modacl (lacl, lcnt, acls, cnt)) < 0
- || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0)
- {
- perror (prog_name);
- return 2;
- }
- break;
- case DeleteAll:
- if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0
- || (lcnt = delacl (lacl, lcnt)) < 0
- || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0)
- {
- perror (prog_name);
- return 2;
- }
- break;
- default:
- if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0
- || (lcnt = modacl (lacl, lcnt, acls, cnt)) < 0
- || (lcnt = addmissing (lacl, lcnt)) < 0
- || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0)
- {
- perror (prog_name);
- return 2;
- }
- break;
+ }
+ else if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0
+ || (lcnt = modacl (lacl, lcnt, acls, cnt)) < 0
+ || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0)
+ {
+ perror (prog_name);
+ return 2;
}
return 0;
}
@@ -400,12 +290,11 @@ static void
usage (FILE * stream)
{
fprintf (stream, ""
- "Usage: %s [-r] {-f ACL_FILE | -s acl_entries} FILE...\n"
- " %s [-r] {-b|[-d acl_entries] [-m acl_entries]} FILE...\n"
+ "Usage: %s [-r] (-f ACL_FILE | -s acl_entries) FILE...\n"
+ " %s [-r] ([-d acl_entries] [-m acl_entries]) FILE...\n"
"\n"
"Modify file and directory access control lists (ACLs)\n"
"\n"
- " -b, --remove-all remove all extended ACL entries\n"
" -d, --delete delete one or more specified ACL entries\n"
" -f, --file set ACL entries for FILE to ACL entries read\n"
" from a ACL_FILE\n"
@@ -417,7 +306,7 @@ usage (FILE * stream)
" -h, --help output usage information and exit\n"
" -V, --version output version information and exit\n"
"\n"
- "At least one of (-b, -d, -f, -m, -s) must be specified\n"
+ "At least one of (-d, -f, -m, -s) must be specified\n"
"\n", prog_name, prog_name);
if (stream == stdout)
{
@@ -451,21 +340,17 @@ usage (FILE * stream)
"\n"
"The following options are supported:\n"
"\n"
- "-b Remove all extended ACL entries. The base ACL entries of the\n"
- " owner, group and others are retained.\n"
- "\n"
"-d Delete one or more specified entries from the file's ACL.\n"
" The owner, group and others entries must not be deleted.\n"
" Acl_entries to be deleted should be specified without\n"
" permissions, as in the following list:\n"
"\n"
- " u[ser]:uid[:]\n"
- " g[roup]:gid[:]\n"
- " m[ask][:]\n"
- " d[efault]:u[ser][:uid]\n"
- " d[efault]:g[roup][:gid]\n"
- " d[efault]:m[ask][:]\n"
- " d[efault]:o[ther][:]\n"
+ " u[ser]:uid\n"
+ " g[roup]:gid\n"
+ " d[efault]:u[ser]:uid\n"
+ " d[efault]:g[roup]:gid\n"
+ " d[efault]:m[ask]:\n"
+ " d[efault]:o[ther]:\n"
"\n"
"-f Take the Acl_entries from ACL_FILE one per line. Whitespace\n"
" characters are ignored, and the character \"#\" may be used\n"
@@ -502,14 +387,14 @@ usage (FILE * stream)
"in a directory that contains default ACL entries will have\n"
"permissions according to the combination of the current umask,\n"
"the explicit permissions requested and the default ACL entries\n"
- "\n", prog_name);
+ "Note: Under Cygwin, the default ACL entries are not taken into\n"
+ "account currently.\n\n", prog_name);
}
else
fprintf(stream, "Try '%s --help' for more information.\n", prog_name);
}
struct option longopts[] = {
- {"remove-all", no_argument, NULL, 'b'},
{"delete", required_argument, NULL, 'd'},
{"file", required_argument, NULL, 'f'},
{"modify", required_argument, NULL, 'm'},
@@ -519,7 +404,7 @@ struct option longopts[] = {
{"version", no_argument, NULL, 'V'},
{0, no_argument, NULL, 0}
};
-const char *opts = "bd:f:hm:rs:V";
+const char *opts = "d:f:hm:rs:V";
static void
print_version ()
@@ -551,15 +436,6 @@ main (int argc, char **argv)
while ((c = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
switch (c)
{
- case 'b':
- if (action == NoAction)
- action = DeleteAll;
- else
- {
- usage (stderr);
- return 1;
- }
- break;
case 'd':
if (action == NoAction)
action = Delete;
diff --git a/winsup/doc/utils.xml b/winsup/utils/utils.xml
index 0e146d8b7..b7e8ff81d 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/utils/utils.xml
@@ -535,16 +535,14 @@ line separates the ACLs for each file.
<command>getfacl</command> displays the owner, the group, and the ACL.
For directories <command>getfacl</command> displays additionally the
default ACL. With no options specified, <command>getfacl</command>
- displays the filename, the owner, the group, the setuid (s), setgid (s),
- and sticky (t) bits if available, and both the ACL and the default ACL,
- if it exists. For more information on Cygwin and Windows ACLs, see
- <xref linkend="ntsec"/> in the Cygwin User's Guide. The format
+ displays the filename, the owner, the group, and both the ACL and the
+ default ACL, if it exists. For more information on Cygwin and Windows
+ ACLs, see <xref linkend="ntsec"/> in the Cygwin User's Guide. The format
for ACL output is as follows:
<screen>
# file: filename
# owner: name or uid
# group: name or uid
- # flags: sst
user::perm
user:name or uid:perm
group::perm
@@ -877,77 +875,89 @@ Write minidump from WIN32PID to FILENAME.dmp
<screen>
Usage: mkgroup [OPTION]...
-Write /etc/group-like output to stdout
-
-Don't use this command to generate a local /etc/group file, unless you
-really need one. See the Cygwin User's Guide for more information.
+Print /etc/group file to stdout
Options:
- -l,--local [machine] print local groups
+ -l,--local [machine[,offset]]
+ print local groups with gid offset offset
(from local machine if no machine specified)
- -L,--Local machine ditto, but generate groupname with machine prefix
- -d,--domain [domain] print domain groups
+ -L,--Local [machine[,offset]]
+ ditto, but generate groupname with machine prefix
+ -d,--domain [domain[,offset]]
+ print domain groups with gid offset offset
(from current domain if no domain specified)
+ -D,--Domain [domain[,offset]]
+ ditto, but generate groupname with machine prefix
-c,--current print current group
- -S,--separator char for -l use character char as domain\group
- separator in groupname instead of default '+'
- -o,--id-offset offset change the default offset (0x10000) added to
- gids of foreign machine accounts.
+ -C,--Current ditto, but generate groupname with machine or
+ domain prefix
+ -S,--separator char for -L, -D, -C use character char as domain\group
+ separator in groupname instead of the default '\'
+ -o,--id-offset offset change the default offset (10000) added to gids
+ in domain or foreign server accounts.
-g,--group groupname only return information for the specified group
- one of -l, -d must be specified, too
+ one of -l, -L, -d, -D must be specified, too
-b,--no-builtin don't print BUILTIN groups
- -U,--unix grouplist print UNIX groups when using -l on a UNIX Samba
- server. grouplist is a comma-separated list of
- groupnames or gid ranges (root,-25,50-100).
- (enumerating large ranges can take a long time!)
+ -U,--unix grouplist additionally print UNIX groups when using -l or -L
+ on a UNIX Samba server
+ grouplist is a comma-separated list of groupnames
+ or gid ranges (root,-25,50-100).
+ (enumerating large ranges can take a long time!)
+ -s,--no-sids (ignored)
+ -u,--users (ignored)
-h,--help print this message
- -v,--version print version information and exit
+ -V,--version print version information and exit
Default is to print local groups on stand-alone machines, plus domain
groups on domain controllers and domain member machines.
</screen>
- <para>The <command>mkgroup</command> program can be used to create a local
- <filename>/etc/group</filename> file. Cygwin doesn't need this file,
- because it reads group information from the Windows account databases,
- but you can add an <filename>/etc/group</filename> file for instance, if
- your machine is often disconnected from its domain controller.
- </para>
-
- <para>Note that this information is static, in contrast to the information
- automatically gathered by Cygwin from the Windows account databases. If
- you change the group information on your system, you'll need to regenerate
- the group file for it to have the new information.</para>
-
- <para>By default, the information generated by <command>mkgroup</command>
- is equivalent to the information generated by Cygwin itself. The
- <literal>-d</literal> and <literal>-l/-L</literal> options allow you to
- specify where the information comes from, some domain, or the local SAM
- of a machine. Note that you can only enumerate accounts from trusted
- domains. Any non-trusted domain will be ignored. Access-restrictions
- of your current account apply. The <literal>-l/-L</literal> when used
- with a machine name, tries to contact that machine to enumerate local
- groups of other machines, typically outside of domains. This scenario
- cannot be covered by Cygwin's account automatism. If you want to use
- the <literal>-L</literal> option, but you don't like the default
- domain/group separator from <filename>/etc/nsswitch.conf</filename>,
- you can specify another separator using the <literal>-S</literal> option,
- for instance:</para>
+ <para>The <command>mkgroup</command> program can be used to help configure
+ Cygwin by creating a <filename>/etc/group</filename> file. Its use is
+ essential to include Windows security information.</para>
+
+ <para>The command is initially called by <command>setup.exe</command> to
+ create a default <filename>/etc/group</filename>. This should be
+ sufficient in most circumstances. However, especially when working in a
+ multi-domain environment, you can use <command>mkgroup</command> manually
+ to create a more complete <filename>/etc/group</filename> file for all
+ domains. Especially when you have the same group name used on multiple
+ machines or in multiple domains, you can use the <literal>-D</literal>,
+ <literal>-L</literal> and <literal>-C</literal> options to create unique
+ domain\group style groupnames.</para>
+
+ <para>Note that this information is static. If you change the group
+ information in your system, you'll need to regenerate the group file for
+ it to have the new information.</para>
+
+ <para>The <literal>-d/-D</literal> and <literal>-l/-L</literal> options
+ allow you to specify where the information comes from, the local SAM of a
+ machine or from the domain, or both. With the <literal>-d/-D</literal>
+ options the program contacts a Domain Controller, which my be unreachable
+ or have restricted access. Comma-separated from the machine or domain,
+ you can specify an offset which is used as base added to the group's RID
+ to compute the gid (offset + RID = gid). This allows you to create the
+ same gids every time you re-run <command>mkgroup</command>. For very
+ simple needs, an entry for the current user's group can be created by
+ using the option <literal>-c</literal> or <literal>-C</literal>. If you
+ want to use one of the <literal>-D</literal>, <literal>-L</literal> or
+ <literal>-C</literal> options, but you don't like the backslash as
+ domain/group separator, you can specify another separator using the
+ <literal>-S</literal> option, for instance:</para>
<example id="utils-mkgroup-ex">
<title>Setting up group entry for current user with different
domain/group separator</title>
<screen>
-<prompt>$</prompt> <userinput>mkgroup -L server1 -S= &gt; /etc/group</userinput>
+<prompt>$</prompt> <userinput>mkgroup -C -S+ &gt; /etc/group</userinput>
+<prompt>$</prompt> <userinput>cat /etc/group</userinput>
+DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144:
</screen>
</example>
- <para>For very simple needs, an entry for the current user's group can be
- created by using the option <literal>-c</literal>.</para>
-
- <para>The <literal>-o</literal> option allows for (unlikely) special cases
- with multiple machines where the GIDs might match otherwise. The
+ <para>The <literal>-o</literal> option allows for special cases (such as
+ multiple domains) where the GIDs might match otherwise. The
<literal>-g</literal> option only prints the information for one group.
The <literal>-U</literal> option allows you to enumerate the standard
UNIX groups on a Samba machine. It's used together with <literal>-l
@@ -963,32 +973,39 @@ groups on domain controllers and domain member machines.
<screen>
Usage: mkpasswd [OPTIONS]...
-Write /etc/passwd-like output to stdout
-
-Don't use this command to generate a local /etc/passwd file, unless you
-really need one. See the Cygwin User's Guide for more information.
+Print /etc/passwd file to stdout
Options:
- -l,--local [machine] print local user accounts
+ -l,--local [machine[,offset]]
+ print local user accounts with uid offset offset
(from local machine if no machine specified)
- -L,--Local machine ditto, but generate username with machine prefix
- -d,--domain [domain] print domain accounts
+ -L,--Local [machine[,offset]]
+ ditto, but generate username with machine prefix
+ -d,--domain [domain[,offset]]
+ print domain accounts with uid offset offset
(from current domain if no domain specified)
+ -D,--Domain [domain[,offset]]
+ ditto, but generate username with domain prefix
-c,--current print current user
- -S,--separator char for -l use character char as domain\user
- separator in username instead of the default '+'
- -o,--id-offset offset change the default offset (0x10000) added to uids
+ -C,--Current ditto, but generate username with machine or
+ domain prefix
+ -S,--separator char for -L, -D, -C use character char as domain\user
+ separator in username instead of the default '\'
+ -o,--id-offset offset change the default offset (10000) added to uids
in domain or foreign server accounts.
-u,--username username only return information for the specified user
- one of -l, -d must be specified, too
- -b,--no-builtin don't print BUILTIN users
+ one of -l, -L, -d, -D must be specified, too
-p,--path-to-home path use specified path instead of user account home dir
or /home prefix
- -U,--unix userlist print UNIX users when using -l on a UNIX Samba
- server. userlist is a comma-separated list of
- usernames or uid ranges (root,-25,50-100).
+ -U,--unix userlist additionally print UNIX users when using -l or -L\
+ on a UNIX Samba server
+ userlist is a comma-separated list of usernames
+ or uid ranges (root,-25,50-100).
(enumerating large ranges can take a long time!)
+ -s,--no-sids (ignored)
+ -m,--no-mount (ignored)
+ -g,--local-groups (ignored)
-h,--help displays this message
-V,--version version information and exit
@@ -996,36 +1013,41 @@ Default is to print local accounts on stand-alone machines, domain accounts
on domain controllers and domain member machines.
</screen>
- <para>The <command>mkpasswd</command> program can be used to create a
- <filename>/etc/passwd</filename> file. Cygwin doesn't need this file,
- because it reads user information from the Windows account databases,
- but you can add an <filename>/etc/passwd</filename> file, for instance
- if your machine is often disconnected from its domain controller.</para>
-
- <para>Note that this information is static, in contrast to the information
- automatically gathered by Cygwin from the Windows account databases. If
- you change the user information on your system, you'll need to regenerate
- the passwd file for it to have the new information.</para>
-
- <para>By default, the information generated by <command>mkpasswd</command>
- is equivalent to the information generated by Cygwin itself. The
- <literal>-d</literal> and <literal>-l/-L</literal> options allow you to
- specify where the information comes from, some domain, or the local SAM
- of a machine. Note that you can only enumerate accounts from trusted
- domains. Any non-trusted domain will be ignored. Access-restrictions
- of your current account apply. The <literal>-l/-L</literal> when used
- with a machine name, tries to contact that machine to enumerate local
- groups of other machines, typically outside of domains. This scenario
- cannot be covered by Cygwin's account automatism. If you want to use
- the <literal>-L</literal> option, but you don't like the default
- domain/group separator from <filename>/etc/nsswitch.conf</filename>,
- you can specify another separator using the <literal>-S</literal> option,
- analog to <command>mkgroup</command>.</para>
-
- <para>For very simple needs, an entry for the current user can be created
- by using the option <literal>-c</literal>.</para>
-
- <para>The <literal>-o</literal> option allows for special cases (such as
+ <para>The <command>mkpasswd</command> program can be used to help configure
+ Cygwin by creating a <filename>/etc/passwd</filename> from your system
+ information. Its use is essential to include Windows security
+ information. However, the actual passwords are determined by Windows, not
+ by the content of <filename>/etc/passwd</filename>.</para>
+
+ <para>The command is initially called by <command>setup.exe</command> to
+ create a default <filename>/etc/passwd</filename>. This should be
+ sufficient in most circumstances. However, especially when working in a
+ multi-domain environment, you can use <command>mkpasswd</command>
+ manually to create a more complete <filename>/etc/passwd</filename> file
+ for all domains. Especially when you have the same user name used on
+ multiple machines or in multiple domains, you can use the
+ <literal>-D</literal>, <literal>-L</literal> and <literal>-C</literal>
+ options to create unique domain\user style usernames.</para>
+
+ <para>Note that this information is static. If you change the user
+ information in your system, you'll need to regenerate the passwd file for
+ it to have the new information.</para>
+
+ <para>The <literal>-d/-D</literal> and <literal>-l/-L</literal> options
+ allow you to specify where the information comes from, the local machine
+ or the domain (default or given), or both. With the
+ <literal>-d/-D</literal> options the program contacts the Domain
+ Controller, which may be unreachable or have restricted access.
+ Comma-separated from the machine or domain, you can specify an offset
+ which is used as base added to the user's RID to compute the uid (offset
+ + RID = uid). This allows to create the same uids every time you re-run
+ <command>mkpasswd</command>. An entry for the current user can be created
+ by using the option <literal>-c</literal> or <literal>-C</literal>. If
+ you want to use one of the <literal>-D</literal>, <literal>-L</literal>
+ or <literal>-C</literal> options, but you don't like the backslash as
+ domain/group separator, you can specify another separator using the
+ <literal>-S</literal> option, similar to the <command>mkgroup</command>.
+ The <literal>-o</literal> option allows for special cases (such as
multiple domains) where the UIDs might match otherwise. The
<literal>-p</literal> option causes <command>mkpasswd</command> to use
the specified prefix instead of the account home dir or <literal>/home/
@@ -1040,8 +1062,7 @@ on domain controllers and domain member machines.
to enumerate the standard UNIX users on a Samba machine. It's used
together with <literal>-l samba-server</literal> or <literal>-L
samba-server</literal>. The normal UNIX users are usually not enumerated,
- but they can show up as file owners in <command>ls -l</command> output.
- </para>
+ but they can show up as file owners in <command>ls -l</command> output. </para>
</sect2>
@@ -1321,8 +1342,8 @@ User operations:
System operations:
-i, --inactive NUM set NUM of days before inactive accounts are disabled
(inactive accounts are those with expired passwords).
- -n, --minage MINDAYS set system minimum password age to MINDAYS days.
- -x, --maxage MAXDAYS set system maximum password age to MAXDAYS days.
+ -n, --minage DAYS set system minimum password age to DAYS days.
+ -x, --maxage DAYS set system maximum password age to DAYS days.
-L, --length LEN set system minimum password length to LEN.
Other options:
@@ -1683,13 +1704,11 @@ Example: regtool.exe get '\user\software\Microsoft\Clock\iFormat'
<title>setfacl</title>
<screen>
-Usage: setfacl [-r] {-f ACL_FILE | -s acl_entries} FILE...
- setfacl [-r] {-b|[-d acl_entries] [-m acl_entries]} FILE...
-
+Usage: setfacl [-r] (-f ACL_FILE | -s acl_entries) FILE...
+ setfacl [-r] ([-d acl_entries] [-m acl_entries]) FILE...
Modify file and directory access control lists (ACLs)
- -b, --remove-all remove all extended ACL entries
-d, --delete delete one or more specified ACL entries
-f, --file set ACL entries for FILE to ACL entries read
from a ACL_FILE
@@ -1701,7 +1720,7 @@ Modify file and directory access control lists (ACLs)
-h, --help output usage information and exit
-V, --version output version information and exit
-At least one of (-b, -d, -f, -m, -s) must be specified
+At least one of (-d, -f, -m, -s) must be specified
</screen>
<para> For each file given as parameter, <command>setfacl</command> will
@@ -1735,21 +1754,17 @@ At least one of (-b, -d, -f, -m, -s) must be specified
<para> The following options are supported: </para>
- <para> <literal>-b</literal> Remove all extended ACL entries. The base
- ACL entries of the owner, group and others are retained.</para>
-
<para> <literal>-d</literal> Delete one or more specified entries from the
file's ACL. The owner, group and others entries must not be deleted.
Acl_entries to be deleted should be specified without permissions, as in
the following list:
<screen>
- u[ser]:uid[:]
- g[roup]:gid[:]
- m[ask][:]
- d[efault]:u[ser][:uid]
- d[efault]:g[roup][:gid]
- d[efault]:m[ask][:]
- d[efault]:o[ther][:]
+ u[ser]:uid
+ g[roup]:gid
+ d[efault]:u[ser]:uid
+ d[efault]:g[roup]:gid
+ d[efault]:m[ask]:
+ d[efault]:o[ther]:
</screen> </para>
<para> <literal>-f</literal> Take the Acl_entries from ACL_FILE one per
@@ -1792,6 +1807,10 @@ $ getfacl source_file | setfacl -f - target_file
directory that contains default ACL entries will have permissions
according to the combination of the current umask, the explicit
permissions requested and the default ACL entries </para>
+
+ <para> Limitations: Under Cygwin, the default ACL entries are not taken
+ into account currently. </para>
+
</sect2>
<sect2 id="setmetamode">