public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
* [PATCH] Use automake (v5)
@ 2021-04-20 20:13 Jon Turney
  2021-04-20 20:15 ` Jon Turney
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Jon Turney @ 2021-04-20 20:13 UTC (permalink / raw)
  To: cygwin-patches; +Cc: Jon Turney

For ease of reviewing, this patch doesn't contain changes to generated
files which would be made by running ./autogen.sh.

v2:
* Include tzmap.h in BUILT_SOURCES
* Make per-file flags appear after user-supplied CXXFLAGS, so they can
override optimization level.
* Correct .o files used to define symbols exported by libm.a
* Drop gcrt0.o mistakenly included in libgmon.a
* Add missing line continuations in GMON_FILES value

v3:
* use per-file flags for .c compilation
* override C{XX,}FLAGS, as they are set on the command line by top-level make

v4:
* Drop -Wno-error=write-strings from path_testsuite CXXFLAGS

v5:
* Update for changes in master
- Add -fno-threadsafe-statics to CXX flags
- Add hypotl.cc
- Remove fenv.cc (in favour of newlib), add fenv.c stub
- Add proc.5 manpage rules
---
 winsup/Makefile.am                     |  19 +
 winsup/Makefile.am.common              |  15 +
 winsup/Makefile.common                 |  51 --
 winsup/autogen.sh                      |   1 +
 winsup/configure.ac                    |  21 +-
 winsup/cygserver/Makefile.am           |  58 ++
 winsup/cygwin/Makefile.am              | 770 +++++++++++++++++++++++++
 winsup/cygwin/config.h.in              |   2 +-
 winsup/doc/Makefile.am                 | 162 ++++++
 winsup/testsuite/Makefile.am           |  64 ++
 winsup/testsuite/config/default.exp    |   4 +-
 winsup/testsuite/cygrun/Makefile.am    |  21 +
 winsup/testsuite/winsup.api/winsup.exp |   6 +-
 winsup/utils/Makefile.am               |  81 +++
 winsup/utils/mingw/Makefile.am         |  50 ++
 15 files changed, 1266 insertions(+), 59 deletions(-)
 create mode 100644 winsup/Makefile.am
 create mode 100644 winsup/Makefile.am.common
 delete mode 100644 winsup/Makefile.common
 create mode 100644 winsup/cygserver/Makefile.am
 create mode 100644 winsup/cygwin/Makefile.am
 create mode 100644 winsup/doc/Makefile.am
 create mode 100644 winsup/testsuite/Makefile.am
 create mode 100644 winsup/testsuite/cygrun/Makefile.am
 create mode 100644 winsup/utils/Makefile.am
 create mode 100644 winsup/utils/mingw/Makefile.am

diff --git a/winsup/Makefile.am b/winsup/Makefile.am
new file mode 100644
index 000000000..067f74688
--- /dev/null
+++ b/winsup/Makefile.am
@@ -0,0 +1,19 @@
+# Makefile.am for winsup stuff
+#
+# 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.
+
+# This makefile requires GNU make.
+
+cygdocdir = $(datarootdir)/doc/Cygwin
+
+cygdoc_DATA = \
+	CYGWIN_LICENSE \
+	COPYING
+
+SUBDIRS = cygwin cygserver doc utils testsuite
+
+cygserver utils testsuite: cygwin
diff --git a/winsup/Makefile.am.common b/winsup/Makefile.am.common
new file mode 100644
index 000000000..884194df2
--- /dev/null
+++ b/winsup/Makefile.am.common
@@ -0,0 +1,15 @@
+# Makefile.am.common - common definitions for the winsup directory
+#
+# 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.
+
+flags_common=-Wall -Wstrict-aliasing -Wwrite-strings -fno-common -pipe -fbuiltin -fmessage-length=0
+
+# compiler flags commonly used (but not for MinGW compilation, because they
+# include the Cygwin header paths via @INCLUDES@)
+
+cxxflags_common=$(INCLUDES) -fno-rtti -fno-exceptions -fno-use-cxa-atexit $(flags_common)
+cflags_common=$(INCLUDES) $(flags_common)
diff --git a/winsup/Makefile.common b/winsup/Makefile.common
deleted file mode 100644
index 3141bd111..000000000
--- a/winsup/Makefile.common
+++ /dev/null
@@ -1,51 +0,0 @@
-# Makefile.common - common definitions for the winsup directory
-#
-# 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.
-
-define justdir
-$(patsubst %/,%,$(dir $1))
-endef
-
-define libname
-$(realpath $(shell ${CC} --print-file-name=$1 $2))
-endef
-
-export PATH:=${winsup_srcdir}:${PATH}
-
-# Allow CFLAGS=-O,-g to control CXXFLAGS too
-opt=$(filter -O%,${CFLAGS}) $(filter -g%,${CFLAGS})
-override CXXFLAGS:=${filter-out -g%,$(filter-out -O%,${CXXFLAGS})} ${opt}
-
-cflags_common:=-Wall -Wstrict-aliasing -Wwrite-strings -fno-common -pipe -fbuiltin -fmessage-length=0
-COMPILE.cc=${CXX} ${INCLUDES} ${CXXFLAGS} -fno-rtti -fno-exceptions -fno-use-cxa-atexit ${cflags_common}
-COMPILE.c=${CC} ${INCLUDES} ${CFLAGS} ${cflags_common}
-
-top_srcdir:=$(call justdir,${winsup_srcdir})
-top_builddir:=$(call justdir,${target_builddir})
-
-cygwin_build:=${target_builddir}/winsup/cygwin
-newlib_build:=${target_builddir}/newlib
-
-VPATH:=${srcdir}
-
-.SUFFIXES:
-.SUFFIXES: .c .cc .def .S .a .o .d .s .E
-
-%.o: %.cc
-	$(strip ${COMPILE.cc} -c -o $@ $<)
-
-%.o: %.c
-	$(strip ${COMPILE.c} -c -o $@ $<)
-
-%.E: %.cc
-	$(strip ${COMPILE.cc} -E -dD -o $@ $<)
-
-%.E: %.c
-	$(strip ${COMPILE.c} -E -dD -o $@ $<)
-
-%.o: %.S
-	$(strip ${COMPILE.S} -c -o $@ $<)
diff --git a/winsup/autogen.sh b/winsup/autogen.sh
index 4a60ef39f..1db91add9 100755
--- a/winsup/autogen.sh
+++ b/winsup/autogen.sh
@@ -1,3 +1,4 @@
 /usr/bin/aclocal --force
 /usr/bin/autoconf -f
+/usr/bin/automake -ac
 /bin/rm -rf autom4te.cache
diff --git a/winsup/configure.ac b/winsup/configure.ac
index 438e629e7..9a11411ab 100644
--- a/winsup/configure.ac
+++ b/winsup/configure.ac
@@ -10,8 +10,10 @@ dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.59])
 AC_INIT([Cygwin],[0],[cygwin@cygwin.com],[cygwin],[https://cygwin.com])
-AC_CONFIG_SRCDIR(Makefile.in)
 AC_CONFIG_AUX_DIR(..)
+AC_CANONICAL_TARGET
+AM_INIT_AUTOMAKE([dejagnu foreign no-define no-dist subdir-objects -Wall -Wno-portability -Wno-extra-portability])
+AM_SILENT_RULES([yes])
 
 realdirpath() {
     test -z "$1" && return 1
@@ -26,13 +28,15 @@ realdirpath() {
 winsup_srcdir="$(realdirpath $srcdir)"
 target_builddir="$(realdirpath ..)"
 
-AC_PROG_INSTALL
 AC_NO_EXECUTABLES
-AC_CANONICAL_TARGET
 
+AC_PROG_INSTALL
+AC_PROG_MKDIR_P
 AC_PROG_CC
 AC_PROG_CXX
 AC_PROG_CPP
+AM_PROG_AS
+
 AC_LANG(C)
 AC_LANG(C++)
 
@@ -82,6 +86,8 @@ AC_SUBST(DEF_DLL_ENTRY)
 AC_SUBST(DIN_FILE)
 AC_SUBST(TLSOFFSETS_H)
 
+AM_CONDITIONAL(TARGET_X86_64, [test $target_cpu = "x86_64"])
+
 AC_CHECK_PROGS([DOCBOOK2XTEXI], [docbook2x-texi db2x_docbook2texi], [true])
 
 if test "x$with_cross_bootstrap" != "xyes"; then
@@ -90,15 +96,24 @@ if test "x$with_cross_bootstrap" != "xyes"; then
     AC_CHECK_PROGS(MINGW_CC, ${target_cpu}-w64-mingw32-gcc)
     test -n "$MINGW_CC" || AC_MSG_ERROR([no acceptable MinGW gcc found in \$PATH])
 fi
+AM_CONDITIONAL(CROSS_BOOTSTRAP, [test "x$with_cross_bootstrap" != "xyes"])
+
 AC_EXEEXT
 
+AC_CHECK_LIB([bfd], [bfd_init], [true],
+	     AC_MSG_WARN([Not building dumper.exe since some required libraries or headers are missing]))
+
+AM_CONDITIONAL(BUILD_DUMPER, [test "x$ac_cv_lib_bfd_bfd_init" = "xyes"])
+
 AC_CONFIG_FILES([
     Makefile
     cygwin/Makefile
     cygserver/Makefile
     doc/Makefile
     utils/Makefile
+    utils/mingw/Makefile
     testsuite/Makefile
+    testsuite/cygrun/Makefile
 ])
 
 AC_OUTPUT
diff --git a/winsup/cygserver/Makefile.am b/winsup/cygserver/Makefile.am
new file mode 100644
index 000000000..d52f93ce0
--- /dev/null
+++ b/winsup/cygserver/Makefile.am
@@ -0,0 +1,58 @@
+# Makefile for Cygwin server
+
+# 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 $(top_srcdir)/Makefile.am.common
+
+cygserver_flags=$(cxxflags_common) -Wimplicit-fallthrough=5 -Werror -DSYSCONFDIR="\"$(sysconfdir)\""
+
+noinst_LIBRARIES = libcygserver.a
+sbin_PROGRAMS = cygserver
+bin_SCRIPTS = cygserver-config
+
+cygserver_SOURCES = \
+	bsd_helper.cc \
+	bsd_log.cc \
+	bsd_mutex.cc \
+	client.cc \
+	cygserver.cc \
+	msg.cc \
+	process.cc \
+	pwdgrp.cc \
+	sem.cc \
+	setpwd.cc \
+	shm.cc \
+	sysv_msg.cc \
+	sysv_sem.cc \
+	sysv_shm.cc \
+	threaded_queue.cc \
+	transport.cc \
+	transport_pipes.cc
+
+cygserver_CXXFLAGS = $(cygserver_flags) -D__OUTSIDE_CYGWIN__
+cygserver_LDADD = -lntdll
+cygserver_LDFLAGS = -static -static-libgcc
+
+# Note: the objects in libcygserver are built without -D__OUTSIDE_CYGWIN__,
+# unlike cygserver.exe
+
+libcygserver_a_SOURCES = \
+	$(cygserver_SOURCES)
+
+libcygserver_a_CXXFLAGS = $(cygserver_flags)
+
+cygdocdir = $(datarootdir)/doc/Cygwin
+
+install-data-local:
+	@$(MKDIR_P) $(DESTDIR)$(cygdocdir)
+	$(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(cygdocdir)/cygserver.README
+	@$(MKDIR_P) $(DESTDIR)$(sysconfdir)/defaults/etc
+	$(INSTALL_DATA) $(srcdir)/cygserver.conf $(DESTDIR)$(sysconfdir)/defaults/etc/cygserver.conf
+
+uninstall-local:
+	rm -f $(DESTDIR)$(cygdocdir)/cygserver.README
+	rm -f $(DESTDIR)$(sysconfdir)/defaults/etc/cygserver.conf
diff --git a/winsup/cygwin/Makefile.am b/winsup/cygwin/Makefile.am
new file mode 100644
index 000000000..ea9d4b382
--- /dev/null
+++ b/winsup/cygwin/Makefile.am
@@ -0,0 +1,770 @@
+# Makefile.am for Cygwin.
+#
+# 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.
+
+# This makefile requires GNU make.
+
+include $(top_srcdir)/Makefile.am.common
+
+COMMON_CFLAGS=-Wimplicit-fallthrough=5 -Werror -fmerge-constants -ftracer
+if TARGET_X86_64
+COMMON_CFLAGS+=-mcmodel=small
+endif
+
+AM_CFLAGS=$(cflags_common) $(COMMON_CFLAGS)
+AM_CXXFLAGS=$(cxxflags_common) $(COMMON_CFLAGS) -fno-threadsafe-statics
+
+if TARGET_X86_64
+# Needed by mcountFunc.S to choose the right code path and symbol names
+AM_CCASFLAGS=-D_WIN64
+endif
+
+target_builddir=@target_builddir@
+newlib_build=$(target_builddir)/newlib
+
+#
+# Specialize libdir and includedir to use tooldir prefixed paths (containing
+# target_alias) as used by newlib, because we overwrite library and header files
+# installed there by newlib.
+#
+
+toollibdir=$(prefix)/$(target_alias)/lib
+toolincludedir=$(prefix)/$(target_alias)/include
+
+# Parameters used in building the cygwin.dll.
+
+DLL_NAME=cygwin1.dll
+TEST_DLL_NAME=cygwin0.dll
+DIN_FILE=@DIN_FILE@
+DEF_FILE=cygwin.def
+TLSOFFSETS_H=@TLSOFFSETS_H@
+LIB_NAME=libcygwin.a
+TEST_LIB_NAME=libcygwin0.a
+
+#
+# sources
+#
+
+# These objects are included directly into the import library
+LIB_FILES= \
+	lib/_cygwin_crt0_common.cc \
+	lib/atexit.c \
+	lib/cygwin_attach_dll.c \
+	lib/cygwin_crt0.c \
+	lib/dll_entry.c \
+	lib/dll_main.cc \
+	lib/dso_handle.c \
+	lib/libcmain.c \
+	lib/premain0.c \
+	lib/premain1.c \
+	lib/premain2.c \
+	lib/premain3.c \
+	lib/pseudo-reloc-dummy.c
+
+LIBC_FILES= \
+	libc/arc4random_stir.c \
+	libc/base64.c \
+	libc/bsdlib.cc \
+	libc/call_once.c \
+	libc/cnd.c \
+	libc/fnmatch.c \
+	libc/fts.c \
+	libc/ftw.c \
+	libc/getentropy.cc \
+	libc/getopt.c \
+	libc/inet_addr.c \
+	libc/inet_network.c \
+	libc/minires-os-if.c \
+	libc/minires.c \
+	libc/msgcat.c \
+	libc/mtx.c \
+	libc/nftw.c \
+	libc/rcmd.cc \
+	libc/rexec.cc \
+	libc/strfmon.c \
+	libc/strptime.cc \
+	libc/thrd.c \
+	libc/tss.c \
+	libc/xsique.cc
+
+MATH_FILES= \
+	math/acoshl.c \
+	math/acosl.c \
+	math/asinhl.c \
+	math/asinl.c \
+	math/atan2l.c \
+	math/atanhl.c \
+	math/atanl.c \
+	math/cabsl.c \
+	math/cacosl.c \
+	math/cargl.c \
+	math/casinl.c \
+	math/catanl.c \
+	math/cbrtl.c \
+	math/ccosl.c \
+	math/ceill.S \
+	math/cephes_emath.c \
+	math/cexpl.c \
+	math/cimagl.c \
+	math/clog10l.c \
+	math/clogl.c \
+	math/conjl.c \
+	math/copysignl.S \
+	math/coshl.c \
+	math/cosl.c \
+	math/cosl_internal.S \
+	math/cossin.c \
+	math/cpowl.c \
+	math/cprojl.c \
+	math/creall.c \
+	math/csinl.c \
+	math/csqrtl.c \
+	math/ctanl.c \
+	math/erfl.c \
+	math/exp10l.c \
+	math/exp2l.S \
+	math/expl.c \
+	math/expm1l.c \
+	math/fabsl.c \
+	math/fdiml.c \
+	math/finite.c \
+	math/floorl.S \
+	math/fmal.c \
+	math/fmaxl.c \
+	math/fminl.c \
+	math/fmodl.c \
+	math/frexpl.S \
+	math/hypotl.c \
+	math/ilogbl.S \
+	math/internal_logl.S \
+	math/isinf.c \
+	math/isnan.c \
+	math/ldexpl.c \
+	math/lgammal.c \
+	math/llrint.c \
+	math/llrintf.c \
+	math/llrintl.c \
+	math/llroundl.c \
+	math/log10l.S \
+	math/log1pl.S \
+	math/log2l.S \
+	math/logbl.c \
+	math/logl.c \
+	math/lrint.c \
+	math/lrintf.c \
+	math/lrintl.c \
+	math/lroundl.c \
+	math/modfl.c \
+	math/nearbyint.S \
+	math/nearbyintf.S \
+	math/nearbyintl.S \
+	math/nextafterl.c \
+	math/nexttoward.c \
+	math/nexttowardf.c \
+	math/pow10l.c \
+	math/powil.c \
+	math/powl.c \
+	math/remainder.S \
+	math/remainderf.S \
+	math/remainderl.S \
+	math/remquol.S \
+	math/rint.c \
+	math/rintf.c \
+	math/rintl.c \
+	math/roundl.c \
+	math/scalbl.S \
+	math/scalbnl.S \
+	math/sinhl.c \
+	math/sinl.c \
+	math/sinl_internal.S \
+	math/sqrtl.c \
+	math/tanhl.c \
+	math/tanl.S \
+	math/tgammal.c \
+	math/truncl.c
+
+REGEX_FILES = \
+	regex/regcomp.c \
+	regex/regerror.c \
+	regex/regexec.c \
+	regex/regfree.c
+
+TZCODE_FILES= \
+	tzcode/localtime_wrapper.c
+
+DLL_FILES= \
+	advapi32.cc \
+	aio.cc \
+	assert.cc \
+	autoload.cc \
+	clock.cc \
+	ctype.cc \
+	cxx.cc \
+	cygheap.cc \
+	cygthread.cc \
+	cygtls.cc \
+	cygwait.cc \
+	cygxdr.cc \
+	dcrt0.cc \
+	debug.cc \
+	devices.cc \
+	dir.cc \
+	dlfcn.cc \
+	dll_init.cc \
+	dtable.cc \
+	environ.cc \
+	errno.cc \
+	exceptions.cc \
+	exec.cc \
+	external.cc \
+	fcntl.cc \
+	fenv.c \
+	fhandler.cc \
+	fhandler_clipboard.cc \
+	fhandler_console.cc \
+	fhandler_cygdrive.cc \
+	fhandler_dev.cc \
+	fhandler_disk_file.cc \
+	fhandler_dsp.cc \
+	fhandler_fifo.cc \
+	fhandler_floppy.cc \
+	fhandler_netdrive.cc \
+	fhandler_nodevice.cc \
+	fhandler_pipe.cc \
+	fhandler_proc.cc \
+	fhandler_process.cc \
+	fhandler_process_fd.cc \
+	fhandler_procnet.cc \
+	fhandler_procsys.cc \
+	fhandler_procsysvipc.cc \
+	fhandler_random.cc \
+	fhandler_raw.cc \
+	fhandler_registry.cc \
+	fhandler_serial.cc \
+	fhandler_signalfd.cc \
+	fhandler_socket.cc \
+	fhandler_socket_inet.cc \
+	fhandler_socket_local.cc \
+	fhandler_socket_unix.cc \
+	fhandler_tape.cc \
+	fhandler_termios.cc \
+	fhandler_timerfd.cc \
+	fhandler_tty.cc \
+	fhandler_virtual.cc \
+	fhandler_windows.cc \
+	fhandler_zero.cc \
+	flock.cc \
+	fork.cc \
+	forkable.cc \
+	glob.cc \
+	glob_pattern_p.cc \
+	globals.cc \
+	grp.cc \
+	heap.cc \
+	hookapi.cc \
+	init.cc \
+	ioctl.cc \
+	ipc.cc \
+	kernel32.cc \
+	ldap.cc \
+	libstdcxx_wrapper.cc \
+	loadavg.cc \
+	lsearch.cc \
+	malloc_wrapper.cc \
+	miscfuncs.cc \
+	mktemp.cc \
+	mmap.cc \
+	mmap_alloc.cc \
+	msg.cc \
+	mount.cc \
+	net.cc \
+	netdb.cc \
+	nfs.cc \
+	nlsfuncs.cc \
+	ntea.cc \
+	passwd.cc \
+	path.cc \
+	pinfo.cc \
+	poll.cc \
+	posix_ipc.cc \
+	posix_timer.cc \
+	pseudo-reloc.cc \
+	pthread.cc \
+	quotactl.cc \
+	random.cc \
+	registry.cc \
+	resource.cc \
+	scandir.cc \
+	sched.cc \
+	sec_acl.cc \
+	sec_auth.cc \
+	sec_helper.cc \
+	sec_posixacl.cc \
+	security.cc \
+	select.cc \
+	sem.cc \
+	setlsapwd.cc \
+	shared.cc \
+	shm.cc \
+	signal.cc \
+	sigproc.cc \
+	smallprint.cc \
+	spawn.cc \
+	strace.cc \
+	strfuncs.cc \
+	strsep.cc \
+	strsig.cc \
+	sync.cc \
+	syscalls.cc \
+	sysconf.cc \
+	syslog.cc \
+	termios.cc \
+	thread.cc \
+	timerfd.cc \
+	times.cc \
+	tls_pbuf.cc \
+	tty.cc \
+	uinfo.cc \
+	uname.cc \
+	wait.cc \
+	wincap.cc \
+	window.cc \
+	winf.cc
+
+MALLOC_FILES= \
+	malloc.cc
+
+GMON_FILES= \
+	gmon.c \
+	mcount.c \
+	profil.c \
+	mcountFunc.S
+
+GENERATED_FILES= \
+	sigfe.s
+
+liblib_a_SOURCES= \
+	$(LIB_FILES)
+
+libdll_a_SOURCES= \
+	$(DLL_FILES) \
+	$(REGEX_FILES) \
+	$(MALLOC_FILES) \
+	$(LIBC_FILES) \
+	$(MATH_FILES) \
+	$(TZCODE_FILES) \
+	$(GENERATED_FILES)
+
+#
+# generated sources
+#
+
+shared_info_magic.h: cygmagic shared_info.h
+	$(srcdir)/cygmagic $@ "$(CC) $(INCLUDES) $(CPPFLAGS) -E -x c++" $(word 2,$^) SHARED_MAGIC 'class shared_info' USER_MAGIC 'class user_info'
+
+child_info_magic.h: cygmagic child_info.h
+	$(srcdir)/cygmagic $@ "$(CC) $(INCLUDES) $(CPPFLAGS) -E -x c++" $(word 2,$^) CHILD_INFO_MAGIC 'class child_info'
+
+globals.h: mkglobals_h globals.cc
+	$^ > $@
+
+localtime.patched.c: tzcode/localtime.c tzcode/localtime.c.patch
+	patch -u -o localtime.patched.c \
+		    $(srcdir)/tzcode/localtime.c \
+		    $(srcdir)/tzcode/localtime.c.patch
+
+$(srcdir)/devices.cc: gendevices devices.in devices.h
+	$(wordlist 1,2,$^) $@
+
+$(srcdir)/$(TLSOFFSETS_H): gentls_offsets cygtls.h
+	$^ $@ $(target_cpu) $(CC) $(AM_CFLAGS) -c || rm $@
+
+BUILT_SOURCES = \
+	child_info_magic.h \
+	shared_info_magic.h \
+	globals.h \
+	localtime.patched.c
+
+# Every time we touch a source file, the version info has to be rebuilt
+# to maintain a correct build date, especially in uname release output
+dirs = $(srcdir) $(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math $(srcdir)/tzcode
+find_src_files = $(wildcard $(dir)/*.[chS]) $(wildcard $(dir)/*.cc)
+src_files := $(foreach dir,$(dirs),$(find_src_files))
+
+# mkvers.sh creates version.cc in the first place, winver.o always
+# second, so version.cc is always older than winver.o
+version.cc: mkvers.sh include/cygwin/version.h winver.rc $(src_files)
+	@echo "Making version.cc and winver.o";\
+	export CC="$(CC)";\
+	/bin/sh $(word 1,$^) $(word 2,$^) $(word 3,$^) $(WINDRES) $(CFLAGS)
+
+winver.o: version.cc
+
+VERSION_OFILES = version.o winver.o
+
+#
+# export renames for mkimport
+#
+
+NEW_FUNCTIONS=$(addprefix --replace=,\
+	atexit= \
+	timezone= \
+	uname=uname_x \
+	__xdrrec_getrec= \
+	__xdrrec_setnonblock= \
+	xdr_array= \
+	xdr_bool= \
+	xdr_bytes= \
+	xdr_char= \
+	xdr_double= \
+	xdr_enum= \
+	xdr_float= \
+	xdr_free= \
+	xdr_hyper= \
+	xdr_int= \
+	xdr_int16_t= \
+	xdr_int32_t= \
+	xdr_int64_t= \
+	xdr_int8_t= \
+	xdr_long= \
+	xdr_longlong_t= \
+	xdr_netobj= \
+	xdr_opaque= \
+	xdr_pointer= \
+	xdr_reference= \
+	xdr_short= \
+	xdr_sizeof= \
+	xdr_string= \
+	xdr_u_char= \
+	xdr_u_hyper= \
+	xdr_u_int= \
+	xdr_u_int16_t= \
+	xdr_u_int32_t= \
+	xdr_u_int64_t= \
+	xdr_u_int8_t= \
+	xdr_u_long= \
+	xdr_u_longlong_t= \
+	xdr_u_short= \
+	xdr_uint16_t= \
+	xdr_uint32_t= \
+	xdr_uint64_t= \
+	xdr_uint8_t= \
+	xdr_union= \
+	xdr_vector= \
+	xdr_void= \
+	xdr_wrapstring= \
+	xdrmem_create= \
+	xdrrec_create= \
+	xdrrec_endofrecord= \
+	xdrrec_eof= \
+	xdrrec_skiprecord= \
+	xdrstdio_create= \
+)
+
+if !TARGET_X86_64
+NEW_FUNCTIONS+=$(addprefix --replace=,\
+	acl=_acl32 \
+	aclcheck=_aclcheck32 \
+	aclfrommode=_aclfrommode32 \
+	aclfrompbits=_aclfrompbits32 \
+	aclfromtext=_aclfromtext32 \
+	aclsort=_aclsort32 \
+	acltomode=_acltomode32 \
+	acltopbits=_acltopbits32 \
+	acltotext=_acltotext32 \
+	chown=_chown32 \
+	facl=_facl32 \
+	fchown=_fchown32 \
+	fcntl=_fcntl64 \
+	fdopen=_fdopen64 \
+	fgetpos=_fgetpos64 \
+	fopen=_fopen64 \
+	freopen=_freopen64 \
+	fseeko=_fseeko64 \
+	fsetpos=_fsetpos64 \
+	fstat=_fstat64 \
+	ftello=_ftello64 \
+	ftruncate=_ftruncate64 \
+	getegid=_getegid32 \
+	geteuid=_geteuid32 \
+	getgid=_getgid32 \
+	getgrent=_getgrent32 \
+	getgrgid=_getgrgid32 \
+	getgrnam=_getgrnam32 \
+	getgroups=_getgroups32 \
+	getpwuid=_getpwuid32 \
+	getpwuid_r=_getpwuid_r32 \
+	getuid=_getuid32 \
+	initgroups=_initgroups32 \
+	lchown=_lchown32 \
+	lseek=_lseek64 \
+	lstat=_lstat64 \
+	mknod=_mknod32 \
+	mmap=_mmap64 \
+	open=_open64 \
+	setegid=_setegid32 \
+	seteuid=_seteuid32 \
+	setgid=_setgid32 \
+	setgroups=_setgroups32 \
+	setregid=_setregid32 \
+	setreuid=_setreuid32 \
+	setuid=_setuid32 \
+	stat=_stat64 \
+	tmpfile=_tmpfile64 \
+	truncate=_truncate64 \
+)
+endif
+
+#
+# per-file compilation flags
+#
+# (these come after, and thus override, the user-supplied CXXFLAGS, as they need
+# to be able to fiddle with the optimization level)
+#
+
+override CFLAGS += $($(*F)_CFLAGS)
+override CXXFLAGS += $($(*F)_CFLAGS)
+
+localtime_wrapper_CFLAGS=-I$(srcdir)/tzcode -fwrapv
+
+# required since gcc 9.x
+exec_CFLAGS=-fno-builtin-execve
+
+fhandler_proc_CFLAGS=-DUSERNAME="\"$(USER)\"" -DHOSTNAME="\"$(HOSTNAME)\"" \
+		     -DGCC_VERSION="\"`$(CC) -v 2>&1 | tail -n 1`\""
+
+if !TARGET_X86_64
+# on x86, exceptions.cc must be compiled with a frame-pointer as it uses RtlCaptureContext()
+exceptions_CFLAGS=-fno-omit-frame-pointer
+endif
+
+dtable_CFLAGS=-fcheck-new
+
+# If an optimization level is explicitly set in CXXFLAGS, set -O3 for these files
+# XXX: this seems to assume it's not -O0?
+#
+# (the indentation here prevents automake trying to process this as an automake
+# conditional)
+ ifneq "${filter -O%,$(CXXFLAGS)}" ""
+  malloc_CFLAGS=-O3
+  sync_CFLAGS=-O3
+ endif
+
+#
+# libraries and installed objects
+#
+# (Don't ever try to use automake's shared library support via libtool to build
+# Cygwin. Instead we have explicit rules to build it.)
+#
+
+SUBLIBS = \
+	libpthread.a \
+	libutil.a \
+	libm.a \
+	libc.a \
+	libdl.a \
+	libresolv.a \
+	librt.a \
+	libacl.a \
+	libssp.a
+
+EXTRALIBS = \
+	libautomode.a \
+	libbinmode.a \
+	libtextmode.a \
+	libtextreadmode.a
+
+noinst_LIBRARIES = \
+	libdll.a \
+	liblib.a
+
+toollib_LIBRARIES = \
+	libgmon.a \
+	$(EXTRALIBS)
+
+CYGWIN_START=crt0.o
+GMON_START=gcrt0.o
+INSTOBJS=automode.o binmode.o textmode.o textreadmode.o
+
+toollib_DATA = \
+	$(CYGWIN_START) \
+	$(GMON_START) \
+	$(INSTOBJS) \
+	$(LIB_NAME) \
+	$(SUBLIBS)
+
+libgmon_a_SOURCES = $(GMON_FILES)
+libgmon_a_LIBADD =
+
+libautomode_a_SOURCES =
+libautomode_a_LIBADD = automode.o
+
+libbinmode_a_SOURCES =
+libbinmode_a_LIBADD = binmode.o
+
+libtextmode_a_SOURCES =
+libtextmode_a_LIBADD = textmode.o
+
+libtextreadmode_a_SOURCES =
+libtextreadmode_a_LIBADD = textreadmode.o
+
+# cygserver library
+cygserver_blddir = ${target_builddir}/winsup/cygserver
+LIBSERVER = $(cygserver_blddir)/libcygserver.a
+
+$(LIBSERVER):
+	$(MAKE) -C $(cygserver_blddir) libcygserver.a
+
+# We build as cygwin0.dll and rename at install time to overcome native
+# rebuilding issues (we don't want the build tools to see a partially built
+# cygwin.dll and attempt to use it instead of the old one).
+
+# linker script
+LDSCRIPT=cygwin.sc
+$(LDSCRIPT): $(LDSCRIPT).in
+	$(CC) -E - -P < $^ -o $@
+
+# cygwin dll
+$(TEST_DLL_NAME): $(LDSCRIPT) dllfixdbg libdll.a $(VERSION_OFILES) $(LIBSERVER)
+	$(CXX) $(CXXFLAGS) \
+	-mno-use-libstdc-wrappers \
+	-Wl,--gc-sections -nostdlib -Wl,-T$(LDSCRIPT) -static \
+	-Wl,--heap=0 -Wl,--out-implib,cygdll.a -shared -o $@ \
+	-e @DLL_ENTRY@ $(DEF_FILE) \
+	-Wl,-whole-archive libdll.a -Wl,-no-whole-archive \
+	$(VERSION_OFILES) \
+	$(LIBSERVER) \
+	$(newlib_build)/libm/libm.a \
+	$(newlib_build)/libc/libc.a \
+	-lgcc -lkernel32 -lntdll -Wl,-Map,cygwin.map
+	$(srcdir)/dllfixdbg $(OBJDUMP) $(OBJCOPY) $@ cygwin1.dbg
+	@ln -f $@ new-cygwin1.dll
+
+# cygwin import library
+toolopts=--cpu=@target_cpu@ --ar=@AR@ --as=@AS@ --nm=@NM@ --objcopy=@OBJCOPY@
+
+$(DEF_FILE): gendef $(srcdir)/$(TLSOFFSETS_H) $(DIN_FILE) common.din
+	$(srcdir)/gendef --cpu=@target_cpu@ --output-def=$(DEF_FILE) --tlsoffsets=$(srcdir)/$(TLSOFFSETS_H) $(srcdir)/$(DIN_FILE) $(srcdir)/common.din
+
+sigfe.s: $(DEF_FILE)
+	@[ -s $@ ] || \
+	{ rm -f $(DEF_FILE); $(MAKE) -s -j1 $(DEF_FILE); }; \
+	[ -s $@ ] && touch $@
+
+LIBCOS=$(addsuffix .o,$(basename $(LIB_FILES)))
+$(LIB_NAME): $(DEF_FILE) $(LIBCOS) | $(TEST_DLL_NAME)
+	$(srcdir)/mkimport $(toolopts) $(NEW_FUNCTIONS) $@ cygdll.a $(wordlist 2,99,$^)
+
+# cygwin import library used by testsuite
+$(TEST_LIB_NAME): $(LIB_NAME)
+	perl -p -e 'BEGIN{binmode(STDIN); binmode(STDOUT);}; s/cygwin1/cygwin0/g' < $? > $@
+
+# sublibs
+# import libraries for some subset of symbols indicated by given objects
+speclib=\
+	$(srcdir)/speclib $(toolopts) \
+	--exclude='cygwin' \
+	--exclude='(?i:dll)' \
+	--exclude='reloc' \
+	--exclude='^main$$' \
+	--exclude='^_main$$'
+
+libc.a: $(LIB_NAME) libm.a libpthread.a libutil.a
+	$(speclib) $^ -v $(@F)
+
+libm.a: $(LIB_NAME) $(newlib_build)/libm/libm.a $(addsuffix .o,$(basename $(MATH_FILES)))
+	$(speclib) $^ $(@F)
+
+libpthread.a: $(LIB_NAME) pthread.o thread.o libc/call_once.o libc/cnd.o \
+	      libc/mtx.o libc/thrd.o libc/tss.o
+	$(speclib) $^ $(@F)
+
+libutil.a: $(LIB_NAME) libc/bsdlib.o
+	$(speclib) $^ $(@F)
+
+libdl.a: $(LIB_NAME) dlfcn.o
+	$(speclib) $^ $(@F)
+
+libresolv.a: $(LIB_NAME) libc/minires.o
+	$(speclib) $^ $(@F)
+
+librt.a: $(LIB_NAME) posix_ipc.o
+	$(speclib) $^ $(@F)
+
+libacl.a: $(LIB_NAME) sec_posixacl.o
+	$(speclib) $^ $(@F)
+
+libssp.a: $(LIB_NAME) $(newlib_build)/libc/ssp/lib.a
+	$(speclib) $^ $(@F)
+
+#
+# all
+#
+
+all-local: $(LIB_NAME) $(TEST_LIB_NAME) $(SUBLIBS)
+
+#
+# clean
+#
+
+clean-local:
+	-rm -f $(BUILT_SOURCES)
+	-rm -f $(DEF_FILE) sigfe.s
+	-rm -f cygwin.sc cygdll.a cygwin.map $(TEST_DLL_NAME) cygwin1.dbg new-cygwin1.dll
+	-rm -f $(LIB_NAME) $(TEST_LIB_NAME) $(SUBLIBS)
+	-rm -f version.cc
+
+maintainer-clean-local:
+	-rm -f $(srcdir)/$(TLSOFFSETS_H) $(srcdir)/devices.cc
+
+#
+# install
+#
+
+man_MANS = regex/regex.3 regex/regex.7
+
+install-exec-hook: install-libs
+install-data-local: install-headers install-ldif
+
+install-libs:
+	@$(MKDIR_P) $(DESTDIR)$(bindir)
+	$(INSTALL_PROGRAM) $(TEST_DLL_NAME) $(DESTDIR)$(bindir)/$(DLL_NAME)
+	(cd $(DESTDIR)$(toollibdir) && ln -sf $(LIB_NAME) libg.a)
+
+install-headers:
+	cd $(srcdir)/include; \
+	for sub in `find . -type d -print | sort`; do \
+	    $(MKDIR_P) $(DESTDIR)$(toolincludedir)/$$sub; \
+	    for i in $$sub/*.h ; do \
+	      $(INSTALL_DATA) $$i $(DESTDIR)$(toolincludedir)/$$sub/`basename $$i` ; \
+	    done ; \
+	done ;
+
+install-ldif:
+	@$(MKDIR_P) $(DESTDIR)$(datarootdir)/cygwin
+	$(INSTALL_DATA) $(srcdir)/cygwin.ldif $(DESTDIR)$(datarootdir)/cygwin
+
+#
+# uninstall
+#
+
+uninstall-hook: uninstall-headers uninstall-ldif uninstall-libs
+
+uninstall-libs:
+	rm -f $(DESTDIR)$(bindir)/cygwin1.dll
+	rm -f $(DESTDIR)$(toollibdir)/libg.a
+
+uninstall-headers:
+	cd $(srcdir)/include; \
+	for sub in `find . -type d -print | sort`; do \
+	    for i in $$sub/*.h ; do \
+	      rm -f $(DESTDIR)$(toolincludedir)/$$sub/`basename $$i` ; \
+	    done ; \
+	done ;
+
+uninstall-ldif:
+	rm -f $(DESTDIR)$(datarootdir)/cygwin/cygwin.ldif
diff --git a/winsup/cygwin/config.h.in b/winsup/cygwin/config.h.in
index 5ddff249f..1c4940951 100644
--- a/winsup/cygwin/config.h.in
+++ b/winsup/cygwin/config.h.in
@@ -1,4 +1,4 @@
-/* config.h.in.  Generated from configure.ac by autoheader.  */
+/* cygwin/config.h.in.  Generated from configure.ac by autoheader.  */
 
 /* Define if DEBUGGING support is requested. */
 #undef DEBUGGING
diff --git a/winsup/doc/Makefile.am b/winsup/doc/Makefile.am
new file mode 100644
index 000000000..534d67480
--- /dev/null
+++ b/winsup/doc/Makefile.am
@@ -0,0 +1,162 @@
+# -*- Makefile -*- for winsup/doc
+#
+# 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.
+
+man1_MANS =
+man3_MANS =
+man5_MANS =
+
+doc_DATA = \
+	cygwin-ug-net/cygwin-ug-net.pdf \
+	cygwin-api/cygwin-api.pdf
+
+htmldir = $(datarootdir)/doc
+
+XMLTO=xmlto --skip-validation --with-dblatex
+DOCBOOK2XTEXI=@DOCBOOK2XTEXI@ --xinclude --info --utf8trans-map=charmap
+
+-include Makefile.dep
+
+.PHONY: install-extra-man install-etc
+
+all-local: Makefile.dep \
+	cygwin-api/cygwin-api.html \
+	cygwin-ug-net/cygwin-ug-net.html \
+	faq/faq.html faq/faq.body \
+	cygwin-ug-net/cygwin-ug-net-nochunks.html.gz \
+	api2man.stamp intro2man.stamp utils2man.stamp \
+	cygwin-api.info cygwin-ug-net.info
+
+clean-local:
+	rm -f Makefile.dep
+	rm -f *.html *.html.gz
+	rm -Rf cygwin-api cygwin-ug-net faq
+	rm -f api2man.stamp intro2man.stamp utils2man.stamp
+	rm -f *.1
+	rm -f *.3
+	rm -f *.5
+	rm -f *.info* charmap
+
+install-html-local: cygwin-ug-net/cygwin-ug-net.html cygwin-api/cygwin-api.html
+	@$(MKDIR_P) $(DESTDIR)$(htmldir)/cygwin-ug-net
+	$(INSTALL_DATA) cygwin-ug-net/*.html $(DESTDIR)$(htmldir)/cygwin-ug-net
+	(cd $(DESTDIR)$(htmldir)/cygwin-ug-net && ln -f cygwin-ug-net.html index.html)
+	$(INSTALL_DATA) $(srcdir)/docbook.css $(DESTDIR)$(htmldir)/cygwin-ug-net
+	@$(MKDIR_P) $(DESTDIR)$(htmldir)/cygwin-api
+	$(INSTALL_DATA) cygwin-api/*.html $(DESTDIR)$(htmldir)/cygwin-api
+	(cd $(DESTDIR)$(htmldir)/cygwin-api && ln -f cygwin-api.html index.html)
+	$(INSTALL_DATA) $(srcdir)/docbook.css $(DESTDIR)$(htmldir)/cygwin-api
+
+install-extra-man: api2man.stamp intro2man.stamp utils2man.stamp
+	@$(MKDIR_P) $(DESTDIR)$(man1dir)
+	$(INSTALL_DATA) *.1 $(DESTDIR)$(man1dir)
+	@$(MKDIR_P) $(DESTDIR)$(man3dir)
+	$(INSTALL_DATA) *.3 $(DESTDIR)$(man3dir)
+	@$(MKDIR_P) $(DESTDIR)$(man5dir)
+	$(INSTALL_DATA) *.5 $(DESTDIR)$(man5dir)
+
+install-info-local: cygwin-ug-net.info cygwin-api.info
+	@$(MKDIR_P) $(DESTDIR)$(infodir)
+	$(INSTALL_DATA) *.info* $(DESTDIR)$(infodir)
+
+install-etc:
+	@$(MKDIR_P) $(DESTDIR)$(sysconfdir)/postinstall
+	$(INSTALL_SCRIPT) $(srcdir)/etc.postinstall.cygwin-doc.sh $(DESTDIR)$(sysconfdir)/postinstall/cygwin-doc.sh
+	@$(MKDIR_P) $(DESTDIR)$(sysconfdir)/preremove
+	$(INSTALL_SCRIPT) $(srcdir)/etc.preremove.cygwin-doc.sh $(DESTDIR)$(sysconfdir)/preremove/cygwin-doc.sh
+
+install-data-hook: install-extra-man install-html-local install-info-local install-etc
+
+uninstall-extra-man:
+	for i in *.1 ; do \
+	    rm -f $(DESTDIR)$(man1dir)/$$i ; \
+	done
+	for i in *.3 ; do \
+	    rm -f $(DESTDIR)$(man3dir)/$$i ; \
+	done
+	for i in *.5 ; do \
+	    rm -f $(DESTDIR)$(man5dir)/$$i ; \
+	done
+
+uninstall-html:
+	for i in cygwin-ug-net/*.html ; do \
+	    rm -f $(DESTDIR)$(htmldir)/$$i ; \
+	done ;
+	rm -f $(DESTDIR)$(htmldir)/cygwin-ug-net/index.html
+	rm -f $(DESTDIR)$(htmldir)/cygwin-ug-net/docbook.css
+	for i in cygwin-api/*.html ; do \
+	    rm -f $(DESTDIR)$(htmldir)/$$i ; \
+	done ;
+	rm -f $(DESTDIR)$(htmldir)/cygwin-api/index.html
+	rm -f $(DESTDIR)$(htmldir)/cygwin-api/docbook.css
+
+uninstall-info:
+	for i in *.info* ; do \
+	    rm -f $(DESTDIR)$(infodir)/$$i ; \
+	done ;
+
+uninstall-etc:
+	rm -f $(DESTDIR)$(sysconfdir)/postinstall/cygwin-doc.sh
+	rm -f $(DESTDIR)$(sysconfdir)/preremove/cygwin-doc.sh
+
+uninstall-hook: uninstall-extra-man uninstall-html uninstall-info uninstall-etc
+
+# nochunks ug html is not installed, but will be deployed to website
+cygwin-ug-net/cygwin-ug-net-nochunks.html.gz: $(cygwin-ug-net_SOURCES) html.xsl
+	$(XMLTO) html-nochunks -m $(srcdir)/html.xsl $<
+	@$(MKDIR_P) cygwin-ug-net
+	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_SOURCES) html.xsl
+	$(XMLTO) html -o cygwin-ug-net/ -m $(srcdir)/html.xsl $<
+
+cygwin-ug-net/cygwin-ug-net.pdf: $(cygwin-ug-net_SOURCES) fo.xsl
+	$(XMLTO) pdf -o cygwin-ug-net/ -m $(srcdir)/fo.xsl $<
+
+utils2man.stamp: $(cygwin-ug-net_SOURCES) man.xsl
+	$(XMLTO) man -m $(srcdir)/man.xsl $<
+	@touch $@
+
+cygwin-ug-net.info: $(cygwin-ug-net_SOURCES) charmap
+	$(DOCBOOK2XTEXI) $(srcdir)/cygwin-ug-net.xml --string-param output-file=cygwin-ug-net
+
+cygwin-api/cygwin-api.html: $(cygwin-api_SOURCES) html.xsl
+	$(XMLTO) html -o cygwin-api/ -m $(srcdir)/html.xsl $<
+
+cygwin-api/cygwin-api.pdf: $(cygwin-api_SOURCES) fo.xsl
+	$(XMLTO) pdf -o cygwin-api/ -m $(srcdir)/fo.xsl $<
+
+api2man.stamp: $(cygwin-api_SOURCES) man.xsl
+	$(XMLTO) man -m $(srcdir)/man.xsl $<
+	@touch $@
+
+cygwin-api.info: $(cygwin-api_SOURCES) charmap
+	$(DOCBOOK2XTEXI) $(srcdir)/cygwin-api.xml --string-param output-file=cygwin-api
+
+# this generates a custom charmap for docbook2x-texi which has a mapping for &reg;
+charmap:
+	cp /usr/share/docbook2X/charmaps/texi.charmap charmap
+	echo "ae (R)" >>charmap
+
+intro2man.stamp: intro.xml man.xsl
+	$(XMLTO) man -m $(srcdir)/man.xsl $<
+	@echo ".so intro.1" >cygwin.1
+	@touch $@
+
+faq/faq.html: $(faq_SOURCES) html.xsl
+	$(XMLTO) html -o faq -m $(srcdir)/html.xsl $(srcdir)/faq.xml
+	sed -i 's;<a name="id[mp][0-9]*"></a>;;g' faq/faq.html
+
+# faq body is not installed, but is intended to be deployed to website, where it
+# can be SSI included in a framing page
+faq/faq.body: faq/faq.html
+	$(srcdir)/bodysnatcher.pl $<
+
+Makefile.dep: cygwin-ug-net.xml cygwin-api.xml faq.xml intro.xml
+	cd $(srcdir) && ./xidepend $^ > "$(CURDIR)/$@"
diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
new file mode 100644
index 000000000..4b8c7dbb7
--- /dev/null
+++ b/winsup/testsuite/Makefile.am
@@ -0,0 +1,64 @@
+# Makefile.am for Cygwin's testsuite.
+#
+# 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.
+
+# This makefile requires GNU make.
+
+noinst_LIBRARIES = libltp.a
+
+libltp_a_CPPFLAGS=-I$(srcdir)/libltp/include
+
+libltp_a_SOURCES = \
+	libltp/lib/dataascii.c \
+	libltp/lib/databin.c \
+	libltp/lib/datapid.c \
+	libltp/lib/forker.c \
+	libltp/lib/get_high_address.c \
+	libltp/lib/libtestsuite.c \
+	libltp/lib/open_flags.c \
+	libltp/lib/parse_opts.c \
+	libltp/lib/pattern.c \
+	libltp/lib/rmobj.c \
+	libltp/lib/search_path.c \
+	libltp/lib/str_to_bytes.c \
+	libltp/lib/string_to_tokens.c \
+	libltp/lib/tst_res.c \
+	libltp/lib/tst_sig.c \
+	libltp/lib/tst_tmpdir.c \
+	libltp/lib/write_log.c
+
+DEJATOOL = winsup
+
+# Add '-v' to RUNTESTFLAGS if V=1
+RUNTESTFLAGS_1 = -v
+RUNTESTFLAGS = $(RUNTESTFLAGS_$(V))
+
+# a temporary directory, to be used for files created by tests
+tmpdir = $(abspath $(objdir)/testsuite/tmp/)
+# the same temporary directory, as an absolute, /cygdrive path (so it can be
+# understood by the test DLL, which will have a different mount table)
+testdll_tmpdir = $(shell cygpath -ma $(tmpdir) | sed -e 's#^\([A-Z]\):#/cygdrive/\L\1#')
+
+site-extra.exp: ../config.status Makefile
+	@rm -f ./tmp0
+	@echo "set runtime_root \"`pwd`/../cygwin\"" >> ./tmp0
+	@echo "set CC \"$(CC)\"" >> ./tmp0
+	@echo "set CFLAGS \"\"" >> ./tmp0
+	@echo "set MINGW_CXX \"$(MINGW_CXX)\"" >> ./tmp0
+	@echo "set tmpdir $(tmpdir)" >> ./tmp0
+	@echo "set testdll_tmpdir $(testdll_tmpdir)" >> ./tmp0
+	@echo "set ltp_includes \"$(srcdir)/libltp/include\"" >> ./tmp0
+	@echo "set ltp_libs \"`pwd`/libltp.a\"" >> ./tmp0
+	@echo "set cygrun \"`pwd`/cygrun/cygrun\"" >> ./tmp0
+	@mv ./tmp0 site-extra.exp
+
+EXTRA_DEJAGNU_SITE_CONFIG = site-extra.exp
+
+clean-local:
+	rm -f *.log *.exe *.exp *.bak *.stackdump winsup.sum
+
+SUBDIRS = cygrun
diff --git a/winsup/testsuite/config/default.exp b/winsup/testsuite/config/default.exp
index 8033ea627..7ef16ee6a 100644
--- a/winsup/testsuite/config/default.exp
+++ b/winsup/testsuite/config/default.exp
@@ -1,7 +1,7 @@
 proc winsup_version {} {
     global env
-    global rootme
-    clone_output "\n[exec grep -a ^%%% $rootme/../cygwin/cygwin0.dll]\n"
+    global runtime_root
+    clone_output "\n[exec grep -a ^%%% $runtime_root/cygwin0.dll]\n"
     if { [info exists env(CYGWIN)] } {
         clone_output "CYGWIN=$env(CYGWIN)\n"
     } else {
diff --git a/winsup/testsuite/cygrun/Makefile.am b/winsup/testsuite/cygrun/Makefile.am
new file mode 100644
index 000000000..eb3b41224
--- /dev/null
+++ b/winsup/testsuite/cygrun/Makefile.am
@@ -0,0 +1,21 @@
+# Makefile.am for Cygwin the testsuite wrapper cygrun.
+#
+# 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.
+
+# This makefile requires GNU make.
+
+# This is built with the MinGW compiler, so is in a separate Makefile here
+# because it's tricky with Automake to use different compilers for the same
+# language in the same Makefile.
+
+override CC = @MINGW_CC@
+INCLUDES =
+
+noinst_PROGRAMS = cygrun
+
+cygrun_SOURCES = \
+	../cygrun.c
diff --git a/winsup/testsuite/winsup.api/winsup.exp b/winsup/testsuite/winsup.api/winsup.exp
index 4978136a1..584aa5755 100644
--- a/winsup/testsuite/winsup.api/winsup.exp
+++ b/winsup/testsuite/winsup.api/winsup.exp
@@ -9,13 +9,15 @@ if { ! [isnative] } {
 set rv ""
 
 set ltp_includes "-I$ltp_includes"
-set ltp_libs "$rootme/libltp.a"
+set ltp_libs "$ltp_libs"
 
 set add_includes $ltp_includes
 set add_libs $ltp_libs
 
 set test_filter ""
 
+set env(PATH) "$runtime_root:$env(PATH)"
+
 if { [info exists env(CYGWIN_TESTSUITE_TESTS)] } {
     set test_filter "$env(CYGWIN_TESTSUITE_TESTS)"
 }
@@ -69,7 +71,7 @@ foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/$subdir/*/*.{cc
 	       set redirect_output /dev/null
 	    }
 	    file mkdir $tmpdir/$base
-	    ws_spawn "$rootme/cygrun ./$base.exe $testdll_tmpdir/$base > $redirect_output"
+	    ws_spawn "$cygrun ./$base.exe $testdll_tmpdir/$base > $redirect_output"
 	    file delete -force $tmpdir/$base
 	    if { $rv } {
 		fail "$testcase (execute)"
diff --git a/winsup/utils/Makefile.am b/winsup/utils/Makefile.am
new file mode 100644
index 000000000..9e5fc8cc0
--- /dev/null
+++ b/winsup/utils/Makefile.am
@@ -0,0 +1,81 @@
+# Makefile for Cygwin utilities
+
+# 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 $(top_srcdir)/Makefile.am.common
+
+CFLAGS_COMMON=-Wimplicit-fallthrough=4 -Werror
+AM_CFLAGS=$(cflags_common) $(CFLAGS_COMMON)
+AM_CXXFLAGS=$(cxxflags_common) $(CFLAGS_COMMON)
+
+bin_PROGRAMS = \
+	chattr \
+	cygpath \
+	gencat \
+	getconf \
+	getfacl \
+	kill \
+	ldd \
+	locale \
+	lsattr \
+	minidumper \
+	mkgroup \
+	mkpasswd \
+	mount \
+	passwd \
+	pldd \
+	ps \
+	regtool \
+	setfacl \
+	setmetamode \
+	ssp \
+	tzset \
+	umount
+
+# dumper is only built if libbfd.a available
+if BUILD_DUMPER
+bin_PROGRAMS += dumper
+endif
+
+# If prog_SOURCES is not specified, automake defaults to the single file prog.c
+cygpath_SOURCES = cygpath.cc
+dumper_SOURCES = dumper.cc module_info.cc
+kill_SOURCES = kill.cc
+ldd_SOURCES = ldd.cc
+locale_SOURCES = locale.cc
+minidumper_SOURCES = minidumper.cc
+mount_SOURCES = mount.cc path.cc
+ps_SOURCES = ps.cc
+regtool_SOURCES = regtool.cc
+umount_SOURCES = umount.cc
+
+# rules to create/update tzmap.h from an online resource
+.PHONY: tzmap
+tzmap:
+	$(srcdir)/tzmap-from-unicode.org > $(srcdir)/$@.h
+
+tzmap.h:
+	$(srcdir)/tzmap-from-unicode.org > $(srcdir)/$@
+
+BUILT_SOURCES = tzmap.h
+
+AM_LDFLAGS = -static -Wl,--enable-auto-import
+LDADD = -lnetapi32
+
+cygpath_CXXFLAGS = -fno-threadsafe-statics $(AM_CXXFLAGS)
+cygpath_LDADD = $(LDADD) -luserenv -lntdll
+dumper_CXXFLAGS = -I$(top_srcdir)/../include $(AM_CXXFLAGS)
+dumper_LDADD = $(LDADD) -lpsapi -lbfd -lintl -liconv -liberty -lz -lntdll
+ldd_LDADD = $(LDADD) -lpsapi -lntdll
+mount_CXXFLAGS = -DFSTAB_ONLY $(AM_CXXFLAGS)
+minidumper_LDADD = $(LDADD) -ldbghelp
+pldd_LDADD = $(LDADD) -lpsapi
+ps_LDADD = $(LDADD) -lpsapi -lntdll
+
+if CROSS_BOOTSTRAP
+SUBDIRS = mingw
+endif
diff --git a/winsup/utils/mingw/Makefile.am b/winsup/utils/mingw/Makefile.am
new file mode 100644
index 000000000..88882c423
--- /dev/null
+++ b/winsup/utils/mingw/Makefile.am
@@ -0,0 +1,50 @@
+# Makefile for Cygwin utilities
+
+# 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.
+
+# We put utilities built with a MinGW compiler in a separate Makefile here
+# because it's tricky with Automake to use different compilers for the same
+# language in the same Makefile.
+
+override CXX = @MINGW_CXX@
+INCLUDES =
+
+include $(top_srcdir)/Makefile.am.common
+
+CFLAGS_COMMON=-Wimplicit-fallthrough=4 -Werror
+AM_CXXFLAGS=-fno-exceptions -fno-rtti -fno-use-cxa-atexit $(flags_common) $(CFLAGS_COMMON)
+
+bin_PROGRAMS = \
+	cygcheck \
+	cygwin-console-helper \
+	ldh \
+	strace
+
+cygcheck_SOURCES = \
+	../bloda.cc \
+	../cygcheck.cc \
+	../dump_setup.cc \
+	../path.cc
+cygcheck_LDADD = -lz -lwininet -lpsapi -lntdll
+
+cygwin_console_helper_SOURCES = ../cygwin-console-helper.cc
+
+ldh_SOURCES = ../ldh.cc
+
+strace_SOURCES = \
+	../path.cc \
+	../strace.cc
+strace_LDADD = -lntdll
+
+noinst_PROGRAMS = path-testsuite
+
+path_testsuite_SOURCES = \
+	../path.cc \
+	../testsuite.cc
+path_testsuite_CXXFLAGS = -DTESTSUITE
+
+TESTS = path-testsuite
-- 
2.31.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-20 20:13 [PATCH] Use automake (v5) Jon Turney
@ 2021-04-20 20:15 ` Jon Turney
  2021-04-21 16:40   ` Corinna Vinschen
  2021-04-27 15:50 ` Jon Turney
  2021-05-02 15:28 ` Jon Turney
  2 siblings, 1 reply; 15+ messages in thread
From: Jon Turney @ 2021-04-20 20:15 UTC (permalink / raw)
  To: Cygwin Patches

On 20/04/2021 21:13, Jon Turney wrote:
> For ease of reviewing, this patch doesn't contain changes to generated
> files which would be made by running ./autogen.sh.

Sorry about getting distracted from this.  To summarize what I believe 
were the outstanding issues with v3 [1]:

[1] https://cygwin.com/pipermail/cygwin-patches/2020q4/010827.html

* 'INCLUDES' is the old name for 'AM_CPPFLAGS' warning from autogen.sh

I plan to clean this up in a future patch

* 'ps$(EXEEXT)' previously defined' warning from autogen.sh

It seems to be a shortcoming of automake that there's no way to suppress 
just that warning.

One possible solution is build ps.exe with a different name and rename 
it while installing, but I think that is counter-productive (in the 
sense that it trades this warning for making the build more complex to 
understand)

* some object files are in a unexpected places in the build file 
hierarchy (compared to naive expectations and/or the non-automake build)

I'm not sure if this is merely an aesthetic issue, or if there are 
problems this causes.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-20 20:15 ` Jon Turney
@ 2021-04-21 16:40   ` Corinna Vinschen
  2021-04-22 11:57     ` Corinna Vinschen
  0 siblings, 1 reply; 15+ messages in thread
From: Corinna Vinschen @ 2021-04-21 16:40 UTC (permalink / raw)
  To: cygwin-patches

On Apr 20 21:15, Jon Turney wrote:
> On 20/04/2021 21:13, Jon Turney wrote:
> > For ease of reviewing, this patch doesn't contain changes to generated
> > files which would be made by running ./autogen.sh.
> 
> Sorry about getting distracted from this.  To summarize what I believe were
> the outstanding issues with v3 [1]:
> 
> [1] https://cygwin.com/pipermail/cygwin-patches/2020q4/010827.html
> 
> * 'INCLUDES' is the old name for 'AM_CPPFLAGS' warning from autogen.sh
> 
> I plan to clean this up in a future patch
> 
> * 'ps$(EXEEXT)' previously defined' warning from autogen.sh
> 
> It seems to be a shortcoming of automake that there's no way to suppress
> just that warning.
> 
> One possible solution is build ps.exe with a different name and rename it
> while installing, but I think that is counter-productive (in the sense that
> it trades this warning for making the build more complex to understand)
> 
> * some object files are in a unexpected places in the build file hierarchy
> (compared to naive expectations and/or the non-automake build)

This is the only minor qualm I have with this patch.  It would be nice
to have the mingw sources and .o files in the mingw subdir.  It would
simply be a bit cleaner.  The files shared between cygwin and mingw
(that's only path.cc, I think) could be handled by an include, i. e.

  utils/

    path.cc (full implementation)

  utils/mingw/

    path.cc:

      #include "../path.cc"

However, this isn't a showstopper, feel free to push what you're comfortable
with.

Still, wWhat do you think?  Any problem to move the mingw stuff to the
mingw subdir entirely?


Thanks,
Corinna

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-21 16:40   ` Corinna Vinschen
@ 2021-04-22 11:57     ` Corinna Vinschen
  2021-04-26 15:03       ` Corinna Vinschen
  0 siblings, 1 reply; 15+ messages in thread
From: Corinna Vinschen @ 2021-04-22 11:57 UTC (permalink / raw)
  To: cygwin-patches

On Apr 21 18:40, Corinna Vinschen wrote:
> On Apr 20 21:15, Jon Turney wrote:
> > On 20/04/2021 21:13, Jon Turney wrote:
> > > For ease of reviewing, this patch doesn't contain changes to generated
> > > files which would be made by running ./autogen.sh.
> > 
> > Sorry about getting distracted from this.  To summarize what I believe were
> > the outstanding issues with v3 [1]:
> > 
> > [1] https://cygwin.com/pipermail/cygwin-patches/2020q4/010827.html
> > 
> > * 'INCLUDES' is the old name for 'AM_CPPFLAGS' warning from autogen.sh
> > 
> > I plan to clean this up in a future patch
> > 
> > * 'ps$(EXEEXT)' previously defined' warning from autogen.sh
> > 
> > It seems to be a shortcoming of automake that there's no way to suppress
> > just that warning.
> > 
> > One possible solution is build ps.exe with a different name and rename it
> > while installing, but I think that is counter-productive (in the sense that
> > it trades this warning for making the build more complex to understand)
> > 
> > * some object files are in a unexpected places in the build file hierarchy
> > (compared to naive expectations and/or the non-automake build)
> 
> This is the only minor qualm I have with this patch.  It would be nice
> to have the mingw sources and .o files in the mingw subdir.  It would
> simply be a bit cleaner.  The files shared between cygwin and mingw
> (that's only path.cc, I think) could be handled by an include, i. e.
> 
>   utils/
> 
>     path.cc (full implementation)
> 
>   utils/mingw/
> 
>     path.cc:
> 
>       #include "../path.cc"

I wonder if it wouldn't make sense to split out the mingw-only parts
of path.cc entirely.  I had a quick view into the file and it turns
out that of the almost 1000 lines in this file, only about 100 lines
are used by mount.  All the rest is only used by mingw code, i. e.,
cygcheck and strace.

That's obviously not part of this patch, but something we should keep
in mind for a later cleanup.


Corinna

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-22 11:57     ` Corinna Vinschen
@ 2021-04-26 15:03       ` Corinna Vinschen
  2021-04-27 15:54         ` Jon Turney
  0 siblings, 1 reply; 15+ messages in thread
From: Corinna Vinschen @ 2021-04-26 15:03 UTC (permalink / raw)
  To: cygwin-patches

On Apr 22 13:57, Corinna Vinschen wrote:
> On Apr 21 18:40, Corinna Vinschen wrote:
> > On Apr 20 21:15, Jon Turney wrote:
> > > On 20/04/2021 21:13, Jon Turney wrote:
> > > > For ease of reviewing, this patch doesn't contain changes to generated
> > > > files which would be made by running ./autogen.sh.
> > > 
> > > Sorry about getting distracted from this.  To summarize what I believe were
> > > the outstanding issues with v3 [1]:
> > > 
> > > [1] https://cygwin.com/pipermail/cygwin-patches/2020q4/010827.html
> > > 
> > > * 'INCLUDES' is the old name for 'AM_CPPFLAGS' warning from autogen.sh
> > > 
> > > I plan to clean this up in a future patch
> > > 
> > > * 'ps$(EXEEXT)' previously defined' warning from autogen.sh
> > > 
> > > It seems to be a shortcoming of automake that there's no way to suppress
> > > just that warning.
> > > 
> > > One possible solution is build ps.exe with a different name and rename it
> > > while installing, but I think that is counter-productive (in the sense that
> > > it trades this warning for making the build more complex to understand)
> > > 
> > > * some object files are in a unexpected places in the build file hierarchy
> > > (compared to naive expectations and/or the non-automake build)
> > 
> > This is the only minor qualm I have with this patch.  It would be nice
> > to have the mingw sources and .o files in the mingw subdir.  It would
> > simply be a bit cleaner.  The files shared between cygwin and mingw
> > (that's only path.cc, I think) could be handled by an include, i. e.
> > 
> >   utils/
> > 
> >     path.cc (full implementation)
> > 
> >   utils/mingw/
> > 
> >     path.cc:
> > 
> >       #include "../path.cc"
> 
> I wonder if it wouldn't make sense to split out the mingw-only parts
> of path.cc entirely.  I had a quick view into the file and it turns
> out that of the almost 1000 lines in this file, only about 100 lines
> are used by mount.  All the rest is only used by mingw code, i. e.,
> cygcheck and strace.
> 
> That's obviously not part of this patch, but something we should keep
> in mind for a later cleanup.

I tried this as a POC and it's not much of a problem.  See the below
patch.  Cleaning up the includes is still to do.


Corinna


diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in
index e4f55dd3c50e..a2d8c426fdac 100644
--- a/winsup/utils/Makefile.in
+++ b/winsup/utils/Makefile.in
@@ -58,10 +58,10 @@ endif
 # List all objects to be compiled in MinGW mode.  Any object not on this
 # list will will be compiled in Cygwin mode implicitly, so there is no
 # need for a CYGWIN_OBJS.
-MINGW_OBJS := bloda.o cygcheck.o cygwin-console-helper.o dump_setup.o ldh.o path.o strace.o
+MINGW_OBJS := bloda.o cygcheck.o cygwin-console-helper.o dump_setup.o ldh.o mingw-path.o strace.o
 MINGW_LDFLAGS:=-static
 
-CYGCHECK_OBJS:=cygcheck.o bloda.o path.o dump_setup.o
+CYGCHECK_OBJS:=cygcheck.o bloda.o mingw-path.o dump_setup.o
 ZLIB:=-lz
 
 .PHONY: all
@@ -69,12 +69,10 @@ all:
 
 # If a binary should link in any objects besides the .o with the same
 # name as the binary, then list those here.
-strace.exe: path.o
-cygcheck.exe: cygcheck.o bloda.o path.o dump_setup.o
+strace.exe: mingw-path.o
+cygcheck.exe: cygcheck.o bloda.o mingw-path.o dump_setup.o
 
-path-mount.o: path.cc
-	${COMPILE.cc} -c -DFSTAB_ONLY -o $@ $<
-mount.exe: path-mount.o
+mount.exe: path.o
 
 .PHONY: tzmap
 tzmap:
diff --git a/winsup/utils/mingw-path.cc b/winsup/utils/mingw-path.cc
new file mode 100644
index 000000000000..6c60a8eb9bae
--- /dev/null
+++ b/winsup/utils/mingw-path.cc
@@ -0,0 +1,795 @@
+/* path.cc
+
+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. */
+
+/* The purpose of this file is to hide all the details about accessing
+   Cygwin's mount table, shortcuts, etc.  If the format or location of
+   the mount table, or the shortcut format changes, this is the file to
+   change to match it. */
+
+#include "path.cc"
+
+/* Used when treating / and \ as equivalent. */
+#define isslash(ch) \
+  ({ \
+      char __c = (ch); \
+      ((__c) == '/' || (__c) == '\\'); \
+   })
+
+
+static const GUID GUID_shortcut =
+  {0x00021401L, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
+
+enum {
+  WSH_FLAG_IDLIST = 0x01,	/* Contains an ITEMIDLIST. */
+  WSH_FLAG_FILE = 0x02,		/* Contains a file locator element. */
+  WSH_FLAG_DESC = 0x04,		/* Contains a description. */
+  WSH_FLAG_RELPATH = 0x08,	/* Contains a relative path. */
+  WSH_FLAG_WD = 0x10,		/* Contains a working dir. */
+  WSH_FLAG_CMDLINE = 0x20,	/* Contains command line args. */
+  WSH_FLAG_ICON = 0x40		/* Contains a custom icon. */
+};
+
+struct win_shortcut_hdr
+  {
+    DWORD size;		/* Header size in bytes.  Must contain 0x4c. */
+    GUID magic;		/* GUID of shortcut files. */
+    DWORD flags;	/* Content flags.  See above. */
+
+    /* The next fields from attr to icon_no are always set to 0 in Cygwin
+       and U/Win shortcuts. */
+    DWORD attr;	/* Target file attributes. */
+    FILETIME ctime;	/* These filetime items are never touched by the */
+    FILETIME mtime;	/* system, apparently. Values don't matter. */
+    FILETIME atime;
+    DWORD filesize;	/* Target filesize. */
+    DWORD icon_no;	/* Icon number. */
+
+    DWORD run;		/* Values defined in winuser.h. Use SW_NORMAL. */
+    DWORD hotkey;	/* Hotkey value. Set to 0.  */
+    DWORD dummy[2];	/* Future extension probably. Always 0. */
+  };
+
+static bool
+cmp_shortcut_header (win_shortcut_hdr *file_header)
+{
+  /* A Cygwin or U/Win shortcut only contains a description and a relpath.
+     Cygwin shortcuts also might contain an ITEMIDLIST. The run type is
+     always set to SW_NORMAL. */
+  return file_header->size == sizeof (win_shortcut_hdr)
+      && !memcmp (&file_header->magic, &GUID_shortcut, sizeof GUID_shortcut)
+      && (file_header->flags & ~WSH_FLAG_IDLIST)
+	 == (WSH_FLAG_DESC | WSH_FLAG_RELPATH)
+      && file_header->run == SW_NORMAL;
+}
+
+int
+get_word (HANDLE fh, int offset)
+{
+  unsigned short rv;
+  unsigned r;
+
+  SetLastError(NO_ERROR);
+  if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
+      && GetLastError () != NO_ERROR)
+    return -1;
+
+  if (!ReadFile (fh, &rv, 2, (DWORD *) &r, 0))
+    return -1;
+
+  return rv;
+}
+
+/*
+ * Check the value of GetLastError() to find out whether there was an error.
+ */
+int
+get_dword (HANDLE fh, int offset)
+{
+  int rv;
+  unsigned r;
+
+  SetLastError(NO_ERROR);
+  if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
+      && GetLastError () != NO_ERROR)
+    return -1;
+
+  if (!ReadFile (fh, &rv, 4, (DWORD *) &r, 0))
+    return -1;
+
+  return rv;
+}
+
+#define EXE_MAGIC ((int)*(unsigned short *)"MZ")
+#define SHORTCUT_MAGIC ((int)*(unsigned short *)"L\0")
+#define SYMLINK_COOKIE "!<symlink>"
+#define SYMLINK_MAGIC ((int)*(unsigned short *)SYMLINK_COOKIE)
+
+bool
+is_exe (HANDLE fh)
+{
+  int magic = get_word (fh, 0x0);
+  return magic == EXE_MAGIC;
+}
+
+bool
+is_symlink (HANDLE fh)
+{
+  bool ret = false;
+  int magic = get_word (fh, 0x0);
+  if (magic != SHORTCUT_MAGIC && magic != SYMLINK_MAGIC)
+    goto out;
+  DWORD got;
+  BY_HANDLE_FILE_INFORMATION local;
+  if (!GetFileInformationByHandle (fh, &local))
+    return false;
+  if (magic == SHORTCUT_MAGIC)
+    {
+      DWORD size;
+      if (!local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+	goto out; /* Not a Cygwin symlink. */
+      if ((size = GetFileSize (fh, NULL)) > 8192)
+	goto out; /* Not a Cygwin symlink. */
+      char buf[size];
+      SetFilePointer (fh, 0, 0, FILE_BEGIN);
+      if (!ReadFile (fh, buf, size, &got, 0))
+	goto out;
+      if (got != size || !cmp_shortcut_header ((win_shortcut_hdr *) buf))
+	goto out; /* Not a Cygwin symlink. */
+      /* TODO: check for invalid path contents
+	 (see symlink_info::check() in ../cygwin/path.cc) */
+    }
+  else /* magic == SYMLINK_MAGIC */
+    {
+      if (!(local.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
+	goto out; /* Not a Cygwin symlink. */
+      char buf[sizeof (SYMLINK_COOKIE) - 1];
+      SetFilePointer (fh, 0, 0, FILE_BEGIN);
+      if (!ReadFile (fh, buf, sizeof (buf), &got, 0))
+	goto out;
+      if (got != sizeof (buf) ||
+	  memcmp (buf, SYMLINK_COOKIE, sizeof (buf)) != 0)
+	goto out; /* Not a Cygwin symlink. */
+    }
+  ret = true;
+out:
+  SetFilePointer (fh, 0, 0, FILE_BEGIN);
+  return ret;
+}
+
+/* Assumes is_symlink(fh) is true */
+bool
+readlink (HANDLE fh, char *path, size_t maxlen)
+{
+  DWORD rv;
+  char *buf, *cp;
+  unsigned short len;
+  win_shortcut_hdr *file_header;
+  BY_HANDLE_FILE_INFORMATION fi;
+
+  if (!GetFileInformationByHandle (fh, &fi)
+      || fi.nFileSizeHigh != 0
+      || fi.nFileSizeLow > 4 * 65536)
+    return false;
+
+  buf = (char *) alloca (fi.nFileSizeLow + 1);
+  file_header = (win_shortcut_hdr *) buf;
+
+  if (!ReadFile (fh, buf, fi.nFileSizeLow, &rv, NULL)
+      || rv != fi.nFileSizeLow)
+    return false;
+
+  if (fi.nFileSizeLow > sizeof (file_header)
+      && cmp_shortcut_header (file_header))
+    {
+      cp = buf + sizeof (win_shortcut_hdr);
+      if (file_header->flags & WSH_FLAG_IDLIST) /* Skip ITEMIDLIST */
+	cp += *(unsigned short *) cp + 2;
+      if (!(len = *(unsigned short *) cp))
+	return false;
+      cp += 2;
+      /* Has appended full path?  If so, use it instead of description. */
+      unsigned short relpath_len = *(unsigned short *) (cp + len);
+      if (cp + len + 2 + relpath_len < buf + fi.nFileSizeLow)
+	{
+	  cp += len + 2 + relpath_len;
+	  len = *(unsigned short *) cp;
+	  cp += 2;
+	}
+      if (*(PWCHAR) cp == 0xfeff)	/* BOM */
+	{
+	  size_t wlen = wcstombs (NULL, (wchar_t *) (cp + 2), 0);
+	  if (wlen == (size_t) -1 || wlen + 1 > maxlen)
+	    return false;
+	  wcstombs (path, (wchar_t *) (cp + 2), wlen + 1);
+	}
+      else if ((size_t) (len + 1) > maxlen)
+	return false;
+      else
+	memcpy (path, cp, len);
+      path[len] = '\0';
+      return true;
+    }
+  else if (strncmp (buf, SYMLINK_COOKIE, strlen (SYMLINK_COOKIE)) == 0
+	   && buf[fi.nFileSizeLow - 1] == '\0')
+    {
+      cp = buf + strlen (SYMLINK_COOKIE);
+      if (*(PWCHAR) cp == 0xfeff)	/* BOM */
+	{
+	  size_t wlen = wcstombs (NULL, (wchar_t *) (cp + 2), 0);
+	  if (wlen == (size_t) -1 || wlen + 1 > maxlen)
+	    return false;
+	  wcstombs (path, (wchar_t *) (cp + 2), wlen + 1);
+	}
+      else if (fi.nFileSizeLow - strlen (SYMLINK_COOKIE) > maxlen)
+	return false;
+      else
+	strcpy (path, cp);
+      return true;
+    }
+  else
+    return false;
+}
+
+static struct opt
+{
+  const char *name;
+  unsigned val;
+  bool clear;
+} oopts[] =
+{
+  {"acl", MOUNT_NOACL, 1},
+  {"auto", 0, 0},
+  {"binary", MOUNT_TEXT, 1},
+  {"cygexec", MOUNT_CYGWIN_EXEC, 0},
+  {"dos", MOUNT_DOS, 0},
+  {"exec", MOUNT_EXEC, 0},
+  {"ihash", MOUNT_IHASH, 0},
+  {"noacl", MOUNT_NOACL, 0},
+  {"nosuid", 0, 0},
+  {"notexec", MOUNT_NOTEXEC, 0},
+  {"nouser", MOUNT_SYSTEM, 0},
+  {"override", MOUNT_OVERRIDE, 0},
+  {"posix=0", MOUNT_NOPOSIX, 0},
+  {"posix=1", MOUNT_NOPOSIX, 1},
+  {"text", MOUNT_TEXT, 0},
+  {"user", MOUNT_SYSTEM, 1}
+};
+
+#ifndef TESTSUITE
+static bool
+read_flags (char *options, unsigned &flags)
+{
+  while (*options)
+    {
+      char *p = strchr (options, ',');
+      if (p)
+	*p++ = '\0';
+      else
+	p = strchr (options, '\0');
+
+      for (opt *o = oopts;
+	   o < (oopts + (sizeof (oopts) / sizeof (oopts[0])));
+	   o++)
+	if (strcmp (options, o->name) == 0)
+	  {
+	    if (o->clear)
+	      flags &= ~o->val;
+	    else
+	      flags |= o->val;
+	    goto gotit;
+	  }
+      return false;
+
+    gotit:
+      options = p;
+    }
+  return true;
+}
+
+#define BUFSIZE 65536
+
+static char *
+get_user ()
+{
+  static char user[UNLEN + 1];
+  char *userenv;
+
+  user[0] = '\0';
+  if ((userenv = getenv ("USER")) || (userenv = getenv ("USERNAME")))
+    strncat (user, userenv, UNLEN);
+  return user;
+}
+
+void
+from_fstab (bool user, PWCHAR path, PWCHAR path_end)
+{
+  mnt_t *m = mount_table + max_mount_entry;
+  char buf[BUFSIZE];
+
+  if (!user)
+    {
+      /* Create a default root dir from path. */
+      wcstombs (buf, path, BUFSIZE);
+      unconvert_slashes (buf);
+      char *native_path = buf;
+      if (!strncmp (native_path, "\\\\?\\", 4))
+	native_path += 4;
+      if (!strncmp (native_path, "UNC\\", 4))
+	*(native_path += 2) = '\\';
+      m->posix = strdup ("/");
+      m->native = strdup (native_path);
+      m->flags = MOUNT_SYSTEM | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC;
+      ++m;
+      /* Create default /usr/bin and /usr/lib entries. */
+      char *trail = strchr (native_path, '\0');
+      strcpy (trail, "\\bin");
+      m->posix = strdup ("/usr/bin");
+      m->native = strdup (native_path);
+      m->flags = MOUNT_SYSTEM | MOUNT_AUTOMATIC;
+      ++m;
+      strcpy (trail, "\\lib");
+      m->posix = strdup ("/usr/lib");
+      m->native = strdup (native_path);
+      m->flags = MOUNT_SYSTEM | MOUNT_AUTOMATIC;
+      ++m;
+      /* Create a default cygdrive entry.  Note that this is a user entry.
+	 This allows to override it with mount, unless the sysadmin created
+	 a cygdrive entry in /etc/fstab. */
+      m->posix = strdup (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX);
+      m->native = strdup ("cygdrive prefix");
+      m->flags = MOUNT_CYGDRIVE;
+      ++m;
+      max_mount_entry = m - mount_table;
+    }
+
+  PWCHAR u = wcscpy (path_end, L"\\etc\\fstab") + 10;
+  if (user)
+    mbstowcs (wcscpy (u, L".d\\") + 3, get_user (), BUFSIZE - (u - path));
+  HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, NULL,
+			  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (h == INVALID_HANDLE_VALUE)
+    return;
+  char *got = buf;
+  DWORD len = 0;
+  /* Using BUFSIZE-1 leaves space to append two \0. */
+  while (ReadFile (h, got, BUFSIZE - 1 - (got - buf),
+		   &len, NULL))
+    {
+      char *end;
+
+      /* 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;
+      while (got < buf + len && (end = strchr (got, '\n')))
+	{
+	  end[end[-1] == '\r' ? -1 : 0] = '\0';
+	  if (from_fstab_line (m, got, user))
+	    ++m;
+	  got = end + 1;
+	}
+      if (len < BUFSIZE - 1)
+	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';
+    }
+  if (got > buf && from_fstab_line (m, got, user))
+    ++m;
+  max_mount_entry = m - mount_table;
+  CloseHandle (h);
+}
+
+static int
+mnt_sort (const void *a, const void *b)
+{
+  const mnt_t *ma = (const mnt_t *) a;
+  const mnt_t *mb = (const mnt_t *) b;
+  int ret;
+
+  ret = (ma->flags & MOUNT_CYGDRIVE) - (mb->flags & MOUNT_CYGDRIVE);
+  if (ret)
+    return ret;
+  ret = (ma->flags & MOUNT_SYSTEM) - (mb->flags & MOUNT_SYSTEM);
+  if (ret)
+    return ret;
+  return strcmp (ma->posix, mb->posix);
+}
+
+extern "C" WCHAR cygwin_dll_path[];
+
+static void
+read_mounts ()
+{
+  HKEY setup_key;
+  LONG ret;
+  DWORD len;
+  WCHAR path[32768];
+  PWCHAR path_end;
+
+  for (mnt_t *m1 = mount_table; m1->posix; m1++)
+    {
+      free (m1->posix);
+      if (m1->native)
+	free ((char *) m1->native);
+      m1->posix = NULL;
+    }
+  max_mount_entry = 0;
+
+  /* First fetch the cygwin1.dll path from the LoadLibrary call in load_cygwin.
+     This utilizes the DLL search order to find a matching cygwin1.dll and to
+     compute the installation path from that DLL's path. */
+  if (cygwin_dll_path[0])
+    wcscpy (path, cygwin_dll_path);
+  /* If we can't load cygwin1.dll, check where cygcheck is living itself and
+     try to fetch installation path from here.  Does cygwin1.dll exist in the
+     same path?  This should only kick in if the cygwin1.dll in the same path
+     has been made non-executable for the current user accidentally. */
+  else if (!GetModuleFileNameW (NULL, path, 32768))
+    return;
+  path_end = wcsrchr (path, L'\\');
+  if (path_end)
+    {
+      if (!cygwin_dll_path[0])
+	{
+	  wcscpy (path_end, L"\\cygwin1.dll");
+	  DWORD attr = GetFileAttributesW (path);
+	  if (attr == (DWORD) -1
+	      || (attr & (FILE_ATTRIBUTE_DIRECTORY
+			  | FILE_ATTRIBUTE_REPARSE_POINT)))
+	    path_end = NULL;
+	}
+      if (path_end)
+	{
+	  *path_end = L'\0';
+	  path_end = wcsrchr (path, L'\\');
+	}
+    }
+  /* If we can't create a valid installation dir from that, try to fetch
+     the installation dir from the setup registry key. */
+  if (!path_end)
+    {
+      for (int i = 0; i < 2; ++i)
+	if ((ret = RegOpenKeyExW (i ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
+				  L"Software\\Cygwin\\setup", 0,
+				  KEY_READ, &setup_key)) == ERROR_SUCCESS)
+	  {
+	    len = 32768 * sizeof (WCHAR);
+	    ret = RegQueryValueExW (setup_key, L"rootdir", NULL, NULL,
+				    (PBYTE) path, &len);
+	    RegCloseKey (setup_key);
+	    if (ret == ERROR_SUCCESS)
+	      break;
+	  }
+      if (ret == ERROR_SUCCESS)
+	path_end = wcschr (path, L'\0');
+    }
+  /* If we can't fetch an installation dir, bail out. */
+  if (!path_end)
+    return;
+  *path_end = L'\0';
+
+  from_fstab (false, path, path_end);
+  from_fstab (true, path, path_end);
+  qsort (mount_table, max_mount_entry, sizeof (mnt_t), mnt_sort);
+}
+#endif /* !defined(TESTSUITE) */
+
+/* Return non-zero if PATH1 is a prefix of PATH2.
+   Both are assumed to be of the same path style and / vs \ usage.
+   Neither may be "".
+   LEN1 = strlen (PATH1).  It's passed because often it's already known.
+
+   Examples:
+   /foo/ is a prefix of /foo  <-- may seem odd, but desired
+   /foo is a prefix of /foo/
+   / is a prefix of /foo/bar
+   / is not a prefix of foo/bar
+   foo/ is a prefix foo/bar
+   /foo is not a prefix of /foobar
+*/
+
+static int
+path_prefix_p (const char *path1, const char *path2, size_t len1)
+{
+  /* Handle case where PATH1 has trailing '/' and when it doesn't.  */
+  if (len1 > 0 && isslash (path1[len1 - 1]))
+    len1--;
+
+  if (len1 == 0)
+    return isslash (path2[0]) && !isslash (path2[1]);
+
+  if (strncasecmp (path1, path2, len1) != 0)
+    return 0;
+
+  return isslash (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
+}
+
+static char *
+vconcat (const char *s, va_list v)
+{
+  int len;
+  char *rv, *arg;
+  va_list save_v = v;
+  int unc;
+
+  if (!s)
+    return 0;
+
+  len = strlen (s);
+
+  unc = isslash (*s) && isslash (s[1]);
+
+  while (1)
+    {
+      arg = va_arg (v, char *);
+      if (arg == 0)
+	break;
+      len += strlen (arg);
+    }
+  va_end (v);
+
+  rv = (char *) malloc (len + 1);
+  strcpy (rv, s);
+  v = save_v;
+  while (1)
+  {
+    arg = va_arg (v, char *);
+    if (arg == 0)
+      break;
+    strcat (rv, arg);
+  }
+  va_end (v);
+
+  char *d, *p;
+
+  /* concat is only used for urls and files, so we can safely
+     canonicalize the results */
+  for (p = d = rv; *p; p++)
+    {
+      *d++ = *p;
+      /* special case for URLs */
+      if (*p == ':' && p[1] == '/' && p[2] == '/' && p > rv + 1)
+	{
+	  *d++ = *++p;
+	  *d++ = *++p;
+	}
+      else if (isslash (*p))
+	{
+	  if (p == rv && unc)
+	    *d++ = *p++;
+	  while (p[1] == '/')
+	    p++;
+	}
+    }
+  *d = 0;
+
+  return rv;
+}
+
+static char *
+concat (const char *s, ...)
+{
+  va_list v;
+
+  va_start (v, s);
+
+  return vconcat (s, v);
+}
+
+/* This is a helper function for when vcygpath is passed what appears
+   to be a relative POSIX path.  We take a Win32 CWD (either as specified
+   in 'cwd' or as retrieved with GetCurrentDirectory() if 'cwd' is NULL)
+   and find the mount table entry with the longest match.  We replace the
+   matching portion with the corresponding POSIX prefix, and to that append
+   's' and anything in 'v'.  The returned result is a mostly-POSIX
+   absolute path -- 'mostly' because the portions of CWD that didn't
+   match the mount prefix will still have '\\' separators.  */
+static char *
+rel_vconcat (const char *cwd, const char *s, va_list v)
+{
+  char pathbuf[MAX_PATH];
+  if (!cwd || *cwd == '\0')
+    {
+      if (!GetCurrentDirectory (MAX_PATH, pathbuf))
+	return NULL;
+      cwd = pathbuf;
+    }
+
+  size_t max_len = 0;
+  mnt_t *m, *match = NULL;
+
+  for (m = mount_table; m->posix; m++)
+    {
+      if (m->flags & MOUNT_CYGDRIVE)
+	continue;
+
+      size_t n = strlen (m->native);
+      if (n < max_len || !path_prefix_p (m->native, cwd, n))
+	continue;
+      max_len = n;
+      match = m;
+    }
+
+  char *temppath;
+  if (!match)
+    // No prefix matched - best effort to return meaningful value.
+    temppath = concat (cwd, "/", s, NULL);
+  else if (strcmp (match->posix, "/") != 0)
+    // Matched on non-root.  Copy matching prefix + remaining 'path'.
+    temppath = concat (match->posix, cwd + max_len, "/", s, NULL);
+  else if (cwd[max_len] == '\0')
+    // Matched on root and there's no remaining 'path'.
+    temppath = concat ("/", s, NULL);
+  else if (isslash (cwd[max_len]))
+    // Matched on root but remaining 'path' starts with a slash anyway.
+    temppath = concat (cwd + max_len, "/", s, NULL);
+  else
+    temppath = concat ("/", cwd + max_len, "/", s, NULL);
+
+  char *res = vconcat (temppath, v);
+  free (temppath);
+  return res;
+}
+
+/* Convert a POSIX path in 's' to an absolute Win32 path, and append
+   anything in 'v' to the end, returning the result.  If 's' is a
+   relative path then 'cwd' is used as the working directory to make
+   it absolute.  Pass NULL in 'cwd' to use GetCurrentDirectory.  */
+static char *
+vcygpath (const char *cwd, const char *s, va_list v)
+{
+  size_t max_len = 0;
+  mnt_t *m, *match = NULL;
+
+#ifndef TESTSUITE
+  if (!max_mount_entry)
+    read_mounts ();
+#endif
+  char *path;
+  if (s[0] == '.' && isslash (s[1]))
+    s += 2;
+
+  if (s[0] == '/' || s[1] == ':')	/* FIXME: too crude? */
+    path = vconcat (s, v);
+  else
+    path = rel_vconcat (cwd, s, v);
+
+  if (!path)
+    return NULL;
+
+  if (strncmp (path, "/./", 3) == 0)
+    memmove (path + 1, path + 3, strlen (path + 3) + 1);
+
+  for (m = mount_table; m->posix; m++)
+    {
+      size_t n = strlen (m->posix);
+      if (n < max_len || !path_prefix_p (m->posix, path, n))
+	continue;
+      if (m->flags & MOUNT_CYGDRIVE)
+	{
+	  if (strlen (path) < n + 2)
+	    continue;
+	  /* If cygdrive path is just '/', fix n for followup evaluation. */
+	  if (n == 1)
+	    n = 0;
+	  if (path[n] != '/')
+	    continue;
+	  if (!isalpha (path[n + 1]))
+	    continue;
+	  if (path[n + 2] != '/')
+	    continue;
+	}
+      max_len = n;
+      match = m;
+    }
+
+  char *native;
+  if (match == NULL)
+    native = strdup (path);
+  else if (max_len == strlen (path))
+    native = strdup (match->native);
+  else if (match->flags & MOUNT_CYGDRIVE)
+    {
+      char drive[3] = { path[max_len + 1], ':', '\0' };
+      native = concat (drive, path + max_len + 2, NULL);
+    }
+  else if (isslash (path[max_len]))
+    native = concat (match->native, path + max_len, NULL);
+  else
+    native = concat (match->native, "\\", path + max_len, NULL);
+  free (path);
+
+  unconvert_slashes (native);
+  for (char *s = strstr (native + 1, "\\.\\"); s && *s; s = strstr (s, "\\.\\"))
+    memmove (s + 1, s + 3, strlen (s + 3) + 1);
+  return native;
+}
+
+char *
+cygpath_rel (const char *cwd, const char *s, ...)
+{
+  va_list v;
+
+  va_start (v, s);
+
+  return vcygpath (cwd, s, v);
+}
+
+char *
+cygpath (const char *s, ...)
+{
+  va_list v;
+
+  va_start (v, s);
+
+  return vcygpath (NULL, s, v);
+}
+
+static mnt_t *m = NULL;
+
+extern "C" FILE *
+setmntent (const char *, const char *)
+{
+  m = mount_table;
+#ifndef TESTSUITE
+  if (!max_mount_entry)
+    read_mounts ();
+#endif
+  return NULL;
+}
+
+extern "C" struct mntent *
+getmntent (FILE *)
+{
+  static mntent mnt;
+  if (!m->posix)
+    return NULL;
+
+  mnt.mnt_fsname = (char *) m->native;
+  mnt.mnt_dir = (char *) m->posix;
+  if (!mnt.mnt_type)
+    mnt.mnt_type = (char *) malloc (16);
+  if (!mnt.mnt_opts)
+    mnt.mnt_opts = (char *) malloc (64);
+
+  strcpy (mnt.mnt_type,
+	  (char *) ((m->flags & MOUNT_SYSTEM) ? "system" : "user"));
+
+  if (m->flags & MOUNT_TEXT)
+    strcpy (mnt.mnt_opts, (char *) "text");
+  else
+    strcpy (mnt.mnt_opts, (char *) "binary");
+
+  if (m->flags & MOUNT_CYGWIN_EXEC)
+    strcat (mnt.mnt_opts, (char *) ",cygexec");
+  else if (m->flags & MOUNT_EXEC)
+    strcat (mnt.mnt_opts, (char *) ",exec");
+  else if (m->flags & MOUNT_NOTEXEC)
+    strcat (mnt.mnt_opts, (char *) ",notexec");
+
+  if (m->flags & MOUNT_NOACL)
+    strcat (mnt.mnt_opts, (char *) ",noacl");
+
+  if (m->flags & MOUNT_NOPOSIX)
+    strcat (mnt.mnt_opts, (char *) ",posix=0");
+
+  if (m->flags & (MOUNT_AUTOMATIC | MOUNT_CYGDRIVE))
+    strcat (mnt.mnt_opts, (char *) ",auto");
+
+  mnt.mnt_freq = 1;
+  mnt.mnt_passno = 1;
+  m++;
+  return &mnt;
+}
diff --git a/winsup/utils/path.cc b/winsup/utils/path.cc
index 29344be02033..7e3f3cab74be 100644
--- a/winsup/utils/path.cc
+++ b/winsup/utils/path.cc
@@ -26,235 +26,11 @@ details. */
 #define _NOMNTENT_MACROS
 #include "../cygwin/include/mntent.h"
 #include "testsuite.h"
-#ifdef FSTAB_ONLY
+#ifdef __CYGWIN__
 #include <sys/cygwin.h>
 #endif
 #include "loadlib.h"
 
-#ifndef FSTAB_ONLY
-/* Used when treating / and \ as equivalent. */
-#define isslash(ch) \
-  ({ \
-      char __c = (ch); \
-      ((__c) == '/' || (__c) == '\\'); \
-   })
-
-
-static const GUID GUID_shortcut =
-  {0x00021401L, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
-
-enum {
-  WSH_FLAG_IDLIST = 0x01,	/* Contains an ITEMIDLIST. */
-  WSH_FLAG_FILE = 0x02,		/* Contains a file locator element. */
-  WSH_FLAG_DESC = 0x04,		/* Contains a description. */
-  WSH_FLAG_RELPATH = 0x08,	/* Contains a relative path. */
-  WSH_FLAG_WD = 0x10,		/* Contains a working dir. */
-  WSH_FLAG_CMDLINE = 0x20,	/* Contains command line args. */
-  WSH_FLAG_ICON = 0x40		/* Contains a custom icon. */
-};
-
-struct win_shortcut_hdr
-  {
-    DWORD size;		/* Header size in bytes.  Must contain 0x4c. */
-    GUID magic;		/* GUID of shortcut files. */
-    DWORD flags;	/* Content flags.  See above. */
-
-    /* The next fields from attr to icon_no are always set to 0 in Cygwin
-       and U/Win shortcuts. */
-    DWORD attr;	/* Target file attributes. */
-    FILETIME ctime;	/* These filetime items are never touched by the */
-    FILETIME mtime;	/* system, apparently. Values don't matter. */
-    FILETIME atime;
-    DWORD filesize;	/* Target filesize. */
-    DWORD icon_no;	/* Icon number. */
-
-    DWORD run;		/* Values defined in winuser.h. Use SW_NORMAL. */
-    DWORD hotkey;	/* Hotkey value. Set to 0.  */
-    DWORD dummy[2];	/* Future extension probably. Always 0. */
-  };
-
-static bool
-cmp_shortcut_header (win_shortcut_hdr *file_header)
-{
-  /* A Cygwin or U/Win shortcut only contains a description and a relpath.
-     Cygwin shortcuts also might contain an ITEMIDLIST. The run type is
-     always set to SW_NORMAL. */
-  return file_header->size == sizeof (win_shortcut_hdr)
-      && !memcmp (&file_header->magic, &GUID_shortcut, sizeof GUID_shortcut)
-      && (file_header->flags & ~WSH_FLAG_IDLIST)
-	 == (WSH_FLAG_DESC | WSH_FLAG_RELPATH)
-      && file_header->run == SW_NORMAL;
-}
-
-int
-get_word (HANDLE fh, int offset)
-{
-  unsigned short rv;
-  unsigned r;
-
-  SetLastError(NO_ERROR);
-  if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
-      && GetLastError () != NO_ERROR)
-    return -1;
-
-  if (!ReadFile (fh, &rv, 2, (DWORD *) &r, 0))
-    return -1;
-
-  return rv;
-}
-
-/*
- * Check the value of GetLastError() to find out whether there was an error.
- */
-int
-get_dword (HANDLE fh, int offset)
-{
-  int rv;
-  unsigned r;
-
-  SetLastError(NO_ERROR);
-  if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
-      && GetLastError () != NO_ERROR)
-    return -1;
-
-  if (!ReadFile (fh, &rv, 4, (DWORD *) &r, 0))
-    return -1;
-
-  return rv;
-}
-
-#define EXE_MAGIC ((int)*(unsigned short *)"MZ")
-#define SHORTCUT_MAGIC ((int)*(unsigned short *)"L\0")
-#define SYMLINK_COOKIE "!<symlink>"
-#define SYMLINK_MAGIC ((int)*(unsigned short *)SYMLINK_COOKIE)
-
-bool
-is_exe (HANDLE fh)
-{
-  int magic = get_word (fh, 0x0);
-  return magic == EXE_MAGIC;
-}
-
-bool
-is_symlink (HANDLE fh)
-{
-  bool ret = false;
-  int magic = get_word (fh, 0x0);
-  if (magic != SHORTCUT_MAGIC && magic != SYMLINK_MAGIC)
-    goto out;
-  DWORD got;
-  BY_HANDLE_FILE_INFORMATION local;
-  if (!GetFileInformationByHandle (fh, &local))
-    return false;
-  if (magic == SHORTCUT_MAGIC)
-    {
-      DWORD size;
-      if (!local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
-	goto out; /* Not a Cygwin symlink. */
-      if ((size = GetFileSize (fh, NULL)) > 8192)
-	goto out; /* Not a Cygwin symlink. */
-      char buf[size];
-      SetFilePointer (fh, 0, 0, FILE_BEGIN);
-      if (!ReadFile (fh, buf, size, &got, 0))
-	goto out;
-      if (got != size || !cmp_shortcut_header ((win_shortcut_hdr *) buf))
-	goto out; /* Not a Cygwin symlink. */
-      /* TODO: check for invalid path contents
-	 (see symlink_info::check() in ../cygwin/path.cc) */
-    }
-  else /* magic == SYMLINK_MAGIC */
-    {
-      if (!(local.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
-	goto out; /* Not a Cygwin symlink. */
-      char buf[sizeof (SYMLINK_COOKIE) - 1];
-      SetFilePointer (fh, 0, 0, FILE_BEGIN);
-      if (!ReadFile (fh, buf, sizeof (buf), &got, 0))
-	goto out;
-      if (got != sizeof (buf) ||
-	  memcmp (buf, SYMLINK_COOKIE, sizeof (buf)) != 0)
-	goto out; /* Not a Cygwin symlink. */
-    }
-  ret = true;
-out:
-  SetFilePointer (fh, 0, 0, FILE_BEGIN);
-  return ret;
-}
-
-/* Assumes is_symlink(fh) is true */
-bool
-readlink (HANDLE fh, char *path, size_t maxlen)
-{
-  DWORD rv;
-  char *buf, *cp;
-  unsigned short len;
-  win_shortcut_hdr *file_header;
-  BY_HANDLE_FILE_INFORMATION fi;
-
-  if (!GetFileInformationByHandle (fh, &fi)
-      || fi.nFileSizeHigh != 0
-      || fi.nFileSizeLow > 4 * 65536)
-    return false;
-
-  buf = (char *) alloca (fi.nFileSizeLow + 1);
-  file_header = (win_shortcut_hdr *) buf;
-
-  if (!ReadFile (fh, buf, fi.nFileSizeLow, &rv, NULL)
-      || rv != fi.nFileSizeLow)
-    return false;
-
-  if (fi.nFileSizeLow > sizeof (file_header)
-      && cmp_shortcut_header (file_header))
-    {
-      cp = buf + sizeof (win_shortcut_hdr);
-      if (file_header->flags & WSH_FLAG_IDLIST) /* Skip ITEMIDLIST */
-	cp += *(unsigned short *) cp + 2;
-      if (!(len = *(unsigned short *) cp))
-	return false;
-      cp += 2;
-      /* Has appended full path?  If so, use it instead of description. */
-      unsigned short relpath_len = *(unsigned short *) (cp + len);
-      if (cp + len + 2 + relpath_len < buf + fi.nFileSizeLow)
-	{
-	  cp += len + 2 + relpath_len;
-	  len = *(unsigned short *) cp;
-	  cp += 2;
-	}
-      if (*(PWCHAR) cp == 0xfeff)	/* BOM */
-	{
-	  size_t wlen = wcstombs (NULL, (wchar_t *) (cp + 2), 0);
-	  if (wlen == (size_t) -1 || wlen + 1 > maxlen)
-	    return false;
-	  wcstombs (path, (wchar_t *) (cp + 2), wlen + 1);
-	}
-      else if ((size_t) (len + 1) > maxlen)
-	return false;
-      else
-	memcpy (path, cp, len);
-      path[len] = '\0';
-      return true;
-    }
-  else if (strncmp (buf, SYMLINK_COOKIE, strlen (SYMLINK_COOKIE)) == 0
-	   && buf[fi.nFileSizeLow - 1] == '\0')
-    {
-      cp = buf + strlen (SYMLINK_COOKIE);
-      if (*(PWCHAR) cp == 0xfeff)	/* BOM */
-	{
-	  size_t wlen = wcstombs (NULL, (wchar_t *) (cp + 2), 0);
-	  if (wlen == (size_t) -1 || wlen + 1 > maxlen)
-	    return false;
-	  wcstombs (path, (wchar_t *) (cp + 2), wlen + 1);
-	}
-      else if (fi.nFileSizeLow - strlen (SYMLINK_COOKIE) > maxlen)
-	return false;
-      else
-	strcpy (path, cp);
-      return true;
-    }
-  else
-    return false;
-}
-#endif /* !FSTAB_ONLY */
-
 #ifndef TESTSUITE
 mnt_t mount_table[255];
 int max_mount_entry;
@@ -302,61 +78,8 @@ conv_fstab_spaces (char *field)
   return field;
 }
 
-#ifndef FSTAB_ONLY
-static struct opt
-{
-  const char *name;
-  unsigned val;
-  bool clear;
-} oopts[] =
-{
-  {"acl", MOUNT_NOACL, 1},
-  {"auto", 0, 0},
-  {"binary", MOUNT_TEXT, 1},
-  {"cygexec", MOUNT_CYGWIN_EXEC, 0},
-  {"dos", MOUNT_DOS, 0},
-  {"exec", MOUNT_EXEC, 0},
-  {"ihash", MOUNT_IHASH, 0},
-  {"noacl", MOUNT_NOACL, 0},
-  {"nosuid", 0, 0},
-  {"notexec", MOUNT_NOTEXEC, 0},
-  {"nouser", MOUNT_SYSTEM, 0},
-  {"override", MOUNT_OVERRIDE, 0},
-  {"posix=0", MOUNT_NOPOSIX, 0},
-  {"posix=1", MOUNT_NOPOSIX, 1},
-  {"text", MOUNT_TEXT, 0},
-  {"user", MOUNT_SYSTEM, 1}
-};
-
-static bool
-read_flags (char *options, unsigned &flags)
-{
-  while (*options)
-    {
-      char *p = strchr (options, ',');
-      if (p)
-	*p++ = '\0';
-      else
-	p = strchr (options, '\0');
-
-      for (opt *o = oopts;
-	   o < (oopts + (sizeof (oopts) / sizeof (oopts[0])));
-	   o++)
-	if (strcmp (options, o->name) == 0)
-	  {
-	    if (o->clear)
-	      flags &= ~o->val;
-	    else
-	      flags |= o->val;
-	    goto gotit;
-	  }
-      return false;
-
-    gotit:
-      options = p;
-    }
-  return true;
-}
+#ifndef __CYGWIN__
+static bool read_flags (char *, unsigned &);
 #endif
 
 bool
@@ -392,7 +115,7 @@ from_fstab_line (mnt_t *m, char *line, bool user)
   cend = find_ws (c);
   *cend = '\0';
   unsigned mount_flags = MOUNT_SYSTEM;
-#ifndef FSTAB_ONLY
+#ifndef __CYGWIN__
   if (!read_flags (c, mount_flags))
 #else
   if (cygwin_internal (CW_CVT_MNT_OPTS, &c, &mount_flags))
@@ -453,514 +176,4 @@ from_fstab_line (mnt_t *m, char *line, bool user)
   return true;
 }
 
-#ifndef FSTAB_ONLY
-
-#define BUFSIZE 65536
-
-static char *
-get_user ()
-{
-  static char user[UNLEN + 1];
-  char *userenv;
-
-  user[0] = '\0';
-  if ((userenv = getenv ("USER")) || (userenv = getenv ("USERNAME")))
-    strncat (user, userenv, UNLEN);
-  return user;
-}
-
-void
-from_fstab (bool user, PWCHAR path, PWCHAR path_end)
-{
-  mnt_t *m = mount_table + max_mount_entry;
-  char buf[BUFSIZE];
-
-  if (!user)
-    {
-      /* Create a default root dir from path. */
-      wcstombs (buf, path, BUFSIZE);
-      unconvert_slashes (buf);
-      char *native_path = buf;
-      if (!strncmp (native_path, "\\\\?\\", 4))
-	native_path += 4;
-      if (!strncmp (native_path, "UNC\\", 4))
-	*(native_path += 2) = '\\';
-      m->posix = strdup ("/");
-      m->native = strdup (native_path);
-      m->flags = MOUNT_SYSTEM | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC;
-      ++m;
-      /* Create default /usr/bin and /usr/lib entries. */
-      char *trail = strchr (native_path, '\0');
-      strcpy (trail, "\\bin");
-      m->posix = strdup ("/usr/bin");
-      m->native = strdup (native_path);
-      m->flags = MOUNT_SYSTEM | MOUNT_AUTOMATIC;
-      ++m;
-      strcpy (trail, "\\lib");
-      m->posix = strdup ("/usr/lib");
-      m->native = strdup (native_path);
-      m->flags = MOUNT_SYSTEM | MOUNT_AUTOMATIC;
-      ++m;
-      /* Create a default cygdrive entry.  Note that this is a user entry.
-	 This allows to override it with mount, unless the sysadmin created
-	 a cygdrive entry in /etc/fstab. */
-      m->posix = strdup (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX);
-      m->native = strdup ("cygdrive prefix");
-      m->flags = MOUNT_CYGDRIVE;
-      ++m;
-      max_mount_entry = m - mount_table;
-    }
-
-  PWCHAR u = wcscpy (path_end, L"\\etc\\fstab") + 10;
-  if (user)
-    mbstowcs (wcscpy (u, L".d\\") + 3, get_user (), BUFSIZE - (u - path));
-  HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, NULL,
-			  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-  if (h == INVALID_HANDLE_VALUE)
-    return;
-  char *got = buf;
-  DWORD len = 0;
-  /* Using BUFSIZE-1 leaves space to append two \0. */
-  while (ReadFile (h, got, BUFSIZE - 1 - (got - buf),
-		   &len, NULL))
-    {
-      char *end;
-
-      /* 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;
-      while (got < buf + len && (end = strchr (got, '\n')))
-	{
-	  end[end[-1] == '\r' ? -1 : 0] = '\0';
-	  if (from_fstab_line (m, got, user))
-	    ++m;
-	  got = end + 1;
-	}
-      if (len < BUFSIZE - 1)
-	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';
-    }
-  if (got > buf && from_fstab_line (m, got, user))
-    ++m;
-  max_mount_entry = m - mount_table;
-  CloseHandle (h);
-}
-#endif /* !FSTAB_ONLY */
 #endif /* !TESTSUITE */
-
-#ifndef FSTAB_ONLY
-
-#ifndef TESTSUITE
-static int
-mnt_sort (const void *a, const void *b)
-{
-  const mnt_t *ma = (const mnt_t *) a;
-  const mnt_t *mb = (const mnt_t *) b;
-  int ret;
-
-  ret = (ma->flags & MOUNT_CYGDRIVE) - (mb->flags & MOUNT_CYGDRIVE);
-  if (ret)
-    return ret;
-  ret = (ma->flags & MOUNT_SYSTEM) - (mb->flags & MOUNT_SYSTEM);
-  if (ret)
-    return ret;
-  return strcmp (ma->posix, mb->posix);
-}
-
-extern "C" WCHAR cygwin_dll_path[];
-
-static void
-read_mounts ()
-{
-  HKEY setup_key;
-  LONG ret;
-  DWORD len;
-  WCHAR path[32768];
-  PWCHAR path_end;
-
-  for (mnt_t *m1 = mount_table; m1->posix; m1++)
-    {
-      free (m1->posix);
-      if (m1->native)
-	free ((char *) m1->native);
-      m1->posix = NULL;
-    }
-  max_mount_entry = 0;
-
-  /* First fetch the cygwin1.dll path from the LoadLibrary call in load_cygwin.
-     This utilizes the DLL search order to find a matching cygwin1.dll and to
-     compute the installation path from that DLL's path. */
-  if (cygwin_dll_path[0])
-    wcscpy (path, cygwin_dll_path);
-  /* If we can't load cygwin1.dll, check where cygcheck is living itself and
-     try to fetch installation path from here.  Does cygwin1.dll exist in the
-     same path?  This should only kick in if the cygwin1.dll in the same path
-     has been made non-executable for the current user accidentally. */
-  else if (!GetModuleFileNameW (NULL, path, 32768))
-    return;
-  path_end = wcsrchr (path, L'\\');
-  if (path_end)
-    {
-      if (!cygwin_dll_path[0])
-	{
-	  wcscpy (path_end, L"\\cygwin1.dll");
-	  DWORD attr = GetFileAttributesW (path);
-	  if (attr == (DWORD) -1
-	      || (attr & (FILE_ATTRIBUTE_DIRECTORY
-			  | FILE_ATTRIBUTE_REPARSE_POINT)))
-	    path_end = NULL;
-	}
-      if (path_end)
-	{
-	  *path_end = L'\0';
-	  path_end = wcsrchr (path, L'\\');
-	}
-    }
-  /* If we can't create a valid installation dir from that, try to fetch
-     the installation dir from the setup registry key. */
-  if (!path_end)
-    {
-      for (int i = 0; i < 2; ++i)
-	if ((ret = RegOpenKeyExW (i ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
-				  L"Software\\Cygwin\\setup", 0,
-				  KEY_READ, &setup_key)) == ERROR_SUCCESS)
-	  {
-	    len = 32768 * sizeof (WCHAR);
-	    ret = RegQueryValueExW (setup_key, L"rootdir", NULL, NULL,
-				    (PBYTE) path, &len);
-	    RegCloseKey (setup_key);
-	    if (ret == ERROR_SUCCESS)
-	      break;
-	  }
-      if (ret == ERROR_SUCCESS)
-	path_end = wcschr (path, L'\0');
-    }
-  /* If we can't fetch an installation dir, bail out. */
-  if (!path_end)
-    return;
-  *path_end = L'\0';
-
-  from_fstab (false, path, path_end);
-  from_fstab (true, path, path_end);
-  qsort (mount_table, max_mount_entry, sizeof (mnt_t), mnt_sort);
-}
-#endif /* !defined(TESTSUITE) */
-
-/* Return non-zero if PATH1 is a prefix of PATH2.
-   Both are assumed to be of the same path style and / vs \ usage.
-   Neither may be "".
-   LEN1 = strlen (PATH1).  It's passed because often it's already known.
-
-   Examples:
-   /foo/ is a prefix of /foo  <-- may seem odd, but desired
-   /foo is a prefix of /foo/
-   / is a prefix of /foo/bar
-   / is not a prefix of foo/bar
-   foo/ is a prefix foo/bar
-   /foo is not a prefix of /foobar
-*/
-
-static int
-path_prefix_p (const char *path1, const char *path2, size_t len1)
-{
-  /* Handle case where PATH1 has trailing '/' and when it doesn't.  */
-  if (len1 > 0 && isslash (path1[len1 - 1]))
-    len1--;
-
-  if (len1 == 0)
-    return isslash (path2[0]) && !isslash (path2[1]);
-
-  if (strncasecmp (path1, path2, len1) != 0)
-    return 0;
-
-  return isslash (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
-}
-
-static char *
-vconcat (const char *s, va_list v)
-{
-  int len;
-  char *rv, *arg;
-  va_list save_v = v;
-  int unc;
-
-  if (!s)
-    return 0;
-
-  len = strlen (s);
-
-  unc = isslash (*s) && isslash (s[1]);
-
-  while (1)
-    {
-      arg = va_arg (v, char *);
-      if (arg == 0)
-	break;
-      len += strlen (arg);
-    }
-  va_end (v);
-
-  rv = (char *) malloc (len + 1);
-  strcpy (rv, s);
-  v = save_v;
-  while (1)
-  {
-    arg = va_arg (v, char *);
-    if (arg == 0)
-      break;
-    strcat (rv, arg);
-  }
-  va_end (v);
-
-  char *d, *p;
-
-  /* concat is only used for urls and files, so we can safely
-     canonicalize the results */
-  for (p = d = rv; *p; p++)
-    {
-      *d++ = *p;
-      /* special case for URLs */
-      if (*p == ':' && p[1] == '/' && p[2] == '/' && p > rv + 1)
-	{
-	  *d++ = *++p;
-	  *d++ = *++p;
-	}
-      else if (isslash (*p))
-	{
-	  if (p == rv && unc)
-	    *d++ = *p++;
-	  while (p[1] == '/')
-	    p++;
-	}
-    }
-  *d = 0;
-
-  return rv;
-}
-
-static char *
-concat (const char *s, ...)
-{
-  va_list v;
-
-  va_start (v, s);
-
-  return vconcat (s, v);
-}
-
-/* This is a helper function for when vcygpath is passed what appears
-   to be a relative POSIX path.  We take a Win32 CWD (either as specified
-   in 'cwd' or as retrieved with GetCurrentDirectory() if 'cwd' is NULL)
-   and find the mount table entry with the longest match.  We replace the
-   matching portion with the corresponding POSIX prefix, and to that append
-   's' and anything in 'v'.  The returned result is a mostly-POSIX
-   absolute path -- 'mostly' because the portions of CWD that didn't
-   match the mount prefix will still have '\\' separators.  */
-static char *
-rel_vconcat (const char *cwd, const char *s, va_list v)
-{
-  char pathbuf[MAX_PATH];
-  if (!cwd || *cwd == '\0')
-    {
-      if (!GetCurrentDirectory (MAX_PATH, pathbuf))
-	return NULL;
-      cwd = pathbuf;
-    }
-
-  size_t max_len = 0;
-  mnt_t *m, *match = NULL;
-
-  for (m = mount_table; m->posix; m++)
-    {
-      if (m->flags & MOUNT_CYGDRIVE)
-	continue;
-
-      size_t n = strlen (m->native);
-      if (n < max_len || !path_prefix_p (m->native, cwd, n))
-	continue;
-      max_len = n;
-      match = m;
-    }
-
-  char *temppath;
-  if (!match)
-    // No prefix matched - best effort to return meaningful value.
-    temppath = concat (cwd, "/", s, NULL);
-  else if (strcmp (match->posix, "/") != 0)
-    // Matched on non-root.  Copy matching prefix + remaining 'path'.
-    temppath = concat (match->posix, cwd + max_len, "/", s, NULL);
-  else if (cwd[max_len] == '\0')
-    // Matched on root and there's no remaining 'path'.
-    temppath = concat ("/", s, NULL);
-  else if (isslash (cwd[max_len]))
-    // Matched on root but remaining 'path' starts with a slash anyway.
-    temppath = concat (cwd + max_len, "/", s, NULL);
-  else
-    temppath = concat ("/", cwd + max_len, "/", s, NULL);
-
-  char *res = vconcat (temppath, v);
-  free (temppath);
-  return res;
-}
-
-/* Convert a POSIX path in 's' to an absolute Win32 path, and append
-   anything in 'v' to the end, returning the result.  If 's' is a
-   relative path then 'cwd' is used as the working directory to make
-   it absolute.  Pass NULL in 'cwd' to use GetCurrentDirectory.  */
-static char *
-vcygpath (const char *cwd, const char *s, va_list v)
-{
-  size_t max_len = 0;
-  mnt_t *m, *match = NULL;
-
-#ifndef TESTSUITE
-  if (!max_mount_entry)
-    read_mounts ();
-#endif
-  char *path;
-  if (s[0] == '.' && isslash (s[1]))
-    s += 2;
-
-  if (s[0] == '/' || s[1] == ':')	/* FIXME: too crude? */
-    path = vconcat (s, v);
-  else
-    path = rel_vconcat (cwd, s, v);
-
-  if (!path)
-    return NULL;
-
-  if (strncmp (path, "/./", 3) == 0)
-    memmove (path + 1, path + 3, strlen (path + 3) + 1);
-
-  for (m = mount_table; m->posix; m++)
-    {
-      size_t n = strlen (m->posix);
-      if (n < max_len || !path_prefix_p (m->posix, path, n))
-	continue;
-      if (m->flags & MOUNT_CYGDRIVE)
-	{
-	  if (strlen (path) < n + 2)
-	    continue;
-	  /* If cygdrive path is just '/', fix n for followup evaluation. */
-	  if (n == 1)
-	    n = 0;
-	  if (path[n] != '/')
-	    continue;
-	  if (!isalpha (path[n + 1]))
-	    continue;
-	  if (path[n + 2] != '/')
-	    continue;
-	}
-      max_len = n;
-      match = m;
-    }
-
-  char *native;
-  if (match == NULL)
-    native = strdup (path);
-  else if (max_len == strlen (path))
-    native = strdup (match->native);
-  else if (match->flags & MOUNT_CYGDRIVE)
-    {
-      char drive[3] = { path[max_len + 1], ':', '\0' };
-      native = concat (drive, path + max_len + 2, NULL);
-    }
-  else if (isslash (path[max_len]))
-    native = concat (match->native, path + max_len, NULL);
-  else
-    native = concat (match->native, "\\", path + max_len, NULL);
-  free (path);
-
-  unconvert_slashes (native);
-  for (char *s = strstr (native + 1, "\\.\\"); s && *s; s = strstr (s, "\\.\\"))
-    memmove (s + 1, s + 3, strlen (s + 3) + 1);
-  return native;
-}
-
-char *
-cygpath_rel (const char *cwd, const char *s, ...)
-{
-  va_list v;
-
-  va_start (v, s);
-
-  return vcygpath (cwd, s, v);
-}
-
-char *
-cygpath (const char *s, ...)
-{
-  va_list v;
-
-  va_start (v, s);
-
-  return vcygpath (NULL, s, v);
-}
-
-static mnt_t *m = NULL;
-
-extern "C" FILE *
-setmntent (const char *, const char *)
-{
-  m = mount_table;
-#ifndef TESTSUITE
-  if (!max_mount_entry)
-    read_mounts ();
-#endif
-  return NULL;
-}
-
-extern "C" struct mntent *
-getmntent (FILE *)
-{
-  static mntent mnt;
-  if (!m->posix)
-    return NULL;
-
-  mnt.mnt_fsname = (char *) m->native;
-  mnt.mnt_dir = (char *) m->posix;
-  if (!mnt.mnt_type)
-    mnt.mnt_type = (char *) malloc (16);
-  if (!mnt.mnt_opts)
-    mnt.mnt_opts = (char *) malloc (64);
-
-  strcpy (mnt.mnt_type,
-	  (char *) ((m->flags & MOUNT_SYSTEM) ? "system" : "user"));
-
-  if (m->flags & MOUNT_TEXT)
-    strcpy (mnt.mnt_opts, (char *) "text");
-  else
-    strcpy (mnt.mnt_opts, (char *) "binary");
-
-  if (m->flags & MOUNT_CYGWIN_EXEC)
-    strcat (mnt.mnt_opts, (char *) ",cygexec");
-  else if (m->flags & MOUNT_EXEC)
-    strcat (mnt.mnt_opts, (char *) ",exec");
-  else if (m->flags & MOUNT_NOTEXEC)
-    strcat (mnt.mnt_opts, (char *) ",notexec");
-
-  if (m->flags & MOUNT_NOACL)
-    strcat (mnt.mnt_opts, (char *) ",noacl");
-
-  if (m->flags & MOUNT_NOPOSIX)
-    strcat (mnt.mnt_opts, (char *) ",posix=0");
-
-  if (m->flags & (MOUNT_AUTOMATIC | MOUNT_CYGDRIVE))
-    strcat (mnt.mnt_opts, (char *) ",auto");
-
-  mnt.mnt_freq = 1;
-  mnt.mnt_passno = 1;
-  m++;
-  return &mnt;
-}
-
-#endif /* !FSTAB_ONLY */

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-20 20:13 [PATCH] Use automake (v5) Jon Turney
  2021-04-20 20:15 ` Jon Turney
@ 2021-04-27 15:50 ` Jon Turney
  2021-04-27 16:52   ` Ken Brown
  2021-05-02 15:28 ` Jon Turney
  2 siblings, 1 reply; 15+ messages in thread
From: Jon Turney @ 2021-04-27 15:50 UTC (permalink / raw)
  To: Cygwin Patches

On 20/04/2021 21:13, Jon Turney wrote:
> For ease of reviewing, this patch doesn't contain changes to generated
> files which would be made by running ./autogen.sh.
   I pushed this patch.

If you have an existing build directory, while you might get away with 
invoking 'make' at the top-level, I would recommend blowing it away and 
configuring again.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-26 15:03       ` Corinna Vinschen
@ 2021-04-27 15:54         ` Jon Turney
  0 siblings, 0 replies; 15+ messages in thread
From: Jon Turney @ 2021-04-27 15:54 UTC (permalink / raw)
  To: Cygwin Patches

On 26/04/2021 16:03, Corinna Vinschen wrote:
> On Apr 22 13:57, Corinna Vinschen wrote:
>> On Apr 21 18:40, Corinna Vinschen wrote:
>>> On Apr 20 21:15, Jon Turney wrote:
>>>> On 20/04/2021 21:13, Jon Turney wrote:
>>>> * some object files are in a unexpected places in the build file hierarchy
>>>> (compared to naive expectations and/or the non-automake build)
>>>
>>> This is the only minor qualm I have with this patch.  It would be nice
>>> to have the mingw sources and .o files in the mingw subdir.  It would
>>> simply be a bit cleaner.  The files shared between cygwin and mingw
>>> (that's only path.cc, I think) could be handled by an include, i. e.
>>>
>>>    utils/
>>>
>>>      path.cc (full implementation)
>>>
>>>    utils/mingw/
>>>
>>>      path.cc:
>>>
>>>        #include "../path.cc"
>>
>> I wonder if it wouldn't make sense to split out the mingw-only parts
>> of path.cc entirely.  I had a quick view into the file and it turns
>> out that of the almost 1000 lines in this file, only about 100 lines
>> are used by mount.  All the rest is only used by mingw code, i. e.,
>> cygcheck and strace.
>>
>> That's obviously not part of this patch, but something we should keep
>> in mind for a later cleanup.
> 
> I tried this as a POC and it's not much of a problem.  See the below
> patch.  Cleaning up the includes is still to do.
> 

Thanks, this seems workable.  I'll take a look.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-27 15:50 ` Jon Turney
@ 2021-04-27 16:52   ` Ken Brown
  2021-04-27 17:00     ` Ken Brown
  0 siblings, 1 reply; 15+ messages in thread
From: Ken Brown @ 2021-04-27 16:52 UTC (permalink / raw)
  To: cygwin-patches

On 4/27/2021 11:50 AM, Jon Turney wrote:
> On 20/04/2021 21:13, Jon Turney wrote:
>> For ease of reviewing, this patch doesn't contain changes to generated
>> files which would be made by running ./autogen.sh.
>   I pushed this patch.
> 
> If you have an existing build directory, while you might get away with invoking 
> 'make' at the top-level, I would recommend blowing it away and configuring again.

I'm confused about how the generated files are going to get regenerated when 
necessary.  I see calls to autogen (which I guess is /usr/bin/autogen.exe from 
the autogen package) in the Makefiles, but I don't see any calls to autogen.sh. 
  Is the latter no longer needed?

Ken

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-27 16:52   ` Ken Brown
@ 2021-04-27 17:00     ` Ken Brown
  2021-04-27 18:32       ` Jon Turney
  0 siblings, 1 reply; 15+ messages in thread
From: Ken Brown @ 2021-04-27 17:00 UTC (permalink / raw)
  To: cygwin-patches

On 4/27/2021 12:52 PM, Ken Brown wrote:
> On 4/27/2021 11:50 AM, Jon Turney wrote:
>> On 20/04/2021 21:13, Jon Turney wrote:
>>> For ease of reviewing, this patch doesn't contain changes to generated
>>> files which would be made by running ./autogen.sh.
>>   I pushed this patch.
>>
>> If you have an existing build directory, while you might get away with 
>> invoking 'make' at the top-level, I would recommend blowing it away and 
>> configuring again.
> 
> I'm confused about how the generated files are going to get regenerated when 
> necessary.  I see calls to autogen (which I guess is /usr/bin/autogen.exe from 
> the autogen package) in the Makefiles, but I don't see any calls to autogen.sh. 
> Is the latter no longer needed?

Oh, never mind.  The Makefiles just call autoconf, etc., as needed.

Ken

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-27 17:00     ` Ken Brown
@ 2021-04-27 18:32       ` Jon Turney
  0 siblings, 0 replies; 15+ messages in thread
From: Jon Turney @ 2021-04-27 18:32 UTC (permalink / raw)
  To: Cygwin Patches

On 27/04/2021 18:00, Ken Brown wrote:
> On 4/27/2021 12:52 PM, Ken Brown wrote:
>> On 4/27/2021 11:50 AM, Jon Turney wrote:
>>> On 20/04/2021 21:13, Jon Turney wrote:
>>>> For ease of reviewing, this patch doesn't contain changes to generated
>>>> files which would be made by running ./autogen.sh.
>>>   I pushed this patch.
>>>
>>> If you have an existing build directory, while you might get away 
>>> with invoking 'make' at the top-level, I would recommend blowing it 
>>> away and configuring again.
>>
>> I'm confused about how the generated files are going to get 
>> regenerated when necessary.  I see calls to autogen (which I guess is 
>> /usr/bin/autogen.exe from the autogen package) in the Makefiles, but I 

That's some cygnus top-level weirdness I don't understand.

>> don't see any calls to autogen.sh. Is the latter no longer needed?

There is (still) an autogen.sh in winsup/ ...

> Oh, never mind.  The Makefiles just call autoconf, etc., as needed.

... but you should now never need to explicitly use it, as 
('maintainer-mode') rules now exist in the Makefile to do what's needed.

If you do need to make changes in the autofoolery which are going to be 
pushed, then specific versions of the autotools still need to be used 
(to avoid these generated files thrashing between forms generated by 
different versions)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-04-20 20:13 [PATCH] Use automake (v5) Jon Turney
  2021-04-20 20:15 ` Jon Turney
  2021-04-27 15:50 ` Jon Turney
@ 2021-05-02 15:28 ` Jon Turney
  2021-05-02 18:25   ` Brian Inglis
  2021-05-03 10:43   ` Corinna Vinschen
  2 siblings, 2 replies; 15+ messages in thread
From: Jon Turney @ 2021-05-02 15:28 UTC (permalink / raw)
  To: Cygwin Patches

On 20/04/2021 21:13, Jon Turney wrote:
> For ease of reviewing, this patch doesn't contain changes to generated
> files which would be made by running ./autogen.sh.

Some possible items of future work I noted:

* Documentation is now always built (rather than dangerously ignoring 
any errors)

Although this is half-arsed at the moment, as we don't require the 
documentation tools at configure time, we'll just fail when the rules 
are executed if they are missing.

Perhaps there should be explicit configuration to build documentation or 
not?

* Use AM_V_GEN to silence (most?) custom rules

* -Wimplicit-fallthrough, -Werror could (should?) be set in top-level 
Makefile.am.common, rather than individual subdirs

* Some custom rules have multiple outputs and workarounds to ensure the 
rule only runs once

Ideally these would be re-written using make 4.3 'grouped targets', but 
perhaps not yet...

* Some custom rules could be simplified

e.g. mkvers.sh generates version.cc and winver.rc, then runs windres on 
windver.rc

* 'make our include directories absolute so we don't have to worry about 
making them relative to the subdirectory we happen to be building in' is 
sufficiently obscure that it at least deserves a comment.

* Rather than a huge list of --replace options to mkimport inline in the 
Makefile, it might be more sensible to augment that tool the read a list 
of replacement names from a file, and put them there.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-05-02 15:28 ` Jon Turney
@ 2021-05-02 18:25   ` Brian Inglis
  2021-05-03 10:40     ` Corinna Vinschen
  2021-05-03 10:43   ` Corinna Vinschen
  1 sibling, 1 reply; 15+ messages in thread
From: Brian Inglis @ 2021-05-02 18:25 UTC (permalink / raw)
  To: cygwin-patches

On 2021-05-02 09:28, Jon Turney wrote:
> Some possible items of future work I noted:

> * -Wimplicit-fallthrough, -Werror could (should?) be set in top-level 
> Makefile.am.common, rather than individual subdirs

Perhaps keep -Werror for Cygwin sources only where we can directly deal with new 
warnings generated due to prompt gcc releases with improvements under Cygwin 
(thanks to Achim and JonY).

With other distros' gcc releases lagging, package builds are getting more 
warnings during cygport builds, which would have to be dealt with either by more 
Cygwin patches and/or working with upstream, by toggling off -Werror, or 
specific -Wno-... options which could result in suppressing useful output, as 
well as delaying package releases.

-- 
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada

This email may be disturbing to some readers as it contains
too much technical detail. Reader discretion is advised.
[Data in binary units and prefixes, physical quantities in SI.]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-05-02 18:25   ` Brian Inglis
@ 2021-05-03 10:40     ` Corinna Vinschen
  0 siblings, 0 replies; 15+ messages in thread
From: Corinna Vinschen @ 2021-05-03 10:40 UTC (permalink / raw)
  To: cygwin-patches

On May  2 12:25, Brian Inglis wrote:
> On 2021-05-02 09:28, Jon Turney wrote:
> > Some possible items of future work I noted:
> 
> > * -Wimplicit-fallthrough, -Werror could (should?) be set in top-level
> > Makefile.am.common, rather than individual subdirs

Careful, the implicit-fallthrough values are different.  Not saying they
*have* to be different, but that certainly requires code changes.

> Perhaps keep -Werror for Cygwin sources only where we can directly deal with
> new warnings generated due to prompt gcc releases with improvements under
> Cygwin (thanks to Achim and JonY).

No, -Werror should be used for all source dirs under winsup.

> With other distros' gcc releases lagging, package builds are getting more
> warnings during cygport builds, which would have to be dealt with either by
> more Cygwin patches and/or working with upstream, by toggling off -Werror,
> or specific -Wno-... options which could result in suppressing useful
> output, as well as delaying package releases.
> 
> -- 
> Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
> 
> This email may be disturbing to some readers as it contains
> too much technical detail. Reader discretion is advised.
> [Data in binary units and prefixes, physical quantities in SI.]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-05-02 15:28 ` Jon Turney
  2021-05-02 18:25   ` Brian Inglis
@ 2021-05-03 10:43   ` Corinna Vinschen
  2021-05-04 18:12     ` Jon Turney
  1 sibling, 1 reply; 15+ messages in thread
From: Corinna Vinschen @ 2021-05-03 10:43 UTC (permalink / raw)
  To: cygwin-patches

On May  2 16:28, Jon Turney wrote:
> On 20/04/2021 21:13, Jon Turney wrote:
> > For ease of reviewing, this patch doesn't contain changes to generated
> > files which would be made by running ./autogen.sh.
> 
> Some possible items of future work I noted:
> 
> * Documentation is now always built (rather than dangerously ignoring any
> errors)
> 
> Although this is half-arsed at the moment, as we don't require the
> documentation tools at configure time, we'll just fail when the rules are
> executed if they are missing.
> 
> Perhaps there should be explicit configuration to build documentation or
> not?

`make doc'?

It wouldn't be tricky to add that to the cygwin.cygport file...

> * Use AM_V_GEN to silence (most?) custom rules
> 
> * -Wimplicit-fallthrough, -Werror could (should?) be set in top-level
> Makefile.am.common, rather than individual subdirs

See my other mail.

> * Some custom rules have multiple outputs and workarounds to ensure the rule
> only runs once
> 
> Ideally these would be re-written using make 4.3 'grouped targets', but
> perhaps not yet...
> 
> * Some custom rules could be simplified
> 
> e.g. mkvers.sh generates version.cc and winver.rc, then runs windres on
> windver.rc
> 
> * 'make our include directories absolute so we don't have to worry about
> making them relative to the subdirectory we happen to be building in' is
> sufficiently obscure that it at least deserves a comment.

I'm not sure I understand... -v, please?

> * Rather than a huge list of --replace options to mkimport inline in the
> Makefile, it might be more sensible to augment that tool the read a list of
> replacement names from a file, and put them there.

Ack


Thanks,
Corinna

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] Use automake (v5)
  2021-05-03 10:43   ` Corinna Vinschen
@ 2021-05-04 18:12     ` Jon Turney
  0 siblings, 0 replies; 15+ messages in thread
From: Jon Turney @ 2021-05-04 18:12 UTC (permalink / raw)
  To: cygwin-patches

On 03/05/2021 11:43, Corinna Vinschen wrote:
> On May  2 16:28, Jon Turney wrote:
>> On 20/04/2021 21:13, Jon Turney wrote:
>>> For ease of reviewing, this patch doesn't contain changes to generated
>>> files which would be made by running ./autogen.sh.
>>
>> Some possible items of future work I noted:
>>
>> * Documentation is now always built (rather than dangerously ignoring any
>> errors)
>>
>> Although this is half-arsed at the moment, as we don't require the
>> documentation tools at configure time, we'll just fail when the rules are
>> executed if they are missing.
>>
>> Perhaps there should be explicit configuration to build documentation or
>> not?
> 
> `make doc'?

Yeah, that's probably the right thing to do.

[...]
>> * 'make our include directories absolute so we don't have to worry about
>> making them relative to the subdirectory we happen to be building in' is
>> sufficiently obscure that it at least deserves a comment.
> 
> I'm not sure I understand... -v, please?

Yeah, that's why it needs comment :)

realdirpath() in winsup/configure.ac makes paths absolute (and canonical)

Therefore we can use things set with it (AC_CYGWIN_INCLUDES, 
target_builddir, winsup_srcdir) in Makefile.am in arbitrarily deep 
subdirectories, and things just happen to work (which wouldn't be the 
case if they contained relative paths)

It's all a hangover from when it used to be even more complex (see 
commit 39e8d907), and looking at this again, this could probably be 
cleaned-up some more (perhaps using $top_builddir, $top_srcdir?).

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2021-05-04 18:13 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-20 20:13 [PATCH] Use automake (v5) Jon Turney
2021-04-20 20:15 ` Jon Turney
2021-04-21 16:40   ` Corinna Vinschen
2021-04-22 11:57     ` Corinna Vinschen
2021-04-26 15:03       ` Corinna Vinschen
2021-04-27 15:54         ` Jon Turney
2021-04-27 15:50 ` Jon Turney
2021-04-27 16:52   ` Ken Brown
2021-04-27 17:00     ` Ken Brown
2021-04-27 18:32       ` Jon Turney
2021-05-02 15:28 ` Jon Turney
2021-05-02 18:25   ` Brian Inglis
2021-05-03 10:40     ` Corinna Vinschen
2021-05-03 10:43   ` Corinna Vinschen
2021-05-04 18:12     ` Jon Turney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).