summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/NEWS31
-rw-r--r--debian/changelog1226
-rw-r--r--debian/compat1
-rw-r--r--debian/control68
-rw-r--r--debian/copyright29
-rw-r--r--debian/hurd-console.default36
-rw-r--r--debian/hurd-dbg.dirs1
-rw-r--r--debian/hurd-dev.install3
-rw-r--r--debian/hurd-dev.lintian-overrides15
-rw-r--r--debian/hurd-doc.docs2
-rw-r--r--debian/hurd-doc.info1
-rw-r--r--debian/hurd-udeb.dirs1
-rw-r--r--debian/hurd-udeb.install68
-rw-r--r--debian/hurd-udeb.links1
-rw-r--r--debian/hurd-udeb.lintian-overrides2
-rw-r--r--debian/hurd.dirs7
-rw-r--r--debian/hurd.examples1
-rw-r--r--debian/hurd.install66
-rw-r--r--debian/hurd.links1
-rw-r--r--debian/hurd.lintian-overrides7
-rw-r--r--debian/hurd.postinst86
-rw-r--r--debian/hurd.postrm20
-rw-r--r--debian/hurd.prerm8
-rw-r--r--debian/local/cdrom.h941
-rwxr-xr-xdebian/local/finish-install.d/51hurd_config-target-network9
-rw-r--r--debian/local/menu.lst19
-rwxr-xr-xdebian/local/partman/commit.d/40hurd_reload-partitions5
-rwxr-xr-xdebian/local/runsystem71
-rwxr-xr-xdebian/local/setup-translators162
-rw-r--r--debian/local/soundcard.h1298
-rwxr-xr-xdebian/make-new-orig.sh13
-rwxr-xr-xdebian/make-new-tarball.sh16
-rw-r--r--debian/patches/console_ignore_bdf_err.patch17
-rw-r--r--debian/patches/console_utf-8.patch19
-rw-r--r--debian/patches/diskfs_no_inherit_dir_group.patch29
-rw-r--r--debian/patches/ext2fs_large_stores.patch2223
-rw-r--r--debian/patches/ext2fs_nowait.patch154
-rw-r--r--debian/patches/extern_inline_fix.patch734
-rw-r--r--debian/patches/hurd_console_startup.patch32
-rw-r--r--debian/patches/init_try_runsystem.gnu.patch75
-rw-r--r--debian/patches/install-msgids.diff36
-rw-r--r--debian/patches/libdiskfs_self-reauth.patch32
-rw-r--r--debian/patches/libdiskfs_sync.patch16
-rw-r--r--debian/patches/libexec.patch103
-rw-r--r--debian/patches/libpager_deadlock.patch20
-rw-r--r--debian/patches/libpager_update_seqno.patch140
-rw-r--r--debian/patches/libports_stability.patch18
-rw-r--r--debian/patches/libpthread_fix.patch75
-rw-r--r--debian/patches/libpthread_globsigdisp.patch59
-rw-r--r--debian/patches/libpthread_procfs.patch83
-rw-r--r--debian/patches/libpthread_sigmask.patch47
-rw-r--r--debian/patches/libpthread_stubs.patch157
-rw-r--r--debian/patches/makedev.diff17
-rw-r--r--debian/patches/makedev_keep_options.patch58
-rw-r--r--debian/patches/makedev_parted_store.patch73
-rw-r--r--debian/patches/pfinet_dhcp.patch560
-rw-r--r--debian/patches/pflocal.patch674
-rw-r--r--debian/patches/posix-sigcodes.patch270
-rw-r--r--debian/patches/proxy-defpager.diff59
-rw-r--r--debian/patches/random-default-fast.patch13
-rw-r--r--debian/patches/rc.patch78
-rw-r--r--debian/patches/runsystem_setup_pflocal.patch21
-rw-r--r--debian/patches/series34
-rw-r--r--debian/patches/startup-usr-support.patch27
-rw-r--r--debian/patches/stat_round.patch52
-rw-r--r--debian/patches/tmp_exec_startup.patch54
-rw-r--r--debian/patches/uptime_w_path_fix.patch16
-rwxr-xr-xdebian/rules63
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/options1
70 files changed, 10355 insertions, 0 deletions
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644
index 00000000..db1335eb
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,31 @@
+hurd (20110319-1) unstable; urgency=low
+
+ * To harmonize with Debian security conventions, the Debian
+ GNU/Hurd login prompt is now a standard login/password prompt,
+ and not a login shell any more. To revert to a standard login, set the
+ shell of the login user to /bin/bash.
+
+ -- Samuel Thibault <sthibault@debian.org> Tue, 15 Mar 2011 00:15:55 +0100
+
+hurd (20050513-4) unstable; urgency=low
+
+ * The Hurd console may now be started automatically on bootup. The
+ file `/etc/default/hurd-console' controls whether the Hurd console
+ will be started, and if so, which options are used. To get the
+ Hurd console on bootup, change ENABLE to `true' and adjust the
+ other options to your liking.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 28 Aug 2005 14:43:31 +0200
+
+hurd (20050119-1) unstable; urgency=low
+
+ * The command line syntax for the console client has slightly
+ changed. It is no longer necessary or even allowed to specify the
+ consnode path to the short `-c' option (e.g. `-c /dev/cons'),
+ /dev/cons is implied as default (but can be changed using the long
+ option, `--consnode=FOO'). When using the mouse or keyboard
+ repeater, the console client command line should now be as follows:
+ console -d vga -d pc_kbd --repeat=kbd -d pc_mouse --repeat=mouse \
+ -d generic_speaker -c /dev/vcs
+
+ -- Michael Banck <mbanck@debian.org> Fri, 21 Jan 2005 02:33:36 +0100
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 00000000..7977e9e4
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,1226 @@
+hurd (20111106-2) UNRELEASED; urgency=low
+
+ * control:
+ - Use hurd-any instead of hurd-i386.
+ - Recommend bf-utf-source to get more than just latin1 on the console.
+ * hurd.postinst: Set up "*random" alternatives and generate seed on
+ first install too.
+ * patches/libexec.patch, hurd.install, hurd-udeb.install, hurd.postinst,
+ rules: Move getty, console-run, and runttys to /sbin, runsystem and rc to
+ /etc/hurd (Closes: Bug#556526).
+ * hurd-udeb.lintian-overrides: Drop override about /libexec
+
+ -- Samuel Thibault <sthibault@debian.org> Sun, 06 Nov 2011 19:51:54 +0100
+
+hurd (20111106-1) unstable; urgency=low
+
+ * New upstream snapshot.
+ - Drop debian/patches/ttys.patch.patch, applied upstream.
+ - Drop debian/patches/auth-intr-cure.patch, applied upstream.
+ - Drop debian/patches/libpthread_tls.patch, applied upstream.
+ - debian/patches/libpthread_procfs.patch: Refresh.
+ - Closes: #639010.
+ * local/setup-translators:
+ - Restore /dev/shm creation.
+ - create /run/shm and /run/lock, to fix locking until we properly start
+ rcS.d scripts.
+ - Add cd[01] SCSI CD-ROMs.
+ * patches/libdiskfs_sync.patch: New patch to fix sync at shutdown.
+ * patches/libpthread_procfs.patch: Add random server.
+ * local/setup-translators: Use random server, set up its entropy pool in
+ /var/spool.
+ * debian/control, debian/local/setup-translators: Use native random server
+ set on /dev/u?random-hurd instead of random-egd on /dev/u?random.
+ (Closes: bug#637231)
+ * debian/hurd.{postinst,prerm}: Handle alternative for /dev/u?random,
+ default to u?random-hurd, generate an initial pseudo-random seed.
+ * debian/hurd.lintian-overrides: Override warnings about the /dev/u?random
+ mangling.
+ * debian/local/cdrom.h: Add header for basic CD-ROM ioctl support.
+ * debian/patches/libpthread_globsigdisp.patch,posix-sigcodes.patch: New
+ patches from Jeremie Koenig to enable global signal support.
+ * debian/patches/libpthread_sigmask.patch: Update to global signal support.
+ * debian/copyright: Fix copyright notice.
+ * debian/control:
+ - Drop article from synopsis.
+ - Tighten hurd-dev dependency on hurd to the same version.
+ * debian/hurd-udeb.install: Only include the necessary console drivers.
+ * debian/patches/random-default-fast.patch: Set default randomness to fast,
+ until we set up a daemon to feed /dev/random with entropy.
+
+ -- Samuel Thibault <sthibault@debian.org> Thu, 18 Aug 2011 01:15:04 +0000
+
+hurd (20110519-3) unstable; urgency=low
+
+ * debian/local/runsystem: Set d-i umask to 022.
+
+ -- Samuel Thibault <sthibault@debian.org> Sat, 11 Jun 2011 19:21:25 +0200
+
+hurd (20110519-2) unstable; urgency=low
+
+ * debian/control: Make the hurd package depend on random-egd, to get
+ /dev/*random working as early as d-i's base install.
+ * debian/local/setup-translators: Add entries for partitions 9-16 too, as the
+ full partman layout at least uses slice 9. Add comX and random translators
+ on installed system.
+ * debian/hurd-console.default: Enable keyboard and mouse repeaters by
+ default for X11.
+ * debian/hurd.lintian-overrides, debian/hurd-dev.lintian-overrides: Update to
+ newer lintian format.
+
+ -- Samuel Thibault <sthibault@debian.org> Wed, 08 Jun 2011 22:26:15 +0000
+
+hurd (20110519-1) unstable; urgency=low
+
+ * New upstream snapshot.
+ * debian/control:
+ - Depend on gcc-4.6 instead of gcc-4.4.
+ - Bump Standards-Version to 3.9.2 (no change needed)
+ * debian/rules: Build with gcc-4.6.
+ * debian/local/runsystem, setup-translators: Enable mouse and keyboard
+ repeaters for g-i support.
+ * debian/local/setup-translators: Pass the --compatible option to procfs to
+ tweak it a bit to get proc-related tools working without too much patching.
+ Add fd[01].
+ * debian/patches/disable-proc_getnports.patch: Remove patch, libc0.3 now
+ has proc_getnports, and the hurd package already breaks older versions.
+ * debian/patches/uptime_w_path_fix.patch: Fix /usr/bin/w-hurd command name,
+ thanks harish badrinath for the notice.
+
+ -- Samuel Thibault <sthibault@debian.org> Sun, 10 Apr 2011 20:42:45 +0200
+
+hurd (20110319-2) unstable; urgency=low
+
+ * debian/hurd.postinst: use useradd from required passwd package instead of
+ adduser, which is not required and thus not available at debootstrap.
+ * debian/control: Bump Standards-Version to 3.9.1 (no change needed).
+
+ -- Samuel Thibault <sthibault@debian.org> Mon, 21 Mar 2011 17:33:19 +0100
+
+hurd (20110319-1) unstable; urgency=low
+
+ [ Samuel Thibault ]
+ * New upstream snapshot.
+ * debian/local/setup-translators: Add inet6 -> 26 symlink.
+ * debian/local/finish-install.d/51hurd_config-target-network: Set pfinet
+ translator on /servers/socket/26 too, add +x permission.
+ * debian/local/partman/commit.d/40hurd_reload-partitions: Add +x permission.
+ * debian/local/runsystem: Don't let d-i start if there is less then 256MiB
+ memory. Tell the user he needs to be patient while the d-i templates get
+ loaded.
+ * debian/patches/ext2fs_nowait.patch: Avoid systematically waiting for all
+ disk writes, as it slows us down awfully.
+ * debian/control: Recommend random-egd, to provide /dev/*random
+ (Closes: Bug#558664). Break old gnumach packages, instead of depending on
+ them. Break libc0.3 before getifaddrs fix, now that pfinet provides a
+ correct response.
+ * debian/patches/auth-intr-cure.patch: Add patch to mitigate
+ reauthentication issue triggered by sudo.
+ * debian/patches/libpager_deadlock.patch: Add patch to fix a known
+ synchronization deadlock.
+ * debian/local/finish-install.d/51hurd_config-target-network: Record active
+ network configuration, not only passive. Create /servers/socket/26 node if
+ it doesn't exist yet.
+ * debian/local/setup-translators, debian/patches/makedev_keep_options.patch:
+ Fix -K option into not starting existing translators.
+ * debian/patches/libdiskfs_self-reauth.patch: Add patch to fix one of the
+ spurious mach port deallocation issues.
+
+ [ Justus Winter ]
+ * debian/hurd.{postinst,postrm}: Add/remove loginpr shell and login user with
+ loginpr shell, to drop the login shell in order to match common Debian
+ convention, in particular for remote telnet access...
+ (Closes: Bug#556522)
+
+ [ Samuel Thibault ]
+ * debian/NEWS: Add a notice about that.
+
+ -- Samuel Thibault <sthibault@debian.org> Sun, 27 Feb 2011 19:02:04 +0100
+
+hurd (20100926-1) unstable; urgency=low
+
+ [ Samuel Thibault ]
+ * New upstream snapshot. Switch to jkoenig's procfs.
+ * debian/control: Depend on gcc-4.4 instead of gcc-4.3. Thanks Emilio!
+ * debian/rules: Fix back debugging symbols into the hurd-dbg package.
+ * debian/local/runsystem: Do not start the Hurd console if the TERM variable
+ is given. Should permit mach-console install for better debugging as well
+ as Xen or sub-hurd support.
+ * debian/patches/disable-proc_getnports.patch: New patch to disable
+ usage of proc_getnports until libc0.3 provides it.
+ * debian/patches/libpthread_procfs.patch: Update patch to integrate procfs
+ build.
+
+ [ Jeremie Koenig ]
+ * debian/patches/libpthread_sigmask.patch: New patch to fix missed signals
+ when using pthread_sigmask.
+
+ -- Samuel Thibault <sthibault@debian.org> Sun, 26 Sep 2010 22:15:43 +0000
+
+hurd (20100829-1) unstable; urgency=low
+
+ [ Samuel Thibault ]
+ * New upstream 20100827 snapshot.
+ - debian/patches/dir_acces_fix.patch: Remove patch, merged upstream.
+ - debian/patches/exec_fix.patch: Likewise.
+ - debian/patches/libdiskfs-rename.patch: Likewise.
+ - debian/patches/libpthread_mutex_owner.patch: Likewise.
+ - debian/patches/libpthread_recursive_mutex_initializer.patch: Likewise.
+ - debian/patches/libpthread_setcancel.patch: Likewise.
+ - debian/patches/pfinet-gcc-4.3-fix.patch: Likewise.
+ - debian/patches/procfs.patch: Likewise.
+ - debian/patches/ext2fs_large_stores.patch: Resync.
+ - debian/patches/libpthread_procfs.patch: New patch, to enable libpthread
+ and procfs build.
+ * debian/rules: Really put debugging symbols into the hurd-dbg package.
+ * debian/patches/hurd_console_startup.patch: Add -d current_vcs to enable
+ /dev/cons/vcs by default.
+ * debian/copyright: Reference /usr/share/common-licenses/GPL-2 instead of
+ just GPL.
+ * debian/hurd.dirs: Add /etc/sysctl.d.
+ * debian/control (hurd-udeb): Add Provides: *-modules.
+ * debian/patches/diskfs_no_inherit_dir_group.patch: Fix documentation too.
+ * debian/control:
+ - Drop duplicate priority and section fields.
+ - Add ${misc:Depends}.
+ - Add dpkg (>= 1.15.4) | install-info dependency.
+ - Drop -1 from gnumach-dev dependency.
+ - Bump Standards-Version to 3.8.4 (no change needed).
+ * debian/local/runsystem.gnu: New runsystem file for the d-i case, incomplete
+ for now.
+ * debian/hurd-udeb.install: Remove getty, runttys, /etc/ttys ftpcp, ftpdir,
+ ftpfs, hostmux, usermux, nfs, isofs.static, rpctrace, gcore, forks. Install
+ local/runsystem.gnu in /libexec, install ext2fs.static in /boot
+ * debian/rules: Do not ship *_pic.a, as mklibs breaks them.
+ * debian/patches/proxy-defpager.diff: New patch to fix proxying defpager.
+ * debian/patches/ext2fs_large_stores.patch: Apply Alioth fix #312328 from
+ Fredrik Hammar to fix random startup crash (Closes: Bug#576519).
+ * debian/patches/procfs.patch: Fix swap size printout.
+ * debian/hurd-udeb.install: remove reboot and halt (will be provided by
+ busybox), remove crash and password (not useful), add procfs, remove rc.
+ * debian/local/runsystem.gnu: Integrate jkoenig d-i changes, rename to
+ debian/local/runsystem.
+ * debian/hurd.links: Add symlink to /usr/src/unifont.bdf from the unifont
+ package to /usr/share/hurd/vga-system.bdf so the console can pick it up
+ when installed.
+ * debian/source/options: Set compression to bzip2.
+ * debian/control: Update Vcs fields to point to the new git repositories.
+ * debian/patches/console_ignore_bdf_err.patch: New patch to ignore erroneous
+ number of glyphs in bdf files.
+ * debian/rules: Remove debian/ChangeLog generation.
+ * debian/local/runsystem: Pass -g option to the console to maximize glyph
+ usage for chinese.
+ * debian/hurd.lintian-overrides: New overrides to announce which servers are
+ supposed to be statically linked, accept hurd to be essential, and accept
+ some setuid binaries.
+ * debian/hurd-udeb.lintian-overrides: New overrides to validate
+ hurd-i386-specific paths.
+ * debian/hurd-dev.lintian-overrides: New overrides to allow libstore_* not
+ being stripped (they wouldn't work, else).
+ * debian/local/runsystem: Export kernel parameters into environment, like
+ Linux does.
+ * debian/control: Use Package-Type instead of XC-Package-Type.
+ * debian/rules: Switch to gcc-4.4 (Closes: Bug#594285).
+
+ [ Guillem Jover ]
+ * Update make-new-tarball.sh to exclude git instead of CVS paths.
+ * Refresh patches with -pab to allow migration to source format 3.0 (quilt).
+ * Switch to source format “3.0 (quilt)”:
+ - Remove quilt from Build-Depends.
+ - Remove patchsys-quilt.mk include from debian/rules.
+
+ [ Michael Banck ]
+ * debian/control (Uploaders): Removed Marcus Brinkmann. (Closes: #503564)
+
+ [ Jeremie Koenig ]
+ * debian/control: Build-Depend on libparted-dev.
+ * debian/local/partman/commit.d/40hurd_reload-partitions: New file for
+ hurd-udeb, make partman restart the partition translators after the
+ partition table has been changed.
+ * debian/hurd-udeb.install: Install file above.
+ * debian/local/runsystem (hurd-udeb): Start mach-defpager.
+ * debian/hurd-udeb.dirs: Include /servers.
+ * Sort out the way device and server nodes are created:
+ - debian/patches/makedev_keep_options.patch: Introduces the -k and -K
+ options to MAKEDEV, respectively to keep active translators running or
+ leave existing files alone completely.
+ - debian/patches/makedev_parted_store.patch: MAKEDEV -p will use parted
+ instead of device stores for disk partitions.
+ - debian/local/setup-translators: New script installed in /usr/lib/hurd,
+ uses MAKEDEV's new options to create all the necessary device and
+ server nodes.
+ - debian/local/runsystem (hurd-udeb): Uses setup-translators in "minimal
+ mode" to prepare the initrd when the installer is started. Parted
+ stores are used to avoid problems when reloading the partition table.
+ - debian/hurd.postinst: Uses setup-translators to create missing nodes on
+ upgrades (on initial installs, debootstrap will use the
+ setup-translators script from the installed hurd package to setup the
+ devices and servers itself).
+ * debian/local/finish-install.d/51hurd_config-target-network: copy the
+ /servers/socket/2 translator settings into the target system.
+ * debian/hurd-udeb.links: Include the unifont.bdf link in hurd-udeb too.
+
+ -- Samuel Thibault <sthibault@debian.org> Fri, 27 Aug 2010 13:12:12 +0200
+
+hurd (20090404-2) unstable; urgency=low
+
+ * debian/patches/libpthread_no_recursive_mutex_initializer.patch: Remove
+ unused patch.
+ * debian/patches/procfs.patch: Fix a couple of memory leaks, fix swap size
+ report.
+ * debian/control: Add missing comma in Build-Depends.
+ * debian/patches/pfinet-gcc-4.3-fix.patch: Cherry-pick upstream patch to fix
+ build with gcc-4.3
+ * debian/rules: Set CC to gcc-4.3 instead of gcc-4.2.
+ * debian/control: Build-Depend on gcc-4.3 instead of gcc-4.2.
+ (Closes: Bug#533782)
+ * debian/control: Add Provides: hurd to the hurd-udeb package, to meet
+ dependencies.
+ * debian/rules: Add --add-udeb="hurd-udeb" option to dh_makeshlibs
+ invocation for the hurd package, to fix udeb dependency generation.
+ * debian/patches/MAKEDEV.patch: New patch to use bash for MAKEDEV.
+ (Closes: Bug#548587)
+ * debian/patches/libdiskfs-rename.patch: New patch to fix ext2fs hang on
+ renaming directory to something/.
+
+ -- Samuel Thibault <sthibault@debian.org> Sun, 11 Oct 2009 04:38:02 +0200
+
+hurd (20090404-1) unstable; urgency=low
+
+ [ Michael Banck ]
+ * New snapshot from CVS.
+ + debian/patches/diskfs_lookup_error_fix.patch: Removed, applied upstream.
+ + debian/patches/libpthread_mutex-no-include.patch: Likewise.
+ + debian/patches/libpthread_pthreadtypes_h.patch: Likewise.
+ + debian/patches/libpthread_spin-lock-inline.patch: Likewise.
+ + debian/patches/lock-memory-clobber.patch: Likewise.
+ + debian/patches/pflocal-port-leak.patch: Likewise.
+ + debian/patches/libpthread_pthreadexit-safety.patch: Removed, no longer
+ needed.
+ + debian/patches/libpthread_tls.patch: Refreshed.
+ * Change packaging to no tarball-in-tarball and quilt.
+ + debian/control (Build-Depends): Added quilt.
+ + debian/rules (DEB_TAR_SRCDIR): Removed.
+ + debian/rules (tarball.mk) No longer include it.
+ + debian/rules (simple-patchsys.mk) Replaced with ...
+ + debian/rules (patchsys-quilt.mk) ... this.
+ + debian/patches/series: New file.
+ + debian/rules (build/hurd): Replace build-tree with $(DEB_SRCDIR).
+ + debian/rules (install/hurd): Likewise.
+ + debian/hurd-doc.docs: Adjust paths.
+ * debian/hurd.postinst: Install ps alternatives link in /bin, not
+ /usr/bin.
+ * debian/hurd.postinst: Install /proc as passive translator only.
+ * debian/patches/uptime_w_path_fix.patch: New patch, run /usr/bin/w instead
+ of /bin/w.
+ * debian/rules: Install fakeroot, uptime and vmstat into /usr/bin, not /bin.
+ * debian/rules (binary-predeb/hurd): Adjust paths.
+ * debian/hurd.install: Likewise.
+ * debian/hurd-udeb.install: Likewise.
+ * debian/hurd.dirs: Added /usr/bin.
+ * debian/hurd.postinst: Update accordingly.
+ * debian/patches/libpthread_mutex_owner.patch: New patch, fix a hang in
+ libpthread, by Neal Walfield.
+
+ [ Samuel Thibault ]
+ * debian/patches/thread-throttle.patch: Remove patch, makes ext2fs hang on
+ big syncs.
+ * debian/control (Build-Depends): Bump libc0.3-dev to (>= 2.9).
+ * debian/patches/stat_round.patch: New temporary patch, fixes symlink issues
+ with tar.
+ * debian/patches/dir_acces_fix.patch: New patch, fixes ext2fs crashes.
+ * debian/patches/libports_stability.patch: New patch to keep the old
+ behavior of libports.
+ * debian/patches/libpthread_fix.patch: New patch from Thomas Schwinge to fix
+ libpthread.
+ * debian/patches/libpthread_setcancel.patch: New patch to fix configuration
+ of octave3.0.
+ * debian/patches/extern_inline_fix.patch: New patch from Marc Dequène to
+ fix extern inline declarations.
+ * debian/patches/exec_fix.patch: New patch to fix random hang of exec.
+ * debian/patches/libpthread_recursive_mutex_initializer.patch: New patch
+ to fix the recursive mutex initializers usage in libraries not linking
+ against libpthread.
+ * debian/control: Now using Standards-Version 3.8.2 (no changes needed).
+ * debian/control: Add myself to uploaders.
+
+ [ Guillem Jover ]
+ * Change hurd-dbg section to debug.
+
+ -- Samuel Thibault <sthibault@debian.org> Sun, 28 Jun 2009 22:19:07 +0000
+
+hurd (20080607-6) unstable; urgency=low
+
+ * debian/rules (install/hurd): Move away ps, uptime, vmstat and w in order
+ to have them handled by update-alternatives.
+ * debian/hurd.install: Update accordingly.
+ * debian/hurd-udev.install: Likewise.
+ * debian/rules (SUID_PROGRAMS): Likewise.
+ * debian/hurd.postinst: Run update-alternatives for ps, uptime, vmstat and
+ w.
+ * debian/hurd.postinst: Setup /proc if it hasn't been already.
+
+ -- Michael Banck <mbanck@debian.org> Fri, 12 Sep 2008 22:58:08 +0200
+
+hurd (20080607-5) unstable; urgency=low
+
+ * debian/patches/procfs.patch: New patch, implements a /proc translator, by
+ Madhusudan C.S., taken from a CVS branch.
+
+ -- Michael Banck <mbanck@debian.org> Tue, 02 Sep 2008 00:24:36 +0200
+
+hurd (20080607-4) unstable; urgency=low
+
+ [ Samuel Thibault ]
+ * debian/patches/pflocal-port-leak.patch: New patch to fix port leaks in
+ pflocal which was making tcl-related builds hang.
+ * debian/patches/lock-memory-clobber.patch: New patch to fix lock safety.
+ * debian/patches/libpthread_mutex-no-include.patch: New patch to drop
+ useless (and problematic) inclusion from mutex.h.
+ * debian/patches/libpthread_spin-lock-inline.patch: New patch to split off
+ inlines from spin-lock.h into spin-lock-inline.h to avoid including too
+ many headers from pthreadtypes.h (fixes glibc 2.7-13 compilation).
+ * debian/patches/libpthread_pthreadtypes_h.patch: Remove comma at end of
+ enumeration.
+ * debian/patches/diskfs_lookup_error_fix.patch: New patch to fix deadlock in
+ lookup error conditions.
+
+ -- Michael Banck <mbanck@debian.org> Fri, 29 Aug 2008 22:53:20 +0200
+
+hurd (20080607-3) unstable; urgency=low
+
+ [ Samuel Thibault ]
+ * debian/patches/libpthread_pthreadtypes_h.patch: fix patch into really
+ installing <pthread/pthreadtypes.h>.
+
+ -- Michael Banck <mbanck@debian.org> Sat, 12 Jul 2008 02:23:21 +0200
+
+hurd (20080607-2) unstable; urgency=low
+
+ [ Samuel Thibault ]
+ * debian/patches/libpthread_pthreadtypes_h.patch: New patch to get pthread
+ types into <pthread/pthreadtypes.h>, which <bits/pthreadtypes.h> will be
+ able to include.
+ * debian/patches/libpthread_stubs.patch: Fix build.
+ * debian/patches/libpthread_pthreadexit-safety.patch: New patch to fix a
+ race during thread exit. Fixes e.g. libatomic-ops' testsuite, and
+ probably also a lot of others'.
+
+ -- Michael Banck <mbanck@debian.org> Fri, 11 Jul 2008 15:33:27 +0200
+
+hurd (20080607-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ + debian/patches/ext2fs_large_stores.patch: Removed copyright year
+ changes.
+ + debian/patches/libpthread_getattr.patch: Removed, applied upstream.
+ + debian/patches/libpthread_inline.patch: Likewise.
+ + debian/patches/mmx.patch: Likewise.
+ + debian/patches/libpthread_stubs.patch: Updated, one hunk got applied
+ upstream.
+ * debian/rules (CC): New variable, set to gcc-4.2.
+ * debian/control (Build-Depends): Added gcc-4.2.
+
+ -- Michael Banck <mbanck@debian.org> Wed, 11 Jun 2008 01:02:01 +0200
+
+hurd (20071119-2) unstable; urgency=low
+
+ [ Michael Banck ]
+ * debian/local/menu.lst: Add some comments.
+ * debian/patches/libpthread_getattr.patch: New patch, implements
+ pthread_getattr_np, taken from CVS.
+
+ [ Guillem Jover ]
+ * debian/copyright: Update FSF address.
+ * debian/control: Use binary:Version and source:Version instead of
+ deprecated Source-Version substvar.
+ * debian/changelog: Fix Neal's mail address in ancient entry.
+ * debian/control: Line-wrap Build-Depends and Uploaders fields.
+ * debian/control: Now using Standards-Version 3.7.3 (no changes needed).
+ * debian/control: Move packages from base Section to admin.
+ * debian/control: Add Homepage field.
+ * debian/control: Add Vcs-Browser and Vcs-Svn fields.
+
+ [ Samuel Thibault]
+ * debian/patches/mmx.patch: New patch to align the stack of created
+ threads.
+ * debian/patches/thread-throttle.patch: New patch, add a fix for ext2fs to
+ keep the superblock in memory so as to avoid a thread creation dead lock.
+ * debian/patches/libpthread_stubs.diff: New patch, add generation of
+ <gnu/stubs-pthread.h> to advertise libpthread stubs.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 18 May 2008 20:22:32 +0200
+
+hurd (20071119-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ + Includes a port of Linux' IPv6 support by Stefan Siegl.
+ (Closes: #274156)
+ + debian/patches/glibc_stat_updates.patch: Removed, applied upstream.
+ + debian/patches/libpthread_no-inline.patch: Likewise.
+ + debian/patches/pfinet_-fno-strict-aliasing.patch: Likewise.
+ + debian/patches/servers.boot-update.patch: Likewise.
+ + debian/patches/siocgifhwaddr.patch: Likewise.
+ + debian/patches/pfinet_dhcp.patch: Rediffed.
+ + debian/patches/pflocal.patch: Likewise.
+
+ [ Samuel Thibault ]
+ * debian/local/soundcard.h: Add _PATCHKEY definition.
+ * debian/patches/libpthread_tls.patch: New patch, replaces
+ debian/patches/libpthread_tls_transitional.patch.
+ * debian/patches/libpthread_inline.patch: New patch to fix extern inlines
+ with gcc 4.3.
+
+ [ Michael Banck ]
+ * debian/patches/runsystem_setup_pflocal.patch: New patch, sets up
+ pflocal during bootup if this has not been done before (in the install
+ case).
+ * debian/hurd.dirs: Added servers/socket.
+ * debian/patches/init_try_runsystem.gnu.patch: New patch, try
+ /libexec/runsystem.gnu as well if /libexec/runsystem is not
+ available.
+ * debian/patches/tmp_exec_startup.patch: New patch, try to attach the
+ exec server to /tmp/exec if /servers/exec is not yet available.
+ * debian/patches/diskfs_no_inherit_dir_group.patch: Update with better
+ patch by Thomas Schwinge.
+ * debian/patches/pfinet_dhcp.patch: Updated with new patch by Christian
+ Dietrich and Stefan Siegl.
+ * debian/local/menu.lst: New file.
+ * debian/hurd.examples: Ship it.
+
+ -- Michael Banck <mbanck@debian.org> Tue, 08 Jan 2008 01:10:07 +0100
+
+hurd (20070606-3) unstable; urgency=low
+
+ [ Michael Banck ]
+ * debian/patches/patches/servers.boot-update.patch: New patch, updates
+ the servers.boot script to use the currently used Grub module lines.
+ * debian/rules (install/hurd::): Install release/servers.boot into /boot.
+ * debian/patches/pfinet_-fno-strict-aliasing.patch: New patch, adding
+ -fno-strict-aliasing to pfinet's CFLAGS to fix compilation with gcc-4.2,
+ taken from CVS.
+ * debian/hurd.dirs: Added /boot.
+
+ [ Samuel Thibault ]
+ * debian/patches/patches/libpthread_no-inline.patch: New patch, removes
+ extern inlines to fix g++ and gettext FTBFS, by Samuel Thibault.
+
+ -- Michael Banck <mbanck@debian.org> Thu, 9 Aug 2007 17:08:01 +0200
+
+hurd (20070606-2) unstable; urgency=low
+
+ * debian/patches/libpthread_tls_transitional.patch: New patch,
+ implements TLS for libpthread, by Samuel Thibault.
+ * debian/patches/libpthread_weak_inline.patch: Removed.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 22 Jul 2007 23:45:39 +0200
+
+hurd (20070606-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ + Includes a patch to make pthread_* function aliases strong.
+ (Closes: #407208)
+ + debian/patches/console_ioperms.patch: Removed, fixed upstream.
+ + debian/patches/no-debian-dir.patch: Removed, applied upstream.
+ * debian/local/soundcard.h: Updated by Samuel Thibault.
+ * debian/control (Build-Depends): Added libc0.3-dev (>= 2.5-5).
+ * debian/copyright: Clarify that the package is maintained by the
+ Debian GNU Hurd maintainers and no longer by upstream.
+ * debian/control (Build-Depends): Bumped gnumach-dev version to
+ 2:1.3.99.dfsg.cvs20070526-1.
+ * debian/control (hurd/Depends): Bumped gnumach version to
+ 2:1.3.99.dfsg.cvs20070526-1.
+
+ -- Michael Banck <mbanck@debian.org> Wed, 6 Jun 2007 18:54:37 +0200
+
+hurd (20060825-2) unstable; urgency=low
+
+ * Rebuilt against gnumach_1:20060826.dfsg.1-1.
+ * debian/control (hurd/Depends): Bump versioned dependency of gnumach
+ to 1:20060826.dfsg.1-1.
+ * debian/control (Build-Depends): Added versioned Build-Depends on
+ gnumach-dev 1:20060826.dfsg.1-1.
+ * debian/control (Build-Depends-Indep): Moved texi2html to ...
+ * debian/control (Build-Depends): ... here.
+
+ -- Michael Banck <mbanck@debian.org> Wed, 30 Aug 2006 00:17:15 +0200
+
+hurd (20060825-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * debian/patches/beta_make.patch: Removed, fixed upstream.
+ * debian/patches/ext2fs_large_stores.patch: Resynced.
+ * debian/patches/pfinet_dhcp.patch: Likewise.
+ * debian/patches/ftpfs_fix.patch: Removed, applied upstream.
+ * debian/patches/gcc-4.0_fixes.patch: Likewise.
+ * debian/patches/libpthread_need_clockid_t.patch: Likewise.
+ * debian/patches/libstore_attribute.patch: Likewise.
+ * debian/patches/magic_port_leak.patch: Likewise.
+ * debian/patches/pfinet_packet_filter.diff: Likewise.
+ * debian/patches/semaphore_restrict_fix.patch: Likewise.
+ * debian/rules (build/hurd::): Assemble all upstream ChangeLogs to one
+ big ChangeLog.
+ * debian/rules (DEB_INSTALL_CHANGELOGS_ALL): New variable, install it.
+ * debian/patches/no_shm_makedev.diff: Renamed to ...
+ * debian/patches/makedev.diff: ... this.
+ * debian/patches/console_utf-8.patch: New patch, setting the Hurd
+ console to UTF-8 by default. (Closes: #348260)
+
+ -- Michael Banck <mbanck@debian.org> Sat, 26 Aug 2006 01:00:41 +0200
+
+hurd (20050513-8) unstable; urgency=low
+
+ * debian/patches/pfinet_packet_filter: New patch, adding support for
+ gathering incoming packets, taken from CVS.
+ * debian/hurd.install: Install hurd.msgids into /usr/share/msgids.
+ * debian/hurd.dirs: Added /usr/share/msgids.
+ * debian/patches/sysvshm.patch: Removed, it was causing deadlocks.
+
+ -- Michael Banck <mbanck@debian.org> Fri, 4 Aug 2006 15:54:09 +0200
+
+hurd (20050513-7) unstable; urgency=low
+
+ * debian/patches/diskfs_no_inherit_dir_group.patch: New patch,
+ enabling SysV style behaviour (i.e. adopt the user's gid, not the
+ one from the parent directory) for group permissions of newly
+ created files by default.
+ * debian/rules (install/hurd::): Install motd.UTF8 into /etc.
+ * debian/patches/install-msgids.diff: New patch, install RPC message
+ IDs in $(datadir)/msgids, by Alfred M. Szmidt.
+ * debian/hurd.postinst: Create symlinks for /dev/kbd and /dev/mouse to
+ /dev/cons/{kbd,mouse} if not present already. (Closes: #355002)
+ * debian/patches/no_shm_makedev.diff: New patch, skip /dev/shm device
+ when generating the standard devices.
+ * debian/hurd.postinst: Create /dev/shm directory if not present
+ already.
+ * debian/patches/ext2fs_large_stores.patch: Include <hurd/pager.h>
+ rather than "../libpager/pager.h" and add pager to libdiskfs'
+ HURDLIBS.
+ * local/soundcard.h: New file by Samuel Thibault.
+ * debian/rules (install/hurd-dev::) New rule, install soundcard.h
+ in debian/tmp/include/sys.
+
+ -- Michael Banck <mbanck@debian.org> Tue, 25 Apr 2006 19:30:33 +0200
+
+hurd (20050513-6) unstable; urgency=low
+
+ * debian/patches/console_ioperms.patch: New patch by Samuel Thibault.
+ * debian/control (hurd): Add versioned Depends on gnumach 1:20050801-3.
+ * debian/patches/beta_make.patch: New patch, support newer make.
+
+ -- Michael Banck <mbanck@debian.org> Thu, 12 Jan 2006 02:42:36 +0100
+
+hurd (20050513-5) unstable; urgency=low
+
+ * debian/patches/thread-throttle.patch: New patch by Sergio Lopez.
+ * debian/patches/gcc-4.0_fixes.patch: New patch by Thomas Schwinge.
+ * debian/patches/libstore_attribute.patch: New patch by Roland
+ McGrath, taken from CVS.
+ * debian/rules (CC): Removed.
+ * debian/control (Build-Depends): Removed gcc-3.3.
+ * debian/patches/libpthread_weak_inline.patch: New patch by Neal
+ Walfield.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 11 Dec 2005 13:31:11 +0100
+
+hurd (20050513-4) unstable; urgency=low
+
+ * debian/rules (DEB_CONFIGURE_USER_FLAGS): Build iso9660fs.static
+ as well.
+ * debian/hurd-udeb.install: Added iso9660fs.static.
+ * debian/patches/hurd_console_startup.patch: New patch, adding
+ support for starting the Hurd console on bootup.
+ * debian/hurd.dirs: Added `etc/default'.
+ * debian/hurd-console.default: New file.
+ * debian/rules (install/hurd::) Install it into debian/hurd/etc/default.
+ * debian/hurd.postinst: Removed creation of user `login'.
+ * debian/NEWS: Mention the possibility of starting the Hurd console
+ on bootup.
+ * debian/patches/magic_port_leak.patch: New patch by Marcus
+ Brinkmann, taken from CVS.
+ * debian/patches/ftpfs_fix.patch: New patch by Samuel Thibault.
+ * debian/patches/sysvshm.patch: New patch by Marcus Brinkmann.
+ * debian/patches/libpager_update_seqno.patch: New patch by Sergio Lopez.
+ * debian/patches/semaphore_restrict_fix.patch: New patch by Samuel
+ Thibault. (Closes: #320121)
+ * debian/control (Build-Depends): Added gcc-3.3.
+ * debian/rules (CC): New variable, set to gcc-3.3.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 28 Aug 2005 14:45:55 +0200
+
+hurd (20050513-3) unstable; urgency=low
+
+ * debian/control (hurd-doc): Fix description to indicate the manual
+ is included in HTML and not PostScript format. (Closes: #309748)
+ * debian/control (hurd-dev): Provide/Replace/Conflict libsem-dev.
+ * debian/control (Build-Depends): Version dependency on debhelper to
+ >= 4.2.
+ * debian/control (hurd-udeb): New package.
+ * debian/hurd-udeb.install: New file.
+ * debian/patches/libpthread_need_clockid_t.patch: Updated from CVS.
+
+ -- Michael Banck <mbanck@debian.org> Thu, 9 Jun 2005 01:40:31 +0200
+
+hurd (20050513-2) unstable; urgency=low
+
+ * debian/patches/libpthread_need_clockid_t.patch: New patch by Neal
+ Walfield.
+ * debian/patches/pflocal.patch: New patch by Neal Walfield.
+
+ -- Michael Banck <mbanck@debian.org> Tue, 17 May 2005 18:37:08 +0200
+
+hurd (20050513-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ + Contains a POSIX semaphore implementation by Neal Walfield.
+ + Contains more libpthread fixes for test suites by Neal Walfield.
+ * debian/hurd.postinst: Handle /bin/fakeroot-hurd by alternatives.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 15 May 2005 13:00:12 +0200
+
+hurd (20050507-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ + Contains libpthread fixes for various test suites by Neal
+ Walfield.
+ * debian/changelog (20050119-3): Added overlooked Closes: tag.
+ * debian/control (hurd-dbg/Priority:) Set to extra as requested by
+ the ftp-masters.
+ * debian/patches/isofs_boot.patch: Removed, applied upstream.
+ * debian/patches/libpthread_linker_script.patch: Likewise.
+
+ -- Michael Banck <mbanck@debian.org> Sat, 7 May 2005 15:28:51 +0200
+
+hurd (20050119-3) unstable; urgency=low
+
+ * debian/control (hurd-dbg): New package.
+ * debian/rules (DEB_DH_STRIP_ARGS): Add support for hurd-dbg.
+ * debian/hurd-dbg.dirs: New file.
+ * debian/control (hurd-doc): New package. (Closes: #264858)
+ (Build-Depends-Indep): Added texi2html.
+ * debian/rules (build/hurd::): Generate html version of the manual.
+ * debian/hurd-doc.info: New file.
+ * debian/hurd-doc.docs: New file.
+
+ -- Michael Banck <mbanck@debian.org> Fri, 15 Apr 2005 23:03:34 +0200
+
+hurd (20050119-2) unstable; urgency=low
+
+ [ Michael Banck ]
+ * debian/hurd-dev.install: Install development libraries into /lib,
+ not /usr/lib.
+ * debian/hurd.install: Install Hurd console drivers into
+ /usr/lib/hurd/console, not /lib/hurd/console.
+ * debian/copyright: Clarify that the FSF is the copyright holder.
+ * debian/copyright: Update download location to Savannah's GNU Hurd
+ project page.
+
+ -- Michael Banck <mbanck@debian.org> Mon, 4 Apr 2005 12:08:40 +0200
+
+hurd (20050119-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ + Contains libpthread header fixes by Neal Walfield and
+ Pietro Ferrari. (Closes: #184344)
+ + Contains console repeaters by Marco Gerards.
+ + Contains mount argp fixes. (Closes: #151407)
+
+ [ Michael Banck]
+ * debian/patches/exec.patch: Removed, no longer needed.
+ * debian/patches/mouse.patch: Likewise.
+ * debian/patches/console_repeater.patch: Removed, applied upstream.
+ * debian/patches/libcons_repeater.patch: Likewise.
+ * debian/patches/netfs_io_select.patch: Likewise.
+ * debian/patches/netfs_nonblock.patch: Likewise.
+ * debian/patches-contrib/kbd.patch: Removed, no longer needed.
+ * debian/patches/libpthread_linker_script.patch: New patch. Install
+ libpthread.a linker script correctly. (Closes: #291307)
+ * debian/rules (install/hurd::): Rename /bin/fakeroot to
+ /bin/fakeroot-hurd.
+ * debian/control (hurd): Removed fakeroot from Provides:, Replaces:
+ and Conflicts:. (Closes: #293511)
+ * debian/hurd.install: Install debian/tmp/bin/fakeroot-hurd instead
+ of debian/tmp/bin/fakeroot.
+ * NEWS: New file. Explain the console-client command line interface
+ changes.
+ * debian/patches/siocgifhwaddr.patch: New patch by Marco Gerards.
+ * debian/patches/isofs_boot.patch: New patch by Alfred M. Szmidt.
+
+ -- Michael Banck <mbanck@debian.org> Wed, 23 Feb 2005 20:52:07 +0100
+
+hurd (20040508-6) unstable; urgency=low
+
+ [ Michael Banck ]
+ * debian/patches/pfinet_dhcp.patch: New patch by Marco Gerards.
+
+ -- Michael Banck <mbanck@debian.org> Sat, 15 Jan 2005 21:04:33 +0100
+
+hurd (20040508-5) unstable; urgency=low
+
+ [ Michael Banck ]
+ * debian/patches-contrib/ext2fs_20040930.diff: Moved to ...
+ * debian/patches/ext2fs_large_stores.diff: ... here, updated from
+ Ognyan Kulev's 20041111 version. Set DISK_CACHE_BLOCKS to
+ 65536 in ext2fs.h.
+
+ -- Michael Banck <mbanck@debian.org> Sun, 12 Dec 2004 17:54:32 +0100
+
+hurd (20040508-4) unstable; urgency=low
+
+ [ Michael Banck ]
+ * debian/changelog: Added back 20040301-1 entry which got lost.
+ * debian/hurd.install: Do not install /sbin/fsck. (Closes: #272655)
+ * debian/patches/rc.patch: Updated to use e2fsprog's /sbin/fsck
+ command-line options. Make sure the root file system is read-only
+ during the fsck run, and update it to be writable again if fsck
+ succeeds. (Closes: #273508)
+ * debian/patches-contrib/ext2fs_20040930.diff: New file. Just put it
+ in debian/patches and recompile the package to get (experimental)
+ support for ext2 files systems larger than 2GB.
+ * debian/control (Maintainer): Changed Maintainer address.
+
+ [ Guillem Jover ]
+ * debian/hurd.postinst:
+ - Move /bin/login suid root chmod to debian/rules.
+ - Set suid bit to other binaries (/bin/ps, /bin/ids, /bin/w).
+ (Closes: #273507)
+ Thanks Ognyan Kulev <ogi@fmi.uni-sofia.bg>.
+
+ -- Michael Banck <mbanck@debian.org> Thu, 7 Oct 2004 20:11:38 +0200
+
+hurd (20040508-3) unstable; urgency=low
+
+ * debian/local/rc: Removed.
+ * debian/patches/rc.patch: New file. (Closes: #254147)
+ * debian/hurd.install: Install tmp/libexec/rc.
+ * debian/patches/console_switch3.patch: Removed.
+ * debian/patches/console_repeater.patch: New patch by Marco Gerards.
+ * debian/patches/libcons_repeater.patch: New patch by Marco Gerards.
+ * debian/patches/netfs_io_select.patch: New patch by Marco Gerards.
+ * debian/patches/netfs_nonblock.patch: New patch by Marco Gerards.
+ * Rebuilt against glibc_2.3.2.ds1-16.
+ * debian/hurd.postinst: Make sure /bin/login is suid. (Closes: #251863)
+ * debian/control (Uploaders): Added myself.
+ * debian/hurd.postinst: Only create the tty devices if they do not
+ exist already. (Closes: #268347)
+
+ -- Michael Banck <mbanck@debian.org> Thu, 9 Sep 2004 22:32:07 +0200
+
+hurd (20040508-2) unstable; urgency=low
+
+ * Fix typo in postinst. (Closes: #253662)
+ Thanks to Michael Banck.
+ * Support /usr tree in startup scripts (Closes: #229572)
+ Thanks to Guillem Jover
+
+ -- Jeff Bailey <jbailey@raspberryginger.com> Fri, 11 Jun 2004 11:17:26 -0400
+
+hurd (20040508-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Switch packaging to cdbs
+ * Do not provide /boot/serverboot or /boot/servers.boot
+ * Update policy to 3.6.1.0
+ * Do not provide update-rc.d, use the one from sysvinit instead
+ (Closes: #246813) - Thanks to Robert Millan
+ * Do not provide /sbin/fsck, use the one from e2fsprogs instead
+ Thanks to Robert Millan
+
+ -- Jeff Bailey <jbailey@raspberryginger.com> Sat, 8 May 2004 16:55:18 -0400
+
+hurd (20040301-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual. exec/exec.c PT_GNU_STACK work-around.
+ Provide example entries for new console in config/ttys.
+ * debian/rules: Do not call autoconf.
+ * debian/control: Remove build dependency autoconf.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 1 Mar 2004 01:36:23 +0200
+
+hurd (20021118-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual, with bug fixes from David Walter.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Tue, 18 Nov 2002 21:32:22 +0200
+
+hurd (20021011-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual.
+ Build libpthread.
+ debian/control: Add libncursesw5-dev as build-dependency.
+ debian/shlibs: Add libpthread
+ debian/control: Add myself as an uploader.
+
+ -- Neal H. Walfield <neal@debian.org> Fri, 11 Oct 2002 21:42:21 -0400
+
+hurd (20020918-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Tue, 18 Sep 2002 23:13:06 +0200
+
+hurd (20020804-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 4 Aug 2002 20:46:28 +0200
+
+hurd (20020523-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 23 May 2002 15:29:40 +0200
+
+hurd (20020418-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 18 Apr 2002 15:22:39 +0200
+
+hurd (20011105-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual (well, the intention was there :).
+ Change terminal type to mach-color.
+ Compiled with -O2 rather than -O3.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 5 Nov 2001 00:00:26 +0100
+
+hurd (20011016-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+ Compiled with -O2 rather than -O3.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Tue, 16 Oct 2001 19:43:21 +0200
+
+hurd (20011013-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+ Compiled with -O2 rather than -O3.
+ * debian/rules: Change way how to find executables by Kevin Kreamer.
+ * debian/control: Add `file' to build dependencies by Kevin Kreamer.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sat, 13 Oct 2001 01:05:30 +0200
+
+hurd (20010817-2) unstable; urgency=low
+
+ * Include a copy of update-rc.d, moved from dpkg to init providing
+ package.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 2 Sep 2001 19:40:00 +0200
+
+hurd (20010817-1) unstable; urgency=low
+
+ * New snapshot from CVS, closes: #105476, #39894.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+ Compiled with -O2 rather than -O3.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Fri, 17 Aug 2001 22:16:01 +0200
+
+hurd (20010718-1) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+ Compiled with -O2 rather than -O3.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 18 Jul 2001 21:43:52 +0200
+
+hurd (20010608) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+ Compiled with -O2 rather than -O3.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Fri, 8 Jun 2001 23:02:47 +0200
+
+hurd (20010527) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sat, 27 May 2001 01:34:21 +0200
+
+hurd (20010426) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+ storeio hack to prevent double activation.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Fri, 27 Apr 2001 00:09:56 +0200
+
+hurd (20010311) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Additional patches:
+ kbd, mouse as usual.
+ Change terminal type to mach-color.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 11 Mar 2001 22:45:21 +0100
+
+hurd (20010111) unstable; urgency=low
+
+ * New snapshot from CVS, containing lots of small bug fixes, and:
+ + Together with gnumach 1.2-9, you can access large stores with
+ storeinfo, storeread (because libstore uses the new interface in
+ gnumach, and off64_t internally).
+ + pfinet contains support for network ioctls. The corresponding
+ changes in the glibc library are not available in Debian yet, though.
+ * streamdev is renamed to streamio.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Fri, 12 Jan 2001 00:06:41 +0100
+
+hurd (20001204) unstable; urgency=low
+
+ * New snapshot from CVS, with a couple of bug fixes:
+ pfinet: Don't leak references.
+ ext2fs, ufs: Avoid a dn_set_?time vs sync thread race.
+ Corretly deny too long filenames.
+ nfsd: Fix a couple of memory leaks.
+
+ * Additional patchs:
+ libdiskfs: Don't crash when symlink target is the empty string.
+ streamdev, kbd, mouse: New translators for X and klog device.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 4 Dec 2000 15:18:39 +0100
+
+hurd (20001127) unstable; urgency=low
+
+ * New snapshot from CVS, really fixes isofs now.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 27 Nov 2000 21:07:03 +0100
+
+hurd (20001126) unstable; urgency=low
+
+ * New snapshot from CVS, closes: #68417, #69281, #68626
+ * Fix in 20001030 closes: #72319
+ * debian/control: Add build dependencies, closes: #75734
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 26 Nov 2000 05:53:19 +0100
+
+hurd (20001030) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Still contains all the goodies, streadev, kbd, mouse. Now opening
+ kbd, mouse more than once doesn't crash them (thanks Erik Verbruggen
+ <ejv@cs.kun.nl>)
+ * sutils/MAKEDEV.sh: kmsg is really klog.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Tue, 30 Oct 2000 18:02:29 +0200
+
+hurd (20000921) unstable; urgency=low
+
+ * New snapshot from CVS
+ * Add streamdev by OKUJI Yoshinori
+ (source: ftp://alpha.gnu.org/contrib/okuji/hurd/streamdev-19990920.tar.gz)
+ * Add kbd and mouse by UCHIYAMA Yasushi <uch@nop.or.jp>.
+ * sutils/MAKEDEV.sh: Add kbd and kmsg. No sense to add mouse, as you need
+ to configure it (see /hurd/mouse --help).
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sat, 23 Sep 2000 04:27:58 +0200
+
+hurd (20000803) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * isofs: Patch to fix symlink handling.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 3 Aug 2000 21:09:44 +0200
+
+hurd (20000726) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Fixes the infamous zero hole bug (actually both of them).
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Wed, 26 Jul 2000 02:24:06 +0200
+
+hurd (20000703) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * exec/hashexec.c (check_hashbang: Fix off by one error in line 178.
+ Patch by Kalle Olavi Niemital.
+
+ -- Marcus Brinkmann <bug-hurd@gnu.org> Mon, 3 Jul 2000 00:44:47 +0200
+
+hurd (20000130) unstable; urgency=low
+
+ * New snapshot from CVS. Closes: Bug#54282, Bug#40302, Bug#56076.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 30 Jan 2000 14:55:39 +0100
+
+hurd (19991209) unstable; urgency=low
+
+ * New snapshot from CVS.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 9 Dec 1999 23:43:23 +0100
+
+hurd (19991022) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * libdiskfs/init-startup.c: Disable periodic syncing before shutting down.
+ This fixes the fs-unclean-on-reboot bug!
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Fri, 22 Oct 1999 21:32:02 +0200
+
+hurd (19991004) unstable; urgency=high
+
+ * New snapshot from CVS.
+ term: Realize bogus devices.
+ ext2fs: Important bug fixes!
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 3 Oct 1999 18:01:17 +0200
+
+hurd (19990923) unstable; urgency=low
+
+ * New snapshot from CVS.
+ MAKEDEV: pty created with mode 0666.
+ Implements pathconf for libdiskfs and libnetfs.
+ Various bug fixes.
+ * Development package now includes pic libraries.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 19 Sep 1999 19:29:00 +0200
+
+hurd (19990907) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * gzip /boot/serverboot to /boot/serverboot.gz
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 23 Aug 1999 15:12:10 +0200
+
+hurd (19990725) unstable; urgency=low
+
+ * New snapshot from CVS.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 25 Jul 1999 16:16:03 +0200
+
+hurd (19990714) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * debian/rules: etc/motd is in base-files, do not include it.
+ * Activate split-init.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Wed, 14 Jul 1999 16:38:00 +0200
+
+hurd (19990616) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Now contains info and ps documentation.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 17 Jun 1999 17:35:54 +0200
+
+hurd (19990524) unstable; urgency=low
+
+ * New snapshot from CVS.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 24 May 1999 15:09:45 +0200
+
+hurd (19990523) unstable; urgency=low
+
+ * New snapshot from CVS, fixes: #38062, #37670, #37878, #37944.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Mon, 24 May 1999 01:08:26 +0200
+
+hurd (19990517fixed) unstable; urgency=low
+
+ * debian/shlibs: corrected.
+ * exec/hashexec.c: Applied patch by Roland to make it work.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 17 May 1999 00:25:11 +0200
+
+hurd (19990517) unstable; urgency=low
+
+ * New snapshot from CVS.
+ * Add shlibs file.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 16 May 1999 15:28:09 +0200
+
+hurd (19990425-1) unstable; urgency=low
+
+ * Put shared library symlinks into the hurd-dev package.
+ * Clarify instructions in provided servers.boot.
+ * libfshelp/fetch-root.c: De-patched a change by tb which produced
+ strange errors.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 29 Apr 1999 22:47:51 +0200
+
+hurd (19990212-2) unstable; urgency=low
+
+ * debian/control: Added Depends line for Hurd.
+ * Update docs to reflect new group maintainership.
+ * debian/copyright: Hurd libraries are *not* under the LGPL, so add a
+ clarifying note.
+ * Put static libraries and header files into /usr/lib and /usr/include
+ for people without the /usr symlink.
+
+ -- Gordon Matzigkeit <bug-hurd@gnu.org> Wed, 17 Feb 1999 15:40:44 -0600
+
+hurd (19990212-1) unstable; urgency=low
+
+ * New upstream version from CVS.
+ * Deleted old libthreads... there's no going back now.
+
+ -- Gordon Matzigkeit <gord@debian.org> Fri, 12 Feb 1999 03:25:55 -0600
+
+hurd (19981204-1) unstable; urgency=low
+
+ * New upstream release, supposed to work with glibc 2.0.106.
+ * Commented out use of old libthreads.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Sun, 20 Dec 1998 04:24:40 +0100
+
+hurd (19980915-2) unstable; urgency=low
+
+ * exec/hashexec.c: Applied patch by Thomas Bushnell to fix make.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Fri, 6 Nov 1998 23:10:11 +0100
+
+hurd (19980915-1) unstable; urgency=low
+
+ * New upstream release.
+ * debian/rules: Strip all binaries.
+ * debian/TODO: New file.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Thu, 8 Oct 1998 03:34:40 +0200
+
+hurd (19980716-2) unstable; urgency=low
+
+ * Reverted libthreads to provide threadsafe malloc, as we use older
+ version of glibc2 for now.
+ * Do not remove size 0 files in 'rules clean', because hurd depends on
+ them.
+ * Do not build profiling libraries.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Tue, 4 Aug 1998 21:58:55 +0200
+
+hurd (19980716-1) unstable; urgency=low
+
+ * Initial Version.
+
+ -- Marcus Brinkmann <brinkmd@debian.org> Tue, 4 Aug 1998 21:58:55 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 00000000..b8626c4c
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+4
diff --git a/debian/control b/debian/control
new file mode 100644
index 00000000..70143527
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,68 @@
+Source: hurd
+Section: admin
+Priority: required
+Maintainer: GNU Hurd Maintainers <debian-hurd@lists.debian.org>
+Standards-Version: 3.9.2
+Build-Depends: mig (>= 1.3-2), gnumach-dev (>= 2:1.3.99.dfsg.cvs20070526),
+ libc0.3-dev (>= 2.9), texinfo, texi2html, libncursesw5-dev, cdbs,
+ debhelper (>= 4.2.0), gcc-4.6, dpkg (>= 1.15.4) | install-info,
+ libparted-dev
+Uploaders: Jeff Bailey <jbailey@raspberryginger.com>,
+ Neal H. Walfield <neal@debian.org>, Michael Banck <mbanck@debian.org>,
+ Samuel Thibault <sthibault@debian.org>
+Homepage: http://www.gnu.org/software/hurd/hurd.html
+Vcs-Browser: http://git.debian.org/?p=pkg-hurd/hurd.git
+Vcs-Git: git://git.debian.org/pkg-hurd/hurd.git
+
+Package: hurd
+Essential: yes
+Depends: ${misc:Depends}, sysv-rc, ${shlibs:Depends}
+Breaks: gnumach (<< 2:1.3.99.dfsg.cvs20070526-1), libc0.3 (<< 2.11.2-12)
+Suggests: hurd-doc
+Recommends: bf-utf-source
+Provides: makedev, login
+Replaces: makedev, login, random-egd
+Conflicts: makedev, login
+Architecture: hurd-any
+Description: GNU Hurd
+ This is the GNU Hurd package. It contains essential system software and
+ libraries.
+
+Package: hurd-dev
+Priority: standard
+Section: libdevel
+Architecture: hurd-any
+Depends: ${misc:Depends}, hurd (= ${binary:Version})
+Provides: libsem-dev
+Replaces: libsem-dev
+Conflicts: libsem-dev
+Description: GNU Hurd (development files)
+ This package includes the header files and the static libraries.
+
+Package: hurd-dbg
+Priority: extra
+Section: debug
+Architecture: hurd-any
+Depends: ${misc:Depends}, hurd (= ${binary:Version})
+Description: GNU Hurd (debugging files)
+ This package includes the unstripped binaries and libraries.
+
+Package: hurd-doc
+Priority: optional
+Section: doc
+Architecture: all
+Depends: ${misc:Depends}
+Suggests: hurd (>= ${source:Version})
+Description: GNU Hurd manual
+ This package includes the manual in info and HTML format.
+
+Package: hurd-udeb
+Package-Type: udeb
+Priority: optional
+Section: debian-installer
+Architecture: hurd-any
+Depends: ${misc:Depends}
+Provides: hurd, ext2-modules, fat-modules, ipv6-modules, isofs-modules, loop-modules, mouse-modules, nfs-modules, socket-modules, ufs-modules
+Description: GNU Hurd - udeb
+ This is the GNU Hurd udeb package. It contains essential system software and
+ libraries.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 00000000..f624df34
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,29 @@
+This package was debianized by Marcus Brinkmann <brinkmd@debian.org>
+on Tue, 4 Aug 1998 21:52:45 +0200
+
+It is currently maintained by the Debian GNU Hurd maintainers, who can be
+reached via <debian-hurd@lists.debian.org>.
+
+Sources are available from http://savannah.gnu.org/projects/hurd
+
+Copyright 1992-2011 the Free Software Foundation, Inc.
+
+Note that the libraries distributed with the GNU Hurd are placed under
+the standard GNU General Public License (*not* the Library General
+Public License).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU General Public License
+version 2 can be found in `/usr/share/common-licenses/GPL-2'.
diff --git a/debian/hurd-console.default b/debian/hurd-console.default
new file mode 100644
index 00000000..133604d8
--- /dev/null
+++ b/debian/hurd-console.default
@@ -0,0 +1,36 @@
+# Options to start the Hurd console.
+
+# Set this to 'true' to run the Hurd console on bootup.
+ENABLE='false'
+
+# The display driver, mandatory. Either `vga' or `ncursesw'.
+DISPLAY='-d vga'
+
+# The keyboard driver, mandatory. Either `pc_kbd' or `xkb' from the
+# console-driver-xkb package.
+KBD='-d pc_kbd'
+
+# The alternative xkb keyboard driver, as provided by the
+# console-driver-xkb package. It uses X11 style keymaps and supports
+# different keymaps. Possible options are:
+# --keymap: The keymap to use. By default en_US is used. Examples of
+# some other keymaps are: fr, us, de, dvorak.
+# --keymapfile: The file that hold the descriptions of the default
+# keymaps file. This file holds the description of all keymaps. This
+# path should be relative to the path set by `xkbdir'. By default
+# "keymap/xfree86" is used.
+# --xkbdir: The root directory of the xkb configuration, by default
+# this is /etc/X11/xkb.
+#KBD='-d xkb'
+
+# The keyboard repeater. Required for running X11.
+KBD_REPEAT='--repeat=kbd'
+
+# The mouse driver. Optional.
+MOUSE='-d pc_mouse --protocol=ps/2'
+
+# The mouse repeater. Required for running X11.
+MOUSE_REPEAT='--repeat=mouse'
+
+# The pc speaker. Optional.
+#SPEAKER='-d generic_speaker'
diff --git a/debian/hurd-dbg.dirs b/debian/hurd-dbg.dirs
new file mode 100644
index 00000000..08d9e7ae
--- /dev/null
+++ b/debian/hurd-dbg.dirs
@@ -0,0 +1 @@
+usr/lib/debug
diff --git a/debian/hurd-dev.install b/debian/hurd-dev.install
new file mode 100644
index 00000000..7bd68e9f
--- /dev/null
+++ b/debian/hurd-dev.install
@@ -0,0 +1,3 @@
+debian/tmp/lib/*.a lib
+debian/tmp/include/* usr/include
+debian/tmp/lib/*.so lib
diff --git a/debian/hurd-dev.lintian-overrides b/debian/hurd-dev.lintian-overrides
new file mode 100644
index 00000000..d87d341b
--- /dev/null
+++ b/debian/hurd-dev.lintian-overrides
@@ -0,0 +1,15 @@
+unstripped-binary-or-object lib/libstore_bunzip2.a
+unstripped-binary-or-object lib/libstore_concat.a
+unstripped-binary-or-object lib/libstore_copy.a
+unstripped-binary-or-object lib/libstore_device.a
+unstripped-binary-or-object lib/libstore_file.a
+unstripped-binary-or-object lib/libstore_gunzip.a
+unstripped-binary-or-object lib/libstore_ileave.a
+unstripped-binary-or-object lib/libstore_memobj.a
+unstripped-binary-or-object lib/libstore_module.a
+unstripped-binary-or-object lib/libstore_mvol.a
+unstripped-binary-or-object lib/libstore_nbd.a
+unstripped-binary-or-object lib/libstore_remap.a
+unstripped-binary-or-object lib/libstore_task.a
+unstripped-binary-or-object lib/libstore_zero.a
+unstripped-binary-or-object lib/libstore_part.a
diff --git a/debian/hurd-doc.docs b/debian/hurd-doc.docs
new file mode 100644
index 00000000..5d7f66d2
--- /dev/null
+++ b/debian/hurd-doc.docs
@@ -0,0 +1,2 @@
+build/doc/hurd*html
+doc/navigating
diff --git a/debian/hurd-doc.info b/debian/hurd-doc.info
new file mode 100644
index 00000000..183900da
--- /dev/null
+++ b/debian/hurd-doc.info
@@ -0,0 +1 @@
+debian/tmp/share/info/hurd.info
diff --git a/debian/hurd-udeb.dirs b/debian/hurd-udeb.dirs
new file mode 100644
index 00000000..a0a464b2
--- /dev/null
+++ b/debian/hurd-udeb.dirs
@@ -0,0 +1 @@
+servers
diff --git a/debian/hurd-udeb.install b/debian/hurd-udeb.install
new file mode 100644
index 00000000..781ed195
--- /dev/null
+++ b/debian/hurd-udeb.install
@@ -0,0 +1,68 @@
+debian/local/runsystem etc/hurd
+debian/local/setup-translators usr/lib/hurd
+debian/local/partman lib
+debian/local/finish-install.d usr/lib
+debian/tmp/lib/*.so.*
+debian/tmp/lib/hurd/console/pc_kbd.so.* usr/lib/hurd/console
+debian/tmp/lib/hurd/console/pc_mouse.so.* usr/lib/hurd/console
+debian/tmp/lib/hurd/console/vga.so.* usr/lib/hurd/console
+debian/tmp/lib/hurd/console-run sbin
+debian/tmp/sbin/e2os
+debian/tmp/sbin/MAKEDEV
+debian/tmp/sbin/losetup
+debian/tmp/sbin/swapon
+debian/tmp/sbin/swapoff
+debian/tmp/bin/boot
+debian/tmp/bin/console
+debian/tmp/bin/shd
+debian/tmp/bin/ps-hurd
+debian/tmp/bin/settrans
+debian/tmp/bin/showtrans
+debian/tmp/bin/syncfs
+debian/tmp/bin/fsysopts
+debian/tmp/bin/storeinfo
+debian/tmp/bin/login
+debian/tmp/usr/bin/w-hurd
+debian/tmp/usr/bin/uptime-hurd
+debian/tmp/bin/ids
+debian/tmp/bin/loginpr
+debian/tmp/bin/sush
+debian/tmp/usr/bin/vmstat-hurd
+debian/tmp/bin/portinfo
+debian/tmp/bin/devprobe
+debian/tmp/bin/vminfo
+debian/tmp/bin/addauth
+debian/tmp/bin/rmauth
+debian/tmp/bin/unsu
+debian/tmp/bin/setauth
+debian/tmp/bin/storecat
+debian/tmp/bin/storeread
+debian/tmp/bin/msgport
+debian/tmp/bin/mount
+debian/tmp/dev/MAKEDEV
+debian/tmp/hurd/auth
+debian/tmp/hurd/console
+debian/tmp/hurd/exec
+debian/tmp/hurd/ext2fs
+debian/tmp/hurd/ext2fs.static /boot
+debian/tmp/hurd/fatfs
+debian/tmp/hurd/fifo
+debian/tmp/hurd/firmlink
+debian/tmp/hurd/fwd
+debian/tmp/hurd/ifsock
+debian/tmp/hurd/init
+debian/tmp/hurd/iso9660fs
+debian/tmp/hurd/mach-defpager
+debian/tmp/hurd/magic
+debian/tmp/hurd/new-fifo
+debian/tmp/hurd/null
+debian/tmp/hurd/pfinet
+debian/tmp/hurd/pflocal
+debian/tmp/hurd/proc
+debian/tmp/hurd/procfs
+debian/tmp/hurd/proxy-defpager
+debian/tmp/hurd/storeio
+debian/tmp/hurd/streamio
+debian/tmp/hurd/symlink
+debian/tmp/hurd/term
+debian/tmp/hurd/tmpfs
diff --git a/debian/hurd-udeb.links b/debian/hurd-udeb.links
new file mode 100644
index 00000000..70c452f7
--- /dev/null
+++ b/debian/hurd-udeb.links
@@ -0,0 +1 @@
+/lib/unifont.bdf /usr/share/hurd/vga-system.bdf
diff --git a/debian/hurd-udeb.lintian-overrides b/debian/hurd-udeb.lintian-overrides
new file mode 100644
index 00000000..0f8c470e
--- /dev/null
+++ b/debian/hurd-udeb.lintian-overrides
@@ -0,0 +1,2 @@
+non-standard-toplevel-dir hurd/
+non-standard-toplevel-dir servers/
diff --git a/debian/hurd.dirs b/debian/hurd.dirs
new file mode 100644
index 00000000..7af900ee
--- /dev/null
+++ b/debian/hurd.dirs
@@ -0,0 +1,7 @@
+servers
+servers/socket
+etc/default
+etc/sysctl.d
+usr/share/msgids
+usr/bin
+boot
diff --git a/debian/hurd.examples b/debian/hurd.examples
new file mode 100644
index 00000000..8b0bfeea
--- /dev/null
+++ b/debian/hurd.examples
@@ -0,0 +1 @@
+debian/local/menu.lst
diff --git a/debian/hurd.install b/debian/hurd.install
new file mode 100644
index 00000000..c0e11492
--- /dev/null
+++ b/debian/hurd.install
@@ -0,0 +1,66 @@
+debian/local/setup-translators usr/lib/hurd
+debian/tmp/lib/*.so.*
+debian/tmp/lib/hurd/console/*.so.* usr/lib/hurd/console
+debian/tmp/hurd/*
+debian/tmp/lib/hurd/rc etc/hurd
+debian/tmp/lib/hurd/getty sbin
+debian/tmp/lib/hurd/console-run sbin
+debian/tmp/lib/hurd/runttys sbin
+debian/tmp/lib/hurd/runsystem.gnu etc/hurd
+debian/tmp/sbin/nfsd
+debian/tmp/sbin/e2os
+debian/tmp/sbin/MAKEDEV
+debian/tmp/sbin/losetup
+debian/tmp/sbin/reboot
+debian/tmp/sbin/halt
+debian/tmp/sbin/swapon
+debian/tmp/sbin/swapoff
+debian/tmp/sbin/fsck.ufs
+debian/tmp/sbin/mkfs.ufs
+debian/tmp/sbin/clri.ufs
+debian/tmp/sbin/stati.ufs
+debian/tmp/bin/boot
+debian/tmp/bin/console
+debian/tmp/bin/shd
+debian/tmp/bin/ps-hurd
+debian/tmp/bin/settrans
+debian/tmp/bin/showtrans
+debian/tmp/bin/syncfs
+debian/tmp/bin/fsysopts
+debian/tmp/bin/storeinfo
+debian/tmp/bin/login
+debian/tmp/usr/bin/w-hurd
+debian/tmp/usr/bin/uptime-hurd
+debian/tmp/bin/ids
+debian/tmp/bin/loginpr
+debian/tmp/bin/sush
+debian/tmp/usr/bin/vmstat-hurd
+debian/tmp/bin/portinfo
+debian/tmp/bin/devprobe
+debian/tmp/bin/vminfo
+debian/tmp/bin/addauth
+debian/tmp/bin/rmauth
+debian/tmp/bin/unsu
+debian/tmp/bin/setauth
+debian/tmp/bin/ftpcp
+debian/tmp/bin/ftpdir
+debian/tmp/bin/storecat
+debian/tmp/bin/storeread
+debian/tmp/bin/msgport
+debian/tmp/bin/rpctrace
+debian/tmp/bin/mount
+debian/tmp/bin/gcore
+debian/tmp/bin/fakeauth
+debian/tmp/usr/bin/fakeroot-hurd
+debian/tmp/bin/forks
+debian/tmp/bin/timertest
+debian/tmp/bin/fstests
+debian/tmp/etc/login
+debian/tmp/etc/login/.bash_login
+debian/tmp/etc/login/.bashrc
+debian/tmp/etc/login/.hushlogin
+debian/tmp/etc/login/.profile
+debian/tmp/etc/login/README
+debian/tmp/etc/ttys
+debian/tmp/dev/MAKEDEV
+debian/tmp/share/msgids/hurd.msgids usr/share/msgids
diff --git a/debian/hurd.links b/debian/hurd.links
new file mode 100644
index 00000000..d1481a66
--- /dev/null
+++ b/debian/hurd.links
@@ -0,0 +1 @@
+/usr/src/unifont.bdf /usr/share/hurd/vga-system.bdf
diff --git a/debian/hurd.lintian-overrides b/debian/hurd.lintian-overrides
new file mode 100644
index 00000000..4a82454d
--- /dev/null
+++ b/debian/hurd.lintian-overrides
@@ -0,0 +1,7 @@
+new-essential-package
+statically-linked-binary hurd/mach-defpager
+setuid-binary bin/ids 4755 root/root
+setuid-binary bin/login 4755 root/root
+setuid-binary bin/ps-hurd 4755 root/root
+setuid-binary usr/bin/w-hurd 4755 root/root
+possibly-insecure-handling-of-tmp-files-in-maintainer-script postinst:65
diff --git a/debian/hurd.postinst b/debian/hurd.postinst
new file mode 100644
index 00000000..23364691
--- /dev/null
+++ b/debian/hurd.postinst
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = configure ] && [ "$2" ]; then
+ # Upgrade from old version: drop /libexec/runsystem
+ update-alternatives --quiet \
+ --remove runsystem /libexec/runsystem.gnu
+fi
+update-alternatives --quiet \
+ --install /etc/hurd/runsystem runsystem /etc/hurd/runsystem.gnu 20
+
+update-alternatives \
+ --install /usr/bin/fakeroot fakeroot /usr/bin/fakeroot-hurd 30
+
+update-alternatives \
+ --install /bin/ps ps /bin/ps-hurd 60
+
+update-alternatives \
+ --install /usr/bin/uptime uptime /usr/bin/uptime-hurd 30
+
+update-alternatives \
+ --install /usr/bin/vmstat vmstat /usr/bin/vmstat-hurd 60
+
+update-alternatives \
+ --install /usr/bin/w w /usr/bin/w-hurd 60
+
+ADDUSERCONF='/etc/adduser.conf'
+
+if test -f $ADDUSERCONF; then
+ FIRST_SYSTEM_UID=$(sed -n "s/^[[:space:]]*FIRST_SYSTEM_UID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF)
+ LAST_SYSTEM_UID=$(sed -n "s/^[[:space:]]*LAST_SYSTEM_UID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF)
+ FIRST_SYSTEM_GID=$(sed -n "s/^[[:space:]]*FIRST_SYSTEM_GID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF)
+ LAST_SYSTEM_GID=$(sed -n "s/^[[:space:]]*LAST_SYSTEM_GID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF)
+fi
+
+if test -z "$FIRST_SYSTEM_UID"; then
+ FIRST_SYSTEM_UID=100
+fi
+if test -z "$LAST_SYSTEM_UID"; then
+ LAST_SYSTEM_UID=999
+fi
+if test -z "$FIRST_SYSTEM_GID"; then
+ FIRST_SYSTEM_GID=100
+fi
+if test -z "$LAST_SYSTEM_GID"; then
+ LAST_SYSTEM_GID=999
+fi
+
+if [ "$1" = configure ]; then
+ add-shell /bin/loginpr || true
+ if ! getent passwd login >/dev/null; then
+ useradd -K UID_MIN=$FIRST_SYSTEM_UID -K UID_MAX=$LAST_SYSTEM_UID \
+ -K GID_MIN=$FIRST_SYSTEM_GID -K GID_MAX=$LAST_SYSTEM_GID \
+ --home-dir /etc/login --no-create-home \
+ --shell /bin/loginpr --comment "login user" \
+ --user-group login
+ fi
+fi
+
+#DEBHELPER#
+
+if [ "$1" = configure ] && [ "$2" ]; then
+ # Upgrade: create the missing device and server nodes
+ if showtrans /dev/random 2> /dev/null | grep -q /tmp/entropy.sock
+ then
+ # old random-egd translator, remove
+ settrans -go /dev/random
+ settrans -go /dev/urandom
+ ( cd /dev ; rm -f random urandom )
+ fi
+ /usr/lib/hurd/setup-translators -K
+fi
+
+update-alternatives --install /dev/random random /dev/random-hurd 10 \
+ --slave /dev/urandom urandom /dev/urandom-hurd
+
+if [ "$1" = configure ] ; then
+ # Generate initial pool
+ UMASK=`umask`
+ umask 077
+ [ -f /var/spool/random-seed ] || dd < /dev/urandom > /var/spool/random-seed bs=1 count=600 2> /dev/null
+ # TODO: will need to run settrans -ga /dev/random at system stop to make
+ # it save it back
+ umask $UMASK
+fi
diff --git a/debian/hurd.postrm b/debian/hurd.postrm
new file mode 100644
index 00000000..ea209f71
--- /dev/null
+++ b/debian/hurd.postrm
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = purge ]; then
+ remove-shell /bin/loginpr
+ if ! deluser --quiet --system login > /dev/null; then
+ echo "
+Removing the user 'login' failed, most likely because the user is still
+logged in. To remove the user and group terminate the session in question
+and execute
+
+ deluser --quiet --system login
+ delgroup --quiet --system login
+"
+ else
+ delgroup --quiet --system login > /dev/null || true
+ fi
+fi
+
+#DEBHELPER#
diff --git a/debian/hurd.prerm b/debian/hurd.prerm
new file mode 100644
index 00000000..78105cdc
--- /dev/null
+++ b/debian/hurd.prerm
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = remove ]; then
+ update-alternatives --remove random /dev/random-hurd
+fi
+
+#DEBHELPER#
diff --git a/debian/local/cdrom.h b/debian/local/cdrom.h
new file mode 100644
index 00000000..f967a852
--- /dev/null
+++ b/debian/local/cdrom.h
@@ -0,0 +1,941 @@
+/*
+ * From
+ * -- <linux/cdrom.h>
+ * General header file for linux CD-ROM drivers
+ * Copyright (C) 1992 David Giller, rafetmad@oxy.edu
+ * 1994, 1995 Eberhard Mönkeberg, emoenke@gwdg.de
+ * 1996 David van Leeuwen, david@tm.tno.nl
+ * 1997, 1998 Erik Andersen, andersee@debian.org
+ * 1998-2002 Jens Axboe, axboe@suse.de
+ */
+
+#ifndef _SYS_CDROM_H
+#define _SYS_CDROM_H
+
+#include <endian.h>
+
+/*******************************************************
+ * As of Linux 2.1.x, all Linux CD-ROM application programs will use this
+ * (and only this) include file. It is my hope to provide Linux with
+ * a uniform interface between software accessing CD-ROMs and the various
+ * device drivers that actually talk to the drives. There may still be
+ * 23 different kinds of strange CD-ROM drives, but at least there will
+ * now be one, and only one, Linux CD-ROM interface.
+ *
+ * Additionally, as of Linux 2.1.x, all Linux application programs
+ * should use the O_NONBLOCK option when opening a CD-ROM device
+ * for subsequent ioctl commands. This allows for neat system errors
+ * like "No medium found" or "Wrong medium type" upon attempting to
+ * mount or play an empty slot, mount an audio disc, or play a data disc.
+ * Generally, changing an application program to support O_NONBLOCK
+ * is as easy as the following:
+ * - drive = open("/dev/cdrom", O_RDONLY);
+ * + drive = open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
+ * It is worth the small change.
+ *
+ * Patches for many common CD programs (provided by David A. van Leeuwen)
+ * can be found at: ftp://ftp.gwdg.de/pub/linux/cdrom/drivers/cm206/
+ *
+ *******************************************************/
+
+/* When a driver supports a certain function, but the cdrom drive we are
+ * using doesn't, we will return the error EDRIVE_CANT_DO_THIS. We will
+ * borrow the "Operation not supported" error from the network folks to
+ * accomplish this. Maybe someday we will get a more targeted error code,
+ * but this will do for now... */
+#define EDRIVE_CANT_DO_THIS EOPNOTSUPP
+
+/*******************************************************
+ * The CD-ROM IOCTL commands -- these should be supported by
+ * all the various cdrom drivers. For the CD-ROM ioctls, we
+ * will commandeer byte 0x53, or 'S'.
+ *******************************************************/
+#define CDROMPAUSE _IO('S', 0x01) /* Pause Audio Operation */
+#define CDROMRESUME _IO('S', 0x02) /* Resume paused Audio Operation */
+#define CDROMPLAYMSF _IOW('S', 0x03, struct cdrom_msf) /* Play Audio MSF */
+#define CDROMPLAYTRKIND _IOW('S', 0x04, struct cdrom_ti) /* Play Audio Track/index */
+#define CDROMREADTOCHDR _IOWR('S', 0x05, struct cdrom_tochdr) /* Read TOC header */
+#define CDROMREADTOCENTRY _IOWR('S', 0x06, struct cdrom_tocentry) /* Read TOC entry */
+#define CDROMSTOP _IO('S', 0x07) /* Stop the cdrom drive */
+#define CDROMSTART _IO('S', 0x08) /* Start the cdrom drive */
+#define CDROMEJECT _IO('S', 0x09) /* Ejects the cdrom media */
+#define CDROMVOLCTRL _IOW('S', 0x0a, struct cdrom_volctrl) /* Control output volume */
+#define CDROMSUBCHNL _IOWR('S', 0x0b, struct cdrom_subchnl) /* Read subchannel data */
+#define CDROMREADMODE2 _IOWR('S', 0x0c, union cdrom_read_mode2) /* Read CDROM mode 2 data (2336 Bytes) */
+#define CDROMREADMODE1 _IOWR('S', 0x0d, union cdrom_read_mode1) /* Read CDROM mode 1 data (2048 Bytes) */
+#define CDROMREADAUDIO _IOWR('S', 0x0e, struct cdrom_read_audio)
+#define CDROMEJECT_SW _IOIW('S', 0x0f, int) /* enable(1)/disable(0) auto-ejecting */
+#define CDROMMULTISESSION _IOWR('S', 0x10, struct cdrom_multisession) /* Obtain the start-of-last-session
+ address of multi session disks */
+#define CDROM_GET_MCN _IOR('S', 0x11, struct cdrom_mcn) /* Obtain the "Universal Product Code"
+ if available */
+#define CDROM_GET_UPC CDROM_GET_MCN /* This one is deprecated,
+ but here anyway for compatibility */
+#define CDROMRESET _IO('S', 0x12) /* hard-reset the drive */
+#define CDROMVOLREAD _IOR('S', 0x13, struct cdrom_volctrl) /* Get the drive's volume setting */
+#define CDROMREADRAW _IOWR('S', 0x14, union cdrom_read_raw) /* read data in raw mode (2352 Bytes) */
+/*
+ * These ioctls are used only used in aztcd.c and optcd.c
+ */
+#define CDROMREADCOOKED _IOR('S', 0x15, struct cdrom_read_cooked) /* read data in cooked mode */
+#define CDROMSEEK _IOW('S', 0x16, struct cdrom_msf) /* seek msf address */
+
+/*
+ * This ioctl is only used by the scsi-cd driver.
+ It is for playing audio in logical block addressing mode.
+ */
+#define CDROMPLAYBLK _IOW('S', 0x17, struct cdrom_blk) /* (struct cdrom_blk) */
+
+/*
+ * These ioctls are only used in optcd.c
+ */
+#define CDROMREADALL _IOR('S', 0x18, struct cdrom_read_all) /* read all 2646 bytes */
+
+/*
+ * These ioctls are (now) only in ide-cd.c for controlling
+ * drive spindown time. They should be implemented in the
+ * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10,
+ * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE...
+ * -Erik
+ */
+#define CDROMGETSPINDOWN _IOR('S', 0x1d, char)
+#define CDROMSETSPINDOWN _IOW('S', 0x1e, char)
+
+/*
+ * These ioctls are implemented through the uniform CD-ROM driver
+ * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
+ * drivers are eventually ported to the uniform CD-ROM driver interface.
+ */
+#define CDROMCLOSETRAY _IO('S', 0x19) /* pendant of CDROMEJECT */
+#define CDROM_SET_OPTIONS _IOIW('S', 0x20, int) /* Set behavior options */
+#define CDROM_CLEAR_OPTIONS _IOIW('S', 0x21, int) /* Clear behavior options */
+#define CDROM_SELECT_SPEED _IOIW('S', 0x22, int) /* Set the CD-ROM speed */
+#define CDROM_SELECT_DISC _IOIW('S', 0x23, int) /* Select disc (for juke-boxes) */
+#define CDROM_MEDIA_CHANGED _IOIW('S', 0x25, int) /* Check is media changed */
+#define CDROM_DRIVE_STATUS _IOIW('S', 0x26, int) /* Get tray position, etc. */
+#define CDROM_DISC_STATUS _IO('S', 0x27) /* Get disc type, etc. */
+#define CDROM_CHANGER_NSLOTS _IO('S', 0x28) /* Get number of slots */
+#define CDROM_LOCKDOOR _IOIW('S', 0x29, int) /* lock or unlock door */
+#define CDROM_DEBUG _IOIW('S', 0x30, int) /* Turn debug messages on/off */
+#define CDROM_GET_CAPABILITY _IO('S', 0x31) /* get capabilities */
+
+/* Note that scsi/scsi_ioctl.h also uses _IO('S', 0x82, ) - 0x5386.
+ * Future CDROM ioctls should be kept below 0x537F
+ */
+
+/* This ioctl is only used by sbpcd at the moment */
+#define CDROMAUDIOBUFSIZ _IOIW('S', 0x82, int) /* set the audio buffer size */
+ /* conflict with SCSI_IOCTL_GET_IDLUN */
+
+/* DVD-ROM Specific ioctls */
+#define DVD_READ_STRUCT _IOWR('S', 0x90, dvd_struct) /* Read structure */
+#if 0
+#define DVD_WRITE_STRUCT _IO('S', 0x91, ) /* Write structure */
+#endif
+#define DVD_AUTH _IOWR('S', 0x92, dvd_authinfo) /* Authentication */
+
+#define CDROM_SEND_PACKET _IOWR('S', 0x93, struct cdrom_generic_command) /* send a packet to the drive */
+#define CDROM_NEXT_WRITABLE _IOR('S', 0x94, long) /* get next writable block */
+#define CDROM_LAST_WRITTEN _IOR('S', 0x95, long) /* get last block written on disc */
+
+/*******************************************************
+ * CDROM IOCTL structures
+ *******************************************************/
+
+/* Address in MSF format */
+#define _IOT_cdrom_msf0 _IOT (_IOTS (char), 3, 0, 0, 0, 0)
+struct cdrom_msf0
+{
+ unsigned char minute;
+ unsigned char second;
+ unsigned char frame;
+};
+
+/* Address in either MSF or logical format */
+#define _IOT_cdrom_addr _IOT (_IOTS (int), 1, 0, 0, 0, 0)
+union cdrom_addr
+{
+ struct cdrom_msf0 msf;
+ int lba;
+};
+
+/* This struct is used by the CDROMPLAYMSF ioctl */
+#define _IOT_cdrom_msf _IOT (_IOTS (char), 6, 0, 0, 0, 0)
+struct cdrom_msf
+{
+ unsigned char cdmsf_min0; /* start minute */
+ unsigned char cdmsf_sec0; /* start second */
+ unsigned char cdmsf_frame0; /* start frame */
+ unsigned char cdmsf_min1; /* end minute */
+ unsigned char cdmsf_sec1; /* end second */
+ unsigned char cdmsf_frame1; /* end frame */
+};
+
+/* This struct is used by the CDROMPLAYTRKIND ioctl */
+#define _IOT_cdrom_ti _IOT (_IOTS (char), 4, 0, 0, 0, 0)
+struct cdrom_ti
+{
+ unsigned char cdti_trk0; /* start track */
+ unsigned char cdti_ind0; /* start index */
+ unsigned char cdti_trk1; /* end track */
+ unsigned char cdti_ind1; /* end index */
+};
+
+/* This struct is used by the CDROMREADTOCHDR ioctl */
+#define _IOT_cdrom_tochdr _IOT (_IOTS (char), 2, 0, 0, 0, 0)
+struct cdrom_tochdr
+{
+ unsigned char cdth_trk0; /* start track */
+ unsigned char cdth_trk1; /* end track */
+};
+
+/* This struct is used by the CDROMVOLCTRL and CDROMVOLREAD ioctls */
+#define _IOT_cdrom_volctrl _IOT (_IOTS (char), 4, 0, 0, 0, 0)
+struct cdrom_volctrl
+{
+ unsigned char channel0;
+ unsigned char channel1;
+ unsigned char channel2;
+ unsigned char channel3;
+};
+
+/* This struct is used by the CDROMSUBCHNL ioctl */
+#define _IOT_cdrom_subchnl _IOT (_IOTS (char), 5, _IOTS (int), 2, 0, 0)
+struct cdrom_subchnl
+{
+ unsigned char cdsc_format;
+ unsigned char cdsc_audiostatus;
+ unsigned char cdsc_adr: 4;
+ unsigned char cdsc_ctrl: 4;
+ unsigned char cdsc_trk;
+ unsigned char cdsc_ind;
+ union cdrom_addr cdsc_absaddr;
+ union cdrom_addr cdsc_reladdr;
+};
+
+/* This struct is used by the CDROMREADTOCENTRY ioctl */
+#define _IOT_cdrom_tocentry _IOT (_IOTS (char), 3, _IOTS (int), 1, _IOTS (char), 1)
+struct cdrom_tocentry
+{
+ unsigned char cdte_track;
+ unsigned char cdte_adr :4;
+ unsigned char cdte_ctrl :4;
+ unsigned char cdte_format;
+ union cdrom_addr cdte_addr;
+ unsigned char cdte_datamode;
+};
+
+/* This struct used by the CDROMREADMODE1, and CDROMREADMODE2 ioctls */
+struct cdrom_read
+{
+ int cdread_lba;
+ char *cdread_bufaddr;
+ int cdread_buflen;
+};
+
+/* This struct is used by the CDROMREADAUDIO ioctl */
+struct cdrom_read_audio
+{
+ union cdrom_addr addr; /* frame address */
+ unsigned char addr_format; /* CDROM_LBA or CDROM_MSF */
+ int nframes; /* number of 2352-byte-frames to read at once */
+ unsigned char *buf; /* frame buffer (size: nframes*2352 bytes) */
+};
+
+/* This struct is used with the CDROMMULTISESSION ioctl */
+#define _IOT_cdrom_multisession _IOT (_IOTS (int), 1, _IOTS (char), 2, 0, 0)
+struct cdrom_multisession
+{
+ union cdrom_addr addr; /* frame address: start-of-last-session
+ (not the new "frame 16"!). Only valid
+ if the "xa_flag" is true. */
+ unsigned char xa_flag; /* 1: "is XA disk" */
+ unsigned char addr_format; /* CDROM_LBA or CDROM_MSF */
+};
+
+/* This struct is used with the CDROM_GET_MCN ioctl.
+ * Very few audio discs actually have Universal Product Code information,
+ * which should just be the Medium Catalog Number on the box. Also note
+ * that the way the codeis written on CD is _not_ uniform across all discs!
+ */
+#define _IOT_cdrom_mcn _IOT (_IOTS (char), 14, 0, 0, 0, 0)
+struct cdrom_mcn
+{
+ unsigned char medium_catalog_number[14]; /* 13 ASCII digits, null-terminated */
+};
+
+/* This is used by the CDROMPLAYBLK ioctl */
+#define _IOT_cdrom_blk _IOT (_IOTS (unsigned), 1, _IOTS (short), 1, 0, 0)
+struct cdrom_blk
+{
+ unsigned from;
+ unsigned short len;
+};
+
+#define CDROM_PACKET_SIZE 12
+
+#define CGC_DATA_UNKNOWN 0
+#define CGC_DATA_WRITE 1
+#define CGC_DATA_READ 2
+#define CGC_DATA_NONE 3
+
+/* for CDROM_PACKET_COMMAND ioctl */
+struct cdrom_generic_command
+{
+ unsigned char cmd[CDROM_PACKET_SIZE];
+ unsigned char *buffer;
+ unsigned int buflen;
+ int stat;
+ struct request_sense *sense;
+ unsigned char data_direction;
+ int quiet;
+ int timeout;
+ void *reserved[1]; /* unused, actually */
+};
+
+/*
+ * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336,
+ * 2340, or 2352 bytes long.
+
+* Sector types of the standard CD-ROM data formats:
+ *
+ * format sector type user data size (bytes)
+ * -----------------------------------------------------------------------------
+ * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW)
+ * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE)
+ * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0)
+ * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE)
+ * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes)
+ *
+ *
+ * The layout of the standard CD-ROM data formats:
+ * -----------------------------------------------------------------------------
+ * - audio (red): | audio_sample_bytes |
+ * | 2352 |
+ *
+ * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC |
+ * | 12 - 4 - 2048 - 4 - 8 - 276 |
+ *
+ * - data (yellow, mode2): | sync - head - data |
+ * | 12 - 4 - 2336 |
+ *
+ * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
+ * | 12 - 4 - 8 - 2048 - 4 - 276 |
+ *
+ * - XA data (green, mode2 form2): | sync - head - sub - data - Spare |
+ * | 12 - 4 - 8 - 2324 - 4 |
+ *
+ */
+
+/* Some generally useful CD-ROM information -- mostly based on the above */
+#define CD_MINS 74 /* max. minutes per CD, not really a limit */
+#define CD_SECS 60 /* seconds per minute */
+#define CD_FRAMES 75 /* frames per second */
+#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */
+#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */
+#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */
+#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */
+#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */
+#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */
+#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */
+#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */
+#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */
+#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */
+#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
+#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */
+#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */
+/* most drives don't deliver everything: */
+#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/
+#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/
+
+union cdrom_read_mode1
+{
+ struct cdrom_msf msf;
+ char buffer[CD_FRAMESIZE];
+};
+
+union cdrom_read_mode2
+{
+ struct cdrom_msf msf;
+ char buffer[CD_FRAMESIZE_RAW0];
+};
+
+union cdrom_read_raw
+{
+ struct cdrom_msf msf;
+ char buffer[CD_FRAMESIZE_RAW];
+};
+
+struct cdrom_read_cooked
+{
+ char buffer[CD_FRAMESIZE];
+};
+
+struct cdrom_read_all
+{
+ char buffer[CD_FRAMESIZE_RAWER];
+};
+
+#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
+#define CD_XA_TAIL (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
+#define CD_XA_SYNC_HEAD (CD_SYNC_SIZE+CD_XA_HEAD) /* sync bytes + header of XA frame */
+
+/* CD-ROM address types (cdrom_tocentry.cdte_format) */
+#define CDROM_LBA 0x01 /* "logical block": first frame is #0 */
+#define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
+
+/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */
+#define CDROM_DATA_TRACK 0x04
+
+/* The leadout track is always 0xAA, regardless of # of tracks on disc */
+#define CDROM_LEADOUT 0xAA
+
+/* audio states (from SCSI-2, but seen with other drives, too) */
+#define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */
+#define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */
+#define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */
+#define CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */
+#define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */
+#define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */
+
+/* capability flags used with the uniform CD-ROM driver */
+#define CDC_CLOSE_TRAY 0x1 /* caddy systems _can't_ close */
+#define CDC_OPEN_TRAY 0x2 /* but _can_ eject. */
+#define CDC_LOCK 0x4 /* disable manual eject */
+#define CDC_SELECT_SPEED 0x8 /* programmable speed */
+#define CDC_SELECT_DISC 0x10 /* select disc from juke-box */
+#define CDC_MULTI_SESSION 0x20 /* read sessions>1 */
+#define CDC_MCN 0x40 /* Medium Catalog Number */
+#define CDC_MEDIA_CHANGED 0x80 /* media changed */
+#define CDC_PLAY_AUDIO 0x100 /* audio functions */
+#define CDC_RESET 0x200 /* hard reset device */
+#define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */
+#define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */
+#define CDC_CD_R 0x2000 /* drive is a CD-R */
+#define CDC_CD_RW 0x4000 /* drive is a CD-RW */
+#define CDC_DVD 0x8000 /* drive is a DVD */
+#define CDC_DVD_R 0x10000 /* drive can write DVD-R */
+#define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */
+#define CDC_MO_DRIVE 0x40000 /* drive is an MO device */
+#define CDC_MRW 0x80000 /* drive can read MRW */
+#define CDC_MRW_W 0x100000 /* drive can write MRW */
+#define CDC_RAM 0x200000 /* ok to open for WRITE */
+
+/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
+#define CDS_NO_INFO 0 /* if not implemented */
+#define CDS_NO_DISC 1
+#define CDS_TRAY_OPEN 2
+#define CDS_DRIVE_NOT_READY 3
+#define CDS_DISC_OK 4
+
+/* return values for the CDROM_DISC_STATUS ioctl */
+/* can also return CDS_NO_[INFO|DISC], from above */
+#define CDS_AUDIO 100
+#define CDS_DATA_1 101
+#define CDS_DATA_2 102
+#define CDS_XA_2_1 103
+#define CDS_XA_2_2 104
+#define CDS_MIXED 105
+
+/* User-configurable behavior options for the uniform CD-ROM driver */
+#define CDO_AUTO_CLOSE 0x1 /* close tray on first open() */
+#define CDO_AUTO_EJECT 0x2 /* open tray on last release() */
+#define CDO_USE_FFLAGS 0x4 /* use O_NONBLOCK information on open */
+#define CDO_LOCK 0x8 /* lock tray on open files */
+#define CDO_CHECK_TYPE 0x10 /* check type on open for data */
+
+/* Special codes used when specifying changer slots. */
+#define CDSL_NONE (INT_MAX-1)
+#define CDSL_CURRENT INT_MAX
+
+/* For partition based multisession access. IDE can handle 64 partitions
+ * per drive - SCSI CD-ROM's use minors to differentiate between the
+ * various drives, so we can't do multisessions the same way there.
+ * Use the -o session=x option to mount on them.
+ */
+#define CD_PART_MAX 64
+#define CD_PART_MASK (CD_PART_MAX - 1)
+
+/*********************************************************************
+ * Generic Packet commands, MMC commands, and such
+ *********************************************************************/
+
+ /* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+#define GPCMD_BLANK 0xa1
+#define GPCMD_CLOSE_TRACK 0x5b
+#define GPCMD_FLUSH_CACHE 0x35
+#define GPCMD_FORMAT_UNIT 0x04
+#define GPCMD_GET_CONFIGURATION 0x46
+#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define GPCMD_GET_PERFORMANCE 0xac
+#define GPCMD_INQUIRY 0x12
+#define GPCMD_LOAD_UNLOAD 0xa6
+#define GPCMD_MECHANISM_STATUS 0xbd
+#define GPCMD_MODE_SELECT_10 0x55
+#define GPCMD_MODE_SENSE_10 0x5a
+#define GPCMD_PAUSE_RESUME 0x4b
+#define GPCMD_PLAY_AUDIO_10 0x45
+#define GPCMD_PLAY_AUDIO_MSF 0x47
+#define GPCMD_PLAY_AUDIO_TI 0x48
+#define GPCMD_PLAY_CD 0xbc
+#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
+#define GPCMD_READ_10 0x28
+#define GPCMD_READ_12 0xa8
+#define GPCMD_READ_BUFFER 0x3c
+#define GPCMD_READ_BUFFER_CAPACITY 0x5c
+#define GPCMD_READ_CDVD_CAPACITY 0x25
+#define GPCMD_READ_CD 0xbe
+#define GPCMD_READ_CD_MSF 0xb9
+#define GPCMD_READ_DISC_INFO 0x51
+#define GPCMD_READ_DVD_STRUCTURE 0xad
+#define GPCMD_READ_FORMAT_CAPACITIES 0x23
+#define GPCMD_READ_HEADER 0x44
+#define GPCMD_READ_TRACK_RZONE_INFO 0x52
+#define GPCMD_READ_SUBCHANNEL 0x42
+#define GPCMD_READ_TOC_PMA_ATIP 0x43
+#define GPCMD_REPAIR_RZONE_TRACK 0x58
+#define GPCMD_REPORT_KEY 0xa4
+#define GPCMD_REQUEST_SENSE 0x03
+#define GPCMD_RESERVE_RZONE_TRACK 0x53
+#define GPCMD_SEND_CUE_SHEET 0x5d
+#define GPCMD_SCAN 0xba
+#define GPCMD_SEEK 0x2b
+#define GPCMD_SEND_DVD_STRUCTURE 0xbf
+#define GPCMD_SEND_EVENT 0xa2
+#define GPCMD_SEND_KEY 0xa3
+#define GPCMD_SEND_OPC 0x54
+#define GPCMD_SET_READ_AHEAD 0xa7
+#define GPCMD_SET_STREAMING 0xb6
+#define GPCMD_START_STOP_UNIT 0x1b
+#define GPCMD_STOP_PLAY_SCAN 0x4e
+#define GPCMD_TEST_UNIT_READY 0x00
+#define GPCMD_VERIFY_10 0x2f
+#define GPCMD_WRITE_10 0x2a
+#define GPCMD_WRITE_12 0xaa
+#define GPCMD_WRITE_AND_VERIFY_10 0x2e
+#define GPCMD_WRITE_BUFFER 0x3b
+/* This is listed as optional in ATAPI 2.6, but is (curiously)
+ * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
+ * Table 377 as an MMC command for SCSi devices though... Most ATAPI
+ * drives support it. */
+#define GPCMD_SET_SPEED 0xbb
+/* This seems to be a SCSI specific CD-ROM opcode
+ * to play data at track/index */
+#define GPCMD_PLAYAUDIO_TI 0x48
+/*
+ * From MS Media Status Notification Support Specification. For
+ * older drives only.
+ */
+#define GPCMD_GET_MEDIA_STATUS 0xda
+
+/* Mode page codes for mode sense/set */
+#define GPMODE_VENDOR_PAGE 0x00
+#define GPMODE_R_W_ERROR_PAGE 0x01
+#define GPMODE_WRITE_PARMS_PAGE 0x05
+#define GPMODE_WCACHING_PAGE 0x08
+#define GPMODE_AUDIO_CTL_PAGE 0x0e
+#define GPMODE_POWER_PAGE 0x1a
+#define GPMODE_FAULT_FAIL_PAGE 0x1c
+#define GPMODE_TO_PROTECT_PAGE 0x1d
+#define GPMODE_CAPABILITIES_PAGE 0x2a
+#define GPMODE_ALL_PAGES 0x3f
+/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor
+ * of MODE_SENSE_POWER_PAGE */
+#define GPMODE_CDROM_PAGE 0x0d
+
+
+
+/* DVD struct types */
+#define DVD_STRUCT_PHYSICAL 0x00
+#define DVD_STRUCT_COPYRIGHT 0x01
+#define DVD_STRUCT_DISCKEY 0x02
+#define DVD_STRUCT_BCA 0x03
+#define DVD_STRUCT_MANUFACT 0x04
+
+struct dvd_layer {
+ unsigned char book_version : 4;
+ unsigned char book_type : 4;
+ unsigned char min_rate : 4;
+ unsigned char disc_size : 4;
+ unsigned char layer_type : 4;
+ unsigned char track_path : 1;
+ unsigned char nlayers : 2;
+ unsigned char track_density : 4;
+ unsigned char linear_density : 4;
+ unsigned char bca : 1;
+ unsigned int start_sector;
+ unsigned int end_sector;
+ unsigned int end_sector_l0;
+};
+
+#define DVD_LAYERS 4
+
+struct dvd_physical {
+ unsigned char type;
+ unsigned char layer_num;
+ struct dvd_layer layer[DVD_LAYERS];
+};
+
+#define _IOT_dvd_copyright _IOT (_IOTS (char), 4, 0, 0, 0, 0)
+struct dvd_copyright {
+ unsigned char type;
+
+ unsigned char layer_num;
+ unsigned char cpst;
+ unsigned char rmi;
+};
+
+struct dvd_disckey {
+ unsigned char type;
+
+ unsigned agid : 2;
+ unsigned char value[2048];
+};
+
+struct dvd_bca {
+ unsigned char type;
+
+ int len;
+ unsigned char value[188];
+};
+
+struct dvd_manufact {
+ unsigned char type;
+
+ unsigned char layer_num;
+ int len;
+ unsigned char value[2048];
+};
+
+typedef union {
+ unsigned char type;
+
+ struct dvd_physical physical;
+ struct dvd_copyright copyright;
+ struct dvd_disckey disckey;
+ struct dvd_bca bca;
+ struct dvd_manufact manufact;
+} dvd_struct;
+
+/*
+ * DVD authentication ioctl
+ */
+
+/* Authentication states */
+#define DVD_LU_SEND_AGID 0
+#define DVD_HOST_SEND_CHALLENGE 1
+#define DVD_LU_SEND_KEY1 2
+#define DVD_LU_SEND_CHALLENGE 3
+#define DVD_HOST_SEND_KEY2 4
+
+/* Termination states */
+#define DVD_AUTH_ESTABLISHED 5
+#define DVD_AUTH_FAILURE 6
+
+/* Other functions */
+#define DVD_LU_SEND_TITLE_KEY 7
+#define DVD_LU_SEND_ASF 8
+#define DVD_INVALIDATE_AGID 9
+#define DVD_LU_SEND_RPC_STATE 10
+#define DVD_HOST_SEND_RPC_STATE 11
+
+/* State data */
+typedef unsigned char dvd_key[5]; /* 40-bit value, MSB is first elem. */
+typedef unsigned char dvd_challenge[10]; /* 80-bit value, MSB is first elem. */
+
+struct dvd_lu_send_agid {
+ unsigned char type;
+ unsigned agid : 2;
+};
+
+struct dvd_host_send_challenge {
+ unsigned char type;
+ unsigned agid : 2;
+
+ dvd_challenge chal;
+};
+
+struct dvd_send_key {
+ unsigned char type;
+ unsigned agid : 2;
+
+ dvd_key key;
+};
+
+struct dvd_lu_send_challenge {
+ unsigned char type;
+ unsigned agid : 2;
+
+ dvd_challenge chal;
+};
+
+#define DVD_CPM_NO_COPYRIGHT 0
+#define DVD_CPM_COPYRIGHTED 1
+
+#define DVD_CP_SEC_NONE 0
+#define DVD_CP_SEC_EXIST 1
+
+#define DVD_CGMS_UNRESTRICTED 0
+#define DVD_CGMS_SINGLE 2
+#define DVD_CGMS_RESTRICTED 3
+
+struct dvd_lu_send_title_key {
+ unsigned char type;
+ unsigned agid : 2;
+
+ dvd_key title_key;
+ int lba;
+ unsigned cpm : 1;
+ unsigned cp_sec : 1;
+ unsigned cgms : 2;
+};
+
+struct dvd_lu_send_asf {
+ unsigned char type;
+ unsigned agid : 2;
+
+ unsigned asf : 1;
+};
+
+struct dvd_host_send_rpcstate {
+ unsigned char type;
+ unsigned char pdrc;
+};
+
+struct dvd_lu_send_rpcstate {
+ unsigned char type : 2;
+ unsigned char vra : 3;
+ unsigned char ucca : 3;
+ unsigned char region_mask;
+ unsigned char rpc_scheme;
+};
+
+typedef union {
+ unsigned char type;
+
+ struct dvd_lu_send_agid lsa;
+ struct dvd_host_send_challenge hsc;
+ struct dvd_send_key lsk;
+ struct dvd_lu_send_challenge lsc;
+ struct dvd_send_key hsk;
+ struct dvd_lu_send_title_key lstk;
+ struct dvd_lu_send_asf lsasf;
+ struct dvd_host_send_rpcstate hrpcs;
+ struct dvd_lu_send_rpcstate lrpcs;
+} dvd_authinfo;
+
+struct request_sense {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char valid : 1;
+ unsigned char error_code : 7;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char error_code : 7;
+ unsigned char valid : 1;
+#endif
+ unsigned char segment_number;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved1 : 2;
+ unsigned char ili : 1;
+ unsigned char reserved2 : 1;
+ unsigned char sense_key : 4;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char sense_key : 4;
+ unsigned char reserved2 : 1;
+ unsigned char ili : 1;
+ unsigned char reserved1 : 2;
+#endif
+ unsigned char information[4];
+ unsigned char add_sense_len;
+ unsigned char command_info[4];
+ unsigned char asc;
+ unsigned char ascq;
+ unsigned char fruc;
+ unsigned char sks[3];
+ unsigned char asb[46];
+};
+
+/*
+ * feature profile
+ */
+#define CDF_RWRT 0x0020 /* "Random Writable" */
+#define CDF_HWDM 0x0024 /* "Hardware Defect Management" */
+#define CDF_MRW 0x0028
+
+/*
+ * media status bits
+ */
+#define CDM_MRW_NOTMRW 0
+#define CDM_MRW_BGFORMAT_INACTIVE 1
+#define CDM_MRW_BGFORMAT_ACTIVE 2
+#define CDM_MRW_BGFORMAT_COMPLETE 3
+
+/*
+ * mrw address spaces
+ */
+#define MRW_LBA_DMA 0
+#define MRW_LBA_GAA 1
+
+/*
+ * mrw mode pages (first is deprecated) -- probed at init time and
+ * cdi->mrw_mode_page is set
+ */
+#define MRW_MODE_PC_PRE1 0x2c
+#define MRW_MODE_PC 0x03
+
+struct mrw_feature_desc {
+ unsigned short feature_code;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved1 : 2;
+ unsigned char feature_version : 4;
+ unsigned char persistent : 1;
+ unsigned char curr : 1;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char curr : 1;
+ unsigned char persistent : 1;
+ unsigned char feature_version : 4;
+ unsigned char reserved1 : 2;
+#endif
+ unsigned char add_len;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved2 : 7;
+ unsigned char write : 1;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char write : 1;
+ unsigned char reserved2 : 7;
+#endif
+ unsigned char reserved3;
+ unsigned char reserved4;
+ unsigned char reserved5;
+};
+
+/* cf. mmc4r02g.pdf 5.3.10 Random Writable Feature (0020h) pg 197 of 635 */
+struct rwrt_feature_desc {
+ unsigned short feature_code;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved1 : 2;
+ unsigned char feature_version : 4;
+ unsigned char persistent : 1;
+ unsigned char curr : 1;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char curr : 1;
+ unsigned char persistent : 1;
+ unsigned char feature_version : 4;
+ unsigned char reserved1 : 2;
+#endif
+ unsigned char add_len;
+ unsigned int last_lba;
+ unsigned int block_size;
+ unsigned short blocking;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved2 : 7;
+ unsigned char page_present : 1;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char page_present : 1;
+ unsigned char reserved2 : 7;
+#endif
+ unsigned char reserved3;
+};
+
+typedef struct {
+ unsigned short disc_information_length;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved1 : 3;
+ unsigned char erasable : 1;
+ unsigned char border_status : 2;
+ unsigned char disc_status : 2;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char disc_status : 2;
+ unsigned char border_status : 2;
+ unsigned char erasable : 1;
+ unsigned char reserved1 : 3;
+#endif
+ unsigned char n_first_track;
+ unsigned char n_sessions_lsb;
+ unsigned char first_track_lsb;
+ unsigned char last_track_lsb;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char did_v : 1;
+ unsigned char dbc_v : 1;
+ unsigned char uru : 1;
+ unsigned char reserved2 : 2;
+ unsigned char dbit : 1;
+ unsigned char mrw_status : 2;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char mrw_status : 2;
+ unsigned char dbit : 1;
+ unsigned char reserved2 : 2;
+ unsigned char uru : 1;
+ unsigned char dbc_v : 1;
+ unsigned char did_v : 1;
+#endif
+ unsigned char disc_type;
+ unsigned char n_sessions_msb;
+ unsigned char first_track_msb;
+ unsigned char last_track_msb;
+ unsigned int disc_id;
+ unsigned int lead_in;
+ unsigned int lead_out;
+ unsigned char disc_bar_code[8];
+ unsigned char reserved3;
+ unsigned char n_opc;
+} disc_information;
+
+typedef struct {
+ unsigned short track_information_length;
+ unsigned char track_lsb;
+ unsigned char session_lsb;
+ unsigned char reserved1;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved2 : 2;
+ unsigned char damage : 1;
+ unsigned char copy : 1;
+ unsigned char track_mode : 4;
+ unsigned char rt : 1;
+ unsigned char blank : 1;
+ unsigned char packet : 1;
+ unsigned char fp : 1;
+ unsigned char data_mode : 4;
+ unsigned char reserved3 : 6;
+ unsigned char lra_v : 1;
+ unsigned char nwa_v : 1;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char track_mode : 4;
+ unsigned char copy : 1;
+ unsigned char damage : 1;
+ unsigned char reserved2 : 2;
+ unsigned char data_mode : 4;
+ unsigned char fp : 1;
+ unsigned char packet : 1;
+ unsigned char blank : 1;
+ unsigned char rt : 1;
+ unsigned char nwa_v : 1;
+ unsigned char lra_v : 1;
+ unsigned char reserved3 : 6;
+#endif
+ unsigned int track_start;
+ unsigned int next_writable;
+ unsigned int free_blocks;
+ unsigned int fixed_packet_size;
+ unsigned int track_size;
+ unsigned int last_rec_address;
+} track_information;
+
+struct feature_header {
+ unsigned int data_len;
+ unsigned char reserved1;
+ unsigned char reserved2;
+ unsigned short curr_profile;
+};
+
+struct mode_page_header {
+ unsigned short mode_data_length;
+ unsigned char medium_type;
+ unsigned char reserved1;
+ unsigned char reserved2;
+ unsigned char reserved3;
+ unsigned short desc_length;
+};
+
+
+#endif /* _SYS_CDROM_H */
diff --git a/debian/local/finish-install.d/51hurd_config-target-network b/debian/local/finish-install.d/51hurd_config-target-network
new file mode 100755
index 00000000..13191653
--- /dev/null
+++ b/debian/local/finish-install.d/51hurd_config-target-network
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Make sure the firmlink is gone
+settrans -ag /target/servers
+
+# Transfer the network configuration to /target
+settrans -pk /target/servers/socket/2 $(fsysopts /servers/socket/2) -6 /servers/socket/26
+settrans -cpk /target/servers/socket/26 $(fsysopts /servers/socket/2) -4 /servers/socket/2
+
diff --git a/debian/local/menu.lst b/debian/local/menu.lst
new file mode 100644
index 00000000..9e2ba4c0
--- /dev/null
+++ b/debian/local/menu.lst
@@ -0,0 +1,19 @@
+# Example GRUB configuration to boot Debian GNU/Hurd off the first partition.
+# Adjust the partition setting for GRUB's root command and the gnumach.gz
+# root device.
+
+timeout 5
+
+default 0
+
+title Debian GNU/Hurd
+root (hd0,0)
+kernel /boot/gnumach.gz root=device:hd0s1
+module /hurd/ext2fs.static --multiboot-command-line=${kernel-command-line} --host-priv-port=${host-port} --device-master-port=${device-port} --exec-server-task=${exec-task} -T typed ${root} $(task-create) $(task-resume)
+module /lib/ld.so.1 /hurd/exec $(exec-task=task-create)
+
+title Debian GNU/Hurd (single user mode)
+root (hd0,0)
+kernel /boot/gnumach.gz -s root=device:hd0s1
+module /hurd/ext2fs.static --multiboot-command-line=${kernel-command-line} --host-priv-port=${host-port} --device-master-port=${device-port} --exec-server-task=${exec-task} -T typed ${root} $(task-create) $(task-resume)
+module /lib/ld.so.1 /hurd/exec $(exec-task=task-create)
diff --git a/debian/local/partman/commit.d/40hurd_reload-partitions b/debian/local/partman/commit.d/40hurd_reload-partitions
new file mode 100755
index 00000000..6c105872
--- /dev/null
+++ b/debian/local/partman/commit.d/40hurd_reload-partitions
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+for part in /dev/[hs]d?s*; do
+ settrans -ag $part
+done
diff --git a/debian/local/runsystem b/debian/local/runsystem
new file mode 100755
index 00000000..198c0f84
--- /dev/null
+++ b/debian/local/runsystem
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export PATH
+
+umask 022
+
+# Create a minimal subset of device and server nodes
+/usr/lib/hurd/setup-translators -m -k -p
+
+/hurd/mach-defpager
+
+mem=`vmstat-hurd --size -k`
+if [ "$mem" -lt 240000 ]
+then
+ echo "You only have ${mem}KiB memory."
+ echo "Debian GNU/Hurd installation has not been optimized for memory usage yet, and thus currently needs at least 256MiB memory, sorry."
+ while true
+ do
+ sleep 60
+ done
+fi
+
+# Get all kernel parameters that can be exported as environment variables
+envvars="$(echo $* | tr ' ' '\012' | egrep '^[-_/[:alnum:]]+=.*$')"
+
+# Invoke init as linuxrc to work around pid != 1
+init='/bin/busybox linuxrc'
+
+# Parse kernel parameters
+for i in $envvars ; do
+ case "$i" in
+ init="/sbin/init"|init="init")
+ # Avoid endless loop
+ : ;;
+ init=*)
+ init=${i#init=}
+ ;;
+ noshell=*)
+ sed -i '/^tty[12]/s/^/#/' /etc/inittab
+ ;;
+ TERM=*)
+ term=yes
+ ;;
+ esac
+done
+
+if [ "$term" != yes ]
+then
+ # No terminal type set, assume we can start the Hurd console
+
+ # Touch the first tty so that the Hurd console is certain to pick it
+ # and not some random other tty.
+ sleep 1
+ touch /dev/tty1
+
+ echo -n "Starting the Hurd console..."
+ console -d vga -g -d pc_mouse --repeat=mouse -d pc_kbd --repeat=kbd -c /dev/vcs &
+ sleep 1
+
+ # Switch over
+ envvars="$envvars TERM=hurd"
+ exec < /dev/tty1 > /dev/tty1 2>&1
+ echo "Console started, initializing installer environment, please wait..."
+
+ # Set the console device used by /sbin/reopen-console
+ echo /dev/tty1 >/var/run/console-device
+fi
+
+# Preset the terminal type for /lib/debian-installer/detect-console
+eval exec env - $envvars TERM_TYPE=virtual $init
diff --git a/debian/local/setup-translators b/debian/local/setup-translators
new file mode 100755
index 00000000..4a019fcd
--- /dev/null
+++ b/debian/local/setup-translators
@@ -0,0 +1,162 @@
+#!/bin/sh
+# Set up device nodes and /servers translators.
+#
+# Use cases:
+# - from d-i's /libexec/runsystem, to create a minimal set of device nodes
+# and translators for the installer environment;
+# - from debootstrap on initial installation, to create device and server
+# nodes before /dev and /servers are firmlinked to the host system.
+# - from hurd.postinst, on upgrade, where only non-existant nodes should be
+# created, and the other ones should be left alone.
+
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export PATH
+
+usage () {
+cat >&2 <<EOU
+Usage: $0 [OPTIONS]
+Set up device nodes and /servers translators.
+
+ -k, --keep-active Keep active translators running
+ -K, --keep-all Don't even set passive translators on existing files
+ -m, --minimal Create a minimal subset of nodes only
+ -p, --parted Prefer parted stores for partition devices
+
+At least one of -k or -K must be given.
+EOU
+}
+
+# Parse command-line arguments
+REPLACE=
+MDFLAGS=
+MINIMAL=
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -k|--keep-active)
+ MDFLAGS="$MDFLAGS -k"
+ REPLACE=y
+ shift;;
+ -K|--keep-all)
+ MDFLAGS="$MDFLAGS -K"
+ REPLACE=n
+ shift;;
+ -m|--minimal)
+ MINIMAL=y
+ shift;;
+ -p|--parted)
+ MDFLAGS="$MDFLAGS -p"
+ shift;;
+ *)
+ usage
+ exit 1;;
+ esac
+done
+
+if [ -z "$REPLACE" ]; then
+ usage
+ exit 1
+fi
+
+# Usage: foldsubst <pat> xxxx yyyy zzzz ...
+# <pat> is substituted for every character of xxxx with sed, the character in
+# question being accessible as a '\0' in <pat>, and the result is used as the
+# new pattern to handle the remaining arguments.
+foldsubst () {
+ [ "$2" ] || { echo $1; return; }
+ expanded=$(echo "$2" | sed "s/./ $1/g"); shift 2
+ foldsubst "$expanded" $@;
+}
+
+# Verbosely attach a translator.
+st () {
+ node=$1
+ cmdl=$2
+ name=${3:-$cmdl}
+
+ echo -n " $name"
+ if [ "$REPLACE" = y ] || ! showtrans $1 > /dev/null 2>&1 ; then
+ # Work around a bug in ext2fs, which crashes if a non-empty
+ # file is turned into a symlink through settrans, by clearing
+ # the passive translator first.
+ settrans -ck $node
+ settrans -ck $node /hurd/$cmdl
+ fi
+}
+
+# Verbosely create device nodes, with some help from foldsubst.
+md () {
+ pattern=$1; shift
+ sedrepl=$(echo $pattern | sed -e 's/X/\\0/' -e 's/Y/\\\\0/')
+ devs=$(foldsubst "$sedrepl" $@)
+
+ echo -n " $pattern"
+ /sbin/MAKEDEV $MDFLAGS $devs
+}
+
+
+echo -n "Setting up translators:"
+cd /servers
+mkdir -p socket
+
+st exec exec
+st default-pager proxy-defpager
+st socket/1 pflocal
+st socket/local 'symlink 1' '(+link)'
+st socket/2 pfinet
+st socket/inet 'symlink 2' '(+link)'
+st socket/inet6 'symlink 26' '(+link)'
+st /proc 'procfs -c'
+
+if [ -z "$MINIMAL" ]; then
+ st password password
+ st crash-kill 'crash --kill' crash-kill
+ st crash-suspend 'crash --suspend' crash-suspend
+ st crash-dump-core 'crash --dump-core' crash-dump-core
+ st crash 'symlink crash-kill' crash
+fi
+
+echo .
+
+
+echo -n "Creating device nodes:"
+cd /dev
+
+md fd
+md fdX 01
+md std
+md vcs
+md hdX 0123
+md hdXsY 0123 123456789
+md hdXs1Y 0123 0123456
+md sdX 0123
+md sdXsY 0123 123456789
+md sdXs1Y 0123 0123456
+md cdX 01
+
+if [ "$MINIMAL" ]; then
+ md loopX 0123
+ md ttyX 1234
+ md ptypX 0123
+ md comX 0123
+else
+ md loopX 01234567
+ md ttyX 123456
+ md ptyp
+ md ptyq
+ md lprX 0123
+ md comX 0123
+ st random-hurd 'random --seed-file /var/spool/random-seed' random
+ st urandom-hurd 'random --seed-file /var/spool/random-seed --fast' urandom
+fi
+
+st kbd 'symlink cons/kbd' kbd
+st mouse 'symlink cons/mouse' mouse
+st shm 'symlink /run/shm' shm
+
+# until we properly start /etc/rcS.d
+mkdir -p /run/lock /run/shm
+chmod 1777 /run/lock /run/shm
+
+echo .
+
diff --git a/debian/local/soundcard.h b/debian/local/soundcard.h
new file mode 100644
index 00000000..3c32819a
--- /dev/null
+++ b/debian/local/soundcard.h
@@ -0,0 +1,1298 @@
+#ifndef _SYS_SOUNDCARD_H
+#define _SYS_SOUNDCARD_H
+/*
+ * Copyright by Hannu Savolainen 1993-1997
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * OSS interface version. With versions earlier than 3.6 this value is
+ * an integer with value less than 361. In versions 3.6 and later
+ * it's a six digit hexadecimal value. For example value
+ * of 0x030600 represents OSS version 3.6.0.
+ * Use ioctl(fd, OSS_GETVERSION, &int) to get the version number of
+ * the currently active driver.
+ */
+#define SOUND_VERSION 0x030802
+#define OPEN_SOUND_SYSTEM
+
+#include <sys/ioctl.h>
+#include <endian.h>
+
+/*
+ * Supported card ID numbers (Should be somewhere else?)
+ */
+
+#define SNDCARD_ADLIB 1
+#define SNDCARD_SB 2
+#define SNDCARD_PAS 3
+#define SNDCARD_GUS 4
+#define SNDCARD_MPU401 5
+#define SNDCARD_SB16 6
+#define SNDCARD_SB16MIDI 7
+#define SNDCARD_UART6850 8
+#define SNDCARD_GUS16 9
+#define SNDCARD_MSS 10
+#define SNDCARD_PSS 11
+#define SNDCARD_SSCAPE 12
+#define SNDCARD_PSS_MPU 13
+#define SNDCARD_PSS_MSS 14
+#define SNDCARD_SSCAPE_MSS 15
+#define SNDCARD_TRXPRO 16
+#define SNDCARD_TRXPRO_SB 17
+#define SNDCARD_TRXPRO_MPU 18
+#define SNDCARD_MAD16 19
+#define SNDCARD_MAD16_MPU 20
+#define SNDCARD_CS4232 21
+#define SNDCARD_CS4232_MPU 22
+#define SNDCARD_MAUI 23
+#define SNDCARD_PSEUDO_MSS 24
+#define SNDCARD_GUSPNP 25
+#define SNDCARD_UART401 26
+/* Sound card numbers 27 to N are reserved. Don't add more numbers here. */
+
+/***********************************
+ * IOCTL Commands for /dev/sequencer
+ */
+
+#ifndef _SIOWR
+/* Use already defined ioctl defines if they exist (except with Sun or Sparc) */
+#define SIOCPARM_MASK IOCPARM_MASK
+#define SIOC_VOID IOC_VOID
+#define SIOC_OUT IOC_OUT
+#define SIOC_IN IOC_IN
+#define SIOC_INOUT IOC_INOUT
+#define _SIOC_SIZE _IOC_SIZE
+#define _SIOC_DIR _IOC_DIR
+#define _SIOC_NONE _IOC_NONE
+#define _SIOC_READ _IOC_READ
+#define _SIOC_WRITE _IOC_WRITE
+#define _SIO _IO
+#define _SIOR _IOR
+#define _SIOW _IOW
+#define _SIOWR _IOWR
+#endif /* !_SIOWR */
+
+#define SNDCTL_SEQ_RESET _SIO ('q', 0)
+#define SNDCTL_SEQ_SYNC _SIO ('q', 1)
+#define SNDCTL_SYNTH_INFO _SIOWR('q', 2, struct synth_info)
+#define SNDCTL_SEQ_CTRLRATE _SIOWR('q', 3, int) /* Set/get timer resolution (HZ) */
+#define SNDCTL_SEQ_GETOUTCOUNT _SIOR ('q', 4, int)
+#define SNDCTL_SEQ_GETINCOUNT _SIOR ('q', 5, int)
+#define SNDCTL_SEQ_PERCMODE _SIOW ('q', 6, int)
+#define SNDCTL_FM_LOAD_INSTR _SIOW ('q', 7, struct sbi_instrument) /* Obsolete. Don't use!!!!!! */
+#define SNDCTL_SEQ_TESTMIDI _SIOW ('q', 8, int)
+#define SNDCTL_SEQ_RESETSAMPLES _SIOW ('q', 9, int)
+#define SNDCTL_SEQ_NRSYNTHS _SIOR ('q',10, int)
+#define SNDCTL_SEQ_NRMIDIS _SIOR ('q',11, int)
+#define SNDCTL_MIDI_INFO _SIOWR('q',12, struct midi_info)
+#define SNDCTL_SEQ_THRESHOLD _SIOW ('q',13, int)
+#define SNDCTL_SYNTH_MEMAVL _SIOWR('q',14, int) /* in=dev#, out=memsize */
+#define SNDCTL_FM_4OP_ENABLE _SIOW ('q',15, int) /* in=dev# */
+#define SNDCTL_SEQ_PANIC _SIO ('q',17)
+#define SNDCTL_SEQ_OUTOFBAND _SIOW ('q',18, struct seq_event_rec)
+#define SNDCTL_SEQ_GETTIME _SIOR ('q',19, int)
+#define SNDCTL_SYNTH_ID _SIOWR('q',20, struct synth_info)
+#define SNDCTL_SYNTH_CONTROL _SIOWR('q',21, struct synth_control)
+#define SNDCTL_SYNTH_REMOVESAMPLE _SIOWR('q',22, struct remove_sample)
+
+typedef struct synth_control
+{
+ /* XXX */
+ char data[62]; /* Device spesific command/data record */
+ int devno; /* Synthesizer # */
+}synth_control;
+#define _IOT_synth_control _IOT (_IOTS (char), 31, _IOTS (char), 31, _IOTS (int), 1)
+
+typedef struct remove_sample
+{
+ int devno; /* Synthesizer # */
+ int bankno; /* MIDI bank # (0=General MIDI) */
+ int instrno; /* MIDI instrument number */
+} remove_sample;
+#define _IOT_remove_sample _IOT (_IOTS (int), 3, 0, 0, 0, 0)
+
+typedef struct seq_event_rec {
+ unsigned char arr[8];
+} seq_event_rec;
+#define _IOT_seq_event_rec _IOT (_IOTS (char), 8, 0, 0, 0, 0)
+
+#define SNDCTL_TMR_TIMEBASE _SIOWR('t', 1, int)
+#define SNDCTL_TMR_START _SIO ('t', 2)
+#define SNDCTL_TMR_STOP _SIO ('t', 3)
+#define SNDCTL_TMR_CONTINUE _SIO ('t', 4)
+#define SNDCTL_TMR_TEMPO _SIOWR('t', 5, int)
+#define SNDCTL_TMR_SOURCE _SIOWR('t', 6, int)
+# define TMR_INTERNAL 0x00000001
+# define TMR_EXTERNAL 0x00000002
+# define TMR_MODE_MIDI 0x00000010
+# define TMR_MODE_FSK 0x00000020
+# define TMR_MODE_CLS 0x00000040
+# define TMR_MODE_SMPTE 0x00000080
+#define SNDCTL_TMR_METRONOME _SIOW ('t', 7, int)
+#define SNDCTL_TMR_SELECT _SIOW ('t', 8, int)
+
+/*
+ * Some big endian/little endian handling macros
+ */
+
+#if defined(__BYTE_ORDER)
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define _PATCHKEY(id) (0xfd00|id)
+# define AFMT_S16_NE AFMT_S16_BE
+# elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define _PATCHKEY(id) ((id<<8)|0x00fd)
+# define AFMT_S16_NE AFMT_S16_LE
+# else
+# error "could not determine byte order"
+# endif
+#endif
+
+/*
+ * Sample loading mechanism for internal synthesizers (/dev/sequencer)
+ * The following patch_info structure has been designed to support
+ * Gravis UltraSound. It tries to be universal format for uploading
+ * sample based patches but is probably too limited.
+ *
+ * (PBD) As Hannu guessed, the GUS structure is too limited for
+ * the WaveFront, but this is the right place for a constant definition.
+ */
+
+struct patch_info {
+ unsigned short key; /* Use WAVE_PATCH here */
+#define WAVE_PATCH _PATCHKEY(0x04)
+#define GUS_PATCH WAVE_PATCH
+#define WAVEFRONT_PATCH _PATCHKEY(0x06)
+
+ short device_no; /* Synthesizer number */
+ short instr_no; /* Midi pgm# */
+
+ unsigned int mode;
+/*
+ * The least significant byte has the same format than the GUS .PAT
+ * files
+ */
+#define WAVE_16_BITS 0x01 /* bit 0 = 8 or 16 bit wave data. */
+#define WAVE_UNSIGNED 0x02 /* bit 1 = Signed - Unsigned data. */
+#define WAVE_LOOPING 0x04 /* bit 2 = looping enabled-1. */
+#define WAVE_BIDIR_LOOP 0x08 /* bit 3 = Set is bidirectional looping. */
+#define WAVE_LOOP_BACK 0x10 /* bit 4 = Set is looping backward. */
+#define WAVE_SUSTAIN_ON 0x20 /* bit 5 = Turn sustaining on. (Env. pts. 3)*/
+#define WAVE_ENVELOPES 0x40 /* bit 6 = Enable envelopes - 1 */
+#define WAVE_FAST_RELEASE 0x80 /* bit 7 = Shut off immediately after note off */
+ /* (use the env_rate/env_offs fields). */
+/* Linux specific bits */
+#define WAVE_VIBRATO 0x00010000 /* The vibrato info is valid */
+#define WAVE_TREMOLO 0x00020000 /* The tremolo info is valid */
+#define WAVE_SCALE 0x00040000 /* The scaling info is valid */
+#define WAVE_FRACTIONS 0x00080000 /* Fraction information is valid */
+/* Reserved bits */
+#define WAVE_ROM 0x40000000 /* For future use */
+#define WAVE_MULAW 0x20000000 /* For future use */
+/* Other bits must be zeroed */
+
+ int len; /* Size of the wave data in bytes */
+ int loop_start, loop_end; /* Byte offsets from the beginning */
+
+/*
+ * The base_freq and base_note fields are used when computing the
+ * playback speed for a note. The base_note defines the tone frequency
+ * which is heard if the sample is played using the base_freq as the
+ * playback speed.
+ *
+ * The low_note and high_note fields define the minimum and maximum note
+ * frequencies for which this sample is valid. It is possible to define
+ * more than one samples for an instrument number at the same time. The
+ * low_note and high_note fields are used to select the most suitable one.
+ *
+ * The fields base_note, high_note and low_note should contain
+ * the note frequency multiplied by 1000. For example value for the
+ * middle A is 440*1000.
+ */
+
+ unsigned int base_freq;
+ unsigned int base_note;
+ unsigned int high_note;
+ unsigned int low_note;
+ int panning; /* -128=left, 127=right */
+ int detuning;
+
+/* New fields introduced in version 1.99.5 */
+
+ /* Envelope. Enabled by mode bit WAVE_ENVELOPES */
+ unsigned char env_rate[ 6 ]; /* GUS HW ramping rate */
+ unsigned char env_offset[ 6 ]; /* 255 == 100% */
+
+ /*
+ * The tremolo, vibrato and scale info are not supported yet.
+ * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or
+ * WAVE_SCALE
+ */
+
+ unsigned char tremolo_sweep;
+ unsigned char tremolo_rate;
+ unsigned char tremolo_depth;
+
+ unsigned char vibrato_sweep;
+ unsigned char vibrato_rate;
+ unsigned char vibrato_depth;
+
+ int scale_frequency;
+ unsigned int scale_factor; /* from 0 to 2048 or 0 to 2 */
+
+ int volume;
+ int fractions;
+ int reserved1;
+ int spare[2];
+ char data[1]; /* The waveform data starts here */
+ };
+
+struct sysex_info {
+ short key; /* Use SYSEX_PATCH or MAUI_PATCH here */
+#define SYSEX_PATCH _PATCHKEY(0x05)
+#define MAUI_PATCH _PATCHKEY(0x06)
+ short device_no; /* Synthesizer number */
+ int len; /* Size of the sysex data in bytes */
+ unsigned char data[1]; /* Sysex data starts here */
+ };
+
+/*
+ * /dev/sequencer input events.
+ *
+ * The data written to the /dev/sequencer is a stream of events. Events
+ * are records of 4 or 8 bytes. The first byte defines the size.
+ * Any number of events can be written with a write call. There
+ * is a set of macros for sending these events. Use these macros if you
+ * want to maximize portability of your program.
+ *
+ * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events.
+ * (All input events are currently 4 bytes long. Be prepared to support
+ * 8 byte events also. If you receive any event having first byte >= 128,
+ * it's a 8 byte event.
+ *
+ * The events are documented at the end of this file.
+ *
+ * Normal events (4 bytes)
+ * There is also a 8 byte version of most of the 4 byte events. The
+ * 8 byte one is recommended.
+ */
+#define SEQ_NOTEOFF 0
+#define SEQ_FMNOTEOFF SEQ_NOTEOFF /* Just old name */
+#define SEQ_NOTEON 1
+#define SEQ_FMNOTEON SEQ_NOTEON
+#define SEQ_WAIT TMR_WAIT_ABS
+#define SEQ_PGMCHANGE 3
+#define SEQ_FMPGMCHANGE SEQ_PGMCHANGE
+#define SEQ_SYNCTIMER TMR_START
+#define SEQ_MIDIPUTC 5
+#define SEQ_DRUMON 6 /*** OBSOLETE ***/
+#define SEQ_DRUMOFF 7 /*** OBSOLETE ***/
+#define SEQ_ECHO TMR_ECHO /* For synching programs with output */
+#define SEQ_AFTERTOUCH 9
+#define SEQ_CONTROLLER 10
+
+/*******************************************
+ * Midi controller numbers
+ *******************************************
+ * Controllers 0 to 31 (0x00 to 0x1f) and
+ * 32 to 63 (0x20 to 0x3f) are continuous
+ * controllers.
+ * In the MIDI 1.0 these controllers are sent using
+ * two messages. Controller numbers 0 to 31 are used
+ * to send the MSB and the controller numbers 32 to 63
+ * are for the LSB. Note that just 7 bits are used in MIDI bytes.
+ */
+
+#define CTL_BANK_SELECT 0x00
+#define CTL_MODWHEEL 0x01
+#define CTL_BREATH 0x02
+/* undefined 0x03 */
+#define CTL_FOOT 0x04
+#define CTL_PORTAMENTO_TIME 0x05
+#define CTL_DATA_ENTRY 0x06
+#define CTL_MAIN_VOLUME 0x07
+#define CTL_BALANCE 0x08
+/* undefined 0x09 */
+#define CTL_PAN 0x0a
+#define CTL_EXPRESSION 0x0b
+/* undefined 0x0c */
+/* undefined 0x0d */
+/* undefined 0x0e */
+/* undefined 0x0f */
+#define CTL_GENERAL_PURPOSE1 0x10
+#define CTL_GENERAL_PURPOSE2 0x11
+#define CTL_GENERAL_PURPOSE3 0x12
+#define CTL_GENERAL_PURPOSE4 0x13
+/* undefined 0x14 - 0x1f */
+
+/* undefined 0x20 */
+/* The controller numbers 0x21 to 0x3f are reserved for the */
+/* least significant bytes of the controllers 0x00 to 0x1f. */
+/* These controllers are not recognised by the driver. */
+
+/* Controllers 64 to 69 (0x40 to 0x45) are on/off switches. */
+/* 0=OFF and 127=ON (intermediate values are possible) */
+#define CTL_DAMPER_PEDAL 0x40
+#define CTL_SUSTAIN 0x40 /* Alias */
+#define CTL_HOLD 0x40 /* Alias */
+#define CTL_PORTAMENTO 0x41
+#define CTL_SOSTENUTO 0x42
+#define CTL_SOFT_PEDAL 0x43
+/* undefined 0x44 */
+#define CTL_HOLD2 0x45
+/* undefined 0x46 - 0x4f */
+
+#define CTL_GENERAL_PURPOSE5 0x50
+#define CTL_GENERAL_PURPOSE6 0x51
+#define CTL_GENERAL_PURPOSE7 0x52
+#define CTL_GENERAL_PURPOSE8 0x53
+/* undefined 0x54 - 0x5a */
+#define CTL_EXT_EFF_DEPTH 0x5b
+#define CTL_TREMOLO_DEPTH 0x5c
+#define CTL_CHORUS_DEPTH 0x5d
+#define CTL_DETUNE_DEPTH 0x5e
+#define CTL_CELESTE_DEPTH 0x5e /* Alias for the above one */
+#define CTL_PHASER_DEPTH 0x5f
+#define CTL_DATA_INCREMENT 0x60
+#define CTL_DATA_DECREMENT 0x61
+#define CTL_NONREG_PARM_NUM_LSB 0x62
+#define CTL_NONREG_PARM_NUM_MSB 0x63
+#define CTL_REGIST_PARM_NUM_LSB 0x64
+#define CTL_REGIST_PARM_NUM_MSB 0x65
+/* undefined 0x66 - 0x78 */
+/* reserved 0x79 - 0x7f */
+
+/* Pseudo controllers (not midi compatible) */
+#define CTRL_PITCH_BENDER 255
+#define CTRL_PITCH_BENDER_RANGE 254
+#define CTRL_EXPRESSION 253 /* Obsolete */
+#define CTRL_MAIN_VOLUME 252 /* Obsolete */
+#define SEQ_BALANCE 11
+#define SEQ_VOLMODE 12
+
+/*
+ * Volume mode decides how volumes are used
+ */
+
+#define VOL_METHOD_ADAGIO 1
+#define VOL_METHOD_LINEAR 2
+
+/*
+ * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as
+ * input events.
+ */
+
+/*
+ * Event codes 0xf0 to 0xfc are reserved for future extensions.
+ */
+
+#define SEQ_FULLSIZE 0xfd /* Long events */
+/*
+ * SEQ_FULLSIZE events are used for loading patches/samples to the
+ * synthesizer devices. These events are passed directly to the driver
+ * of the associated synthesizer device. There is no limit to the size
+ * of the extended events. These events are not queued but executed
+ * immediately when the write() is called (execution can take several
+ * seconds of time).
+ *
+ * When a SEQ_FULLSIZE message is written to the device, it must
+ * be written using exactly one write() call. Other events cannot
+ * be mixed to the same write.
+ *
+ * For FM synths (YM3812/OPL3) use struct sbi_instrument and write it to the
+ * /dev/sequencer. Don't write other data together with the instrument structure
+ * Set the key field of the structure to FM_PATCH. The device field is used to
+ * route the patch to the corresponding device.
+ *
+ * For wave table use struct patch_info. Initialize the key field
+ * to WAVE_PATCH.
+ */
+#define SEQ_PRIVATE 0xfe /* Low level HW dependent events (8 bytes) */
+#define SEQ_EXTENDED 0xff /* Extended events (8 bytes) OBSOLETE */
+
+/*
+ * Record for FM patches
+ */
+
+typedef unsigned char sbi_instr_data[32];
+
+struct sbi_instrument {
+ unsigned short key; /* FM_PATCH or OPL3_PATCH */
+#define FM_PATCH _PATCHKEY(0x01)
+#define OPL3_PATCH _PATCHKEY(0x03)
+ short device; /* Synth# (0-4) */
+ int channel; /* Program# to be initialized */
+ sbi_instr_data operators; /* Register settings for operator cells (.SBI format) */
+ };
+
+/* XXX */
+#define _IOT_sbi_instrument _IOT (_IOTS (short), 2, _IOTS (int), 1, _IOTS(char), 3)
+
+struct synth_info { /* Read only */
+ char name[30];
+ int device; /* 0-N. INITIALIZE BEFORE CALLING */
+ int synth_type;
+#define SYNTH_TYPE_FM 0
+#define SYNTH_TYPE_SAMPLE 1
+#define SYNTH_TYPE_MIDI 2 /* Midi interface */
+
+ int synth_subtype;
+#define FM_TYPE_ADLIB 0x00
+#define FM_TYPE_OPL3 0x01
+#define MIDI_TYPE_MPU401 0x401
+
+#define SAMPLE_TYPE_BASIC 0x10
+#define SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC
+#define SAMPLE_TYPE_WAVEFRONT 0x11
+
+ int perc_mode; /* No longer supported */
+ int nr_voices;
+ int nr_drums; /* Obsolete field */
+ int instr_bank_size;
+ unsigned int capabilities;
+#define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */
+#define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */
+#define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */
+ int dummies[19]; /* Reserve space */
+ };
+#define _IOT_synth_info _IOT (_IOTS (char), 30, _IOTS (int), 27, 0, 0)
+
+struct sound_timer_info {
+ char name[32];
+ int caps;
+ };
+
+#define MIDI_CAP_MPU401 1 /* MPU-401 intelligent mode */
+
+struct midi_info {
+ char name[30];
+ int device; /* 0-N. INITIALIZE BEFORE CALLING */
+ unsigned int capabilities; /* To be defined later */
+ int dev_type;
+ int dummies[18]; /* Reserve space */
+ };
+#define _IOT_midi_info _IOT (_IOTS (char), 30, _IOTS (int), 21, 0, 0)
+
+/********************************************
+ * ioctl commands for the /dev/midi##
+ */
+typedef struct {
+ unsigned char cmd;
+ char nr_args, nr_returns;
+ unsigned char data[30];
+ } mpu_command_rec;
+#define _IOT__IOTBASE_mpu_command_rec _IOT (_IOTS (char), 3, _IOTS (char), 30, 0, 0)
+
+#define SNDCTL_MIDI_PRETIME _SIOWR('m', 0, int)
+#define SNDCTL_MIDI_MPUMODE _SIOWR('m', 1, int)
+#define SNDCTL_MIDI_MPUCMD _SIOWR('m', 2, mpu_command_rec)
+
+/********************************************
+ * IOCTL commands for /dev/dsp and /dev/audio
+ */
+
+#define SNDCTL_DSP_RESET _SIO ('p', 0)
+#define SNDCTL_DSP_SYNC _SIO ('p', 1)
+#define SNDCTL_DSP_SPEED _SIOWR('p', 2, int)
+#define SNDCTL_DSP_STEREO _SIOWR('p', 3, int)
+#define SNDCTL_DSP_GETBLKSIZE _SIOWR('p', 4, int)
+#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT
+#define SNDCTL_DSP_CHANNELS _SIOWR('p', 6, int)
+#define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS
+#define SOUND_PCM_WRITE_FILTER _SIOWR('p', 7, int)
+#define SNDCTL_DSP_POST _SIO ('p', 8)
+#define SNDCTL_DSP_SUBDIVIDE _SIOWR('p', 9, int)
+#define SNDCTL_DSP_SETFRAGMENT _SIOWR('p',10, int)
+
+/* Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */
+#define SNDCTL_DSP_GETFMTS _SIOR ('p',11, int) /* Returns a mask */
+#define SNDCTL_DSP_SETFMT _SIOWR('p',5, int) /* Selects ONE fmt*/
+# define AFMT_QUERY 0x00000000 /* Return current fmt */
+# define AFMT_MU_LAW 0x00000001
+# define AFMT_A_LAW 0x00000002
+# define AFMT_IMA_ADPCM 0x00000004
+# define AFMT_U8 0x00000008
+# define AFMT_S16_LE 0x00000010 /* Little endian signed 16*/
+# define AFMT_S16_BE 0x00000020 /* Big endian signed 16 */
+# define AFMT_S8 0x00000040
+# define AFMT_U16_LE 0x00000080 /* Little endian U16 */
+# define AFMT_U16_BE 0x00000100 /* Big endian U16 */
+# define AFMT_MPEG 0x00000200 /* MPEG (2) audio */
+# define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */
+
+/*
+ * Buffer status queries.
+ */
+typedef struct audio_buf_info {
+ int fragments; /* # of available fragments (partially usend ones not counted) */
+ int fragstotal; /* Total # of fragments allocated */
+ int fragsize; /* Size of a fragment in bytes */
+
+ int bytes; /* Available space in bytes (includes partially used fragments) */
+ /* Note! 'bytes' could be more than fragments*fragsize */
+ } audio_buf_info;
+#define _IOT__IOTBASE_audio_buf_info _IOT (_IOTS (int), 4, 0, 0, 0, 0)
+
+#define SNDCTL_DSP_GETOSPACE _SIOR ('p',12, audio_buf_info)
+#define SNDCTL_DSP_GETISPACE _SIOR ('p',13, audio_buf_info)
+#define SNDCTL_DSP_NONBLOCK _SIO ('p',14)
+#define SNDCTL_DSP_GETCAPS _SIOR ('p',15, int)
+# define DSP_CAP_REVISION 0x000000ff /* Bits for revision level (0 to 255) */
+# define DSP_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */
+# define DSP_CAP_REALTIME 0x00000200 /* Real time capability */
+# define DSP_CAP_BATCH 0x00000400 /* Device has some kind of */
+ /* internal buffers which may */
+ /* cause some delays and */
+ /* decrease precision of timing */
+# define DSP_CAP_COPROC 0x00000800 /* Has a coprocessor */
+ /* Sometimes it's a DSP */
+ /* but usually not */
+# define DSP_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */
+# define DSP_CAP_MMAP 0x00002000 /* Supports mmap() */
+# define DSP_CAP_MULTI 0x00004000 /* support multiple open */
+# define DSP_CAP_BIND 0x00008000 /* channel binding to front/rear/cneter/lfe */
+
+
+#define SNDCTL_DSP_GETTRIGGER _SIOR ('p',16, int)
+#define SNDCTL_DSP_SETTRIGGER _SIOW ('p',16, int)
+# define PCM_ENABLE_INPUT 0x00000001
+# define PCM_ENABLE_OUTPUT 0x00000002
+
+typedef struct count_info {
+ int bytes; /* Total # of bytes processed */
+ int blocks; /* # of fragment transitions since last time */
+ int ptr; /* Current DMA pointer value */
+ } count_info;
+#define _IOT__IOTBASE_count_info _IOT (_IOTS (int), 3, 0, 0, 0, 0)
+
+#define SNDCTL_DSP_GETIPTR _SIOR ('p',17, count_info)
+#define SNDCTL_DSP_GETOPTR _SIOR ('p',18, count_info)
+
+typedef struct buffmem_desc {
+ unsigned *buffer;
+ int size;
+ } buffmem_desc;
+/* XXX */
+/* #define SNDCTL_DSP_MAPINBUF _SIOR ('p', 19, buffmem_desc) */
+/* #define SNDCTL_DSP_MAPOUTBUF _SIOR ('p', 20, buffmem_desc) */
+#define SNDCTL_DSP_SETSYNCRO _SIO ('p', 21)
+#define SNDCTL_DSP_SETDUPLEX _SIO ('p', 22)
+#define SNDCTL_DSP_GETODELAY _SIOR ('p', 23, int)
+
+#define SNDCTL_DSP_GETCHANNELMASK _SIOWR('p', 64, int)
+#define SNDCTL_DSP_BIND_CHANNEL _SIOWR('p', 65, int)
+# define DSP_BIND_QUERY 0x00000000
+# define DSP_BIND_FRONT 0x00000001
+# define DSP_BIND_SURR 0x00000002
+# define DSP_BIND_CENTER_LFE 0x00000004
+# define DSP_BIND_HANDSET 0x00000008
+# define DSP_BIND_MIC 0x00000010
+# define DSP_BIND_MODEM1 0x00000020
+# define DSP_BIND_MODEM2 0x00000040
+# define DSP_BIND_I2S 0x00000080
+# define DSP_BIND_SPDIF 0x00000100
+
+#define SNDCTL_DSP_SETSPDIF _SIOW ('p', 66, int)
+#define SNDCTL_DSP_GETSPDIF _SIOR ('p', 67, int)
+# define SPDIF_PRO 0x0001
+# define SPDIF_N_AUD 0x0002
+# define SPDIF_COPY 0x0004
+# define SPDIF_PRE 0x0008
+# define SPDIF_CC 0x07f0
+# define SPDIF_L 0x0800
+# define SPDIF_DRS 0x4000
+# define SPDIF_V 0x8000
+
+/*
+ * Application's profile defines the way how playback underrun situations should be handled.
+ *
+ * APF_NORMAL (the default) and APF_NETWORK make the driver to cleanup the
+ * playback buffer whenever an underrun occurs. This consumes some time
+ * prevents looping the existing buffer.
+ * APF_CPUINTENS is intended to be set by CPU intensive applications which
+ * are likely to run out of time occasionally. In this mode the buffer cleanup is
+ * disabled which saves CPU time but also let's the previous buffer content to
+ * be played during the "pause" after the underrun.
+ */
+#define SNDCTL_DSP_PROFILE _SIOW ('p', 23, int)
+#define APF_NORMAL 0 /* Normal applications */
+#define APF_NETWORK 1 /* Underruns probably caused by an "external" delay */
+#define APF_CPUINTENS 2 /* Underruns probably caused by "overheating" the CPU */
+
+#define SOUND_PCM_READ_RATE _SIOR ('p', 2, int)
+#define SOUND_PCM_READ_CHANNELS _SIOR ('p', 6, int)
+#define SOUND_PCM_READ_BITS _SIOR ('p', 5, int)
+#define SOUND_PCM_READ_FILTER _SIOR ('p', 7, int)
+
+/* Some alias names */
+#define SOUND_PCM_WRITE_BITS SNDCTL_DSP_SETFMT
+#define SOUND_PCM_WRITE_RATE SNDCTL_DSP_SPEED
+#define SOUND_PCM_POST SNDCTL_DSP_POST
+#define SOUND_PCM_RESET SNDCTL_DSP_RESET
+#define SOUND_PCM_SYNC SNDCTL_DSP_SYNC
+#define SOUND_PCM_SUBDIVIDE SNDCTL_DSP_SUBDIVIDE
+#define SOUND_PCM_SETFRAGMENT SNDCTL_DSP_SETFRAGMENT
+#define SOUND_PCM_GETFMTS SNDCTL_DSP_GETFMTS
+#define SOUND_PCM_SETFMT SNDCTL_DSP_SETFMT
+#define SOUND_PCM_GETOSPACE SNDCTL_DSP_GETOSPACE
+#define SOUND_PCM_GETISPACE SNDCTL_DSP_GETISPACE
+#define SOUND_PCM_NONBLOCK SNDCTL_DSP_NONBLOCK
+#define SOUND_PCM_GETCAPS SNDCTL_DSP_GETCAPS
+#define SOUND_PCM_GETTRIGGER SNDCTL_DSP_GETTRIGGER
+#define SOUND_PCM_SETTRIGGER SNDCTL_DSP_SETTRIGGER
+#define SOUND_PCM_SETSYNCRO SNDCTL_DSP_SETSYNCRO
+#define SOUND_PCM_GETIPTR SNDCTL_DSP_GETIPTR
+#define SOUND_PCM_GETOPTR SNDCTL_DSP_GETOPTR
+#define SOUND_PCM_MAPINBUF SNDCTL_DSP_MAPINBUF
+#define SOUND_PCM_MAPOUTBUF SNDCTL_DSP_MAPOUTBUF
+
+/*
+ * ioctl calls to be used in communication with coprocessors and
+ * DSP chips.
+ */
+
+typedef struct copr_buffer {
+ int command; /* Set to 0 if not used */
+ int flags;
+#define CPF_NONE 0x0000
+#define CPF_FIRST 0x0001 /* First block */
+#define CPF_LAST 0x0002 /* Last block */
+ int len;
+ int offs; /* If required by the device (0 if not used) */
+
+ unsigned char data[4000]; /* NOTE! 4000 is not 4k */
+ } copr_buffer;
+/* XXX */
+#define _IOT__IOTBASE_copr_buffer _IOT (_IOTS (int), 4, _IOTS (char), 31, _IOTS (char), 3)
+
+typedef struct copr_debug_buf {
+ int command; /* Used internally. Set to 0 */
+ int parm1;
+ int parm2;
+ int flags;
+ int len; /* Length of data in bytes */
+ } copr_debug_buf;
+#define _IOT__IOTBASE_copr_debug_buf _IOT (_IOTS (int), 5, 0, 0, 0, 0)
+
+typedef struct copr_msg {
+ int len;
+ unsigned char data[4000];
+ } copr_msg;
+/* XXX */
+#define _IOT__IOTBASE_copr_msg _IOT (_IOTS (int), 1, _IOTS (char), 31, _IOTS (char), 3)
+
+#define SNDCTL_COPR_RESET _SIO ('o', 0)
+#define SNDCTL_COPR_LOAD _SIOWR('o', 1, copr_buffer)
+#define SNDCTL_COPR_RDATA _SIOWR('o', 2, copr_debug_buf)
+#define SNDCTL_COPR_RCODE _SIOWR('o', 3, copr_debug_buf)
+#define SNDCTL_COPR_WDATA _SIOW ('o', 4, copr_debug_buf)
+#define SNDCTL_COPR_WCODE _SIOW ('o', 5, copr_debug_buf)
+#define SNDCTL_COPR_RUN _SIOWR('o', 6, copr_debug_buf)
+#define SNDCTL_COPR_HALT _SIOWR('o', 7, copr_debug_buf)
+#define SNDCTL_COPR_SENDMSG _SIOWR('o', 8, copr_msg)
+#define SNDCTL_COPR_RCVMSG _SIOR ('o', 9, copr_msg)
+
+/*********************************************
+ * IOCTL commands for /dev/mixer
+ */
+
+/*
+ * Mixer devices
+ *
+ * There can be up to 20 different analog mixer channels. The
+ * SOUND_MIXER_NRDEVICES gives the currently supported maximum.
+ * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells
+ * the devices supported by the particular mixer.
+ */
+
+#define SOUND_MIXER_NRDEVICES 25
+#define SOUND_MIXER_VOLUME 0
+#define SOUND_MIXER_BASS 1
+#define SOUND_MIXER_TREBLE 2
+#define SOUND_MIXER_SYNTH 3
+#define SOUND_MIXER_PCM 4
+#define SOUND_MIXER_SPEAKER 5
+#define SOUND_MIXER_LINE 6
+#define SOUND_MIXER_MIC 7
+#define SOUND_MIXER_CD 8
+#define SOUND_MIXER_IMIX 9 /* Recording monitor */
+#define SOUND_MIXER_ALTPCM 10
+#define SOUND_MIXER_RECLEV 11 /* Recording level */
+#define SOUND_MIXER_IGAIN 12 /* Input gain */
+#define SOUND_MIXER_OGAIN 13 /* Output gain */
+/*
+ * The AD1848 codec and compatibles have three line level inputs
+ * (line, aux1 and aux2). Since each card manufacturer have assigned
+ * different meanings to these inputs, it's inpractical to assign
+ * specific meanings (line, cd, synth etc.) to them.
+ */
+#define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */
+#define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */
+#define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */
+#define SOUND_MIXER_DIGITAL1 17 /* Digital (input) 1 */
+#define SOUND_MIXER_DIGITAL2 18 /* Digital (input) 2 */
+#define SOUND_MIXER_DIGITAL3 19 /* Digital (input) 3 */
+#define SOUND_MIXER_PHONEIN 20 /* Phone input */
+#define SOUND_MIXER_PHONEOUT 21 /* Phone output */
+#define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */
+#define SOUND_MIXER_RADIO 23 /* Radio in */
+#define SOUND_MIXER_MONITOR 24 /* Monitor (usually mic) volume */
+
+/* Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX) */
+/* Not counted to SOUND_MIXER_NRDEVICES, but use the same number space */
+#define SOUND_ONOFF_MIN 28
+#define SOUND_ONOFF_MAX 30
+
+/* Note! Number 31 cannot be used since the sign bit is reserved */
+#define SOUND_MIXER_NONE 31
+
+/*
+ * The following unsupported macros are no longer functional.
+ * Use SOUND_MIXER_PRIVATE# macros in future.
+ */
+#define SOUND_MIXER_ENHANCE SOUND_MIXER_NONE
+#define SOUND_MIXER_MUTE SOUND_MIXER_NONE
+#define SOUND_MIXER_LOUD SOUND_MIXER_NONE
+
+
+#define SOUND_DEVICE_LABELS {"Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", \
+ "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \
+ "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", \
+ "PhoneIn", "PhoneOut", "Video", "Radio", "Monitor"}
+
+#define SOUND_DEVICE_NAMES {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", \
+ "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \
+ "line1", "line2", "line3", "dig1", "dig2", "dig3", \
+ "phin", "phout", "video", "radio", "monitor"}
+
+/* Device bitmask identifiers */
+
+#define SOUND_MIXER_RECSRC 0xff /* Arg contains a bit for each recording source */
+#define SOUND_MIXER_DEVMASK 0xfe /* Arg contains a bit for each supported device */
+#define SOUND_MIXER_RECMASK 0xfd /* Arg contains a bit for each supported recording source */
+#define SOUND_MIXER_CAPS 0xfc
+# define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only one recording source at a time */
+#define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */
+#define SOUND_MIXER_OUTSRC 0xfa /* Arg contains a bit for each input source to output */
+#define SOUND_MIXER_OUTMASK 0xf9 /* Arg contains a bit for each supported input source to output */
+
+/* Device mask bits */
+
+#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME)
+#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS)
+#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE)
+#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH)
+#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM)
+#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER)
+#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE)
+#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC)
+#define SOUND_MASK_CD (1 << SOUND_MIXER_CD)
+#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX)
+#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM)
+#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV)
+#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN)
+#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN)
+#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1)
+#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2)
+#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3)
+#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1)
+#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2)
+#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3)
+#define SOUND_MASK_PHONEIN (1 << SOUND_MIXER_PHONEIN)
+#define SOUND_MASK_PHONEOUT (1 << SOUND_MIXER_PHONEOUT)
+#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO)
+#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO)
+#define SOUND_MASK_MONITOR (1 << SOUND_MIXER_MONITOR)
+
+/* Obsolete macros */
+#define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE)
+#define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE)
+#define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD)
+
+#define MIXER_READ(dev) _SIOR('r', dev, int)
+#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME)
+#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS)
+#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE)
+#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH)
+#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM)
+#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER)
+#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE)
+#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC)
+#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD)
+#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX)
+#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM)
+#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV)
+#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN)
+#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN)
+#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1)
+#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2)
+#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3)
+
+/* Obsolete macros */
+#define SOUND_MIXER_READ_MUTE MIXER_READ(SOUND_MIXER_MUTE)
+#define SOUND_MIXER_READ_ENHANCE MIXER_READ(SOUND_MIXER_ENHANCE)
+#define SOUND_MIXER_READ_LOUD MIXER_READ(SOUND_MIXER_LOUD)
+
+#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC)
+#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK)
+#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK)
+#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS)
+#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS)
+
+#define MIXER_WRITE(dev) _SIOWR('r', dev, int)
+#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME)
+#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS)
+#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE)
+#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH)
+#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM)
+#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER)
+#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE)
+#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC)
+#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD)
+#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX)
+#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM)
+#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV)
+#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN)
+#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN)
+#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1)
+#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2)
+#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3)
+
+/* Obsolete macros */
+#define SOUND_MIXER_WRITE_MUTE MIXER_WRITE(SOUND_MIXER_MUTE)
+#define SOUND_MIXER_WRITE_ENHANCE MIXER_WRITE(SOUND_MIXER_ENHANCE)
+#define SOUND_MIXER_WRITE_LOUD MIXER_WRITE(SOUND_MIXER_LOUD)
+
+#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC)
+
+typedef struct mixer_info
+{
+ char id[16];
+/* XXX */
+ char name[15];
+ int modify_counter;
+ int fillers[10];
+} mixer_info;
+#define _IOT__IOTBASE_mixer_info _IOT (_IOTS (char), 31, _IOTS (int), 11, 0, 0)
+
+typedef struct _old_mixer_info /* Obsolete */
+{
+ char id[16];
+ char name[32];
+} _old_mixer_info;
+#define _IOT__IOTBASE__old_mixer_info _IOT (_IOTS (char), 17, _IOTS (char), 31, 0, 0)
+
+#define SOUND_MIXER_INFO _SIOR ('r', 101, mixer_info)
+#define SOUND_OLD_MIXER_INFO _SIOR ('r', 101, _old_mixer_info)
+
+/*
+ * A mechanism for accessing "proprietary" mixer features. This method
+ * permits passing 128 bytes of arbitrary data between a mixer application
+ * and the mixer driver. Interpretation of the record is defined by
+ * the particular mixer driver.
+ */
+typedef unsigned char mixer_record[128];
+/* XXX */
+#define _IOT__IOTBASE_mixer_record _IOT (_IOTS (char), 31, _IOTS (char), 31, _IOTS (char), 3)
+
+#define SOUND_MIXER_ACCESS _SIOWR('r', 102, mixer_record)
+
+/*
+ * Two ioctls for special souncard function
+ */
+#define SOUND_MIXER_AGC _SIOWR('r', 103, int)
+#define SOUND_MIXER_3DSE _SIOWR('r', 104, int)
+
+/*
+ * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers.
+ * These features can be used when accessing device specific features.
+ */
+#define SOUND_MIXER_PRIVATE1 _SIOWR('r', 111, int)
+#define SOUND_MIXER_PRIVATE2 _SIOWR('r', 112, int)
+#define SOUND_MIXER_PRIVATE3 _SIOWR('r', 113, int)
+#define SOUND_MIXER_PRIVATE4 _SIOWR('r', 114, int)
+#define SOUND_MIXER_PRIVATE5 _SIOWR('r', 115, int)
+
+/*
+ * SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used
+ * for querying current mixer settings from the driver and for loading
+ * default volume settings _prior_ activating the mixer (loading
+ * doesn't affect current state of the mixer hardware). These calls
+ * are for internal use only.
+ */
+
+typedef struct mixer_vol_table {
+ char name[31];
+ int num; /* Index to volume table */
+ int levels[32];
+} mixer_vol_table;
+#define _IOT__IOTBASE_mixer_vol_table _IOT (_IOTS (char), 31, _IOTS (int), 31, _IOTS (int), 2)
+
+#define SOUND_MIXER_GETLEVELS _SIOWR('r', 116, mixer_vol_table)
+#define SOUND_MIXER_SETLEVELS _SIOWR('r', 117, mixer_vol_table)
+
+/*
+ * An ioctl for identifying the driver version. It will return value
+ * of the SOUND_VERSION macro used when compiling the driver.
+ * This call was introduced in OSS version 3.6 and it will not work
+ * with earlier versions (returns EINVAL).
+ */
+#define OSS_GETVERSION _SIOR ('r', 118, int)
+
+/*
+ * Level 2 event types for /dev/sequencer
+ */
+
+/*
+ * The 4 most significant bits of byte 0 specify the class of
+ * the event:
+ *
+ * 0x8X = system level events,
+ * 0x9X = device/port specific events, event[1] = device/port,
+ * The last 4 bits give the subtype:
+ * 0x02 = Channel event (event[3] = chn).
+ * 0x01 = note event (event[4] = note).
+ * (0x01 is not used alone but always with bit 0x02).
+ * event[2] = MIDI message code (0x80=note off etc.)
+ *
+ */
+
+#define EV_SEQ_LOCAL 0x80
+#define EV_TIMING 0x81
+#define EV_CHN_COMMON 0x92
+#define EV_CHN_VOICE 0x93
+#define EV_SYSEX 0x94
+/*
+ * Event types 200 to 220 are reserved for application use.
+ * These numbers will not be used by the driver.
+ */
+
+/*
+ * Events for event type EV_CHN_VOICE
+ */
+
+#define MIDI_NOTEOFF 0x80
+#define MIDI_NOTEON 0x90
+#define MIDI_KEY_PRESSURE 0xA0
+
+/*
+ * Events for event type EV_CHN_COMMON
+ */
+
+#define MIDI_CTL_CHANGE 0xB0
+#define MIDI_PGM_CHANGE 0xC0
+#define MIDI_CHN_PRESSURE 0xD0
+#define MIDI_PITCH_BEND 0xE0
+
+#define MIDI_SYSTEM_PREFIX 0xF0
+
+/*
+ * Timer event types
+ */
+#define TMR_WAIT_REL 1 /* Time relative to the prev time */
+#define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */
+#define TMR_STOP 3
+#define TMR_START 4
+#define TMR_CONTINUE 5
+#define TMR_TEMPO 6
+#define TMR_ECHO 8
+#define TMR_CLOCK 9 /* MIDI clock */
+#define TMR_SPP 10 /* Song position pointer */
+#define TMR_TIMESIG 11 /* Time signature */
+
+/*
+ * Local event types
+ */
+#define LOCL_STARTAUDIO 1
+
+#if (!defined(__KERNEL__) && !defined(KERNEL) && !defined(INKERNEL) && !defined(_KERNEL)) || defined(USE_SEQ_MACROS)
+/*
+ * Some convenience macros to simplify programming of the
+ * /dev/sequencer interface
+ *
+ * These macros define the API which should be used when possible.
+ */
+#define SEQ_DECLAREBUF() SEQ_USE_EXTBUF()
+
+void seqbuf_dump(void); /* This function must be provided by programs */
+
+extern int OSS_init(int seqfd, int buflen);
+extern void OSS_seqbuf_dump(int fd, unsigned char *buf, int buflen);
+extern void OSS_seq_advbuf(int len, int fd, unsigned char *buf, int buflen);
+extern void OSS_seq_needbuf(int len, int fd, unsigned char *buf, int buflen);
+extern void OSS_patch_caching(int dev, int chn, int patch,
+ int fd, unsigned char *buf, int buflen);
+extern void OSS_drum_caching(int dev, int chn, int patch,
+ int fd, unsigned char *buf, int buflen);
+extern void OSS_write_patch(int fd, unsigned char *buf, int len);
+extern int OSS_write_patch2(int fd, unsigned char *buf, int len);
+
+#define SEQ_PM_DEFINES int __foo_bar___
+#ifdef OSSLIB
+# define SEQ_USE_EXTBUF() \
+ extern unsigned char *_seqbuf; \
+ extern int _seqbuflen;extern int _seqbufptr
+# define SEQ_DEFINEBUF(len) SEQ_USE_EXTBUF();static int _requested_seqbuflen=len
+# define _SEQ_ADVBUF(len) OSS_seq_advbuf(len, seqfd, _seqbuf, _seqbuflen)
+# define _SEQ_NEEDBUF(len) OSS_seq_needbuf(len, seqfd, _seqbuf, _seqbuflen)
+# define SEQ_DUMPBUF() OSS_seqbuf_dump(seqfd, _seqbuf, _seqbuflen)
+
+# define SEQ_LOAD_GMINSTR(dev, instr) \
+ OSS_patch_caching(dev, -1, instr, seqfd, _seqbuf, _seqbuflen)
+# define SEQ_LOAD_GMDRUM(dev, drum) \
+ OSS_drum_caching(dev, -1, drum, seqfd, _seqbuf, _seqbuflen)
+#else /* !OSSLIB */
+
+# define SEQ_LOAD_GMINSTR(dev, instr)
+# define SEQ_LOAD_GMDRUM(dev, drum)
+
+# define SEQ_USE_EXTBUF() \
+ extern unsigned char _seqbuf[]; \
+ extern int _seqbuflen;extern int _seqbufptr
+
+#ifndef USE_SIMPLE_MACROS
+/* Sample seqbuf_dump() implementation:
+ *
+ * SEQ_DEFINEBUF (2048); -- Defines a buffer for 2048 bytes
+ *
+ * int seqfd; -- The file descriptor for /dev/sequencer.
+ *
+ * void
+ * seqbuf_dump ()
+ * {
+ * if (_seqbufptr)
+ * if (write (seqfd, _seqbuf, _seqbufptr) == -1)
+ * {
+ * perror ("write /dev/sequencer");
+ * exit (-1);
+ * }
+ * _seqbufptr = 0;
+ * }
+ */
+
+#define SEQ_DEFINEBUF(len) unsigned char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0
+#define _SEQ_NEEDBUF(len) if ((_seqbufptr+(len)) > _seqbuflen) seqbuf_dump()
+#define _SEQ_ADVBUF(len) _seqbufptr += len
+#define SEQ_DUMPBUF seqbuf_dump
+#else
+/*
+ * This variation of the sequencer macros is used just to format one event
+ * using fixed buffer.
+ *
+ * The program using the macro library must define the following macros before
+ * using this library.
+ *
+ * #define _seqbuf name of the buffer (unsigned char[])
+ * #define _SEQ_ADVBUF(len) If the applic needs to know the exact
+ * size of the event, this macro can be used.
+ * Otherwise this must be defined as empty.
+ * #define _seqbufptr Define the name of index variable or 0 if
+ * not required.
+ */
+#define _SEQ_NEEDBUF(len) /* empty */
+#endif
+#endif /* !OSSLIB */
+
+#define SEQ_VOLUME_MODE(dev, mode) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\
+ _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\
+ _seqbuf[_seqbufptr+2] = (dev);\
+ _seqbuf[_seqbufptr+3] = (mode);\
+ _seqbuf[_seqbufptr+4] = 0;\
+ _seqbuf[_seqbufptr+5] = 0;\
+ _seqbuf[_seqbufptr+6] = 0;\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+
+/*
+ * Midi voice messages
+ */
+
+#define _CHN_VOICE(dev, event, chn, note, parm) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_CHN_VOICE;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ _seqbuf[_seqbufptr+2] = (event);\
+ _seqbuf[_seqbufptr+3] = (chn);\
+ _seqbuf[_seqbufptr+4] = (note);\
+ _seqbuf[_seqbufptr+5] = (parm);\
+ _seqbuf[_seqbufptr+6] = (0);\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_START_NOTE(dev, chn, note, vol) \
+ _CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol)
+
+#define SEQ_STOP_NOTE(dev, chn, note, vol) \
+ _CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol)
+
+#define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \
+ _CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure)
+
+/*
+ * Midi channel messages
+ */
+
+#define _CHN_COMMON(dev, event, chn, p1, p2, w14) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_CHN_COMMON;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ _seqbuf[_seqbufptr+2] = (event);\
+ _seqbuf[_seqbufptr+3] = (chn);\
+ _seqbuf[_seqbufptr+4] = (p1);\
+ _seqbuf[_seqbufptr+5] = (p2);\
+ *(short *)&_seqbuf[_seqbufptr+6] = (w14);\
+ _SEQ_ADVBUF(8);}
+/*
+ * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits
+ * sending any MIDI bytes but it's absolutely not possible. Trying to do
+ * so _will_ cause problems with MPU401 intelligent mode).
+ *
+ * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be
+ * sent by calling SEQ_SYSEX() several times (there must be no other events
+ * between them). First sysex fragment must have 0xf0 in the first byte
+ * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte
+ * between these sysex start and end markers cannot be larger than 0x7f. Also
+ * lengths of each fragments (except the last one) must be 6.
+ *
+ * Breaking the above rules may work with some MIDI ports but is likely to
+ * cause fatal problems with some other devices (such as MPU401).
+ */
+#define SEQ_SYSEX(dev, buf, len) \
+ {int ii, ll=(len); \
+ unsigned char *bufp=buf;\
+ if (ll>6)ll=6;\
+ _SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_SYSEX;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ for(ii=0;ii<ll;ii++)\
+ _seqbuf[_seqbufptr+ii+2] = bufp[ii];\
+ for(ii=ll;ii<6;ii++)\
+ _seqbuf[_seqbufptr+ii+2] = 0xff;\
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_CHN_PRESSURE(dev, chn, pressure) \
+ _CHN_COMMON(dev, MIDI_CHN_PRESSURE, chn, pressure, 0, 0)
+
+#define SEQ_SET_PATCH SEQ_PGM_CHANGE
+#ifdef OSSLIB
+# define SEQ_PGM_CHANGE(dev, chn, patch) \
+ {OSS_patch_caching(dev, chn, patch, seqfd, _seqbuf, _seqbuflen); \
+ _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0);}
+#else
+# define SEQ_PGM_CHANGE(dev, chn, patch) \
+ _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0)
+#endif
+
+#define SEQ_CONTROL(dev, chn, controller, value) \
+ _CHN_COMMON(dev, MIDI_CTL_CHANGE, chn, controller, 0, value)
+
+#define SEQ_BENDER(dev, chn, value) \
+ _CHN_COMMON(dev, MIDI_PITCH_BEND, chn, 0, 0, value)
+
+
+#define SEQ_V2_X_CONTROL(dev, voice, controller, value) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\
+ _seqbuf[_seqbufptr+1] = SEQ_CONTROLLER;\
+ _seqbuf[_seqbufptr+2] = (dev);\
+ _seqbuf[_seqbufptr+3] = (voice);\
+ _seqbuf[_seqbufptr+4] = (controller);\
+ _seqbuf[_seqbufptr+5] = ((value)&0xff);\
+ _seqbuf[_seqbufptr+6] = ((value>>8)&0xff);\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+/*
+ * The following 5 macros are incorrectly implemented and obsolete.
+ * Use SEQ_BENDER and SEQ_CONTROL (with proper controller) instead.
+ */
+#define SEQ_PITCHBEND(dev, voice, value) SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER, value)
+#define SEQ_BENDER_RANGE(dev, voice, value) SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER_RANGE, value)
+#define SEQ_EXPRESSION(dev, voice, value) SEQ_CONTROL(dev, voice, CTL_EXPRESSION, value*128)
+#define SEQ_MAIN_VOLUME(dev, voice, value) SEQ_CONTROL(dev, voice, CTL_MAIN_VOLUME, (value*16383)/100)
+#define SEQ_PANNING(dev, voice, pos) SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2)
+
+/*
+ * Timing and syncronization macros
+ */
+
+#define _TIMER_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr+0] = EV_TIMING; \
+ _seqbuf[_seqbufptr+1] = (ev); \
+ _seqbuf[_seqbufptr+2] = 0;\
+ _seqbuf[_seqbufptr+3] = 0;\
+ *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_START_TIMER() _TIMER_EVENT(TMR_START, 0)
+#define SEQ_STOP_TIMER() _TIMER_EVENT(TMR_STOP, 0)
+#define SEQ_CONTINUE_TIMER() _TIMER_EVENT(TMR_CONTINUE, 0)
+#define SEQ_WAIT_TIME(ticks) _TIMER_EVENT(TMR_WAIT_ABS, ticks)
+#define SEQ_DELTA_TIME(ticks) _TIMER_EVENT(TMR_WAIT_REL, ticks)
+#define SEQ_ECHO_BACK(key) _TIMER_EVENT(TMR_ECHO, key)
+#define SEQ_SET_TEMPO(value) _TIMER_EVENT(TMR_TEMPO, value)
+#define SEQ_SONGPOS(pos) _TIMER_EVENT(TMR_SPP, pos)
+#define SEQ_TIME_SIGNATURE(sig) _TIMER_EVENT(TMR_TIMESIG, sig)
+
+/*
+ * Local control events
+ */
+
+#define _LOCAL_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr+0] = EV_SEQ_LOCAL; \
+ _seqbuf[_seqbufptr+1] = (ev); \
+ _seqbuf[_seqbufptr+2] = 0;\
+ _seqbuf[_seqbufptr+3] = 0;\
+ *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_PLAYAUDIO(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO, devmask)
+/*
+ * Events for the level 1 interface only
+ */
+
+#define SEQ_MIDIOUT(device, byte) {_SEQ_NEEDBUF(4);\
+ _seqbuf[_seqbufptr] = SEQ_MIDIPUTC;\
+ _seqbuf[_seqbufptr+1] = (byte);\
+ _seqbuf[_seqbufptr+2] = (device);\
+ _seqbuf[_seqbufptr+3] = 0;\
+ _SEQ_ADVBUF(4);}
+
+/*
+ * Patch loading.
+ */
+#ifdef OSSLIB
+# define SEQ_WRPATCH(patchx, len) \
+ OSS_write_patch(seqfd, (char*)(patchx), len)
+# define SEQ_WRPATCH2(patchx, len) \
+ OSS_write_patch2(seqfd, (char*)(patchx), len)
+#else
+# define SEQ_WRPATCH(patchx, len) \
+ {if (_seqbufptr) SEQ_DUMPBUF();\
+ if (write(seqfd, (char*)(patchx), len)==-1) \
+ perror("Write patch: /dev/sequencer");}
+# define SEQ_WRPATCH2(patchx, len) \
+ (SEQ_DUMPBUF(), write(seqfd, (char*)(patchx), len))
+#endif
+
+#endif
+#endif /* sys/soundcard.h */
diff --git a/debian/make-new-orig.sh b/debian/make-new-orig.sh
new file mode 100755
index 00000000..8f427623
--- /dev/null
+++ b/debian/make-new-orig.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+if [ -z $1 ]; then
+ echo "Please provide the directory to tar up as an argument"
+ exit 1
+fi
+
+TARBALL=$(echo $1 | tr - _).orig.tar.gz
+
+tar -czvf $TARBALL --exclude=debian $1
+
diff --git a/debian/make-new-tarball.sh b/debian/make-new-tarball.sh
new file mode 100755
index 00000000..5af64b97
--- /dev/null
+++ b/debian/make-new-tarball.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+if [ -z $1 ]; then
+ echo "Please provide the directory to tar up as an argument"
+ exit 1
+fi
+
+BASENAME=$(basename $1)
+DIRNAME=$(dirname $1)
+
+tar -czvf hurd.tgz \
+ --exclude=.git --exclude=.gitignore --exclude=debian \
+ -C $DIRNAME $BASENAME
+
diff --git a/debian/patches/console_ignore_bdf_err.patch b/debian/patches/console_ignore_bdf_err.patch
new file mode 100644
index 00000000..c3ea30cb
--- /dev/null
+++ b/debian/patches/console_ignore_bdf_err.patch
@@ -0,0 +1,17 @@
+reduce-font overestimates the number of characters in the font.
+
+diff --git a/console-client/bdf.c b/console-client/bdf.c
+index 30501f4..ee8aa30 100644
+--- a/console-client/bdf.c
++++ b/console-client/bdf.c
+@@ -415,8 +415,10 @@ bdf_read (FILE *filep, bdf_font_t *font, int *linecount)
+ glyphs. */
+ if (!strcmp (line, "ENDFONT"))
+ {
++ /*
+ if (parser.glyphs != bdf->glyphs_count)
+ err = BDF_COUNT_MISMATCH;
++ */
+ done = 1;
+ }
+ else
diff --git a/debian/patches/console_utf-8.patch b/debian/patches/console_utf-8.patch
new file mode 100644
index 00000000..663e21bd
--- /dev/null
+++ b/debian/patches/console_utf-8.patch
@@ -0,0 +1,19 @@
+2006-08-26 Michael Banck <mbanck@debian.org>
+
+ * console.c (DEFAULT_ENCODING): Set to UTF-8.
+
+---
+ console/console.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/console/console.c
++++ b/console/console.c
+@@ -58,7 +58,7 @@ int netfs_maxsymlinks = 16; /* Arbitrary
+ /* Handy source of time. */
+ volatile struct mapped_time_value *console_maptime;
+
+-#define DEFAULT_ENCODING "ISO-8859-1"
++#define DEFAULT_ENCODING "UTF-8"
+ #define DEFAULT_INTENSITY CONS_ATTR_INTENSITY_NORMAL
+ #define DEFAULT_UNDERLINED 0
+ #define DEFAULT_BLINKING 0
diff --git a/debian/patches/diskfs_no_inherit_dir_group.patch b/debian/patches/diskfs_no_inherit_dir_group.patch
new file mode 100644
index 00000000..8d17f3e0
--- /dev/null
+++ b/debian/patches/diskfs_no_inherit_dir_group.patch
@@ -0,0 +1,29 @@
+Follow POSIX rules for gid of new nodes.
+---
+ opts-common.c | 2 +-
+ libdiskfs/init-init.c | 3 +++
+ 2 file changed, 4 insertion(+), 1 deletion(-)
+
+--- a/libdiskfs/init-init.c
++++ b/libdiskfs/init-init.c
+@@ -57,6 +57,9 @@ diskfs_init_diskfs (void)
+ {
+ error_t err;
+
++ /* See `node-create.c'. */
++ _diskfs_no_inherit_dir_group = 1;
++
+ if (diskfs_boot_filesystem ())
+ /* This is a boot filesystem, we have to do some things specially. */
+ {
+--- a/libdiskfs/opts-common.c
++++ b/libdiskfs/opts-common.c
+@@ -52,7 +52,7 @@ const struct argp_option diskfs_common_options[] =
+ {"nogrpid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"sysvgroups", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"inherit-dir-group", OPT_INHERIT_DIR_GROUP, 0, 0,
+- "Create new nodes with gid of parent dir (default)"},
++ "Create new nodes with gid of parent dir"},
+ {"grpid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"bsdgroups", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {0, 0}
diff --git a/debian/patches/ext2fs_large_stores.patch b/debian/patches/ext2fs_large_stores.patch
new file mode 100644
index 00000000..0855f760
--- /dev/null
+++ b/debian/patches/ext2fs_large_stores.patch
@@ -0,0 +1,2223 @@
+Support for >2GB volumes
+---
+ console/pager.c | 10
+ ext2fs/balloc.c | 57 +++--
+ ext2fs/ext2_fs.h | 3
+ ext2fs/ext2fs.c | 8
+ ext2fs/ext2fs.h | 145 +++++++++++--
+ ext2fs/getblk.c | 31 +-
+ ext2fs/hyper.c | 34 ++-
+ ext2fs/ialloc.c | 41 +++
+ ext2fs/inode.c | 58 +++--
+ ext2fs/pager.c | 497 +++++++++++++++++++++++++++++++++++++++++++----
+ ext2fs/pokel.c | 41 +++
+ ext2fs/truncate.c | 11 -
+ fatfs/pager.c | 11 -
+ isofs/pager.c | 12 -
+ libdiskfs/disk-pager.c | 6
+ libdiskfs/diskfs-pager.h | 3
+ libpager/data-request.c | 17 -
+ libpager/data-return.c | 78 +++++--
+ libpager/pager-create.c | 4
+ libpager/pager.h | 29 ++
+ libpager/priv.h | 1
+ storeio/pager.c | 9
+ tmpfs/pager-stubs.c | 8
+ ufs/pager.c | 11 -
+ 24 files changed, 940 insertions(+), 185 deletions(-)
+
+--- a/console/pager.c
++++ b/console/pager.c
+@@ -94,6 +94,14 @@ pager_unlock_page (struct user_pager_inf
+ }
+
+
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page)
++{
++ assert (!"unrequested notification on eviction");
++}
++
++
+ /* Tell how big the file is. */
+ error_t
+ pager_report_extent (struct user_pager_info *upi,
+@@ -159,7 +167,7 @@ user_pager_create (struct user_pager *us
+
+ /* XXX Are the values 1 and MEMORY_OBJECT_COPY_DELAY correct? */
+ user_pager->pager = pager_create (upi, pager_bucket,
+- 1, MEMORY_OBJECT_COPY_DELAY);
++ 1, MEMORY_OBJECT_COPY_DELAY, 0);
+ if (!user_pager->pager)
+ {
+ free (upi);
+--- a/ext2fs/balloc.c
++++ b/ext2fs/balloc.c
+@@ -92,7 +92,7 @@ ext2_free_blocks (block_t block, unsigne
+ block, count);
+ }
+ gdp = group_desc (block_group);
+- bh = bptr (gdp->bg_block_bitmap);
++ bh = disk_cache_block_ref (gdp->bg_block_bitmap);
+
+ if (in_range (gdp->bg_block_bitmap, block, gcount) ||
+ in_range (gdp->bg_inode_bitmap, block, gcount) ||
+@@ -114,6 +114,7 @@ ext2_free_blocks (block_t block, unsigne
+ }
+
+ record_global_poke (bh);
++ disk_cache_block_ref_ptr (gdp);
+ record_global_poke (gdp);
+
+ block += gcount;
+@@ -139,7 +140,7 @@ ext2_new_block (block_t goal,
+ block_t prealloc_goal,
+ block_t *prealloc_count, block_t *prealloc_block)
+ {
+- char *bh;
++ char *bh = 0;
+ char *p, *r;
+ int i, j, k, tmp;
+ unsigned long lmap;
+@@ -164,9 +165,10 @@ ext2_new_block (block_t goal,
+
+ ext2_debug ("goal=%u", goal);
+
+-repeat:
++ repeat:
++ assert (! bh);
+ /*
+- * First, test whether the goal block is free.
++ * First, test whether the goal block is free.
+ */
+ if (goal < sblock->s_first_data_block || goal >= sblock->s_blocks_count)
+ goal = sblock->s_first_data_block;
+@@ -179,7 +181,7 @@ repeat:
+ if (j)
+ goal_attempts++;
+ #endif
+- bh = bptr (gdp->bg_block_bitmap);
++ bh = disk_cache_block_ref (gdp->bg_block_bitmap);
+
+ ext2_debug ("goal is at %d:%d", i, j);
+
+@@ -194,8 +196,8 @@ repeat:
+ if (j)
+ {
+ /*
+- * The goal was occupied; search forward for a free
+- * block within the next 32 blocks
++ * The goal was occupied; search forward for a free
++ * block within the next 32 blocks
+ */
+ lmap = ((((unsigned long *) bh)[j >> 5]) >>
+ ((j & 31) + 1));
+@@ -242,13 +244,16 @@ repeat:
+ j = k;
+ goto got_block;
+ }
++
++ disk_cache_block_deref (bh);
++ bh = 0;
+ }
+
+ ext2_debug ("bit not found in block group %d", i);
+
+ /*
+- * Now search the rest of the groups. We assume that
+- * i and gdp correctly point to the last group visited.
++ * Now search the rest of the groups. We assume that
++ * i and gdp correctly point to the last group visited.
+ */
+ for (k = 0; k < groups_count; k++)
+ {
+@@ -264,7 +269,8 @@ repeat:
+ spin_unlock (&global_lock);
+ return 0;
+ }
+- bh = bptr (gdp->bg_block_bitmap);
++ assert (! bh);
++ bh = disk_cache_block_ref (gdp->bg_block_bitmap);
+ r = memscan (bh, 0, sblock->s_blocks_per_group >> 3);
+ j = (r - bh) << 3;
+ if (j < sblock->s_blocks_per_group)
+@@ -274,21 +280,25 @@ repeat:
+ sblock->s_blocks_per_group);
+ if (j >= sblock->s_blocks_per_group)
+ {
++ disk_cache_block_deref (bh);
++ bh = 0;
+ ext2_error ("free blocks count corrupted for block group %d", i);
+ spin_unlock (&global_lock);
+ return 0;
+ }
+
+-search_back:
++ search_back:
++ assert (bh);
+ /*
+- * We have succeeded in finding a free byte in the block
+- * bitmap. Now search backwards up to 7 bits to find the
+- * start of this group of free blocks.
++ * We have succeeded in finding a free byte in the block
++ * bitmap. Now search backwards up to 7 bits to find the
++ * start of this group of free blocks.
+ */
+ for (k = 0; k < 7 && j > 0 && !test_bit (j - 1, bh); k++, j--);
+
+-got_block:
+-
++ got_block:
++ assert (bh);
++
+ ext2_debug ("using block group %d (%d)", i, gdp->bg_free_blocks_count);
+
+ tmp = j + i * sblock->s_blocks_per_group + sblock->s_first_data_block;
+@@ -301,6 +311,8 @@ got_block:
+ if (set_bit (j, bh))
+ {
+ ext2_warning ("bit already set for block %d", j);
++ disk_cache_block_deref (bh);
++ bh = 0;
+ goto repeat;
+ }
+
+@@ -317,7 +329,7 @@ got_block:
+ ext2_debug ("found bit %d", j);
+
+ /*
+- * Do block preallocation now if required.
++ * Do block preallocation now if required.
+ */
+ #ifdef EXT2_PREALLOCATE
+ if (prealloc_goal)
+@@ -348,6 +360,7 @@ got_block:
+ j = tmp;
+
+ record_global_poke (bh);
++ bh = 0;
+
+ if (j >= sblock->s_blocks_count)
+ {
+@@ -360,12 +373,14 @@ got_block:
+ j, goal_hits, goal_attempts);
+
+ gdp->bg_free_blocks_count--;
++ disk_cache_block_ref_ptr (gdp);
+ record_global_poke (gdp);
+
+ sblock->s_free_blocks_count--;
+ sblock_dirty = 1;
+
+ sync_out:
++ assert (! bh);
+ spin_unlock (&global_lock);
+ alloc_sync (0);
+
+@@ -387,9 +402,12 @@ ext2_count_free_blocks ()
+ gdp = NULL;
+ for (i = 0; i < groups_count; i++)
+ {
++ void *bh;
+ gdp = group_desc (i);
+ desc_count += gdp->bg_free_blocks_count;
+- x = count_free (bptr (gdp->bg_block_bitmap), block_size);
++ bh = disk_cache_block_ref (gdp->bg_block_bitmap);
++ x = count_free (bh, block_size);
++ disk_cache_block_deref (bh);
+ printf ("group %d: stored = %d, counted = %lu",
+ i, gdp->bg_free_blocks_count, x);
+ bitmap_count += x;
+@@ -450,7 +468,7 @@ ext2_check_blocks_bitmap ()
+
+ gdp = group_desc (i);
+ desc_count += gdp->bg_free_blocks_count;
+- bh = bptr (gdp->bg_block_bitmap);
++ bh = disk_cache_block_ref (gdp->bg_block_bitmap);
+
+ if (!EXT2_HAS_RO_COMPAT_FEATURE (sblock,
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
+@@ -476,6 +494,7 @@ ext2_check_blocks_bitmap ()
+ ext2_error ("block #%d of the inode table in group %d is marked free", j, i);
+
+ x = count_free (bh, block_size);
++ disk_cache_block_deref (bh);
+ if (gdp->bg_free_blocks_count != x)
+ ext2_error ("wrong free blocks count for group %d,"
+ " stored = %d, counted = %lu",
+--- a/ext2fs/ext2_fs.h
++++ b/ext2fs/ext2_fs.h
+@@ -25,7 +25,8 @@
+ /*
+ * Define EXT2FS_DEBUG to produce debug messages
+ */
+-#undef EXT2FS_DEBUG
++/* #undef EXT2FS_DEBUG */
++#define EXT2FS_DEBUG
+
+ /*
+ * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
+--- a/ext2fs/ext2fs.c
++++ b/ext2fs/ext2fs.c
+@@ -106,7 +106,7 @@ parse_opt (int key, char *arg, struct ar
+ if (values == 0)
+ return ENOMEM;
+ state->hook = values;
+- bzero (values, sizeof *values);
++ memset (values, 0, sizeof *values);
+ values->sb_block = SBLOCK_BLOCK;
+ break;
+
+@@ -181,9 +181,9 @@ main (int argc, char **argv)
+ /* Map the entire disk. */
+ create_disk_pager ();
+
+- pokel_init (&global_pokel, diskfs_disk_pager, disk_image);
++ pokel_init (&global_pokel, diskfs_disk_pager, disk_cache);
+
+- get_hypermetadata();
++ map_hypermetadata ();
+
+ inode_init ();
+
+@@ -211,6 +211,8 @@ diskfs_reload_global_state ()
+ {
+ pokel_flush (&global_pokel);
+ pager_flush (diskfs_disk_pager, 1);
++ sblock = 0;
+ get_hypermetadata ();
++ map_hypermetadata ();
+ return 0;
+ }
+--- a/ext2fs/ext2fs.h
++++ b/ext2fs/ext2fs.h
+@@ -23,7 +23,9 @@
+ #include <hurd/pager.h>
+ #include <hurd/fshelp.h>
+ #include <hurd/iohelp.h>
++#include <hurd/store.h>
+ #include <hurd/diskfs.h>
++#include <hurd/ihash.h>
+ #include <assert.h>
+ #include <rwlock.h>
+ #include <sys/mman.h>
+@@ -186,6 +188,8 @@ struct user_pager_info
+ /* ---------------------------------------------------------------- */
+ /* pager.c */
+
++#define DISK_CACHE_BLOCKS 65536
++
+ #include <hurd/diskfs-pager.h>
+
+ /* Set up the disk pager. */
+@@ -209,10 +213,54 @@ extern struct store *store;
+ /* What the user specified. */
+ extern struct store_parsed *store_parsed;
+
+-/* Mapped image of the disk. */
+-extern void *disk_image;
++/* Mapped image of cached blocks of the disk. */
++extern void *disk_cache;
++extern store_offset_t disk_cache_size;
++extern int disk_cache_blocks;
++
++#define DC_INCORE 0x01 /* Not in core. */
++#define DC_UNTOUCHED 0x02 /* Not touched by disk_pager_read_paged
++ or disk_cache_block_ref. */
++#define DC_FIXED 0x04 /* Must not be re-associated. */
++
++/* Flags that forbid re-association of page. DC_UNTOUCHED is included
++ because this flag is used only when page is already to be
++ re-associated, so it's not good candidate for another
++ remapping. */
++#define DC_DONT_REUSE (DC_INCORE | DC_UNTOUCHED | DC_FIXED)
++
++#define DC_NO_BLOCK ((block_t) -1L)
++
++#ifndef NDEBUG
++#define DISK_CACHE_LAST_READ_XOR 0xDEADBEEF
++#endif
+
+-/* Our in-core copy of the super-block (pointer into the disk_image). */
++/* Disk cache blocks' meta info. */
++struct disk_cache_info
++{
++ block_t block;
++ uint16_t flags;
++ uint16_t ref_count;
++#ifndef NDEBUG
++ block_t last_read, last_read_xor;
++#endif
++};
++
++/* block num --> pointer to in-memory block */
++extern hurd_ihash_t disk_cache_bptr;
++/* Metadata about cached block. */
++extern struct disk_cache_info *disk_cache_info;
++/* Lock for these mappings */
++extern struct mutex disk_cache_lock;
++/* Fired when a re-association is done. */
++extern struct condition disk_cache_reassociation;
++
++void *disk_cache_block_ref (block_t block);
++void disk_cache_block_ref_ptr (void *ptr);
++void disk_cache_block_deref (void *ptr);
++int disk_cache_block_is_ref (block_t block);
++
++/* Our in-core copy of the super-block (pointer into the disk_cache). */
+ struct ext2_super_block *sblock;
+ /* True if sblock has been modified. */
+ int sblock_dirty;
+@@ -242,6 +290,9 @@ vm_address_t zeroblock;
+
+ /* Get the superblock from the disk, & setup various global info from it. */
+ void get_hypermetadata ();
++
++/* Map `sblock' and `group_desc_image' pointers to disk cache. */
++void map_hypermetadata ();
+
+ /* ---------------------------------------------------------------- */
+ /* Random stuff calculated from the super block. */
+@@ -265,21 +316,51 @@ spin_lock_t generation_lock;
+ unsigned long next_generation;
+
+ /* ---------------------------------------------------------------- */
+-/* Functions for looking inside disk_image */
++/* Functions for looking inside disk_cache */
+
+-#define trunc_block(offs) (((offs) >> log2_block_size) << log2_block_size)
++#define trunc_block(offs) \
++ ((off_t) ((offs) >> log2_block_size) << log2_block_size)
+ #define round_block(offs) \
+- ((((offs) + block_size - 1) >> log2_block_size) << log2_block_size)
++ ((off_t) (((offs) + block_size - 1) >> log2_block_size) << log2_block_size)
+
+ /* block num --> byte offset on disk */
+-#define boffs(block) ((block) << log2_block_size)
++#define boffs(block) ((off_t) (block) << log2_block_size)
+ /* byte offset on disk --> block num */
+ #define boffs_block(offs) ((offs) >> log2_block_size)
+
++/* pointer to in-memory block -> index in disk_cache_info */
++#define bptr_index(ptr) (((char *)ptr - (char *)disk_cache) >> log2_block_size)
++
+ /* byte offset on disk --> pointer to in-memory block */
+-#define boffs_ptr(offs) (((char *)disk_image) + (offs))
++EXT2FS_EI char *
++boffs_ptr (off_t offset)
++{
++ block_t block = boffs_block (offset);
++ mutex_lock (&disk_cache_lock);
++ char *ptr = hurd_ihash_find (disk_cache_bptr, block);
++ mutex_unlock (&disk_cache_lock);
++ assert (ptr);
++ ptr += offset % block_size;
++ ext2_debug ("(%Ld) = %p", offset, ptr);
++ return ptr;
++}
++
+ /* pointer to in-memory block --> byte offset on disk */
+-#define bptr_offs(ptr) ((char *)(ptr) - ((char *)disk_image))
++EXT2FS_EI off_t
++bptr_offs (void *ptr)
++{
++ vm_offset_t mem_offset = (char *)ptr - (char *)disk_cache;
++ off_t offset;
++ assert (mem_offset < disk_cache_size);
++ mutex_lock (&disk_cache_lock);
++ offset = (off_t) disk_cache_info[boffs_block (mem_offset)].block
++ << log2_block_size;
++ assert (offset || mem_offset < block_size);
++ offset += mem_offset % block_size;
++ mutex_unlock (&disk_cache_lock);
++ ext2_debug ("(%p) = %Ld", ptr, offset);
++ return offset;
++}
+
+ /* block num --> pointer to in-memory block */
+ #define bptr(block) boffs_ptr(boffs(block))
+@@ -296,14 +377,24 @@ struct ext2_group_desc *group_desc_image
+
+ /* Convert an inode number to the dinode on disk. */
+ EXT2FS_EI struct ext2_inode *
+-dino (ino_t inum)
++dino_ref (ino_t inum)
+ {
+ unsigned long inodes_per_group = sblock->s_inodes_per_group;
+ unsigned long bg_num = (inum - 1) / inodes_per_group;
+ unsigned long group_inum = (inum - 1) % inodes_per_group;
+- struct ext2_group_desc *bg = group_desc(bg_num);
++ struct ext2_group_desc *bg = group_desc (bg_num);
+ block_t block = bg->bg_inode_table + (group_inum / inodes_per_block);
+- return ((struct ext2_inode *)bptr(block)) + group_inum % inodes_per_block;
++ struct ext2_inode *inode = disk_cache_block_ref (block);
++ inode += group_inum % inodes_per_block;
++ ext2_debug ("(%qd) = %p", inum, inode);
++ return inode;
++}
++
++EXT2FS_EI void
++dino_deref (struct ext2_inode *inode)
++{
++ ext2_debug ("(%p)", inode);
++ disk_cache_block_deref (inode);
+ }
+
+ /* ---------------------------------------------------------------- */
+@@ -356,27 +447,38 @@ global_block_modified (block_t block)
+ EXT2FS_EI void
+ record_global_poke (void *ptr)
+ {
+- int boffs = trunc_block (bptr_offs (ptr));
+- global_block_modified (boffs_block (boffs));
+- pokel_add (&global_pokel, boffs_ptr(boffs), block_size);
++ block_t block = boffs_block (bptr_offs (ptr));
++ void *block_ptr = bptr (block);
++ ext2_debug ("(%p = %p)", ptr, block_ptr);
++ assert (disk_cache_block_is_ref (block));
++ global_block_modified (block);
++ pokel_add (&global_pokel, block_ptr, block_size);
+ }
+
+ /* This syncs a modification to a non-file block. */
+ EXT2FS_EI void
+ sync_global_ptr (void *bptr, int wait)
+ {
+- vm_offset_t boffs = trunc_block (bptr_offs (bptr));
+- global_block_modified (boffs_block (boffs));
+- pager_sync_some (diskfs_disk_pager, trunc_page (boffs), vm_page_size, wait);
++ block_t block = boffs_block (bptr_offs (bptr));
++ void *block_ptr = bptr (block);
++ ext2_debug ("(%p -> %u)", bptr, (block_t)block);
++ global_block_modified (block);
++ disk_cache_block_deref (block_ptr);
++ pager_sync_some (diskfs_disk_pager,
++ block_ptr - disk_cache, block_size, wait);
++
+ }
+
+ /* This records a modification to one of a file's indirect blocks. */
+ EXT2FS_EI void
+ record_indir_poke (struct node *node, void *ptr)
+ {
+- int boffs = trunc_block (bptr_offs (ptr));
+- global_block_modified (boffs_block (boffs));
+- pokel_add (&node->dn->indir_pokel, boffs_ptr(boffs), block_size);
++ block_t block = boffs_block (bptr_offs (ptr));
++ void *block_ptr = bptr (block);
++ ext2_debug ("(%d, %p)", (int)node->cache_id, ptr);
++ assert (disk_cache_block_is_ref (block));
++ global_block_modified (block);
++ pokel_add (&node->dn->indir_pokel, block_ptr, block_size);
+ }
+
+ /* ---------------------------------------------------------------- */
+@@ -384,6 +486,7 @@ record_indir_poke (struct node *node, vo
+ EXT2FS_EI void
+ sync_global (int wait)
+ {
++ ext2_debug ("%d", wait);
+ pokel_sync (&global_pokel, wait);
+ }
+
+--- a/ext2fs/getblk.c
++++ b/ext2fs/getblk.c
+@@ -52,7 +52,7 @@ ext2_discard_prealloc (struct node *node
+ if (node->dn->info.i_prealloc_count)
+ {
+ int i = node->dn->info.i_prealloc_count;
+- ext2_debug ("discarding %d prealloced blocks for inode %d",
++ ext2_debug ("discarding %d prealloced blocks for inode %Ld",
+ i, node->cache_id);
+ node->dn->info.i_prealloc_count = 0;
+ ext2_free_blocks (node->dn->info.i_prealloc_block, i);
+@@ -104,8 +104,8 @@ ext2_alloc_block (struct node *node, blo
+
+ if (result && zero)
+ {
+- char *bh = bptr (result);
+- bzero (bh, block_size);
++ char *bh = disk_cache_block_ref (result);
++ memset (bh, 0, block_size);
+ record_indir_poke (node, bh);
+ }
+
+@@ -122,6 +122,8 @@ inode_getblk (struct node *node, int nr,
+ block_t hint;
+ #endif
+
++ assert (0 <= nr && nr < EXT2_N_BLOCKS);
++
+ *result = node->dn->info.i_data[nr];
+ if (*result)
+ return 0;
+@@ -180,14 +182,20 @@ block_getblk (struct node *node, block_t
+ {
+ int i;
+ block_t goal = 0;
+- block_t *bh = (block_t *)bptr (block);
++ block_t *bh = (block_t *)disk_cache_block_ref (block);
+
+ *result = bh[nr];
+ if (*result)
+- return 0;
++ {
++ disk_cache_block_deref (bh);
++ return 0;
++ }
+
+ if (!create)
+- return EINVAL;
++ {
++ disk_cache_block_deref (bh);
++ return EINVAL;
++ }
+
+ if (node->dn->info.i_next_alloc_block == new_block)
+ goal = node->dn->info.i_next_alloc_goal;
+@@ -207,7 +215,10 @@ block_getblk (struct node *node, block_t
+
+ *result = ext2_alloc_block (node, goal, zero);
+ if (!*result)
+- return ENOSPC;
++ {
++ disk_cache_block_deref (bh);
++ return ENOSPC;
++ }
+
+ bh[nr] = *result;
+
+@@ -243,9 +254,9 @@ ext2_getblk (struct node *node, block_t
+ return EIO;
+ }
+ /*
+- * If this is a sequential block allocation, set the next_alloc_block
+- * to this block now so that all the indblock and data block
+- * allocations use the same goal zone
++ * If this is a sequential block allocation, set the next_alloc_block
++ * to this block now so that all the indblock and data block
++ * allocations use the same goal zone
+ */
+
+ ext2_debug ("block = %u, next = %u, goal = %u", block,
+--- a/ext2fs/hyper.c
++++ b/ext2fs/hyper.c
+@@ -58,12 +58,15 @@ static int ext2fs_clean; /* fs clean bef
+ void
+ get_hypermetadata (void)
+ {
+- error_t err = diskfs_catch_exception ();
+- if (err)
+- ext2_panic ("can't read superblock: %s", strerror (err));
+-
+- sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS);
++ error_t err;
++ size_t read = 0;
+
++ assert (! sblock);
++ err = store_read (store, SBLOCK_OFFS >> store->log2_block_size,
++ SBLOCK_SIZE, (void **)&sblock, &read);
++ if (err || read != SBLOCK_SIZE)
++ ext2_panic ("Cannot read hypermetadata");
++
+ if (sblock->s_magic != EXT2_SUPER_MAGIC
+ #ifdef EXT2FS_PRE_02B_COMPAT
+ && sblock->s_magic != EXT2_PRE_02B_MAGIC
+@@ -152,15 +155,22 @@ get_hypermetadata (void)
+
+ allocate_mod_map ();
+
+- diskfs_end_catch_exception ();
++ /* A handy source of page-aligned zeros. */
++ if (zeroblock == 0)
++ zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0);
++
++ munmap (sblock, SBLOCK_SIZE);
++ sblock = NULL;
++}
++
++void
++map_hypermetadata (void)
++{
++ sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS);
+
+ /* Cache a convenient pointer to the block group descriptors for allocation.
+ These are stored in the filesystem blocks following the superblock. */
+ group_desc_image = (struct ext2_group_desc *) bptr (bptr_block (sblock) + 1);
+-
+- /* A handy source of page-aligned zeros. */
+- if (zeroblock == 0)
+- zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0);
+ }
+
+ error_t
+@@ -183,6 +193,7 @@ diskfs_set_hypermetadata (int wait, int
+ if (sblock_dirty)
+ {
+ sblock_dirty = 0;
++ disk_cache_block_ref_ptr (sblock);
+ record_global_poke (sblock);
+ }
+
+@@ -199,7 +210,8 @@ diskfs_readonly_changed (int readonly)
+
+ (*(readonly ? store_set_flags : store_clear_flags)) (store, STORE_READONLY);
+
+- mprotect (disk_image, store->size, PROT_READ | (readonly ? 0 : PROT_WRITE));
++ mprotect (disk_cache, disk_cache_size,
++ PROT_READ | (readonly ? 0 : PROT_WRITE));
+
+ if (!readonly && !(sblock->s_state & EXT2_VALID_FS))
+ ext2_warning ("UNCLEANED FILESYSTEM NOW WRITABLE");
+--- a/ext2fs/ialloc.c
++++ b/ext2fs/ialloc.c
+@@ -60,7 +60,7 @@ diskfs_free_node (struct node *np, mode_
+
+ assert (!diskfs_readonly);
+
+- ext2_debug ("freeing inode %u", inum);
++ ext2_debug ("freeing inode %Lu", inum);
+
+ spin_lock (&global_lock);
+
+@@ -75,22 +75,25 @@ diskfs_free_node (struct node *np, mode_
+ bit = (inum - 1) % sblock->s_inodes_per_group;
+
+ gdp = group_desc (block_group);
+- bh = bptr (gdp->bg_inode_bitmap);
++ bh = disk_cache_block_ref (gdp->bg_inode_bitmap);
+
+ if (!clear_bit (bit, bh))
+ ext2_warning ("bit already cleared for inode %Ld", inum);
+ else
+ {
++ disk_cache_block_ref_ptr (bh);
+ record_global_poke (bh);
+
+ gdp->bg_free_inodes_count++;
+ if (S_ISDIR (old_mode))
+ gdp->bg_used_dirs_count--;
++ disk_cache_block_ref_ptr (gdp);
+ record_global_poke (gdp);
+
+ sblock->s_free_inodes_count++;
+ }
+
++ disk_cache_block_deref (bh);
+ sblock_dirty = 1;
+ spin_unlock (&global_lock);
+ alloc_sync(0);
+@@ -111,14 +114,15 @@ diskfs_free_node (struct node *np, mode_
+ ino_t
+ ext2_alloc_inode (ino_t dir_inum, mode_t mode)
+ {
+- char *bh;
++ char *bh = 0;
+ int i, j, inum, avefreei;
+ struct ext2_group_desc *gdp;
+ struct ext2_group_desc *tmp;
+
+ spin_lock (&global_lock);
+
+-repeat:
++ repeat:
++ assert (! bh);
+ gdp = NULL;
+ i = 0;
+
+@@ -213,7 +217,7 @@ repeat:
+ return 0;
+ }
+
+- bh = bptr (gdp->bg_inode_bitmap);
++ bh = disk_cache_block_ref (gdp->bg_inode_bitmap);
+ if ((inum =
+ find_first_zero_bit ((unsigned long *) bh, sblock->s_inodes_per_group))
+ < sblock->s_inodes_per_group)
+@@ -221,12 +225,17 @@ repeat:
+ if (set_bit (inum, bh))
+ {
+ ext2_warning ("bit already set for inode %d", inum);
++ disk_cache_block_deref (bh);
++ bh = 0;
+ goto repeat;
+ }
+ record_global_poke (bh);
++ bh = 0;
+ }
+ else
+ {
++ disk_cache_block_deref (bh);
++ bh = 0;
+ if (gdp->bg_free_inodes_count != 0)
+ {
+ ext2_error ("free inodes count corrupted in group %d", i);
+@@ -248,15 +257,25 @@ repeat:
+ gdp->bg_free_inodes_count--;
+ if (S_ISDIR (mode))
+ gdp->bg_used_dirs_count++;
++ disk_cache_block_ref_ptr (gdp);
+ record_global_poke (gdp);
+
+ sblock->s_free_inodes_count--;
+ sblock_dirty = 1;
+
+ sync_out:
++ assert (! bh);
+ spin_unlock (&global_lock);
+ alloc_sync (0);
+
++ /* Make sure the coming read_node won't complain about bad
++ fields. */
++ {
++ struct ext2_inode *di = dino_ref (inum);
++ memset (di, 0, sizeof *di);
++ dino_deref (di);
++ }
++
+ return inum;
+ }
+
+@@ -354,10 +373,12 @@ ext2_count_free_inodes ()
+ gdp = NULL;
+ for (i = 0; i < groups_count; i++)
+ {
++ void *bh;
+ gdp = group_desc (i);
+ desc_count += gdp->bg_free_inodes_count;
+- x = count_free (bptr (gdp->bg_inode_bitmap),
+- sblock->s_inodes_per_group / 8);
++ bh = disk_cache_block_ref (gdp->bg_inode_bitmap);
++ x = count_free (bh, sblock->s_inodes_per_group / 8);
++ disk_cache_block_deref (bh);
+ ext2_debug ("group %d: stored = %d, counted = %lu",
+ i, gdp->bg_free_inodes_count, x);
+ bitmap_count += x;
+@@ -387,10 +408,12 @@ ext2_check_inodes_bitmap ()
+ gdp = NULL;
+ for (i = 0; i < groups_count; i++)
+ {
++ void *bh;
+ gdp = group_desc (i);
+ desc_count += gdp->bg_free_inodes_count;
+- x = count_free (bptr (gdp->bg_inode_bitmap),
+- sblock->s_inodes_per_group / 8);
++ bh = disk_cache_block_ref (gdp->bg_inode_bitmap);
++ x = count_free (bh, sblock->s_inodes_per_group / 8);
++ disk_cache_block_deref (bh);
+ if (gdp->bg_free_inodes_count != x)
+ ext2_error ("wrong free inodes count in group %d, "
+ "stored = %d, counted = %lu",
+--- a/ext2fs/inode.c
++++ b/ext2fs/inode.c
+@@ -92,7 +92,7 @@ diskfs_cached_lookup (ino_t inum, struct
+ dn->dir_idx = 0;
+ dn->pager = 0;
+ rwlock_init (&dn->alloc_lock);
+- pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_image);
++ pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_cache);
+
+ /* Create the new node. */
+ np = diskfs_make_node (dn);
+@@ -201,13 +201,17 @@ read_node (struct node *np)
+ error_t err;
+ struct stat *st = &np->dn_stat;
+ struct disknode *dn = np->dn;
+- struct ext2_inode *di = dino (np->cache_id);
++ struct ext2_inode *di;
+ struct ext2_inode_info *info = &dn->info;
+
++ ext2_debug ("(%d)", np->cache_id);
++
+ err = diskfs_catch_exception ();
+ if (err)
+ return err;
+
++ di = dino_ref (np->cache_id);
++
+ st->st_fstype = FSTYPE_EXT2FS;
+ st->st_fsid = getpid (); /* This call is very cheap. */
+ st->st_ino = np->cache_id;
+@@ -285,7 +289,9 @@ read_node (struct node *np)
+ info->i_high_size = di->i_size_high;
+ if (info->i_high_size) /* XXX */
+ {
++ dino_deref (di);
+ ext2_warning ("cannot handle large file inode %Ld", np->cache_id);
++ diskfs_end_catch_exception ();
+ return EFBIG;
+ }
+ }
+@@ -307,20 +313,12 @@ read_node (struct node *np)
+ }
+ dn->info_i_translator = di->i_translator;
+
++ dino_deref (di);
+ diskfs_end_catch_exception ();
+
+ if (S_ISREG (st->st_mode) || S_ISDIR (st->st_mode)
+ || (S_ISLNK (st->st_mode) && st->st_blocks))
+- {
+- unsigned offset;
+-
+- np->allocsize = np->dn_stat.st_size;
+-
+- /* Round up to a block multiple. */
+- offset = np->allocsize & ((1 << log2_block_size) - 1);
+- if (offset > 0)
+- np->allocsize += block_size - offset;
+- }
++ np->allocsize = round_block (np->dn_stat.st_size);
+ else
+ /* Allocsize should be zero for anything except directories, files, and
+ long symlinks. These are the only things allowed to have any blocks
+@@ -408,7 +406,9 @@ write_node (struct node *np)
+ {
+ error_t err;
+ struct stat *st = &np->dn_stat;
+- struct ext2_inode *di = dino (np->cache_id);
++ struct ext2_inode *di;
++
++ ext2_debug ("(%d)", np->cache_id);
+
+ if (np->dn->info.i_prealloc_count)
+ ext2_discard_prealloc (np);
+@@ -419,12 +419,14 @@ write_node (struct node *np)
+
+ assert (!diskfs_readonly);
+
+- ext2_debug ("writing inode %d to disk", np->cache_id);
++ ext2_debug ("writing inode %Ld to disk", np->cache_id);
+
+ err = diskfs_catch_exception ();
+ if (err)
+ return NULL;
+
++ di = dino_ref (np->cache_id);
++
+ di->i_generation = st->st_gen;
+
+ /* We happen to know that the stat mode bits are the same
+@@ -505,6 +507,7 @@ write_node (struct node *np)
+ diskfs_end_catch_exception ();
+ np->dn_stat_dirty = 0;
+
++ /* Leave invoking dino_deref (di) to the caller. */
+ return di;
+ }
+ else
+@@ -664,7 +667,7 @@ diskfs_set_translator (struct node *np,
+ if (err)
+ return err;
+
+- di = dino (np->cache_id);
++ di = dino_ref (np->cache_id);
+ blkno = di->i_translator;
+
+ if (namelen && !blkno)
+@@ -677,6 +680,7 @@ diskfs_set_translator (struct node *np,
+ 0, 0, 0);
+ if (blkno == 0)
+ {
++ dino_deref (di);
+ diskfs_end_catch_exception ();
+ return ENOSPC;
+ }
+@@ -700,15 +704,20 @@ diskfs_set_translator (struct node *np,
+ np->dn_stat.st_mode &= ~S_IPTRANS;
+ np->dn_set_ctime = 1;
+ }
++ else
++ dino_deref (di);
+
+ if (namelen)
+ {
++ void *blkptr;
++
+ buf[0] = namelen & 0xFF;
+ buf[1] = (namelen >> 8) & 0xFF;
+- bcopy (name, buf + 2, namelen);
++ memcpy (buf + 2, name, namelen);
+
+- bcopy (buf, bptr (blkno), block_size);
+- record_global_poke (bptr (blkno));
++ blkptr = disk_cache_block_ref (blkno);
++ memcpy (blkptr, buf, block_size);
++ record_global_poke (blkptr);
+
+ np->dn_stat.st_mode |= S_IPTRANS;
+ np->dn_set_ctime = 1;
+@@ -726,7 +735,7 @@ diskfs_get_translator (struct node *np,
+ error_t err = 0;
+ daddr_t blkno;
+ unsigned datalen;
+- const void *transloc;
++ void *transloc;
+
+ assert (sblock->s_creator_os == EXT2_OS_HURD);
+
+@@ -734,9 +743,11 @@ diskfs_get_translator (struct node *np,
+ if (err)
+ return err;
+
+- blkno = (dino (np->cache_id))->i_translator;
++ struct ext2_inode *di = dino_ref (np->cache_id);
++ blkno = di->i_translator;
++ dino_deref (di);
+ assert (blkno);
+- transloc = bptr (blkno);
++ transloc = disk_cache_block_ref (blkno);
+
+ datalen =
+ ((unsigned char *)transloc)[0] + (((unsigned char *)transloc)[1] << 8);
+@@ -751,6 +762,7 @@ diskfs_get_translator (struct node *np,
+ memcpy (*namep, transloc + 2, datalen);
+ }
+
++ disk_cache_block_deref (transloc);
+ diskfs_end_catch_exception ();
+
+ *namelen = datalen;
+@@ -772,7 +784,7 @@ write_symlink (struct node *node, const
+
+ assert (node->dn_stat.st_blocks == 0);
+
+- bcopy (target, node->dn->info.i_data, len);
++ memcpy (node->dn->info.i_data, target, len);
+ node->dn_stat.st_size = len - 1;
+ node->dn_set_ctime = 1;
+ node->dn_set_mtime = 1;
+@@ -789,7 +801,7 @@ read_symlink (struct node *node, char *t
+
+ assert (node->dn_stat.st_size < MAX_INODE_SYMLINK);
+
+- bcopy (node->dn->info.i_data, target, node->dn_stat.st_size);
++ memcpy (target, node->dn->info.i_data, node->dn_stat.st_size);
+ return 0;
+ }
+
+--- a/ext2fs/pager.c
++++ b/ext2fs/pager.c
+@@ -18,17 +18,18 @@
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
++#include <unistd.h>
+ #include <string.h>
+ #include <errno.h>
+ #include <hurd/store.h>
+ #include "ext2fs.h"
+
++/* XXX */
++#include "../libpager/priv.h"
++
+ /* A ports bucket to hold pager ports. */
+ struct port_bucket *pager_bucket;
+
+-/* Mapped image of the disk. */
+-void *disk_image;
+-
+ spin_lock_t node_to_page_lock = SPIN_LOCK_INITIALIZER;
+
+ #ifdef DONT_CACHE_MEMORY_OBJECTS
+@@ -163,6 +164,9 @@ file_pager_read_page (struct node *node,
+ block_t pending_blocks = 0;
+ int num_pending_blocks = 0;
+
++ ext2_debug ("reading inode %Ld page %u[%d]",
++ node->cache_id, page, vm_page_size);
++
+ /* Read the NUM_PENDING_BLOCKS blocks in PENDING_BLOCKS, into the buffer
+ pointed to by BUF (allocating it if necessary) at offset OFFS. OFFS in
+ adjusted by the amount read, and NUM_PENDING_BLOCKS is zeroed. Any read
+@@ -171,7 +175,8 @@ file_pager_read_page (struct node *node,
+ {
+ if (num_pending_blocks > 0)
+ {
+- block_t dev_block = pending_blocks << log2_dev_blocks_per_fs_block;
++ store_offset_t dev_block = (store_offset_t) pending_blocks
++ << log2_dev_blocks_per_fs_block;
+ size_t amount = num_pending_blocks << log2_block_size;
+ /* The buffer we try to read into; on the first read, we pass in a
+ size of zero, so that the read is guaranteed to allocate a new
+@@ -198,7 +203,7 @@ file_pager_read_page (struct node *node,
+ else
+ /* We've already got some buffer, so copy into it. */
+ {
+- bcopy (new_buf, *buf + offs, new_len);
++ memcpy (*buf + offs, new_buf, new_len);
+ free_page_buf (new_buf); /* Return NEW_BUF to our pool. */
+ STAT_INC (file_pagein_freed_bufs);
+ }
+@@ -254,7 +259,7 @@ file_pager_read_page (struct node *node,
+ break;
+ STAT_INC (file_pagein_alloced_bufs);
+ }
+- bzero (*buf + offs, block_size);
++ memset (*buf + offs, 0, block_size);
+ offs += block_size;
+ }
+ else
+@@ -295,16 +300,17 @@ pending_blocks_write (struct pending_blo
+ if (pb->num > 0)
+ {
+ error_t err;
+- block_t dev_block = pb->block << log2_dev_blocks_per_fs_block;
++ store_offset_t dev_block = (store_offset_t) pb->block
++ << log2_dev_blocks_per_fs_block;
+ size_t length = pb->num << log2_block_size, amount;
+
+- ext2_debug ("writing block %u[%ld]", pb->block, pb->num);
++ ext2_debug ("writing block %u[%Ld]", pb->block, pb->num);
+
+ if (pb->offs > 0)
+ /* Put what we're going to write into a page-aligned buffer. */
+ {
+ void *page_buf = get_page_buf ();
+- bcopy (pb->buf + pb->offs, (void *)page_buf, length);
++ memcpy ((void *)page_buf, pb->buf + pb->offs, length);
+ err = store_write (store, dev_block, page_buf, length, &amount);
+ free_page_buf (page_buf);
+ }
+@@ -357,7 +363,7 @@ pending_blocks_add (struct pending_block
+ return 0;
+ }
+
+-/* Write one page for the pager backing NODE, at offset PAGE, into BUF. This
++/* Write one page for the pager backing NODE, at OFFSET, into BUF. This
+ may need to write several filesystem blocks to satisfy one page, and tries
+ to consolidate the i/o if possible. */
+ static error_t
+@@ -381,7 +387,7 @@ file_pager_write_page (struct node *node
+ else if (offset + left > node->allocsize)
+ left = node->allocsize - offset;
+
+- ext2_debug ("writing inode %d page %d[%d]", node->cache_id, offset, left);
++ ext2_debug ("writing inode %Ld page %u[%d]", node->cache_id, offset, left);
+
+ STAT_INC (file_pageouts);
+
+@@ -409,16 +415,31 @@ disk_pager_read_page (vm_offset_t page,
+ {
+ error_t err;
+ size_t length = vm_page_size, read = 0;
+- vm_size_t dev_end = store->size;
++ store_offset_t offset = page, dev_end = store->size;
+
+- if (page + vm_page_size > dev_end)
+- length = dev_end - page;
++ mutex_lock (&disk_cache_lock);
++ int index = offset >> log2_block_size;
++ offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size)
++ + offset % block_size;
++ disk_cache_info[index].flags |= DC_INCORE;
++ disk_cache_info[index].flags &=~ DC_UNTOUCHED;
++#ifndef NDEBUG
++ disk_cache_info[index].last_read = disk_cache_info[index].block;
++ disk_cache_info[index].last_read_xor
++ = disk_cache_info[index].block ^ DISK_CACHE_LAST_READ_XOR;
++#endif
++ ext2_debug ("(%Ld)", offset >> log2_block_size);
++ mutex_unlock (&disk_cache_lock);
++
++ if (offset + vm_page_size > dev_end)
++ length = dev_end - offset;
+
+- err = store_read (store, page >> store->log2_block_size, length, buf, &read);
++ err = store_read (store, offset >> store->log2_block_size, length,
++ buf, &read);
+ if (read != length)
+ return EIO;
+ if (!err && length != vm_page_size)
+- bzero ((void *)(*buf + length), vm_page_size - length);
++ memset ((void *)(*buf + length), 0, vm_page_size - length);
+
+ *writelock = 0;
+
+@@ -430,26 +451,38 @@ disk_pager_write_page (vm_offset_t page,
+ {
+ error_t err = 0;
+ size_t length = vm_page_size, amount;
+- vm_size_t dev_end = store->size;
++ store_offset_t offset = page, dev_end = store->size;
++
++ mutex_lock (&disk_cache_lock);
++ int index = offset >> log2_block_size;
++ assert (disk_cache_info[index].block != DC_NO_BLOCK);
++ offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size)
++ + offset % block_size;
++#ifndef NDEBUG /* Not strictly needed. */
++ assert ((disk_cache_info[index].last_read ^ DISK_CACHE_LAST_READ_XOR)
++ == disk_cache_info[index].last_read_xor);
++ assert (disk_cache_info[index].last_read
++ == disk_cache_info[index].block);
++#endif
++ mutex_unlock (&disk_cache_lock);
+
+- if (page + vm_page_size > dev_end)
+- length = dev_end - page;
++ if (offset + vm_page_size > dev_end)
++ length = dev_end - offset;
+
+- ext2_debug ("writing disk page %d[%d]", page, length);
++ ext2_debug ("writing disk page %Ld[%d]", offset, length);
+
+ STAT_INC (disk_pageouts);
+
+ if (modified_global_blocks)
+ /* Be picky about which blocks in a page that we write. */
+ {
+- vm_offset_t offs = page;
+ struct pending_blocks pb;
+
+ pending_blocks_init (&pb, buf);
+
+ while (length > 0 && !err)
+ {
+- block_t block = boffs_block (offs);
++ block_t block = boffs_block (offset);
+
+ /* We don't clear the block modified bit here because this paging
+ write request may not be the same one that actually set the bit,
+@@ -467,7 +500,7 @@ disk_pager_write_page (vm_offset_t page,
+ /* Otherwise just skip it. */
+ err = pending_blocks_skip (&pb);
+
+- offs += block_size;
++ offset += block_size;
+ length -= block_size;
+ }
+
+@@ -476,7 +509,7 @@ disk_pager_write_page (vm_offset_t page,
+ }
+ else
+ {
+- err = store_write (store, page >> store->log2_block_size,
++ err = store_write (store, offset >> store->log2_block_size,
+ buf, length, &amount);
+ if (!err && length != amount)
+ err = EIO;
+@@ -484,6 +517,18 @@ disk_pager_write_page (vm_offset_t page,
+
+ return err;
+ }
++
++static void
++disk_pager_notify_evict (vm_offset_t page)
++{
++ int index = page >> log2_block_size;
++
++ ext2_debug ("(block %u)", index);
++
++ mutex_lock (&disk_cache_lock);
++ disk_cache_info[index].flags &= ~DC_INCORE;
++ mutex_unlock (&disk_cache_lock);
++}
+
+ /* Satisfy a pager read request for either the disk pager or file pager
+ PAGER, to the page at offset PAGE into BUF. WRITELOCK should be set if
+@@ -493,9 +538,11 @@ pager_read_page (struct user_pager_info
+ vm_address_t *buf, int *writelock)
+ {
+ if (pager->type == DISK)
+- return disk_pager_read_page (page, (void **)buf, writelock);
++ return disk_pager_read_page (page, (void **)buf,
++ writelock);
+ else
+- return file_pager_read_page (pager->node, page, (void **)buf, writelock);
++ return file_pager_read_page (pager->node, page, (void **)buf,
++ writelock);
+ }
+
+ /* Satisfy a pager write request for either the disk pager or file pager
+@@ -509,6 +556,14 @@ pager_write_page (struct user_pager_info
+ else
+ return file_pager_write_page (pager->node, page, (void *)buf);
+ }
++
++void
++pager_notify_evict (struct user_pager_info *pager, vm_offset_t page)
++{
++ if (pager->type == DISK)
++ disk_pager_notify_evict (page);
++}
++
+
+ /* Make page PAGE writable, at least up to ALLOCSIZE. This function and
+ diskfs_grow are the only places that blocks are actually added to the
+@@ -558,10 +613,10 @@ pager_unlock_page (struct user_pager_inf
+
+ #ifdef EXT2FS_DEBUG
+ if (dn->last_page_partially_writable)
+- ext2_debug ("made page %u[%lu] in inode %d partially writable",
++ ext2_debug ("made page %u[%Lu] in inode %Ld partially writable",
+ page, node->allocsize - page, node->cache_id);
+ else
+- ext2_debug ("made page %u[%u] in inode %d writable",
++ ext2_debug ("made page %u[%u] in inode %Ld writable",
+ page, vm_page_size, node->cache_id);
+ #endif
+
+@@ -619,8 +674,8 @@ diskfs_grow (struct node *node, off_t si
+ block_t old_page_end_block =
+ round_page (old_size) >> log2_block_size;
+
+- ext2_debug ("growing inode %d to %lu bytes (from %lu)", node->cache_id,
+- new_size, old_size);
++ ext2_debug ("growing inode %Ld to %Lu bytes (from %Lu)",
++ node->cache_id, new_size, old_size);
+
+ if (dn->last_page_partially_writable
+ && old_page_end_block > end_block)
+@@ -656,11 +711,11 @@ diskfs_grow (struct node *node, off_t si
+
+ STAT_INC (file_grows);
+
+- ext2_debug ("new size: %ld%s.", new_size,
++ ext2_debug ("new size: %Lu%s.", new_size,
+ dn->last_page_partially_writable
+ ? " (last page writable)": "");
+ if (err)
+- ext2_warning ("inode=%Ld, target=%Ld: %s",
++ ext2_warning ("inode=%Ld, target=%Lu: %s",
+ node->cache_id, new_size, strerror (err));
+
+ node->allocsize = new_size;
+@@ -765,6 +820,374 @@ pager_dropweak (struct user_pager_info *
+ {
+ }
+
++/* Cached blocks from disk. */
++void *disk_cache;
++
++/* DISK_CACHE size in bytes and blocks. */
++store_offset_t disk_cache_size;
++int disk_cache_blocks;
++
++/* block num --> pointer to in-memory block */
++hurd_ihash_t disk_cache_bptr;
++/* Cached blocks' info. */
++struct disk_cache_info *disk_cache_info;
++/* Hint index for which cache block to reuse next. */
++int disk_cache_hint;
++/* Lock for these structures. */
++struct mutex disk_cache_lock;
++/* Fired when a re-association is done. */
++struct condition disk_cache_reassociation;
++
++/* Finish mapping initialization. */
++static void
++disk_cache_init (void)
++{
++ if (block_size != vm_page_size)
++ ext2_panic ("Block size %d != vm_page_size %d",
++ block_size, vm_page_size);
++
++ mutex_init (&disk_cache_lock);
++ condition_init (&disk_cache_reassociation);
++
++ /* Allocate space for block num -> in-memory pointer mapping. */
++ if (hurd_ihash_create (&disk_cache_bptr, HURD_IHASH_NO_LOCP))
++ ext2_panic ("Can't allocate memory for disk_pager_bptr");
++
++ /* Allocate space for disk cache blocks' info. */
++ disk_cache_info = malloc ((sizeof *disk_cache_info) * disk_cache_blocks);
++ if (!disk_cache_info)
++ ext2_panic ("Cannot allocate space for disk cache info");
++
++ /* Initialize disk_cache_info. */
++ for (int i = 0; i < disk_cache_blocks; i++)
++ {
++ disk_cache_info[i].block = DC_NO_BLOCK;
++ disk_cache_info[i].flags = 0;
++ disk_cache_info[i].ref_count = 0;
++#ifndef NDEBUG
++ disk_cache_info[i].last_read = DC_NO_BLOCK;
++ disk_cache_info[i].last_read_xor
++ = DC_NO_BLOCK ^ DISK_CACHE_LAST_READ_XOR;
++#endif
++ }
++ disk_cache_hint = 0;
++
++ /* Map the superblock and the block group descriptors. */
++ block_t fixed_first = boffs_block (SBLOCK_OFFS);
++ block_t fixed_last = fixed_first
++ + (round_block ((sizeof *group_desc_image) * groups_count)
++ >> log2_block_size);
++ ext2_debug ("%d-%d\n", fixed_first, fixed_last);
++ assert (fixed_last - fixed_first + 1 <= (block_t)disk_cache_blocks + 3);
++ for (block_t i = fixed_first; i <= fixed_last; i++)
++ {
++ disk_cache_block_ref (i);
++ assert (disk_cache_info[i-fixed_first].block == i);
++ disk_cache_info[i-fixed_first].flags |= DC_FIXED;
++ }
++}
++
++static void
++disk_cache_return_unused (void)
++{
++ int index;
++
++ /* XXX: Touch all pages. It seems that sometimes GNU Mach "forgets"
++ to notify us about evicted pages. Disk cache must be
++ unlocked. */
++ for (vm_offset_t i = 0; i < disk_cache_size; i += vm_page_size)
++ *(volatile char *)(disk_cache + i);
++
++ /* Release some references to cached blocks. */
++ pokel_sync (&global_pokel, 1);
++
++ /* Return unused pages that are in core. */
++ int pending_begin = -1, pending_end = -1;
++ mutex_lock (&disk_cache_lock);
++ for (index = 0; index < disk_cache_blocks; index++)
++ if (! (disk_cache_info[index].flags & (DC_DONT_REUSE & ~DC_INCORE))
++ && ! disk_cache_info[index].ref_count)
++ {
++ ext2_debug ("return %u -> %d",
++ disk_cache_info[index].block, index);
++ if (index != pending_end)
++ {
++ /* Return previous region, if there is such, ... */
++ if (pending_end >= 0)
++ {
++ mutex_unlock (&disk_cache_lock);
++ pager_return_some (diskfs_disk_pager,
++ pending_begin * vm_page_size,
++ (pending_end - pending_begin)
++ * vm_page_size,
++ 1);
++ mutex_lock (&disk_cache_lock);
++ }
++ /* ... and start new region. */
++ pending_begin = index;
++ }
++ pending_end = index + 1;
++ }
++
++ mutex_unlock (&disk_cache_lock);
++
++ /* Return last region, if there is such. */
++ if (pending_end >= 0)
++ pager_return_some (diskfs_disk_pager,
++ pending_begin * vm_page_size,
++ (pending_end - pending_begin) * vm_page_size,
++ 1);
++ else
++ {
++ printf ("ext2fs: disk cache is starving\n");
++
++ /* Give it some time. This should happen rarely. */
++ sleep (1);
++ }
++}
++
++/* Map block and return pointer to it. */
++void *
++disk_cache_block_ref (block_t block)
++{
++ int index;
++ void *bptr;
++
++ assert (0 <= block && block < store->size >> log2_block_size);
++
++ ext2_debug ("(%u)", block);
++
++ mutex_lock (&disk_cache_lock);
++
++ bptr = hurd_ihash_find (disk_cache_bptr, block);
++ if (bptr)
++ /* Already mapped. */
++ {
++ index = bptr_index (bptr);
++
++ /* In process of re-associating? */
++ if (disk_cache_info[index].flags & DC_UNTOUCHED)
++ {
++ /* Wait re-association to finish. */
++ condition_wait (&disk_cache_reassociation, &disk_cache_lock);
++ mutex_unlock (&disk_cache_lock);
++
++#if 0
++ printf ("Re-association -- wait finished.\n");
++#endif
++
++ /* Try again. */
++ return disk_cache_block_ref (block); /* tail recursion */
++ }
++
++ /* Just increment reference and return. */
++ assert (disk_cache_info[index].ref_count + 1
++ > disk_cache_info[index].ref_count);
++ disk_cache_info[index].ref_count++;
++
++ ext2_debug ("cached %u -> %d (ref_count = %d, flags = 0x%x, ptr = %p)",
++ disk_cache_info[index].block, index,
++ disk_cache_info[index].ref_count,
++ disk_cache_info[index].flags, bptr);
++
++ mutex_unlock (&disk_cache_lock);
++
++ return bptr;
++ }
++
++ /* Search for a block that is not in core and is not referenced. */
++ index = disk_cache_hint;
++ while ((disk_cache_info[index].flags & DC_DONT_REUSE)
++ || (disk_cache_info[index].ref_count))
++ {
++ ext2_debug ("reject %u -> %d (ref_count = %d, flags = 0x%x)",
++ disk_cache_info[index].block, index,
++ disk_cache_info[index].ref_count,
++ disk_cache_info[index].flags);
++
++ /* Just move to next block. */
++ index++;
++ if (index >= disk_cache_blocks)
++ index -= disk_cache_blocks;
++
++ /* If we return to where we started, than there is no suitable
++ block. */
++ if (index == disk_cache_hint)
++ break;
++ }
++
++ /* The next place in the disk cache becomes the current hint. */
++ disk_cache_hint = index + 1;
++ if (disk_cache_hint >= disk_cache_blocks)
++ disk_cache_hint -= disk_cache_blocks;
++
++ /* Is suitable place found? */
++ if ((disk_cache_info[index].flags & DC_DONT_REUSE)
++ || disk_cache_info[index].ref_count)
++ /* No place is found. Try to release some blocks and try
++ again. */
++ {
++ ext2_debug ("flush %u -> %d", disk_cache_info[index].block, index);
++
++ mutex_unlock (&disk_cache_lock);
++
++ disk_cache_return_unused ();
++
++ return disk_cache_block_ref (block); /* tail recursion */
++ }
++
++ /* Suitable place is found. */
++
++ /* Calculate pointer to data. */
++ bptr = (char *)disk_cache + (index << log2_block_size);
++ ext2_debug ("map %u -> %d (%p)", block, index, bptr);
++
++ /* This pager_return_some is used only to set PM_FORCEREAD for the
++ page. DC_UNTOUCHED is set so that we catch if someone has
++ referenced the block while we didn't hold disk_cache_lock. */
++ disk_cache_info[index].flags |= DC_UNTOUCHED;
++
++#if 0 /* XXX: Let's see if this is needed at all. */
++
++ mutex_unlock (&disk_cache_lock);
++ pager_return_some (diskfs_disk_pager, bptr - disk_cache, vm_page_size, 1);
++ mutex_lock (&disk_cache_lock);
++
++ /* Has someone used our bptr? Has someone mapped requested block
++ while we have unlocked disk_cache_lock? If so, environment has
++ changed and we have to restart operation. */
++ if ((! (disk_cache_info[index].flags & DC_UNTOUCHED))
++ || hurd_ihash_find (disk_cache_bptr, block))
++ {
++ mutex_unlock (&disk_cache_lock);
++ return disk_cache_block_ref (block); /* tail recursion */
++ }
++
++#elif 0
++
++ /* XXX: Use libpager internals. */
++
++ mutex_lock (&diskfs_disk_pager->interlock);
++ int page = (bptr - disk_cache) / vm_page_size;
++ assert (page >= 0);
++ int is_incore = (page < diskfs_disk_pager->pagemapsize
++ && (diskfs_disk_pager->pagemap[page] & PM_INCORE));
++ mutex_unlock (&diskfs_disk_pager->interlock);
++ if (is_incore)
++ {
++ mutex_unlock (&disk_cache_lock);
++ printf ("INCORE\n");
++ return disk_cache_block_ref (block); /* tail recursion */
++ }
++
++#endif
++
++ /* Re-associate. */
++ if (disk_cache_info[index].block != DC_NO_BLOCK)
++ /* Remove old association. */
++ hurd_ihash_remove (disk_cache_bptr, disk_cache_info[index].block);
++ /* New association. */
++ if (hurd_ihash_add (disk_cache_bptr, block, bptr))
++ ext2_panic ("Couldn't hurd_ihash_add new disk block");
++ assert (! (disk_cache_info[index].flags & DC_DONT_REUSE & ~DC_UNTOUCHED));
++ disk_cache_info[index].block = block;
++ assert (! disk_cache_info[index].ref_count);
++ disk_cache_info[index].ref_count = 1;
++
++ /* All data structures are set up. */
++ mutex_unlock (&disk_cache_lock);
++
++ /* Try to read page. */
++ *(volatile char *) bptr;
++
++ /* Check if it's actually read. */
++ mutex_lock (&disk_cache_lock);
++ if (disk_cache_info[index].flags & DC_UNTOUCHED)
++ /* It's not read. */
++ {
++ /* Remove newly created association. */
++ hurd_ihash_remove (disk_cache_bptr, block);
++ disk_cache_info[index].block = DC_NO_BLOCK;
++ disk_cache_info[index].flags &=~ DC_UNTOUCHED;
++ disk_cache_info[index].ref_count = 0;
++ mutex_unlock (&disk_cache_lock);
++
++ /* Prepare next time association of this page to succeed. */
++ pager_flush_some (diskfs_disk_pager, bptr - disk_cache,
++ vm_page_size, 0);
++
++#if 0
++ printf ("Re-association failed.\n");
++#endif
++
++ /* Try again. */
++ return disk_cache_block_ref (block); /* tail recursion */
++ }
++ mutex_unlock (&disk_cache_lock);
++
++ /* Re-association was successful. */
++ condition_broadcast (&disk_cache_reassociation);
++
++ ext2_debug ("(%u) = %p", block, bptr);
++ return bptr;
++}
++
++void
++disk_cache_block_ref_ptr (void *ptr)
++{
++ int index;
++
++ mutex_lock (&disk_cache_lock);
++ index = bptr_index (ptr);
++ assert (disk_cache_info[index].ref_count >= 1);
++ assert (disk_cache_info[index].ref_count + 1
++ > disk_cache_info[index].ref_count);
++ disk_cache_info[index].ref_count++;
++ assert (! (disk_cache_info[index].flags & DC_UNTOUCHED));
++ ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)",
++ ptr,
++ disk_cache_info[index].ref_count,
++ disk_cache_info[index].flags);
++ mutex_unlock (&disk_cache_lock);
++}
++
++void
++disk_cache_block_deref (void *ptr)
++{
++ int index;
++
++ assert (disk_cache <= ptr && ptr <= disk_cache + disk_cache_size);
++
++ mutex_lock (&disk_cache_lock);
++ index = bptr_index (ptr);
++ ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)",
++ ptr,
++ disk_cache_info[index].ref_count - 1,
++ disk_cache_info[index].flags);
++ assert (! (disk_cache_info[index].flags & DC_UNTOUCHED));
++ assert (disk_cache_info[index].ref_count >= 1);
++ disk_cache_info[index].ref_count--;
++ mutex_unlock (&disk_cache_lock);
++}
++
++/* Not used. */
++int
++disk_cache_block_is_ref (block_t block)
++{
++ int ref;
++ void *ptr;
++
++ mutex_lock (&disk_cache_lock);
++ ptr = hurd_ihash_find (disk_cache_bptr, block);
++ if (! ptr)
++ ref = 0;
++ else /* XXX: Should check for DC_UNTOUCHED too. */
++ ref = disk_cache_info[bptr_index (ptr)].ref_count;
++ mutex_unlock (&disk_cache_lock);
++
++ return ref;
++}
++
+ /* Create the DISK pager. */
+ void
+ create_disk_pager (void)
+@@ -774,8 +1197,12 @@ create_disk_pager (void)
+ ext2_panic ("can't create disk pager: %s", strerror (errno));
+ upi->type = DISK;
+ pager_bucket = ports_create_bucket ();
+- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size,
+- &disk_image);
++ get_hypermetadata ();
++ disk_cache_blocks = DISK_CACHE_BLOCKS;
++ disk_cache_size = disk_cache_blocks << log2_block_size;
++ diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 1,
++ disk_cache_size, &disk_cache);
++ disk_cache_init ();
+ }
+
+ /* Call this to create a FILE_DATA pager and return a send right.
+@@ -815,7 +1242,7 @@ diskfs_get_filemap (struct node *node, v
+ diskfs_nref_light (node);
+ node->dn->pager =
+ pager_create (upi, pager_bucket, MAY_CACHE,
+- MEMORY_OBJECT_COPY_DELAY);
++ MEMORY_OBJECT_COPY_DELAY, 0);
+ if (node->dn->pager == 0)
+ {
+ diskfs_nrele_light (node);
+--- a/ext2fs/pokel.c
++++ b/ext2fs/pokel.c
+@@ -67,12 +67,27 @@ pokel_add (struct pokel *pokel, void *lo
+ vm_offset_t p_offs = pl->offset;
+ vm_size_t p_end = p_offs + pl->length;
+
+- if (p_offs == offset && p_end == end)
+- break;
++ if (p_offs <= offset && end <= p_end)
++ {
++ if (pokel->image == disk_cache)
++ for (vm_offset_t i = offset; i < end; i += block_size)
++ disk_cache_block_deref (disk_cache + i);
++
++ break;
++ }
+ else if (p_end >= offset && end >= p_offs)
+ {
+ pl->offset = offset < p_offs ? offset : p_offs;
+ pl->length = (end > p_end ? end : p_end) - pl->offset;
++
++ if (pokel->image == disk_cache)
++ {
++ vm_offset_t i_begin = p_offs > offset ? p_offs : offset;
++ vm_offset_t i_end = p_end < end ? p_end : end;
++ for (vm_offset_t i = i_begin; i < i_end; i += block_size)
++ disk_cache_block_deref (disk_cache + i);
++ }
++
+ ext2_debug ("extended 0x%x[%ul] to 0x%x[%ul]",
+ p_offs, p_end - p_offs, pl->offset, pl->length);
+ break;
+@@ -106,18 +121,28 @@ void
+ _pokel_exec (struct pokel *pokel, int sync, int wait)
+ {
+ struct poke *pl, *pokes, *last = NULL;
+-
++
+ spin_lock (&pokel->lock);
+ pokes = pokel->pokes;
+ pokel->pokes = NULL;
+ spin_unlock (&pokel->lock);
+
+ for (pl = pokes; pl; last = pl, pl = pl->next)
+- if (sync)
+- {
+- ext2_debug ("syncing 0x%x[%ul]", pl->offset, pl->length);
+- pager_sync_some (pokel->pager, pl->offset, pl->length, wait);
+- }
++ {
++ if (sync)
++ {
++ ext2_debug ("syncing 0x%x[%ul]", pl->offset, pl->length);
++ pager_sync_some (pokel->pager, pl->offset, pl->length, wait);
++ }
++
++ if (pokel->image == disk_cache)
++ {
++ vm_offset_t begin = trunc_block (pl->offset);
++ vm_offset_t end = round_block (pl->offset + pl->length);
++ for (vm_offset_t i = begin; i != end; i += block_size)
++ disk_cache_block_deref (pokel->image + i);
++ }
++ }
+
+ if (last)
+ {
+--- a/ext2fs/truncate.c
++++ b/ext2fs/truncate.c
+@@ -124,7 +124,7 @@ trunc_indirect (struct node *node, block
+ {
+ unsigned index;
+ int modified = 0, all_freed = 1;
+- block_t *ind_bh = (block_t *)bptr (*p);
++ block_t *ind_bh = (block_t *)disk_cache_block_ref (*p);
+ unsigned first = end < offset ? 0 : end - offset;
+
+ for (index = first; index < addr_per_block; index++)
+@@ -139,11 +139,16 @@ trunc_indirect (struct node *node, block
+
+ if (first == 0 && all_freed)
+ {
+- pager_flush_some (diskfs_disk_pager, boffs (*p), block_size, 1);
++ pager_flush_some (diskfs_disk_pager,
++ bptr_index (ind_bh) << log2_block_size,
++ block_size, 1);
+ free_block_run_free_ptr (fbr, p);
++ disk_cache_block_deref (ind_bh);
+ }
+ else if (modified)
+ record_indir_poke (node, ind_bh);
++ else
++ disk_cache_block_deref (ind_bh);
+ }
+ }
+
+@@ -218,7 +223,7 @@ poke_pages (memory_object_t obj, vm_offs
+ /* Flush all the data past the new size from the kernel. Also force any
+ delayed copies of this data to take place immediately. (We are implicitly
+ changing the data to zeros and doing it without the kernel's immediate
+- knowledge; accordingl we must help out the kernel thusly.) */
++ knowledge; accordingly we must help out the kernel thusly.) */
+ static void
+ force_delayed_copies (struct node *node, off_t length)
+ {
+--- a/fatfs/pager.c
++++ b/fatfs/pager.c
+@@ -596,6 +596,13 @@ pager_unlock_page (struct user_pager_inf
+ return 0;
+ }
+
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page)
++{
++ assert (!"unrequested notification on eviction");
++}
++
+ /* Grow the disk allocated to locked node NODE to be at least SIZE
+ bytes, and set NODE->allocsize to the actual allocated size. (If
+ the allocated size is already SIZE bytes, do nothing.) CRED
+@@ -752,7 +759,7 @@ create_fat_pager (void)
+ struct user_pager_info *upi = malloc (sizeof (struct user_pager_info));
+ upi->type = FAT;
+ pager_bucket = ports_create_bucket ();
+- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE,
++ diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0,
+ bytes_per_sector * sectors_per_fat,
+ &fat_image);
+ }
+@@ -794,7 +801,7 @@ diskfs_get_filemap (struct node *node, v
+ diskfs_nref_light (node);
+ node->dn->pager =
+ pager_create (upi, pager_bucket, MAY_CACHE,
+- MEMORY_OBJECT_COPY_DELAY);
++ MEMORY_OBJECT_COPY_DELAY, 0);
+ if (node->dn->pager == 0)
+ {
+ diskfs_nrele_light (node);
+--- a/isofs/pager.c
++++ b/isofs/pager.c
+@@ -94,6 +94,13 @@ pager_unlock_page (struct user_pager_inf
+ return EROFS;
+ }
+
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page)
++{
++ assert (!"unrequested notification on eviction");
++}
++
+ /* Tell how big the file is. */
+ error_t
+ pager_report_extent (struct user_pager_info *pager,
+@@ -137,7 +144,7 @@ create_disk_pager (void)
+ upi->type = DISK;
+ upi->np = 0;
+ pager_bucket = ports_create_bucket ();
+- diskfs_start_disk_pager (upi, pager_bucket, 1, store->size, &disk_image);
++ diskfs_start_disk_pager (upi, pager_bucket, 1, 0, store->size, &disk_image);
+ upi->p = diskfs_disk_pager;
+ }
+
+@@ -168,7 +175,8 @@ diskfs_get_filemap (struct node *np, vm_
+ upi->type = FILE_DATA;
+ upi->np = np;
+ diskfs_nref_light (np);
+- upi->p = pager_create (upi, pager_bucket, 1, MEMORY_OBJECT_COPY_DELAY);
++ upi->p = pager_create (upi, pager_bucket, 1,
++ MEMORY_OBJECT_COPY_DELAY, 0);
+ if (upi->p == 0)
+ {
+ diskfs_nrele_light (np);
+--- a/libdiskfs/disk-pager.c
++++ b/libdiskfs/disk-pager.c
+@@ -46,7 +46,8 @@ service_paging_requests (any_t arg)
+
+ void
+ diskfs_start_disk_pager (struct user_pager_info *upi,
+- struct port_bucket *pager_bucket, int may_cache,
++ struct port_bucket *pager_bucket,
++ int may_cache, int notify_on_evict,
+ size_t size, void **image)
+ {
+ error_t err;
+@@ -58,7 +59,8 @@ diskfs_start_disk_pager (struct user_pag
+
+ /* Create the pager. */
+ diskfs_disk_pager = pager_create (upi, pager_bucket,
+- may_cache, MEMORY_OBJECT_COPY_NONE);
++ may_cache, MEMORY_OBJECT_COPY_NONE,
++ notify_on_evict);
+ assert (diskfs_disk_pager);
+
+ /* Get a port to the disk pager. */
+--- a/libdiskfs/diskfs-pager.h
++++ b/libdiskfs/diskfs-pager.h
+@@ -33,7 +33,8 @@
+ mapped is returned in IMAGE. INFO, PAGER_BUCKET, & MAY_CACHE are passed
+ to `pager_create'. */
+ extern void diskfs_start_disk_pager (struct user_pager_info *info,
+- struct port_bucket *pager_bucket, int may_cache,
++ struct port_bucket *pager_bucket,
++ int may_cache, int notify_on_evict,
+ size_t size, void **image);
+
+ extern struct pager *diskfs_disk_pager;
+--- a/libpager/data-request.c
++++ b/libpager/data-request.c
+@@ -40,11 +40,11 @@ _pager_seqnos_memory_object_data_request
+ if (!p)
+ return EOPNOTSUPP;
+
+- /* Acquire the right to meddle with the pagemap */
++ /* Acquire the right to meddle with the pagemap. */
+ mutex_lock (&p->interlock);
+ _pager_wait_for_seqno (p, seqno);
+
+- /* sanity checks -- we don't do multi-page requests yet. */
++ /* Sanity checks -- we don't do multi-page requests yet. */
+ if (control != p->memobjcntl)
+ {
+ printf ("incg data request: wrong control port\n");
+@@ -121,7 +123,8 @@ _pager_seqnos_memory_object_data_request
+ goto error_read;
+
+ memory_object_data_supply (p->memobjcntl, offset, page, length, 1,
+- write_lock ? VM_PROT_WRITE : VM_PROT_NONE, 0,
++ write_lock ? VM_PROT_WRITE : VM_PROT_NONE,
++ p->notify_on_evict ? 1 : 0,
+ MACH_PORT_NULL);
+ mutex_lock (&p->interlock);
+ _pager_mark_object_error (p, offset, length, 0);
+--- a/libpager/data-return.c
++++ b/libpager/data-return.c
+@@ -39,6 +39,7 @@ _pager_do_write_request (mach_port_t obj
+ struct pager *p;
+ short *pm_entries;
+ int npages, i;
++ char *notified;
+ error_t *pagerrs;
+ struct lock_request *lr;
+ struct lock_list {struct lock_request *lr;
+@@ -71,9 +72,6 @@ _pager_do_write_request (mach_port_t obj
+ goto release_out;
+ }
+
+- if (! dirty)
+- goto release_out;
+-
+ if (p->pager_state != NORMAL)
+ {
+ printf ("pager in wrong state for write\n");
+@@ -83,6 +81,11 @@ _pager_do_write_request (mach_port_t obj
+ npages = length / __vm_page_size;
+ pagerrs = alloca (npages * sizeof (error_t));
+
++ notified = alloca (npages * (sizeof *notified));
++#ifndef NDEBUG
++ memset (notified, -1, npages * (sizeof *notified));
++#endif
++
+ _pager_block_termination (p); /* until we are done with the pagemap
+ when the write completes. */
+
+@@ -90,6 +93,23 @@ _pager_do_write_request (mach_port_t obj
+
+ pm_entries = &p->pagemap[offset / __vm_page_size];
+
++ if (! dirty && ! kcopy)
++ {
++ /* Prepare notified array. */
++ for (i = 0; i < npages; i++)
++ notified[i] = (p->notify_on_evict
++ && ! (pm_entries[i] & PM_PAGEINWAIT));
++
++ _pager_release_seqno (p, seqno);
++ goto notify;
++ }
++
++ if (! dirty)
++ {
++ _pager_allow_termination (p);
++ goto release_out;
++ }
++
+ /* Make sure there are no other in-progress writes for any of these
+ pages before we begin. This imposes a little more serialization
+ than we really have to require (because *all* future writes on
+@@ -120,10 +140,6 @@ _pager_do_write_request (mach_port_t obj
+ for (i = 0; i < npages; i++)
+ pm_entries[i] |= PM_PAGINGOUT | PM_INIT;
+
+- if (!kcopy)
+- for (i = 0; i < npages; i++)
+- pm_entries[i] &= ~PM_INCORE;
+-
+ /* If this write occurs while a lock is pending, record
+ it. We have to keep this list because a lock request
+ might come in while we do the I/O; in that case there
+@@ -163,7 +179,10 @@ _pager_do_write_request (mach_port_t obj
+ for (i = 0; i < npages; i++)
+ {
+ if (omitdata & (1 << i))
+- continue;
++ {
++ notified[i] = 0;
++ continue;
++ }
+
+ if (pm_entries[i] & PM_WRITEWAIT)
+ wakeup = 1;
+@@ -179,14 +198,22 @@ _pager_do_write_request (mach_port_t obj
+ pm_entries[i] |= PM_INVALID;
+
+ if (pm_entries[i] & PM_PAGEINWAIT)
+- memory_object_data_supply (p->memobjcntl,
+- offset + (vm_page_size * i),
+- data + (vm_page_size * i),
+- vm_page_size, 1,
+- VM_PROT_NONE, 0, MACH_PORT_NULL);
++ {
++ memory_object_data_supply (p->memobjcntl,
++ offset + (vm_page_size * i),
++ data + (vm_page_size * i),
++ vm_page_size, 1,
++ VM_PROT_NONE, 0, MACH_PORT_NULL);
++ notified[i] = 0;
++ }
+ else
+- munmap ((caddr_t) (data + (vm_page_size * i)),
+- vm_page_size);
++ {
++ munmap ((caddr_t) (data + (vm_page_size * i)),
++ vm_page_size);
++ notified[i] = (! kcopy && p->notify_on_evict);
++ if (! kcopy)
++ pm_entries[i] &= ~PM_INCORE;
++ }
+
+ pm_entries[i] &= ~(PM_PAGINGOUT | PM_PAGEINWAIT | PM_WRITEWAIT);
+ }
+@@ -198,10 +225,29 @@ _pager_do_write_request (mach_port_t obj
+ if (wakeup)
+ condition_broadcast (&p->wakeup);
+
++ notify:
+ _pager_allow_termination (p);
+-
+ mutex_unlock (&p->interlock);
+
++ for (i = 0; i < npages; i++)
++ {
++ assert (notified[i] == 0 || notified[i] == 1);
++ if (notified[i])
++ {
++ short *pm_entry = &pm_entries[i];
++
++ /* Do notify user. */
++ pager_notify_evict (p->upi, offset + (i * vm_page_size));
++
++ /* Clear any error that is left. Notification on eviction
++ is used only to change association of page, so any
++ error may no longer be valid. */
++ mutex_lock (&p->interlock);
++ *pm_entry = SET_PM_ERROR (SET_PM_NEXTERROR (*pm_entry, 0), 0);
++ mutex_unlock (&p->interlock);
++ }
++ }
++
+ ports_port_deref (p);
+ return 0;
+
+--- a/libpager/pager-create.c
++++ b/libpager/pager-create.c
+@@ -22,7 +22,8 @@ struct pager *
+ pager_create (struct user_pager_info *upi,
+ struct port_bucket *bucket,
+ boolean_t may_cache,
+- memory_object_copy_strategy_t copy_strategy)
++ memory_object_copy_strategy_t copy_strategy,
++ boolean_t notify_on_evict)
+ {
+ struct pager *p;
+
+@@ -38,6 +39,7 @@ pager_create (struct user_pager_info *up
+ p->attribute_requests = 0;
+ p->may_cache = may_cache;
+ p->copy_strategy = copy_strategy;
++ p->notify_on_evict = notify_on_evict;
+ p->memobjcntl = MACH_PORT_NULL;
+ p->memobjname = MACH_PORT_NULL;
+ p->seqno = -1;
+--- a/libpager/pager.h
++++ b/libpager/pager.h
+@@ -32,18 +32,21 @@ int pager_demuxer (mach_msg_header_t *in
+ mach_msg_header_t *outp);
+
+ /* Create a new pager. The pager will have a port created for it
+- (using libports, in BUCKET) and will be immediately ready
+- to receive requests. U_PAGER will be provided to later calls to
++ (using libports, in BUCKET) and will be immediately ready to
++ receive requests. U_PAGER will be provided to later calls to
+ pager_find_address. The pager will have one user reference
+ created. MAY_CACHE and COPY_STRATEGY are the original values of
+- those attributes as for memory_object_ready. Users may create
+- references to pagers by use of the relevant ports library
+- functions. On errors, return null and set errno. */
++ those attributes as for memory_object_ready. If NOTIFY_ON_EVICT is
++ non-zero, pager_notify_evict user callback will be called when page
++ is evicted. Users may create references to pagers by use of the
++ relevant ports library functions. On errors, return null and set
++ errno. */
+ struct pager *
+ pager_create (struct user_pager_info *u_pager,
+ struct port_bucket *bucket,
+ boolean_t may_cache,
+- memory_object_copy_strategy_t copy_strategy);
++ memory_object_copy_strategy_t copy_strategy,
++ boolean_t notify_on_evict);
+
+ /* Return the user_pager_info struct associated with a pager. */
+ struct user_pager_info *
+@@ -110,7 +113,7 @@ pager_offer_page (struct pager *pager,
+ /* Change the attributes of the memory object underlying pager PAGER.
+ Args MAY_CACHE and COPY_STRATEGY are as for
+ memory_object_change_atributes. Wait for the kernel to report completion
+- off WAIT is set.*/
++ iff WAIT is set. */
+ void
+ pager_change_attributes (struct pager *pager,
+ boolean_t may_cache,
+@@ -172,6 +175,18 @@ error_t
+ pager_unlock_page (struct user_pager_info *pager,
+ vm_offset_t address);
+
++/* The user must define this function. It is used when you want be
++ able to change association of pages to backing store. To use it,
++ pass non-zero value in NOTIFY_ON_EVICT when pager is created with
++ pager_create. You can change association of page only when
++ pager_notify_evict has been called and you haven't touched page
++ content after that. Note there is a possibility that a page is
++ evicted, but user is not notified about that. The user should be
++ able to handle this case. */
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page);
++
+ /* The user must define this function. It should report back (in
+ *OFFSET and *SIZE the minimum valid address the pager will accept
+ and the size of the object. */
+--- a/libpager/priv.h
++++ b/libpager/priv.h
+@@ -45,6 +45,7 @@ struct pager
+
+ boolean_t may_cache;
+ memory_object_copy_strategy_t copy_strategy;
++ boolean_t notify_on_evict;
+
+ /* Interface ports */
+ memory_object_control_t memobjcntl;
+--- a/storeio/pager.c
++++ b/storeio/pager.c
+@@ -109,6 +109,13 @@ pager_unlock_page (struct user_pager_inf
+ return 0;
+ }
+
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page)
++{
++ assert (!"unrequested notification on eviction");
++}
++
+ /* The user must define this function. It should report back (in
+ *OFFSET and *SIZE the minimum valid address the pager will accept
+ and the size of the object. */
+@@ -232,7 +239,7 @@ dev_get_memory_object (struct dev *dev,
+ {
+ dev->pager =
+ pager_create ((struct user_pager_info *)dev, pager_port_bucket,
+- 1, MEMORY_OBJECT_COPY_DELAY);
++ 1, MEMORY_OBJECT_COPY_DELAY, 0);
+ if (dev->pager == NULL)
+ {
+ mutex_unlock (&dev->pager_lock);
+--- a/tmpfs/pager-stubs.c
++++ b/tmpfs/pager-stubs.c
+@@ -57,6 +57,14 @@ pager_unlock_page (struct user_pager_inf
+ return EIEIO;
+ }
+
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page)
++{
++ abort();
++}
++
++
+ /* The user must define this function. It should report back (in
+ *OFFSET and *SIZE the minimum valid address the pager will accept
+ and the size of the object. */
+--- a/ufs/pager.c
++++ b/ufs/pager.c
+@@ -425,6 +425,13 @@ pager_unlock_page (struct user_pager_inf
+ return err;
+ }
+
++void
++pager_notify_evict (struct user_pager_info *pager,
++ vm_offset_t page)
++{
++ assert (!"unrequested notification on eviction");
++}
++
+ /* Implement the pager_report_extent callback from the pager library. See
+ <hurd/pager.h> for the interface description. */
+ inline error_t
+@@ -477,7 +484,7 @@ create_disk_pager (void)
+ upi->type = DISK;
+ upi->np = 0;
+ pager_bucket = ports_create_bucket ();
+- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size,
++ diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0, store->size,
+ &disk_image);
+ upi->p = diskfs_disk_pager;
+ }
+@@ -570,7 +577,7 @@ diskfs_get_filemap (struct node *np, vm_
+ upi->unlocked_pagein_length = 0;
+ diskfs_nref_light (np);
+ upi->p = pager_create (upi, pager_bucket,
+- MAY_CACHE, MEMORY_OBJECT_COPY_DELAY);
++ MAY_CACHE, MEMORY_OBJECT_COPY_DELAY, 0);
+ if (upi->p == 0)
+ {
+ diskfs_nrele_light (np);
diff --git a/debian/patches/ext2fs_nowait.patch b/debian/patches/ext2fs_nowait.patch
new file mode 100644
index 00000000..061f9760
--- /dev/null
+++ b/debian/patches/ext2fs_nowait.patch
@@ -0,0 +1,154 @@
+Avoid waiting for disk I/O completion. This improves performance quite a bit,
+and should not be less safe.
+
+diff --git a/ext2fs/dir.c b/ext2fs/dir.c
+index 66d8c8a..f0f52f7 100644
+--- a/ext2fs/dir.c
++++ b/ext2fs/dir.c
+@@ -690,7 +690,7 @@ diskfs_direnter_hard (struct node *dp, const char *name, struct node *np,
+ }
+ }
+
+- diskfs_file_update (dp, 1);
++ diskfs_file_update (dp, diskfs_synchronous);
+
+ return 0;
+ }
+@@ -727,7 +727,7 @@ diskfs_dirremove_hard (struct node *dp, struct dirstat *ds)
+ if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1)
+ dp->dn->dirents[ds->idx]--;
+
+- diskfs_file_update (dp, 1);
++ diskfs_file_update (dp, diskfs_synchronous);
+
+ return 0;
+ }
+@@ -753,7 +753,7 @@ diskfs_dirrewrite_hard (struct node *dp, struct node *np, struct dirstat *ds)
+
+ munmap ((caddr_t) ds->mapbuf, ds->mapextent);
+
+- diskfs_file_update (dp, 1);
++ diskfs_file_update (dp, diskfs_synchronous);
+
+ return 0;
+ }
+diff --git a/ext2fs/truncate.c b/ext2fs/truncate.c
+index 077225b..2058a1c 100644
+--- a/ext2fs/truncate.c
++++ b/ext2fs/truncate.c
+@@ -294,7 +294,7 @@ diskfs_truncate (struct node *node, off_t length)
+ node->dn_stat.st_size = length;
+ node->dn_set_mtime = 1;
+ node->dn_set_ctime = 1;
+- diskfs_node_update (node, 1);
++ diskfs_node_update (node, diskfs_synchronous);
+ return 0;
+ }
+
+@@ -309,6 +309,7 @@ diskfs_truncate (struct node *node, off_t length)
+ {
+ diskfs_node_rdwr (node, (void *)zeroblock, length, block_size - offset,
+ 1, 0, 0);
++ /* Make sure that really happens to avoid leaks. */
+ diskfs_file_update (node, 1);
+ }
+
+@@ -323,7 +324,7 @@ diskfs_truncate (struct node *node, off_t length)
+ node->dn_stat.st_size = length;
+ node->dn_set_mtime = 1;
+ node->dn_set_ctime = 1;
+- diskfs_node_update (node, 1);
++ diskfs_node_update (node, diskfs_synchronous);
+
+ err = diskfs_catch_exception ();
+ if (!err)
+diff --git a/libdiskfs/dir-init.c b/libdiskfs/dir-init.c
+index 2cba3a4..4efded0 100644
+--- a/libdiskfs/dir-init.c
++++ b/libdiskfs/dir-init.c
+@@ -63,6 +63,6 @@ diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred)
+ return err;
+ }
+
+- diskfs_node_update (dp, 1);
++ diskfs_node_update (dp, diskfs_synchronous);
+ return 0;
+ }
+diff --git a/libdiskfs/dir-link.c b/libdiskfs/dir-link.c
+index 7cc8863..df1bb6a 100644
+--- a/libdiskfs/dir-link.c
++++ b/libdiskfs/dir-link.c
+@@ -101,7 +101,7 @@ diskfs_S_dir_link (struct protid *dircred,
+ }
+ np->dn_stat.st_nlink++;
+ np->dn_set_ctime = 1;
+- diskfs_node_update (np, 1);
++ diskfs_node_update (np, diskfs_synchronous);
+
+ /* Attach it */
+ if (tnp)
+diff --git a/libdiskfs/dir-rename.c b/libdiskfs/dir-rename.c
+index 867e395..298669b 100644
+--- a/libdiskfs/dir-rename.c
++++ b/libdiskfs/dir-rename.c
+@@ -164,7 +164,7 @@ diskfs_S_dir_rename (struct protid *fromcred,
+ }
+ fnp->dn_stat.st_nlink++;
+ fnp->dn_set_ctime = 1;
+- diskfs_node_update (fnp, 1);
++ diskfs_node_update (fnp, diskfs_synchronous);
+
+ if (tnp)
+ {
+diff --git a/libdiskfs/dir-renamed.c b/libdiskfs/dir-renamed.c
+index ce8f415..319a41a 100644
+--- a/libdiskfs/dir-renamed.c
++++ b/libdiskfs/dir-renamed.c
+@@ -177,7 +177,7 @@ diskfs_rename_dir (struct node *fdp, struct node *fnp, const char *fromname,
+ }
+ fnp->dn_stat.st_nlink++;
+ fnp->dn_set_ctime = 1;
+- diskfs_node_update (fnp, 1);
++ diskfs_node_update (fnp, diskfs_synchronous);
+
+ if (tnp)
+ {
+diff --git a/libdiskfs/file-set-trans.c b/libdiskfs/file-set-trans.c
+index 26a19eb..c9b2c61 100644
+--- a/libdiskfs/file-set-trans.c
++++ b/libdiskfs/file-set-trans.c
+@@ -196,7 +196,7 @@ diskfs_S_file_set_translator (struct protid *cred,
+ if (!error)
+ {
+ np->dn_stat.st_mode = newmode;
+- diskfs_node_update (np, 1);
++ diskfs_node_update (np, diskfs_synchronous);
+ }
+ mutex_unlock (&np->lock);
+ return error;
+diff --git a/libdiskfs/node-create.c b/libdiskfs/node-create.c
+index 4a7d108..5b5e463 100644
+--- a/libdiskfs/node-create.c
++++ b/libdiskfs/node-create.c
+@@ -131,7 +131,7 @@ diskfs_create_node (struct node *dir,
+ if (S_ISDIR (mode))
+ err = diskfs_init_dir (np, dir, cred);
+
+- diskfs_node_update (np, 1);
++ diskfs_node_update (np, diskfs_synchronous);
+
+ if (err)
+ {
+diff --git a/libdiskfs/node-drop.c b/libdiskfs/node-drop.c
+index f44966b..c3d32c9 100644
+--- a/libdiskfs/node-drop.c
++++ b/libdiskfs/node-drop.c
+@@ -78,7 +78,7 @@ diskfs_drop_node (struct node *np)
+ np->dn_stat.st_mode = 0;
+ np->dn_stat.st_rdev = 0;
+ np->dn_set_ctime = np->dn_set_atime = 1;
+- diskfs_node_update (np, 1);
++ diskfs_node_update (np, diskfs_synchronous);
+ diskfs_free_node (np, savemode);
+ }
+ else
diff --git a/debian/patches/extern_inline_fix.patch b/debian/patches/extern_inline_fix.patch
new file mode 100644
index 00000000..b9eacbff
--- /dev/null
+++ b/debian/patches/extern_inline_fix.patch
@@ -0,0 +1,734 @@
+Use libc's __extern_inline which works properly according to optimization flags
+---
+ libdiskfs/diskfs.h | 17 ++++++----
+ libpipe/pipe.h | 74 ++++++++++++++++++++++++++++++++------------
+ libpipe/pq.h | 57 ++++++++++++++++++++++++++-------
+ libshouldbeinlibc/idvec.h | 29 ++++++++++++-----
+ libshouldbeinlibc/maptime.h | 13 ++++---
+ libshouldbeinlibc/ugids.h | 25 ++++++++++----
+ libstore/store.h | 13 ++++---
+ libthreads/rwlock.h | 27 +++++++++++-----
+ 8 files changed, 184 insertions(+), 71 deletions(-)
+
+--- a/libdiskfs/diskfs.h
++++ b/libdiskfs/diskfs.h
+@@ -27,10 +27,7 @@
+ #include <hurd/fshelp.h>
+ #include <hurd/iohelp.h>
+ #include <idvec.h>
+-
+-#ifndef DISKFS_EXTERN_INLINE
+-#define DISKFS_EXTERN_INLINE extern inline
+-#endif
++#include <features.h>
+
+ /* Each user port referring to a file points to one of these
+ (with the aid of the ports library). */
+@@ -781,10 +778,16 @@ error_t diskfs_start_protid (struct pero
+ the user to install is USER. */
+ void diskfs_finish_protid (struct protid *cred, struct iouser *user);
+
++extern struct protid * diskfs_begin_using_protid_port (file_t port);
++
++extern void diskfs_end_using_protid_port (struct protid *cred);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Called by MiG to translate ports into struct protid *.
+ fsmutations.h arranges for this to happen for the io and
+ fs interfaces. */
+-DISKFS_EXTERN_INLINE struct protid *
++__extern_inline struct protid *
+ diskfs_begin_using_protid_port (file_t port)
+ {
+ return ports_lookup_port (diskfs_port_bucket, port, diskfs_protid_class);
+@@ -793,13 +796,15 @@ diskfs_begin_using_protid_port (file_t p
+ /* Called by MiG after server routines have been run; this
+ balances begin_using_protid_port, and is arranged for the io
+ and fs interfaces by fsmutations.h. */
+-DISKFS_EXTERN_INLINE void
++__extern_inline void
+ diskfs_end_using_protid_port (struct protid *cred)
+ {
+ if (cred)
+ ports_port_deref (cred);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Called when a protid CRED has no more references. (Because references\
+ to protids are maintained by the port management library, this is
+ installed in the clean routines list.) The ports library will
+--- a/libpipe/pipe.h
++++ b/libpipe/pipe.h
+@@ -24,13 +24,10 @@
+ #define EWOULDBLOCK EAGAIN /* XXX */
+
+ #include <cthreads.h> /* For conditions & mutexes */
++#include <features.h>
+
+ #include "pq.h"
+
+-#ifndef PIPE_EI
+-#define PIPE_EI extern inline
+-#endif
+-
+
+ /* A description of a class of pipes and how to operate on them. */
+ struct pipe_class
+@@ -107,9 +104,24 @@ struct pipe
+ /* Pipe flags. */
+ #define PIPE_BROKEN 0x1 /* This pipe isn't connected. */
+
++
++extern size_t pipe_readable (struct pipe *pipe, int data_only);
++
++extern int pipe_is_readable (struct pipe *pipe, int data_only);
++
++extern error_t pipe_wait_readable (struct pipe *pipe, int noblock, int data_only);
++
++extern error_t pipe_select_readable (struct pipe *pipe, int data_only);
++
++extern error_t pipe_wait_writable (struct pipe *pipe, int noblock);
++
++extern error_t pipe_select_writable (struct pipe *pipe);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the number of characters quickly readable from PIPE. If DATA_ONLY
+ is true, then `control' packets are ignored. */
+-PIPE_EI size_t
++__extern_inline size_t
+ pipe_readable (struct pipe *pipe, int data_only)
+ {
+ size_t readable = 0;
+@@ -128,7 +140,7 @@ pipe_readable (struct pipe *pipe, int da
+ then `control' packets are ignored. Note that this is different than
+ (pipe_readable (PIPE) > 0) in the case where a control packet containing
+ only ports is present. */
+-PIPE_EI int
++__extern_inline int
+ pipe_is_readable (struct pipe *pipe, int data_only)
+ {
+ struct pq *pq = pipe->queue;
+@@ -143,7 +155,7 @@ pipe_is_readable (struct pipe *pipe, int
+ this operation will return EWOULDBLOCK instead of blocking when no data is
+ immediately available. If DATA_ONLY is true, then `control' packets are
+ ignored. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_wait_readable (struct pipe *pipe, int noblock, int data_only)
+ {
+ while (! pipe_is_readable (pipe, data_only) && ! (pipe->flags & PIPE_BROKEN))
+@@ -160,7 +172,7 @@ pipe_wait_readable (struct pipe *pipe, i
+ returns once threads waiting using pipe_wait_readable have been woken and
+ given a chance to read, and if there is still data available thereafter.
+ If DATA_ONLY is true, then `control' packets are ignored. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_select_readable (struct pipe *pipe, int data_only)
+ {
+ while (! pipe_is_readable (pipe, data_only) && ! (pipe->flags & PIPE_BROKEN))
+@@ -172,7 +184,7 @@ pipe_select_readable (struct pipe *pipe,
+ /* Block until data can be written to PIPE. If NOBLOCK is true, then
+ EWOULDBLOCK is returned instead of blocking if this can't be done
+ immediately. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_wait_writable (struct pipe *pipe, int noblock)
+ {
+ size_t limit = pipe->write_limit;
+@@ -193,7 +205,7 @@ pipe_wait_writable (struct pipe *pipe, i
+ /* Block until some data can be written to PIPE. This call only returns once
+ threads waiting using pipe_wait_writable have been woken and given a
+ chance to write, and if there is still space available thereafter. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_select_writable (struct pipe *pipe)
+ {
+ size_t limit = pipe->write_limit;
+@@ -203,6 +215,8 @@ pipe_select_writable (struct pipe *pipe)
+ return 0;
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Creates a new pipe of class CLASS and returns it in RESULT. */
+ error_t pipe_create (struct pipe_class *class, struct pipe **pipe);
+
+@@ -223,8 +237,28 @@ void _pipe_no_readers (struct pipe *pipe
+ should be locked. */
+ void _pipe_no_writers (struct pipe *pipe);
+
++extern void pipe_acquire_reader (struct pipe *pipe);
++
++extern void pipe_acquire_writer (struct pipe *pipe);
++
++extern void pipe_release_reader (struct pipe *pipe);
++
++extern void pipe_release_writer (struct pipe *pipe);
++
++extern void pipe_add_reader (struct pipe *pipe);
++
++extern void pipe_add_writer (struct pipe *pipe);
++
++extern void pipe_remove_reader (struct pipe *pipe);
++
++extern void pipe_remove_writer (struct pipe *pipe);
++
++extern void pipe_drain (struct pipe *pipe);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Lock PIPE and increment its readers count. */
+-PIPE_EI void
++__extern_inline void
+ pipe_acquire_reader (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -233,7 +267,7 @@ pipe_acquire_reader (struct pipe *pipe)
+ }
+
+ /* Lock PIPE and increment its writers count. */
+-PIPE_EI void
++__extern_inline void
+ pipe_acquire_writer (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -243,7 +277,7 @@ pipe_acquire_writer (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be locked) reader count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_release_reader (struct pipe *pipe)
+ {
+ if (--pipe->readers == 0)
+@@ -254,7 +288,7 @@ pipe_release_reader (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be locked) writer count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_release_writer (struct pipe *pipe)
+ {
+ if (--pipe->writers == 0)
+@@ -264,7 +298,7 @@ pipe_release_writer (struct pipe *pipe)
+ }
+
+ /* Increment PIPE's reader count. PIPE should be unlocked. */
+-PIPE_EI void
++__extern_inline void
+ pipe_add_reader (struct pipe *pipe)
+ {
+ pipe_acquire_reader (pipe);
+@@ -272,7 +306,7 @@ pipe_add_reader (struct pipe *pipe)
+ }
+
+ /* Increment PIPE's writer count. PIPE should be unlocked. */
+-PIPE_EI void
++__extern_inline void
+ pipe_add_writer (struct pipe *pipe)
+ {
+ pipe_acquire_writer (pipe);
+@@ -281,7 +315,7 @@ pipe_add_writer (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be unlocked) reader count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_remove_reader (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -290,7 +324,7 @@ pipe_remove_reader (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be unlocked) writer count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_remove_writer (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -298,12 +332,14 @@ pipe_remove_writer (struct pipe *pipe)
+ }
+
+ /* Empty out PIPE of any data. PIPE should be locked. */
+-PIPE_EI void
++__extern_inline void
+ pipe_drain (struct pipe *pipe)
+ {
+ pq_drain (pipe->queue);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Writes up to LEN bytes of DATA, to PIPE, which should be locked, and
+ returns the amount written in AMOUNT. If present, the information in
+ CONTROL & PORTS is written in a preceding control packet. If an error is
+--- a/libpipe/pq.h
++++ b/libpipe/pq.h
+@@ -25,10 +25,7 @@
+ #include <stddef.h> /* for size_t */
+ #include <string.h>
+ #include <mach/mach.h>
+-
+-#ifndef PQ_EI
+-#define PQ_EI extern inline
+-#endif
++#include <features.h>
+
+
+ struct packet
+@@ -70,13 +67,19 @@ error_t packet_set_ports (struct packet
+ /* If PACKET has any ports, deallocates them. */
+ void packet_dealloc_ports (struct packet *packet);
+
++extern size_t packet_readable (struct packet *packet);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the number of bytes of data in PACKET. */
+-PQ_EI size_t
++__extern_inline size_t
+ packet_readable (struct packet *packet)
+ {
+ return packet->buf_end - packet->buf_start;
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Append the bytes in DATA, of length DATA_LEN, to what's already in PACKET,
+ and return the amount appended in AMOUNT if that's not the null pointer. */
+ error_t packet_write (struct packet *packet,
+@@ -94,14 +97,20 @@ error_t packet_read (struct packet *pack
+ error_t packet_read_ports (struct packet *packet,
+ mach_port_t **ports, size_t *num_ports);
+
++extern void packet_read_source (struct packet *packet, void **source);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Return the source addressd in PACKET in SOURCE, deallocating it from
+ PACKET. */
+-PQ_EI void
++__extern_inline void
+ packet_read_source (struct packet *packet, void **source)
+ {
+ *source = packet->source;
+ packet->source = 0;
+ }
++
++# endif /* Use extern inlines. */
+
+ /* The packet size above which we start to do things differently to avoid
+ copying around data. */
+@@ -125,9 +134,17 @@ int packet_extend (struct packet *packet
+ returned. */
+ error_t packet_realloc (struct packet *packet, size_t new_len);
+
++extern int packet_fit (struct packet *packet, size_t amount);
++
++extern error_t packet_ensure (struct packet *packet, size_t amount);
++
++extern int packet_ensure_efficiently (struct packet *packet, size_t amount);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Try to make space in PACKET for AMOUNT more bytes without growing the
+ buffer, returning true if we could do it. */
+-PQ_EI int
++__extern_inline int
+ packet_fit (struct packet *packet, size_t amount)
+ {
+ char *buf = packet->buf, *end = packet->buf_end;
+@@ -159,7 +176,7 @@ packet_fit (struct packet *packet, size_
+
+ /* Make sure that PACKET has room for at least AMOUNT more bytes, or return
+ the reason why not. */
+-PQ_EI error_t
++__extern_inline error_t
+ packet_ensure (struct packet *packet, size_t amount)
+ {
+ if (! packet_fit (packet, amount))
+@@ -176,7 +193,7 @@ packet_ensure (struct packet *packet, si
+ it can be done efficiently, e.g., the packet can be grown in place, rather
+ than moving the contents (or there is little enough data so that copying
+ it is OK). True is returned if room was made, false otherwise. */
+-PQ_EI int
++__extern_inline int
+ packet_ensure_efficiently (struct packet *packet, size_t amount)
+ {
+ if (! packet_fit (packet, amount))
+@@ -189,6 +206,8 @@ packet_ensure_efficiently (struct packet
+ }
+ return 0;
+ }
++
++# endif /* Use extern inlines. */
+
+ struct pq
+ {
+@@ -201,10 +220,14 @@ struct pq
+ the packet, or deallocated by calling pipe_dealloc_addr. */
+ struct packet *pq_queue (struct pq *pq, unsigned type, void *source);
+
++extern struct packet * pq_tail (struct pq *pq, unsigned type, void *source);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the tail of the packet queue PQ, which may mean pushing a new
+ packet if TYPE and SOURCE do not match the current tail, or this is the
+ first packet. */
+-PQ_EI struct packet *
++__extern_inline struct packet *
+ pq_tail (struct pq *pq, unsigned type, void *source)
+ {
+ struct packet *tail = pq->tail;
+@@ -214,16 +237,24 @@ pq_tail (struct pq *pq, unsigned type, v
+ return tail;
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Remove the first packet (if any) in PQ, deallocating any resources it
+ holds. True is returned if a packet was found, false otherwise. */
+ int pq_dequeue (struct pq *pq);
+
++extern struct packet * pq_head (struct pq *pq, unsigned type, void *source);
++
++extern struct packet * pq_next (struct pq *pq, unsigned type, void *source);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the next available packet in PQ, without removing it from the
+ queue, or NULL if there is none, or the next packet isn't appropriate.
+ A packet is inappropriate if SOURCE is non-NULL its source field doesn't
+ match it, or TYPE is non-NULL and the packet's type field doesn't match
+ it. */
+-PQ_EI struct packet *
++__extern_inline struct packet *
+ pq_head (struct pq *pq, unsigned type, void *source)
+ {
+ struct packet *head = pq->head;
+@@ -237,7 +268,7 @@ pq_head (struct pq *pq, unsigned type, v
+ }
+
+ /* The same as pq_head, but first discards the head of the queue. */
+-PQ_EI struct packet *
++__extern_inline struct packet *
+ pq_next (struct pq *pq, unsigned type, void *source)
+ {
+ if (!pq->head)
+@@ -246,6 +277,8 @@ pq_next (struct pq *pq, unsigned type, v
+ return pq_head (pq, type, source);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Dequeues all packets in PQ. */
+ void pq_drain (struct pq *pq);
+
+--- a/libshouldbeinlibc/idvec.h
++++ b/libshouldbeinlibc/idvec.h
+@@ -24,10 +24,7 @@
+ #include <hurd/hurd_types.h>
+ #include <errno.h>
+ #include <string.h>
+-
+-#ifndef IDVEC_EI
+-#define IDVEC_EI extern inline
+-#endif
++#include <features.h>
+
+ struct idvec
+ {
+@@ -50,22 +47,30 @@ void idvec_free_wrapper (struct idvec *i
+ /* Free IDVEC and any storage associated with it. */
+ void idvec_free (struct idvec *idvec);
+
++extern void idvec_clear (struct idvec *idvec);
++
++extern int idvec_is_empty (const struct idvec *idvec);
++
++extern int idvec_equal (const struct idvec *idvec1, const struct idvec *idvec2);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Mark IDVEC as not containing any ids. */
+-IDVEC_EI void
++__extern_inline void
+ idvec_clear (struct idvec *idvec)
+ {
+ idvec->num = 0;
+ }
+
+ /* Returns true if IDVEC contains no ids. */
+-IDVEC_EI int
++__extern_inline int
+ idvec_is_empty (const struct idvec *idvec)
+ {
+ return idvec->num == 0;
+ }
+
+ /* Return true if IDVEC1 has contents identical to IDVEC2. */
+-IDVEC_EI int
++__extern_inline int
+ idvec_equal (const struct idvec *idvec1, const struct idvec *idvec2)
+ {
+ size_t num = idvec1->num;
+@@ -74,6 +79,8 @@ idvec_equal (const struct idvec *idvec1,
+ || memcmp (idvec1->ids, idvec2->ids, num * sizeof *idvec1->ids) == 0);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Ensure that IDVEC has enough spaced allocated to hold NUM ids, thus
+ ensuring that any subsequent ids added won't return a memory allocation
+ error unless it would result in more ids that NUM. ENOMEM is returned if
+@@ -87,13 +94,19 @@ error_t idvec_grow (struct idvec *idvec,
+ /* Returns true if IDVEC contains ID, at or after position POS. */
+ int idvec_tail_contains (const struct idvec *idvec, unsigned pos, uid_t id);
+
++extern int idvec_contains (const struct idvec *idvec, uid_t id);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns true if IDVEC contains ID. */
+-IDVEC_EI int
++__extern_inline int
+ idvec_contains (const struct idvec *idvec, uid_t id)
+ {
+ return idvec_tail_contains (idvec, 0, id);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Insert ID into IDVEC at position POS, returning ENOMEM if there wasn't
+ enough memory, or 0. */
+ error_t idvec_insert (struct idvec *idvec, unsigned pos, uid_t id);
+--- a/libshouldbeinlibc/maptime.h
++++ b/libshouldbeinlibc/maptime.h
+@@ -21,13 +21,10 @@
+ #ifndef __MAPTIME_H__
+ #define __MAPTIME_H__
+
+-#ifndef MAPTIME_EI
+-#define MAPTIME_EI extern inline
+-#endif
+-
+ #include <mach/time_value.h>
+ #include <sys/time.h>
+ #include <errno.h>
++#include <features.h>
+
+ /* Return the mach mapped time page in MTIME. If USE_MACH_DEV is false, then
+ the hurd time device DEV_NAME, or "/dev/time" if DEV_NAME is 0, is
+@@ -37,8 +34,12 @@
+ error_t maptime_map (int use_mach_dev, char *dev_name,
+ volatile struct mapped_time_value **mtime);
+
++extern void maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Read the current time from MTIME into TV. This should be very fast. */
+-MAPTIME_EI void
++__extern_inline void
+ maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv)
+ {
+ do
+@@ -49,4 +50,6 @@ maptime_read (volatile struct mapped_tim
+ while (tv->tv_sec != mtime->check_seconds);
+ }
+
++# endif /* Use extern inlines. */
++
+ #endif /* __MAPTIME_H__ */
+--- a/libshouldbeinlibc/ugids.h
++++ b/libshouldbeinlibc/ugids.h
+@@ -23,10 +23,7 @@
+
+ #include <stdlib.h> /* For inline function stuff. */
+ #include <idvec.h>
+-
+-#ifndef UGIDS_EI
+-#define UGIDS_EI extern inline
+-#endif
++#include <features.h>
+
+ /* A structure holding a set of the common various types of ids. */
+ struct ugids
+@@ -47,8 +44,18 @@ struct ugids
+ /* Return a new ugids structure, or 0 if an allocation error occurs. */
+ struct ugids *make_ugids ();
+
++extern void ugids_fini (struct ugids *ugids);
++
++extern void ugids_free (struct ugids *ugids);
++
++extern int ugids_is_empty (const struct ugids *ugids);
++
++extern int ugids_equal (const struct ugids *ugids1, const struct ugids *ugids2);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Free all resources used by UGIDS except UGIDS itself. */
+-UGIDS_EI void
++__extern_inline void
+ ugids_fini (struct ugids *ugids)
+ {
+ idvec_fini (&ugids->eff_uids);
+@@ -60,7 +67,7 @@ ugids_fini (struct ugids *ugids)
+ }
+
+ /* Free all resources used by UGIDS. */
+-UGIDS_EI void
++__extern_inline void
+ ugids_free (struct ugids *ugids)
+ {
+ ugids_fini (ugids);
+@@ -68,7 +75,7 @@ ugids_free (struct ugids *ugids)
+ }
+
+ /* Return true if UGIDS contains no ids. */
+-UGIDS_EI int
++__extern_inline int
+ ugids_is_empty (const struct ugids *ugids)
+ {
+ /* We needn't test the imp_*_gids vectors because they are subsets of the
+@@ -81,7 +88,7 @@ ugids_is_empty (const struct ugids *ugid
+ }
+
+ /* Free all resources used by UGIDS except UGIDS itself. */
+-UGIDS_EI int
++__extern_inline int
+ ugids_equal (const struct ugids *ugids1, const struct ugids *ugids2)
+ {
+ return
+@@ -93,6 +100,8 @@ ugids_equal (const struct ugids *ugids1,
+ && idvec_equal (&ugids1->imp_avail_gids, &ugids2->imp_avail_gids);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Add all ids in NEW to UGIDS. */
+ error_t ugids_merge (struct ugids *ugids, const struct ugids *new);
+
+--- a/libstore/store.h
++++ b/libstore/store.h
+@@ -33,10 +33,7 @@
+ #include <mach.h>
+ #include <device/device.h>
+ #include <hurd/hurd_types.h>
+-
+-#ifndef STORE_EI
+-#define STORE_EI extern inline
+-#endif
++#include <features.h>
+
+
+ /* Type for addresses inside the store. */
+@@ -270,9 +267,13 @@ error_t store_set_child_flags (struct st
+ STORE's flags. */
+ error_t store_clear_child_flags (struct store *store, int flags);
+
++extern int store_is_securely_returnable (struct store *store, int open_flags);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns true if STORE can safely be returned to a user who has accessed it
+ via a node using OPEN_FLAGS, without compromising security. */
+-STORE_EI int
++__extern_inline int
+ store_is_securely_returnable (struct store *store, int open_flags)
+ {
+ int flags = store->flags;
+@@ -283,6 +284,8 @@ store_is_securely_returnable (struct sto
+ || (flags & STORE_HARD_READONLY)));
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Fills in the values of the various fields in STORE that are derivable from
+ the set of runs & the block size. */
+ void _store_derive (struct store *store);
+--- a/libthreads/rwlock.h
++++ b/libthreads/rwlock.h
+@@ -21,6 +21,7 @@
+
+ #include <cthreads.h>
+ #include <assert.h>
++#include <features.h>
+
+ struct rwlock
+ {
+@@ -31,12 +32,20 @@ struct rwlock
+ int readers_waiting;
+ };
+
+-#ifndef RWLOCK_EI
+-#define RWLOCK_EI extern inline
+-#endif
++extern void rwlock_reader_lock (struct rwlock *lock);
++
++extern void rwlock_writer_lock (struct rwlock *lock);
++
++extern void rwlock_reader_unlock (struct rwlock *lock);
++
++extern void rwlock_writer_unlock (struct rwlock *lock);
++
++extern void rwlock_init (struct rwlock *lock);
++
++# ifdef __USE_EXTERN_INLINES
+
+ /* Get a reader lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_reader_lock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -53,7 +62,7 @@ rwlock_reader_lock (struct rwlock *lock)
+ }
+
+ /* Get a writer lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_writer_lock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -70,7 +79,7 @@ rwlock_writer_lock (struct rwlock *lock)
+ }
+
+ /* Release a reader lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_reader_unlock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -82,7 +91,7 @@ rwlock_reader_unlock (struct rwlock *loc
+ }
+
+ /* Release a writer lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_writer_unlock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -94,7 +103,7 @@ rwlock_writer_unlock (struct rwlock *loc
+ }
+
+ /* Initialize reader-writer lock LOCK */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_init (struct rwlock *lock)
+ {
+ mutex_init (&lock->master);
+@@ -104,6 +113,8 @@ rwlock_init (struct rwlock *lock)
+ lock->writers_waiting = 0;
+ }
+
++# endif /* Use extern inlines. */
++
+ #define RWLOCK_INITIALIZER \
+ { MUTEX_INITIALIZER, CONDITION_INITIALIZER, 0, 0, 0 }
+
diff --git a/debian/patches/hurd_console_startup.patch b/debian/patches/hurd_console_startup.patch
new file mode 100644
index 00000000..8e9301c8
--- /dev/null
+++ b/debian/patches/hurd_console_startup.patch
@@ -0,0 +1,32 @@
+Automatically startup the hurd console when enabled.
+---
+ daemons/runsystem.sh | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/daemons/runsystem.sh
++++ b/daemons/runsystem.sh
+@@ -127,10 +127,24 @@ while : ; do
+ trap "kill -$sig \${runttys_pid}" $sig
+ done
+
++ # Touch the first tty so that the Hurd console is certain to pick it
++ # and not some random other tty.
++ touch /dev/tty1
++
+ # This program reads /etc/ttys and starts the programs it says to.
+ ${RUNTTYS} &
+ runttys_pid=$!
+
++ # Startup the Hurd console if configured.
++ if [ -e /etc/default/hurd-console ]; then
++ unset DISPLAY KBD KBD_REPEAT MOUSE MOUSE_REPEAT SPEAKER
++ . /etc/default/hurd-console
++ fi
++ if [ "$ENABLE" = "true" ]; then
++ console ${DISPLAY} ${KBD} ${KBD_REPEAT} \
++ ${SPEAKER} ${MOUSE} ${MOUSE_REPEAT} -d current_vcs -c /dev/vcs
++ fi
++
+ # Wait for runttys to die, meanwhile handling trapped signals.
+ wait
+
diff --git a/debian/patches/init_try_runsystem.gnu.patch b/debian/patches/init_try_runsystem.gnu.patch
new file mode 100644
index 00000000..817a6d84
--- /dev/null
+++ b/debian/patches/init_try_runsystem.gnu.patch
@@ -0,0 +1,75 @@
+Also try runsystem.gnu
+---
+ daemons/console-run.c | 7 +++++++
+ init/init.c | 24 ++++++++++++++++++++----
+ 2 files changed, 27 insertions(+), 4 deletions(-)
+
+--- a/init/init.c
++++ b/init/init.c
+@@ -1082,10 +1082,12 @@ start_child (const char *prog, char **pr
+ static void
+ launch_something (const char *why)
+ {
++ file_t something;
+ static unsigned int try;
+ static const char *const tries[] =
+ {
+ "/libexec/runsystem",
++ "/libexec/runsystem.gnu",
+ _PATH_BSHELL,
+ "/bin/shd", /* XXX */
+ };
+@@ -1093,12 +1095,26 @@ launch_something (const char *why)
+ if (why)
+ error (0, 0, "%s %s", tries[try - 1], why);
+
+- if (try == 0 && start_child (tries[try++], &global_argv[1]) == 0)
+- return;
++ something = file_name_lookup (tries[try], O_EXEC, 0);
++ if (something != MACH_PORT_NULL)
++ {
++ mach_port_deallocate (mach_task_self (), something);
++ if (try == 0 && start_child (tries[try++], &global_argv[1]) == 0)
++ return;
++ }
++ else
++ try++;
+
+ while (try < sizeof tries / sizeof tries[0])
+- if (start_child (tries[try++], NULL) == 0)
+- return;
++ {
++ something = file_name_lookup (tries[try], O_EXEC, 0);
++ if (something != MACH_PORT_NULL)
++ {
++ mach_port_deallocate (mach_task_self (), something);
++ if (start_child (tries[try++], NULL) == 0)
++ return;
++ }
++ }
+
+ crash_system ();
+ }
+--- a/daemons/console-run.c
++++ b/daemons/console-run.c
+@@ -49,6 +49,7 @@ int
+ main (int argc, char **argv)
+ {
+ mach_port_t consdev = get_console ();
++ mach_port_t runsystem;
+ char *consname;
+
+ if (consdev == MACH_PORT_NULL)
+@@ -62,6 +63,12 @@ main (int argc, char **argv)
+ if (argc < 2)
+ error (1, 0, "Usage: %s PROGRAM [ARG...]", program_invocation_short_name);
+
++ /* Check whether runsystem exists before opening a console for it. */
++ runsystem = file_name_lookup (argv[1], O_RDONLY, 0);
++ if (runsystem == MACH_PORT_NULL)
++ error (127, errno, "cannot open file `%s' for execution", argv[1]);
++ mach_port_deallocate (mach_task_self (), runsystem);
++
+ if (open_console (&consname))
+ setenv ("FALLBACK_CONSOLE", consname, 1);
+
diff --git a/debian/patches/install-msgids.diff b/debian/patches/install-msgids.diff
new file mode 100644
index 00000000..305e0e0d
--- /dev/null
+++ b/debian/patches/install-msgids.diff
@@ -0,0 +1,36 @@
+2005-08-25 Alfred M. Szmidt <ams@gnu.org>
+
+ * Makefile (MSGIDS): New variable.
+ (all, install-msgids, $(datadir)/msgids): New targets.
+ (install): Specify install-header and install-msgids as
+ prerequisites.
+
+---
+ hurd/Makefile | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/hurd/Makefile
++++ b/hurd/Makefile
+@@ -22,15 +22,20 @@ DIST_FILES = subsystems $(notdir $(hdrs)
+
+ INSTHDRS = hurd_types.h version.h ioctl_types.h paths.h shared.h console.h \
+ $(notdir $(wildcard $(srcdir)/*.defs))
++MSGIDS := hurd.msgids $(patsubst %.defs,%.msgids,$(filter %.defs,$(INSTHDRS)))
+
+ include ../Makeconf
+
+-install-headers install: $(includedir)/hurd \
++all: $(MSGIDS)
++
++install: install-msgids install-headers
++install-headers: $(includedir)/hurd \
+ $(addprefix $(includedir)/hurd/,$(INSTHDRS))
++install-msgids: $(MSGIDS) $(datadir)/msgids; $(INSTALL_DATA) $^
+
+ $(includedir)/hurd/%: $(srcdir)/%; $(INSTALL_DATA) $< $@
+
+-$(includedir)/hurd:;mkdir -p $@
++$(datadir)/msgids $(includedir)/hurd:;mkdir -p $@
+
+ %.msgids: $(srcdir)/%.defs
+ if grep -q '^subsystem' $<; \
diff --git a/debian/patches/libdiskfs_self-reauth.patch b/debian/patches/libdiskfs_self-reauth.patch
new file mode 100644
index 00000000..b3e048b2
--- /dev/null
+++ b/debian/patches/libdiskfs_self-reauth.patch
@@ -0,0 +1,32 @@
+"RPC to self with rendez-vous leading to duplicate port destroy"
+
+http://lists.gnu.org/archive/html/bug-hurd/2011-03/msg00045.html
+
+diff --git a/libfshelp/fetch-root.c b/libfshelp/fetch-root.c
+index 54d3c0c..6585052 100644
+--- a/libfshelp/fetch-root.c
++++ b/libfshelp/fetch-root.c
+@@ -79,7 +79,9 @@ fshelp_fetch_root (struct transbox *box, void *cookie,
+ if (err)
+ ret = MACH_PORT_NULL;
+
+- mach_port_destroy (mach_task_self (), rend);
++ /* crdir could be ourselves, and thus diskfs_S_io_reauthenticate
++ * would get the same name, so don't _destroy_ it !! */
++ mach_port_mod_refs (mach_task_self (), rend, MACH_PORT_RIGHT_RECEIVE, -1);
+
+ return ret;
+ }
+diff --git a/libshouldbeinlibc/exec-reauth.c b/libshouldbeinlibc/exec-reauth.c
+index dd267ef..12b34fc 100644
+--- a/libshouldbeinlibc/exec-reauth.c
++++ b/libshouldbeinlibc/exec-reauth.c
+@@ -59,7 +59,7 @@ exec_reauth (auth_t auth, int secure, int must_reauth,
+ if (!err)
+ err = auth_user_authenticate (auth, ref, MACH_MSG_TYPE_MAKE_SEND,
+ &newport);
+- mach_port_destroy (mach_task_self (), ref);
++ mach_port_mod_refs (mach_task_self (), ref, MACH_PORT_RIGHT_RECEIVE, -1);
+ if (err)
+ {
+ if (must_reauth)
diff --git a/debian/patches/libdiskfs_sync.patch b/debian/patches/libdiskfs_sync.patch
new file mode 100644
index 00000000..19e45170
--- /dev/null
+++ b/debian/patches/libdiskfs_sync.patch
@@ -0,0 +1,16 @@
+Set diskfs stores as readonly on shutdown before enabling RPCs again.
+
+diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c
+index bf1acf2..700a26e 100644
+--- a/libdiskfs/init-startup.c
++++ b/libdiskfs/init-startup.c
+@@ -148,6 +148,9 @@ diskfs_S_startup_dosync (mach_port_t handle)
+ diskfs_set_hypermetadata (1, 1);
+ _diskfs_diskdirty = 0;
+
++ diskfs_readonly = 1;
++ diskfs_readonly_changed (1);
++
+ ports_resume_class_rpcs (diskfs_protid_class);
+ }
+
diff --git a/debian/patches/libexec.patch b/debian/patches/libexec.patch
new file mode 100644
index 00000000..d46b7692
--- /dev/null
+++ b/debian/patches/libexec.patch
@@ -0,0 +1,103 @@
+diff --git a/config/ttys b/config/ttys
+index 6a548d5..d10bfcc 100644
+--- a/config/ttys
++++ b/config/ttys
+@@ -4,11 +4,11 @@
+
+ # name program type status comments
+
+-console "/libexec/getty 9600" mach-color on secure trusted console
+-tty1 "/libexec/getty 38400" hurd on secure trusted console
+-tty2 "/libexec/getty 38400" hurd on secure trusted console
+-tty3 "/libexec/getty 38400" hurd on secure trusted console
+-tty4 "/libexec/getty 38400" hurd on secure trusted console
+-tty5 "/libexec/getty 38400" hurd on secure trusted console
+-tty6 "/libexec/getty 38400" hurd on secure trusted console
+-#com0 "/libexec/getty 9600" dialup on secure
++console "/sbin/getty 9600" mach-color on secure trusted console
++tty1 "/sbin/getty 38400" hurd on secure trusted console
++tty2 "/sbin/getty 38400" hurd on secure trusted console
++tty3 "/sbin/getty 38400" hurd on secure trusted console
++tty4 "/sbin/getty 38400" hurd on secure trusted console
++tty5 "/sbin/getty 38400" hurd on secure trusted console
++tty6 "/sbin/getty 38400" hurd on secure trusted console
++#com0 "/sbin/getty 9600" dialup on secure
+diff --git a/daemons/runsystem.sh b/daemons/runsystem.sh
+index c3cb2d6..0ce4f59 100644
+--- a/daemons/runsystem.sh
++++ b/daemons/runsystem.sh
+@@ -23,8 +23,8 @@ fallback_shells='/bin/sh /bin/bash /bin/csh /bin/ash /bin/shd'
+ SHELL=/bin/sh
+
+ # Programs that do multi-user startup.
+-RUNCOM=/libexec/rc
+-RUNTTYS=/libexec/runttys
++RUNCOM=/etc/hurd/rc
++RUNTTYS=/sbin/runttys
+ # Signals that we should pass down to runttys.
+ runttys_sigs='TERM INT HUP TSTP'
+
+diff --git a/doc/hurd.texi b/doc/hurd.texi
+index ea73a4c..7d7af39 100644
+--- a/doc/hurd.texi
++++ b/doc/hurd.texi
+@@ -570,7 +570,7 @@ The @option{--multiboot-command-line} option tells the file system server that
+ it is a root filesystem, which triggers it to run @command{/hurd/init} as PID
+ 1. @command{/hurd/init} starts the @command{/hurd/proc} and
+ @command{/hurd/auth} servers. After the servers are launched
+-@command{/hurd/init} starts the @command{/libexec/runsystem.sh} script to
++@command{/hurd/init} starts the @command{/etc/hurd/runsystem.sh} script to
+ finish booting.
+
+ After the Hurd has been booted, other sets of core Hurd servers can be
+diff --git a/init/init.c b/init/init.c
+index d66bee0..14d822e 100644
+--- a/init/init.c
++++ b/init/init.c
+@@ -888,7 +888,7 @@ frob_kernel_process (void)
+ /** Running userland. **/
+
+ /* In the "split-init" setup, we just run a single program (usually
+- /libexec/runsystem) that is not expected to ever exit (or stop).
++ /etc/hurd/runsystem) that is not expected to ever exit (or stop).
+ If it does exit (or can't be started), we go to an emergency single-user
+ shell as a fallback. */
+
+@@ -1004,7 +1004,7 @@ process_signal (int signo)
+ }
+ }
+
+-/* Start the child program PROG. It is run via /libexec/console-run
++/* Start the child program PROG. It is run via /sbin/console-run
+ with the given additional arguments. */
+ static int
+ start_child (const char *prog, char **progargs)
+@@ -1016,7 +1016,7 @@ start_child (const char *prog, char **progargs)
+
+ if (progargs == 0)
+ {
+- const char *argv[] = { "/libexec/console-run", prog, 0 };
++ const char *argv[] = { "/sbin/console-run", prog, 0 };
+ err = argz_create ((char **) argv, &args, &arglen);
+ }
+ else
+@@ -1026,7 +1026,7 @@ start_child (const char *prog, char **progargs)
+ ++argc;
+ {
+ const char *argv[2 + argc + 1];
+- argv[0] = "/libexec/console-run";
++ argv[0] = "/sbin/console-run";
+ argv[1] = prog;
+ argv[2 + argc] = 0;
+ while (argc-- > 0)
+@@ -1086,8 +1086,8 @@ launch_something (const char *why)
+ static unsigned int try;
+ static const char *const tries[] =
+ {
+- "/libexec/runsystem",
+- "/libexec/runsystem.gnu",
++ "/etc/hurd/runsystem",
++ "/etc/hurd/runsystem.gnu",
+ _PATH_BSHELL,
+ "/bin/shd", /* XXX */
+ };
diff --git a/debian/patches/libpager_deadlock.patch b/debian/patches/libpager_deadlock.patch
new file mode 100644
index 00000000..ea2d9087
--- /dev/null
+++ b/debian/patches/libpager_deadlock.patch
@@ -0,0 +1,20 @@
+See http://lists.gnu.org/archive/html/bug-hurd/2010-03/msg00127.html
+for the story. This should be completely safe, but Sergio believes
+memory_object_lock_request shouldn't actually block.
+
+diff --git a/libpager/lock-object.c b/libpager/lock-object.c
+index d108666..d8d4a1b 100644
+--- a/libpager/lock-object.c
++++ b/libpager/lock-object.c
+@@ -65,9 +65,11 @@ _pager_lock_object (struct pager *p,
+ }
+ }
+
++ mutex_unlock (&p->interlock);
+ memory_object_lock_request (p->memobjcntl, offset, size, should_return,
+ should_flush, lock_value,
+ sync ? p->port.port_right : MACH_PORT_NULL);
++ mutex_lock (&p->interlock);
+
+ if (sync)
+ {
diff --git a/debian/patches/libpager_update_seqno.patch b/debian/patches/libpager_update_seqno.patch
new file mode 100644
index 00000000..6246e8a1
--- /dev/null
+++ b/debian/patches/libpager_update_seqno.patch
@@ -0,0 +1,140 @@
+2005-08-10 Sergio Lopez <koro@sinrega.org>
+
+ * seqnos.c (_pager_stubs_update_seqno): New function.
+ * priv.h (_pager_stubs_update_seqno): New function.
+
+ * notify-stubs.c (_pager_do_seqnos_mach_notify_port_deleted):
+ Call _pager_stubs_update_seqno to properly update seqno.
+ (_pager_do_seqnos_mach_notify_msg_accepted): Likewise.
+ (_pager_do_seqnos_mach_notify_port_destroyed): Likewise.
+ (_pager_do_seqnos_mach_notify_send_once): Likewise.
+ (_pager_do_seqnos_mach_notify_dead_name): Likewise.
+ * stubs.c (_pager_seqnos_memory_object_data_write): Likewise.
+ (_pager_seqnos_memory_object_supply_completed): Likewise.
+
+---
+ libpager/notify-stubs.c | 6 ++++++
+ libpager/priv.h | 1 +
+ libpager/seqnos.c | 22 ++++++++++++++++++++++
+ libpager/stubs.c | 9 +++++++++
+ 4 files changed, 38 insertions(+)
+
+--- a/libpager/notify-stubs.c
++++ b/libpager/notify-stubs.c
+@@ -18,6 +18,7 @@
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
++#include "priv.h"
+ #include "notify_S.h"
+ #include <errno.h>
+
+@@ -29,6 +30,7 @@ _pager_do_seqnos_mach_notify_port_delete
+ mach_port_t name
+ __attribute__ ((unused)))
+ {
++ _pager_stubs_update_seqno (notify, seqno);
+ return 0;
+ }
+
+@@ -40,6 +42,7 @@ _pager_do_seqnos_mach_notify_msg_accepte
+ mach_port_t name
+ __attribute__ ((unused)))
+ {
++ _pager_stubs_update_seqno (notify, seqno);
+ return 0;
+ }
+
+@@ -51,6 +54,7 @@ _pager_do_seqnos_mach_notify_port_destro
+ mach_port_t name
+ __attribute__ ((unused)))
+ {
++ _pager_stubs_update_seqno (notify, seqno);
+ return 0;
+ }
+
+@@ -60,6 +64,7 @@ _pager_do_seqnos_mach_notify_send_once (
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)))
+ {
++ _pager_stubs_update_seqno (notify, seqno);
+ return 0;
+ }
+
+@@ -71,5 +76,6 @@ _pager_do_seqnos_mach_notify_dead_name (
+ mach_port_t name
+ __attribute__ ((unused)))
+ {
++ _pager_stubs_update_seqno (notify, seqno);
+ return 0;
+ }
+--- a/libpager/priv.h
++++ b/libpager/priv.h
+@@ -134,6 +134,7 @@ struct port_class *_pager_class;
+
+ void _pager_wait_for_seqno (struct pager *, int);
+ void _pager_release_seqno (struct pager *, int);
++void _pager_stubs_update_seqno (mach_port_t, int);
+ void _pager_block_termination (struct pager *);
+ void _pager_allow_termination (struct pager *);
+ error_t _pager_pagemap_resize (struct pager *, vm_address_t);
+--- a/libpager/seqnos.c
++++ b/libpager/seqnos.c
+@@ -47,3 +47,25 @@ _pager_release_seqno (struct pager *p,
+ condition_broadcast (&p->wakeup);
+ }
+ }
++
++
++/* This function is called by stub functions to properly update
++ seqno. */
++void
++_pager_stubs_update_seqno (mach_port_t object,
++ int seqno)
++{
++ struct pager *p;
++
++ p = ports_lookup_port (0, object, _pager_class);
++ if (p)
++ {
++ mutex_lock (&p->interlock);
++ _pager_wait_for_seqno (p, seqno);
++ _pager_release_seqno (p, seqno);
++ mutex_unlock (&p->interlock);
++
++ ports_port_deref (p);
++ }
++}
++
+--- a/libpager/stubs.c
++++ b/libpager/stubs.c
+@@ -29,6 +29,9 @@ _pager_seqnos_memory_object_copy (mach_p
+ mach_port_t new)
+ {
+ printf ("m_o_copy called\n");
++
++ _pager_stubs_update_seqno (old, seq);
++
+ return EOPNOTSUPP;
+ }
+
+@@ -41,6 +44,9 @@ _pager_seqnos_memory_object_data_write (
+ vm_size_t data_cnt)
+ {
+ printf ("m_o_data_write called\n");
++
++ _pager_stubs_update_seqno (old, seq);
++
+ return EOPNOTSUPP;
+ }
+
+@@ -54,6 +60,9 @@ _pager_seqnos_memory_object_supply_compl
+ vm_offset_t err_off)
+ {
+ printf ("m_o_supply_completed called\n");
++
++ _pager_stubs_update_seqno (obj, seq);
++
+ return EOPNOTSUPP;
+ }
+
diff --git a/debian/patches/libports_stability.patch b/debian/patches/libports_stability.patch
new file mode 100644
index 00000000..84edc491
--- /dev/null
+++ b/debian/patches/libports_stability.patch
@@ -0,0 +1,18 @@
+Ideally we should be able to time out and see translators go away automatically,
+however it makes all threads often wake at the same time and overload Mach.
+
+---
+ libports/manage-multithread.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/libports/manage-multithread.c
++++ b/libports/manage-multithread.c
+@@ -157,6 +157,8 @@ ports_manage_port_operations_multithread
+ return 0;
+ }
+
++ thread_timeout = global_timeout = 0; /* XXX */
++
+ nreqthreads = 1;
+ totalthreads = 1;
+ thread_function (1);
diff --git a/debian/patches/libpthread_fix.patch b/debian/patches/libpthread_fix.patch
new file mode 100644
index 00000000..56e03850
--- /dev/null
+++ b/debian/patches/libpthread_fix.patch
@@ -0,0 +1,75 @@
+Temporary patch from Thomas Schwinge to fix libpthread bugs.
+
+---
+ libpthread/sysdeps/mach/hurd/pt-init-specific.c | 29 ++++++++++++++++++++++++
+ libpthread/sysdeps/mach/pt-thread-dealloc.c | 2 +
+ libpthread/sysdeps/mach/pt-thread-halt.c | 19 ++++++++++++++-
+ 3 files changed, 48 insertions(+), 2 deletions(-)
+
+--- a/libpthread/sysdeps/mach/pt-thread-dealloc.c
++++ b/libpthread/sysdeps/mach/pt-thread-dealloc.c
+@@ -38,4 +38,6 @@ __pthread_thread_dealloc (struct __pthre
+ assert. */
+ __mach_port_destroy (__mach_task_self (),
+ thread->wakeupmsg.msgh_remote_port);
++
++ thread->have_kernel_resources = 0;
+ }
+--- a/libpthread/sysdeps/mach/pt-thread-halt.c
++++ b/libpthread/sysdeps/mach/pt-thread-halt.c
+@@ -32,6 +32,21 @@
+ void
+ __pthread_thread_halt (struct __pthread *thread)
+ {
+- error_t err = __thread_terminate (thread->kernel_thread);
+- assert_perror (err);
++ if (thread->have_kernel_resources)
++ {
++ if (thread == _pthread_self ())
++ {
++ while (1)
++ {
++ error_t err = __thread_suspend (thread->kernel_thread);
++ assert_perror (err);
++ assert (! "Failed to suspend self.");
++ }
++ }
++ else
++ {
++ error_t err = __thread_terminate (thread->kernel_thread);
++ assert_perror (err);
++ }
++ }
+ }
+--- /dev/null
++++ b/libpthread/sysdeps/mach/hurd/pt-init-specific.c
+@@ -0,0 +1,29 @@
++/* __pthread_init_specific. Mach version.
++ Copyright (C) 2002, 2009 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Library General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Library General Public License for more details.
++
++ You should have received a copy of the GNU Library General Public
++ License along with the GNU C Library; see the file COPYING.LIB. If not,
++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#include <pthread.h>
++#include <pt-internal.h>
++
++error_t
++__pthread_init_specific (struct __pthread *thread)
++{
++ thread->thread_specifics = 0;
++ thread->have_kernel_resources = 0;
++ return 0;
++}
diff --git a/debian/patches/libpthread_globsigdisp.patch b/debian/patches/libpthread_globsigdisp.patch
new file mode 100644
index 00000000..06c3486c
--- /dev/null
+++ b/debian/patches/libpthread_globsigdisp.patch
@@ -0,0 +1,59 @@
+commit 60d1b9b9198bc8c618596cb0e48687bd41e8adb7
+Author: Jeremie Koenig <jk@jk.fr.eu.org>
+Date: Fri Jun 10 05:46:39 2011 +0000
+
+ Mark new threads as global signal receivers
+
+ * sysdeps/mach/hurd/pt-sigstate-init.c (__pthread_sigstate_init):
+ Call _hurd_sigstate_set_global_rcv for newly created threads.
+ * sysdeps/mach/pt-thread-halt.c (__pthread_thread_halt):
+ Call _hurd_sigstate_delete on terminated threads.
+
+diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c b/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c
+index da5a945..f8398f4 100644
+--- a/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c
++++ b/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c
+@@ -19,6 +19,7 @@
+
+ #include <pthread.h>
+ #include <hurd/threadvar.h>
++#include <hurd/signal.h>
+
+ #include <pt-internal.h>
+
+@@ -30,8 +31,21 @@ __pthread_sigstate_init (struct __pthread *thread)
+ thread->stackaddr);
+
+ /* The real initialization happens internally in glibc the first
+- time that _hurd_thead_sigstate is called. */
++ time that _hurd_self_sigstate is called. */
+ *location = 0;
+
++ /* Mark the thread as a global signal receiver so as to conform with
++ the pthread semantics. However, we must be careful. The first
++ pthread created is the main thread, during libpthread initialization.
++ We must not mark it, otherwise the sigprocmask call in
++ __pthread_create would try to access _hurd_global_sigstate,
++ which is not initialized yet. When glibc runs _hurdsig_init later
++ on, the message thread is created, which must not be marked either. */
++ if (__pthread_num_threads > 2)
++ {
++ struct hurd_sigstate *ss = _hurd_thread_sigstate (thread->kernel_thread);
++ _hurd_sigstate_set_global_rcv (ss);
++ }
++
+ return 0;
+ }
+diff --git a/libpthread/sysdeps/mach/pt-thread-halt.c b/libpthread/sysdeps/mach/pt-thread-halt.c
+index a9c3858..808043d 100644
+--- a/libpthread/sysdeps/mach/pt-thread-halt.c
++++ b/libpthread/sysdeps/mach/pt-thread-halt.c
+@@ -34,6 +34,8 @@ __pthread_thread_halt (struct __pthread *thread)
+ {
+ if (thread->have_kernel_resources)
+ {
++ _hurd_sigstate_delete (thread->kernel_thread);
++
+ if (thread == _pthread_self ())
+ {
+ while (1)
diff --git a/debian/patches/libpthread_procfs.patch b/debian/patches/libpthread_procfs.patch
new file mode 100644
index 00000000..8d3ddbe0
--- /dev/null
+++ b/debian/patches/libpthread_procfs.patch
@@ -0,0 +1,83 @@
+Include libpthread and procfs in the build
+
+Index: hurd-debian/Makefile
+===================================================================
+--- hurd-debian.orig/Makefile 2010-09-27 19:42:53.000000000 +0000
++++ hurd-debian/Makefile 2010-09-27 19:45:57.000000000 +0000
+@@ -31,7 +31,8 @@
+ # Hurd libraries
+ lib-subdirs = libshouldbeinlibc libihash libiohelp libports libthreads \
+ libpager libfshelp libdiskfs libtrivfs libps \
+- libnetfs libpipe libstore libhurdbugaddr libftpconn libcons
++ libnetfs libpipe libstore libhurdbugaddr libftpconn libcons \
++ libpthread
+
+ # Hurd programs
+ prog-subdirs = auth proc exec init term \
+@@ -40,7 +41,7 @@
+ login daemons boot console \
+ hostmux usermux ftpfs trans \
+ console-client utils sutils ufs-fsck ufs-utils \
+- benchmarks fstests
++ benchmarks fstests procfs random
+
+ ifeq ($(HAVE_SUN_RPC),yes)
+ prog-subdirs += nfs nfsd
+Index: hurd-debian/procfs/Makefile
+===================================================================
+--- hurd-debian.orig/procfs/Makefile 2010-09-27 19:50:41.000000000 +0000
++++ hurd-debian/procfs/Makefile 2010-09-27 19:50:46.000000000 +0000
+@@ -1,26 +1,30 @@
+-TARGET = procfs
+-OBJS = procfs.o netfs.o procfs_dir.o \
+- process.o proclist.o rootdir.o dircat.o main.o
+-LIBS = -lnetfs -lps
++# Makefile - for procfs
++#
++# Copyright (C) 2008 Free Software Foundation, Inc.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2, or (at
++# your option) any later version.
++#
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++dir := procfs
++makemode := server
++
++target = procfs
+
+-CC = gcc
+-CFLAGS = -Wall -g
+-CPPFLAGS =
+-LDFLAGS =
++SRCS = procfs.c netfs.c procfs_dir.c process.c proclist.c rootdir.c dircat.c main.c
++LCLHDRS = dircat.h main.h process.h procfs.h procfs_dir.h proclist.h rootdir.h
+
+-ifdef PROFILE
+-CFLAGS= -g -pg
+-CPPFLAGS= -DPROFILE
+-LDFLAGS= -static
+-LIBS= -lnetfs -lfshelp -liohelp -lps -lports -lthreads -lihash -lshouldbeinlibc
+-endif
++OBJS = $(SRCS:.c=.o)
++HURDLIBS = netfs fshelp iohelp ps ports threads ihash shouldbeinlibc
+
+-CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
+-
+-all: $(TARGET)
+-
+-$(TARGET): $(OBJS)
+- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+-
+-clean:
+- $(RM) $(TARGET) $(OBJS)
++include ../Makeconf
diff --git a/debian/patches/libpthread_sigmask.patch b/debian/patches/libpthread_sigmask.patch
new file mode 100644
index 00000000..7315a80d
--- /dev/null
+++ b/debian/patches/libpthread_sigmask.patch
@@ -0,0 +1,47 @@
+* libpthread/sysdeps/mach/hurd/pt-sigstate.c (__pthread_sigstate): Wake up the message
+thread if any pending signals have been unblocked (code grabbed from glibc).
+---
+ libpthread/sysdeps/mach/hurd/pt-sigstate.c | 9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+Index: hurd/libpthread/sysdeps/mach/hurd/pt-sigstate.c
+===================================================================
+--- hurd.orig/libpthread/sysdeps/mach/hurd/pt-sigstate.c 2011-05-29 15:23:30.000000000 +0000
++++ hurd/libpthread/sysdeps/mach/hurd/pt-sigstate.c 2011-06-10 04:53:53.000000000 +0000
+@@ -21,6 +21,7 @@
+ #include <assert.h>
+ #include <signal.h>
+ #include <hurd/signal.h>
++#include <hurd/msg.h>
+
+ #include <pt-internal.h>
+
+@@ -31,11 +32,12 @@
+ {
+ error_t err = 0;
+ struct hurd_sigstate *ss;
++ sigset_t pending;
+
+ ss = _hurd_thread_sigstate (thread->kernel_thread);
+ assert (ss);
+
+- __pthread_spin_lock (&ss->lock);
++ _hurd_sigstate_lock (ss);
+
+ if (oset)
+ *oset = ss->blocked;
+@@ -63,7 +65,13 @@
+ if (! err && clear_pending)
+ __sigemptyset (&ss->pending);
+
+- __pthread_spin_unlock (&ss->lock);
++ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
++ _hurd_sigstate_unlock (ss);
++
++ if (! err && pending)
++ /* Send a message to the signal thread so it
++ will wake up and check for pending signals. */
++ __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
+
+ return err;
+ }
diff --git a/debian/patches/libpthread_stubs.patch b/debian/patches/libpthread_stubs.patch
new file mode 100644
index 00000000..7b0db6a3
--- /dev/null
+++ b/debian/patches/libpthread_stubs.patch
@@ -0,0 +1,157 @@
+Add warnings about non-implemented functions.
+---
+ config.make.in | 1 +
+ libpthread/Makefile | 14 +++++++++++++-
+ libpthread/include/libc-symbols.h | 1 +
+ libpthread/sysdeps/generic/pt-atfork.c | 2 ++
+ libpthread/sysdeps/generic/pt-getcpuclockid.c | 1 +
+ libpthread/sysdeps/generic/pt-getschedparam.c | 2 ++
+ libpthread/sysdeps/generic/pt-key-create.c | 2 ++
+ libpthread/sysdeps/generic/pt-key-delete.c | 2 ++
+ libpthread/sysdeps/generic/pt-mutex-getprioceiling.c | 2 ++
+ libpthread/sysdeps/generic/pt-mutex-setprioceiling.c | 2 ++
+ libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c | 2 ++
+ libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c | 2 ++
+ libpthread/sysdeps/generic/pt-setschedparam.c | 2 ++
+ libpthread/sysdeps/generic/pt-setschedprio.c | 2 ++
+ 14 files changed, 36 insertions(+), 1 deletion(-)
+
+--- a/config.make.in
++++ b/config.make.in
+@@ -44,6 +44,7 @@ RANLIB = @RANLIB@
+ MIG = @MIG@
+ MIGCOM = $(MIG) -cc cat - /dev/null
+ AWK = @AWK@
++OBJDUMP = objdump
+
+ # Compilation flags. Append these to the definitions already made by
+ # the specific Makefile.
+--- a/libpthread/Makefile
++++ b/libpthread/Makefile
+@@ -186,7 +186,7 @@ CPPFLAGS += \
+ -imacros $(srcdir)/not-in-libc.h
+
+
+-install: install-headers $(libdir)/libpthread2.a $(libdir)/libpthread2_pic.a
++install: install-headers $(libdir)/libpthread2.a $(libdir)/libpthread2_pic.a install-stubs-pthread
+ install-headers: $(addprefix $(includedir)/, $(sysdeps_headers))
+
+ # XXX: If $(libdir)/libpthread2.a is installed and
+@@ -205,6 +205,18 @@ $(libdir)/libpthread2_pic.a: $(libdir)/l
+ mv $< $@
+ $(INSTALL_DATA) $(srcdir)/libpthread_pic.a $<
+
++install-stubs-pthread: stubs-pthread.h
++ mkdir -p $(includedir)/gnu
++ $(INSTALL_DATA) $< $(includedir)/gnu/stubs-pthread.h
++
++stubs-pthread.h: $(OBJS)
++ $(OBJDUMP) -h $^ | \
++ $(AWK) '/\.gnu\.glibc-stub\./ { \
++ sub(/\.gnu\.glibc-stub\./, "", $$2); \
++ stubs[$$2] = 1; } \
++ END { for (s in stubs) print "#define __stub_" s }' > $@T
++ mv -f $@T $@
++
+ .PHONY: $(addprefix $(includedir)/, $(sysdeps_headers))
+
+ $(addprefix $(includedir)/, $(sysdeps_headers)):
+--- a/libpthread/include/libc-symbols.h
++++ b/libpthread/include/libc-symbols.h
+@@ -252,6 +252,7 @@
+
+ /* A canned warning for sysdeps/stub functions. */
+ #define stub_warning(name) \
++ __make_section_unallocated (".gnu.glibc-stub." #name) \
+ link_warning (name, \
+ "warning: " #name " is not implemented and will always fail")
+
+--- a/libpthread/sysdeps/generic/pt-atfork.c
++++ b/libpthread/sysdeps/generic/pt-atfork.c
+@@ -27,3 +27,5 @@ pthread_atfork (void (*prepare) (void),
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_atfork)
+--- a/libpthread/sysdeps/generic/pt-getcpuclockid.c
++++ b/libpthread/sysdeps/generic/pt-getcpuclockid.c
+@@ -30,5 +30,6 @@ pthread_getcpuclockid (pthread_t thread,
+ return 0;
+ #else
+ return ENOSYS;
++stub_warning (pthread_getcpuclockid)
+ #endif
+ }
+--- a/libpthread/sysdeps/generic/pt-getschedparam.c
++++ b/libpthread/sysdeps/generic/pt-getschedparam.c
+@@ -26,3 +26,5 @@ pthread_getschedparam (pthread_t thread,
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_getschedparam)
+--- a/libpthread/sysdeps/generic/pt-key-create.c
++++ b/libpthread/sysdeps/generic/pt-key-create.c
+@@ -25,3 +25,5 @@ pthread_key_create (pthread_key_t *key,
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_key_create)
+--- a/libpthread/sysdeps/generic/pt-key-delete.c
++++ b/libpthread/sysdeps/generic/pt-key-delete.c
+@@ -25,3 +25,5 @@ pthread_key_delete (pthread_key_t key)
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_key_delete)
+--- a/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c
++++ b/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c
+@@ -26,3 +26,5 @@ pthread_mutex_getprioceiling (const pthr
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_mutex_getprioceiling)
+--- a/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c
++++ b/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c
+@@ -26,3 +26,5 @@ pthread_mutex_setprioceiling (pthread_mu
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_mutex_setprioceiling)
+--- a/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c
++++ b/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c
+@@ -26,3 +26,5 @@ pthread_mutexattr_getprioceiling (const
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_mutexattr_getprioceiling)
+--- a/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c
++++ b/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c
+@@ -26,3 +26,5 @@ pthread_mutexattr_setprioceiling (pthrea
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_mutexattr_setprioceiling)
+--- a/libpthread/sysdeps/generic/pt-setschedparam.c
++++ b/libpthread/sysdeps/generic/pt-setschedparam.c
+@@ -26,3 +26,5 @@ pthread_setschedparam (pthread_t thread,
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_setschedparam)
+--- a/libpthread/sysdeps/generic/pt-setschedprio.c
++++ b/libpthread/sysdeps/generic/pt-setschedprio.c
+@@ -25,3 +25,5 @@ pthread_setschedprio (pthread_t thread,
+ {
+ return ENOSYS;
+ }
++
++stub_warning (pthread_setschedprio)
diff --git a/debian/patches/makedev.diff b/debian/patches/makedev.diff
new file mode 100644
index 00000000..f53320c5
--- /dev/null
+++ b/debian/patches/makedev.diff
@@ -0,0 +1,17 @@
+Do not create the shm node since Marcus' SHM implementation uses a directory
+there.
+---
+ sutils/MAKEDEV.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sutils/MAKEDEV.sh
++++ b/sutils/MAKEDEV.sh
+@@ -86,7 +86,7 @@ function mkdev {
+ ;;
+
+ std)
+- mkdev console tty null zero full fd time mem klog shm
++ mkdev console tty null zero full fd time mem klog
+ ;;
+ console|com[0-9])
+ st $I root 600 /hurd/term ${DEVDIR}/$I device $I;;
diff --git a/debian/patches/makedev_keep_options.patch b/debian/patches/makedev_keep_options.patch
new file mode 100644
index 00000000..69a57e48
--- /dev/null
+++ b/debian/patches/makedev_keep_options.patch
@@ -0,0 +1,58 @@
+Add options -k and -K to MAKEDEV.sh to chose not to overwrite existing entries.
+
+TODO: submit to bug-hurd
+
+Index: hurd/sutils/MAKEDEV.sh
+===================================================================
+--- hurd.orig/sutils/MAKEDEV.sh 2010-07-01 18:14:22.000000000 +0200
++++ hurd/sutils/MAKEDEV.sh 2010-07-01 18:17:37.000000000 +0200
+@@ -8,6 +8,8 @@
+ ECHO=: # Change to "echo" to echo commands.
+ EXEC="" # Change to ":" to suppress command execution.
+ DEVDIR=`pwd` # Reset below by -D/--devdir command line option.
++STFLAGS="-g" # Set to -k if active translators are to be kept.
++KEEP= # Set to something if existing files are to be left alone.
+
+ while :; do
+ case "$1" in
+@@ -18,6 +20,8 @@
+
+ -D, --devdir=DIR Use DIR when a device node name must be
+ embedded in a translator; default is the cwd
++ -k, --keep-active Leave any existing active translator running
++ -K, --keep-all Don't overwrite existing files
+ -n, --dry-run Don't actually execute any commands
+ -v, --verbose Show what commands are executed to make the devices
+ -?, --help Give this help list
+@@ -28,11 +32,14 @@
+ --devdir=*) DEVDIR="`echo "$1" | sed 's/^--devdir=//'`"; shift 1;;
+ -D) DEVDIR="$2"; shift 2;;
+ -D*) DEVDIR="`echo "$1" | sed 's/^-D//'`"; shift 1;;
++ --keep-active|-k) STFLAGS="-k"; shift;;
++ --keep-all|-K) KEEP=1; shift;;
+ --verbose|-v) ECHO=echo; shift;;
+ --dry-run|-n) EXEC=:; shift;;
+ -nv|-vn) ECHO=echo; EXEC=:; shift;;
+ --usage)
+- echo "Usage: $0 [-V?] [-D DIR] [--help] [--usage] [--version] [--devdir=DIR] DEVNAME..."
++ echo "Usage: $0 [-V?] [-D DIR] [--help] [--usage] [--version]"
++ echo " [--devdir=DIR] [--keep-active] [--keep-all] DEVNAME..."
+ exit 0;;
+ --version|-V)
+ echo "STANDARD_HURD_VERSION_MAKEDEV_"; exit 0;;
+@@ -61,10 +68,13 @@
+ local OWNER="$2"
+ local PERM="$3"
+ shift 3
+- if cmd settrans -cg "$NODE"; then
++ if [ "$KEEP" ] && showtrans "$NODE" > /dev/null 2>&1 ; then
++ return;
++ fi
++ if cmd settrans $STFLAGS -c "$NODE"; then
+ cmd chown "$OWNER" "$NODE"
+ cmd chmod "$PERM" "$NODE"
+- cmd settrans "$NODE" "$@"
++ cmd settrans $STFLAGS "$NODE" "$@"
+ fi
+ }
+
diff --git a/debian/patches/makedev_parted_store.patch b/debian/patches/makedev_parted_store.patch
new file mode 100644
index 00000000..757b1b40
--- /dev/null
+++ b/debian/patches/makedev_parted_store.patch
@@ -0,0 +1,73 @@
+Add option -p to MAKEDEV to use user-space parted stores for partition devices.
+
+TODO: use in installed system, test, and submit to bug-hurd. IIRC the issue with
+it was that the swapper does not like parted-based stores.
+
+Index: hurd/sutils/MAKEDEV.sh
+===================================================================
+--- hurd.orig/sutils/MAKEDEV.sh 2010-07-08 00:48:13.000000000 +0000
++++ hurd/sutils/MAKEDEV.sh 2010-07-08 01:18:26.000000000 +0000
+@@ -10,6 +10,7 @@
+ DEVDIR=`pwd` # Reset below by -D/--devdir command line option.
+ STFLAGS="-g" # Set to -k if active translators are to be kept.
+ KEEP= # Set to something if existing files are to be left alone.
++USE_PARTSTORE= # Whether to use the newer part: stores
+
+ while :; do
+ case "$1" in
+@@ -22,6 +23,8 @@
+ embedded in a translator; default is the cwd
+ -k, --keep-active Leave any existing active translator running
+ -K, --keep-all Don't overwrite existing files
++ -p, --parted Prefer user-space parted stores to kernel devices
++ for partition devices
+ -n, --dry-run Don't actually execute any commands
+ -v, --verbose Show what commands are executed to make the devices
+ -?, --help Give this help list
+@@ -34,11 +37,12 @@
+ -D*) DEVDIR="`echo "$1" | sed 's/^-D//'`"; shift 1;;
+ --keep-active|-k) STFLAGS="-k"; shift;;
+ --keep-all|-K) KEEP=1; shift;;
++ --parted|-p) USE_PARTSTORE=1; shift;;
+ --verbose|-v) ECHO=echo; shift;;
+ --dry-run|-n) EXEC=:; shift;;
+ -nv|-vn) ECHO=echo; EXEC=:; shift;;
+ --usage)
+- echo "Usage: $0 [-V?] [-D DIR] [--help] [--usage] [--version]"
++ echo "Usage: $0 [-V?] [-D DIR] [--help] [--usage] [--version] [--parted]"
+ echo " [--devdir=DIR] [--keep-active] [--keep-all] DEVNAME..."
+ exit 0;;
+ --version|-V)
+@@ -150,6 +154,7 @@
+ ;;
+
+ [hrsc]d*)
++ local sliceno=
+ local n="${I#?d}"
+ local major="${n%%[!0-9]*}"
+ if [ -z "$major" ]; then
+@@ -170,7 +175,9 @@
+ ;;
+ esac
+ case "$rest" in
+- '') ;; # Whole slice
++ '') # Whole slice, can use parted stores
++ sliceno=$slice
++ ;;
+ [a-z]) ;; # BSD partition after slice
+ *)
+ lose "$I: Invalid partition \`$rest'"
+@@ -183,7 +190,12 @@
+ esac
+
+ # The device name passed all syntax checks, so finally use it!
+- st $I root 640 /hurd/storeio $I
++ if [ "$USE_PARTSTORE" ] && [ -z "$rest" ] && [ "$sliceno" ]; then
++ local dev=${I%s[0-9]*}
++ st $I root 640 /hurd/storeio -T typed part:$sliceno:device:$dev
++ else
++ st $I root 640 /hurd/storeio $I
++ fi
+ ;;
+
+ # /dev/shm is used by the POSIX.1 shm_open call in libc.
diff --git a/debian/patches/pfinet_dhcp.patch b/debian/patches/pfinet_dhcp.patch
new file mode 100644
index 00000000..30c0902a
--- /dev/null
+++ b/debian/patches/pfinet_dhcp.patch
@@ -0,0 +1,560 @@
+2007-10-14 Christian Dietrich <stettberger@dokucode.de>
+
+ * options.c (options): Marked -a, -g -m, -p, -A, -G
+ OPTION_ARG_OPTIONAL. Adding -d option.
+ (parse_interface_copy_device): New function.
+ (parse_opt): When selecting another interface with -i
+ set the options from e.g. a prior fsysopts call as default
+ values. For -a, -g, -p, -g, -A, -G set the optional
+ argument as value. When there is no argument, delete the
+ value (e.g. unset default gateway). Delete delete default gateways
+ only if the set gateway is on an interface modified in this call.
+ Add always an route for dhcp packages on all devices. By doing
+ this we can send dhcp renew packages.
+ (trivfs_append_args): Add --gateway only once.
+
+2007-10-14 Marco Gerards <metgerards@student.han.nl>
+
+ * options.c (options): Add the option `dhcp'.
+ (parse_hook_add_interface): Initialize the `dhcp' member for the
+ parse hook.
+ (parse_opt): In case pfinet is started with the argument `--dhcp',
+ set the address to `0.0.0.0', the netmask to `255.0.0.0' and add
+ the route for `0.0.0.0' so broadcasting works.
+
+ * linux-src/net/ipv4/devinet.c (inet_insert_ifa) [_HURD_]: Don't
+ fail when the address is `0.0.0.0'.
+
+---
+ pfinet/linux-src/net/ipv4/devinet.c | 2
+ pfinet/options.c | 381 ++++++++++++++++++++++++++----------
+ 2 files changed, 278 insertions(+), 105 deletions(-)
+
+--- a/pfinet/options.c
++++ b/pfinet/options.c
+@@ -60,23 +60,26 @@ extern struct inet6_dev *ipv6_find_idev
+ extern int inet6_addr_add (int ifindex, struct in6_addr *pfx, int plen);
+ extern int inet6_addr_del (int ifindex, struct in6_addr *pfx, int plen);
+
++#ifdef CONFIG_IPV6
++static struct rt6_info * ipv6_get_dflt_router (void);
++#endif
++
+
+ /* Pfinet options. Used for both startup and runtime. */
+ static const struct argp_option options[] =
+ {
+- {"interface", 'i', "DEVICE", 0, "Network interface to use", 1},
++ {"interface", 'i', "DEVICE", 0, "Network interface to use", 1},
+ {0,0,0,0,"These apply to a given interface:", 2},
+- {"address", 'a', "ADDRESS", 0, "Set the network address"},
+- {"netmask", 'm', "MASK", 0, "Set the netmask"},
+- {"peer", 'p', "ADDRESS", 0, "Set the peer address"},
+- {"gateway", 'g', "ADDRESS", 0, "Set the default gateway"},
+- {"ipv4", '4', "NAME", 0, "Put active IPv4 translator on NAME"},
++ {"address", 'a', "ADDRESS", OPTION_ARG_OPTIONAL, "Set the network address"},
++ {"netmask", 'm', "MASK", OPTION_ARG_OPTIONAL, "Set the netmask"},
++ {"peer", 'p', "ADDRESS", OPTION_ARG_OPTIONAL, "Set the peer address"},
++ {"gateway", 'g', "ADDRESS", OPTION_ARG_OPTIONAL, "Set the default gateway"},
++ {"ipv4", '4', "NAME", 0, "Put active IPv4 translator on NAME"},
+ #ifdef CONFIG_IPV6
+- {"ipv6", '6', "NAME", 0, "Put active IPv6 translator on NAME"},
+- {"address6", 'A', "ADDR/LEN",0, "Set the global IPv6 address"},
+- {"gateway6", 'G', "ADDRESS", 0, "Set the IPv6 default gateway"},
++ {"ipv6", '6', "NAME", 0, "Put active IPv6 translator on NAME"},
++ {"address6", 'A', "ADDR/LEN", OPTION_ARG_OPTIONAL, "Set the global IPv6 address"},
++ {"gateway6", 'G', "ADDRESS", OPTION_ARG_OPTIONAL, "Set the IPv6 default gateway"},
+ #endif
+- {"shutdown", 's', 0, 0, "Shut it down"},
+ {0}
+ };
+
+@@ -112,6 +115,50 @@ struct parse_hook
+ struct parse_interface *curint;
+ };
+
++static void
++parse_interface_copy_device(struct device *src,
++ struct parse_interface *dst)
++{
++ uint32_t broad;
++ struct rt_key key = { 0 };
++ struct inet6_dev *idev = NULL;
++ struct fib_result res;
++
++ inquire_device (src, &dst->address, &dst->netmask,
++ &dst->peer, &broad);
++ /* Get gateway */
++ dst->gateway = INADDR_NONE;
++ key.oif = src->ifindex;
++ if (! main_table->tb_lookup (main_table, &key, &res)
++ && FIB_RES_GW(res) != INADDR_ANY)
++ dst->gateway = FIB_RES_GW (res);
++#ifdef CONFIG_IPV6
++ if (trivfs_protid_portclasses[PORTCLASS_INET6] != MACH_PORT_NULL)
++ idev = ipv6_find_idev(src);
++
++ if (idev)
++ {
++ struct inet6_ifaddr *ifa = idev->addr_list;
++
++ /* Look for IPv6 default router and add it to the interface,
++ * if it belongs to it.
++ */
++ struct rt6_info *rt6i = ipv6_get_dflt_router();
++ if (rt6i->rt6i_dev == src)
++ memcpy (&dst->gateway6, &rt6i->rt6i_gateway, sizeof (struct in6_addr));
++ /* Search for global address and set it in dst */
++ do
++ {
++ if (!IN6_IS_ADDR_LINKLOCAL (&ifa->addr)) {
++ memcpy (&dst->address6, ifa, sizeof (struct inet6_ifaddr));
++ break;
++ }
++ }
++ while ((ifa = ifa->if_next));
++ }
++#endif
++}
++
+ /* Adds an empty interface slot to H, and sets H's current interface to it, or
+ returns an error. */
+ static error_t
+@@ -122,6 +169,7 @@ parse_hook_add_interface (struct parse_h
+ (h->num_interfaces + 1) * sizeof (struct parse_interface));
+ if (! new)
+ return ENOMEM;
++
+ h->interfaces = new;
+ h->num_interfaces++;
+ h->curint = new + h->num_interfaces - 1;
+@@ -183,10 +231,16 @@ parse_opt (int opt, char *arg, struct ar
+ if (addr == INADDR_NONE) PERR (EINVAL, "Malformed %s", type); \
+ addr; })
+
++ if (!arg && state->next < state->argc
++ && (*state->argv[state->next] != '-'))
++ {
++ arg = state->argv[state->next];
++ state->next ++;
++ }
++
+ switch (opt)
+ {
+- struct parse_interface *in;
+- uint32_t gateway;
++ struct parse_interface *in, *gw4_in;
+ #ifdef CONFIG_IPV6
+ struct parse_interface *gw6_in;
+ char *ptr;
+@@ -217,29 +271,59 @@ parse_opt (int opt, char *arg, struct ar
+ if (err)
+ FAIL (err, 10, err, "%s", arg);
+
++ /* Set old interface values */
++ parse_interface_copy_device (in->device, in);
+ break;
+
+ case 'a':
+- h->curint->address = ADDR (arg, "address");
+- if (!IN_CLASSA (ntohl (h->curint->address))
+- && !IN_CLASSB (ntohl (h->curint->address))
+- && !IN_CLASSC (ntohl (h->curint->address)))
+- {
+- if (IN_MULTICAST (ntohl (h->curint->address)))
+- FAIL (EINVAL, 1, 0,
+- "%s: Cannot set interface address to multicast address",
+- arg);
+- else
+- FAIL (EINVAL, 1, 0,
+- "%s: Illegal or undefined network address", arg);
+- }
++ if (arg)
++ {
++ h->curint->address = ADDR (arg, "address");
++ if (!IN_CLASSA (ntohl (h->curint->address))
++ && !IN_CLASSB (ntohl (h->curint->address))
++ && !IN_CLASSC (ntohl (h->curint->address)))
++ {
++ if (IN_MULTICAST (ntohl (h->curint->address)))
++ FAIL (EINVAL, 1, 0,
++ "%s: Cannot set interface address to multicast address",
++ arg);
++ else
++ FAIL (EINVAL, 1, 0,
++ "%s: Illegal or undefined network address", arg);
++ }
++ } else {
++ h->curint->address = ADDR ("0.0.0.0", "address");
++ h->curint->netmask = ADDR ("255.0.0.0", "netmask");
++ h->curint->gateway = INADDR_NONE;
++ }
+ break;
++
+ case 'm':
+- h->curint->netmask = ADDR (arg, "netmask"); break;
++ if (arg)
++ h->curint->netmask = ADDR (arg, "netmask");
++ else
++ h->curint->netmask = INADDR_NONE;
++ break;
++
+ case 'p':
+- h->curint->peer = ADDR (arg, "peer"); break;
++ if (arg)
++ h->curint->peer = ADDR (arg, "peer");
++ else
++ h->curint->peer = INADDR_NONE;
++ break;
++
+ case 'g':
+- h->curint->gateway = ADDR (arg, "gateway"); break;
++ if (arg)
++ {
++ /* Remove an possible other default gateway */
++ for (in = h->interfaces; in < h->interfaces + h->num_interfaces;
++ in++)
++ in->gateway = INADDR_NONE;
++ h->curint->gateway = ADDR (arg, "gateway");
++ }
++ else
++ h->curint->gateway = INADDR_NONE;
++ break;
+
+ case '4':
+ pfinet_bind (PORTCLASS_INET, arg);
+@@ -254,36 +338,46 @@ parse_opt (int opt, char *arg, struct ar
+ break;
+
+ case 'A':
+- if ((ptr = strchr (arg, '/')))
++ if (arg)
+ {
+- h->curint->address6.prefix_len = atoi (ptr + 1);
+- if (h->curint->address6.prefix_len > 128)
+- FAIL (EINVAL, 1, 0, "%s: The prefix-length is invalid", arg);
++ if ((ptr = strchr (arg, '/')))
++ {
++ h->curint->address6.prefix_len = atoi (ptr + 1);
++ if (h->curint->address6.prefix_len > 128)
++ FAIL (EINVAL, 1, 0, "%s: The prefix-length is invalid", arg);
++
++ *ptr = 0;
++ }
++ else
++ {
++ h->curint->address6.prefix_len = 64;
++ fprintf (stderr, "No prefix-length given, "
++ "defaulting to %s/64.\n", arg);
++ }
+
+- *ptr = 0;
++ if (inet_pton (AF_INET6, arg, &h->curint->address6.addr) <= 0)
++ PERR (EINVAL, "Malformed address");
++
++ if (IN6_IS_ADDR_MULTICAST (&h->curint->address6.addr))
++ FAIL (EINVAL, 1, 0, "%s: Cannot set interface address to "
++ "multicast address", arg);
+ }
+ else
+- {
+- h->curint->address6.prefix_len = 64;
+- fprintf (stderr, "No prefix-length given, defaulting to %s/64.\n",
+- arg);
+- }
+-
+- if (inet_pton (AF_INET6, arg, &h->curint->address6.addr) <= 0)
+- PERR (EINVAL, "Malformed address");
+-
+- if (IN6_IS_ADDR_MULTICAST (&h->curint->address6.addr))
+- FAIL (EINVAL, 1, 0, "%s: Cannot set interface address to "
+- "multicast address", arg);
++ memset (&h->curint->address6, 0, sizeof (struct inet6_ifaddr));
+ break;
+
+ case 'G':
+- if (inet_pton (AF_INET6, arg, &h->curint->gateway6) <= 0)
+- PERR (EINVAL, "Malformed gateway");
++ if (arg)
++ {
++ if (inet_pton (AF_INET6, arg, &h->curint->gateway6) <= 0)
++ PERR (EINVAL, "Malformed gateway");
+
+- if (IN6_IS_ADDR_MULTICAST (&h->curint->gateway6))
+- FAIL (EINVAL, 1, 0, "%s: Cannot set gateway to "
+- "multicast address", arg);
++ if (IN6_IS_ADDR_MULTICAST (&h->curint->gateway6))
++ FAIL (EINVAL, 1, 0, "%s: Cannot set gateway to "
++ "multicast address", arg);
++ }
++ else
++ memset (&h->curint->gateway6, 0, sizeof (struct in6_addr));
+ break;
+ #endif /* CONFIG_IPV6 */
+
+@@ -323,20 +417,19 @@ parse_opt (int opt, char *arg, struct ar
+ /* Specifying a netmask for an address-less interface is a no-no. */
+ FAIL (EDESTADDRREQ, 14, 0, "Cannot set netmask");
+ #endif
+-
+- gateway = INADDR_NONE;
+ #ifdef CONFIG_IPV6
+ gw6_in = NULL;
+ #endif
++ gw4_in = NULL;
+ for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
+ {
++ /* delete interface if it doesn't match the actual netmask */
++ if (! ( (h->curint->address & h->curint->netmask)
++ == (h->curint->gateway & h->curint->netmask)))
++ h->curint->gateway = INADDR_NONE;
++
+ if (in->gateway != INADDR_NONE)
+- {
+- if (gateway != INADDR_NONE)
+- FAIL (err, 15, 0, "Cannot have multiple default gateways");
+- gateway = in->gateway;
+- in->gateway = INADDR_NONE;
+- }
++ gw4_in = in;
+
+ #ifdef CONFIG_IPV6
+ if (!IN6_IS_ADDR_UNSPECIFIED (&in->gateway6))
+@@ -361,15 +454,20 @@ parse_opt (int opt, char *arg, struct ar
+ idev = ipv6_find_idev(in->device);
+ #endif
+
+- if (in->address != INADDR_NONE || in->netmask != INADDR_NONE)
++ if (in->address == INADDR_NONE && in->netmask == INADDR_NONE)
++ {
++ h->curint->address = ADDR ("0.0.0.0", "address");
++ h->curint->netmask = ADDR ("255.0.0.0", "netmask");
++ }
++
++ if (in->device)
++ err = configure_device (in->device, in->address, in->netmask,
++ in->peer, INADDR_NONE);
++
++ if (err)
+ {
+- err = configure_device (in->device, in->address, in->netmask,
+- in->peer, INADDR_NONE);
+- if (err)
+- {
+- __mutex_unlock (&global_lock);
+- FAIL (err, 16, 0, "cannot configure interface");
+- }
++ __mutex_unlock (&global_lock);
++ FAIL (err, 16, 0, "cannot configure interface");
+ }
+
+ #ifdef CONFIG_IPV6
+@@ -377,24 +475,25 @@ parse_opt (int opt, char *arg, struct ar
+ continue;
+
+ /* First let's remove all non-local addresses. */
+- struct inet6_ifaddr *ifa = idev->addr_list;
+-
+- while (ifa)
+- {
+- struct inet6_ifaddr *c_ifa = ifa;
+- ifa = ifa->if_next;
+-
+- if (IN6_ARE_ADDR_EQUAL (&c_ifa->addr, &in->address6.addr))
+- memset (&in->address6, 0, sizeof (struct inet6_ifaddr));
+-
+- else if (!IN6_IS_ADDR_LINKLOCAL (&c_ifa->addr)
+- && !IN6_IS_ADDR_SITELOCAL (&c_ifa->addr))
+- inet6_addr_del (in->device->ifindex, &c_ifa->addr,
+- c_ifa->prefix_len);
+- }
+-
+- if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr))
+- {
++ struct inet6_ifaddr *ifa = idev->addr_list;
++
++ while (ifa)
++ {
++ struct inet6_ifaddr *c_ifa = ifa;
++ ifa = ifa->if_next;
++
++ if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr)
++ && IN6_ARE_ADDR_EQUAL (&c_ifa->addr, &in->address6.addr))
++ memset (&in->address6, 0, sizeof (struct inet6_ifaddr));
++
++ else if (!IN6_IS_ADDR_LINKLOCAL (&c_ifa->addr)
++ && !IN6_IS_ADDR_SITELOCAL (&c_ifa->addr))
++ inet6_addr_del (in->device->ifindex, &c_ifa->addr,
++ c_ifa->prefix_len);
++ }
++
++ if (!IN6_IS_ADDR_UNSPECIFIED (&in->address6.addr))
++ {
+ /* Now assign the new address */
+ inet6_addr_add (in->device->ifindex, &in->address6.addr,
+ in->address6.prefix_len);
+@@ -418,33 +517,40 @@ parse_opt (int opt, char *arg, struct ar
+ req.nlh.nlmsg_seq = 0;
+ req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm);
+
+- bzero (&req.rtm, sizeof req.rtm);
+- bzero (&rta, sizeof rta);
++ memset (&req.rtm, 0, sizeof req.rtm);
++ memset (&rta, 0, sizeof rta);
+ req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.rtm.rtm_type = RTN_UNICAST;
+ req.rtm.rtm_protocol = RTPROT_STATIC;
+- rta.rta_gw = &gateway;
+
+- if (gateway == INADDR_NONE)
++ if (!gw4_in)
+ {
+- /* Delete any existing default route. */
+- req.nlh.nlmsg_type = RTM_DELROUTE;
+- req.nlh.nlmsg_flags = 0;
+- tb = fib_get_table (req.rtm.rtm_table);
+- if (tb)
+- {
+- err = - (*tb->tb_delete) (tb, &req.rtm, &rta, &req.nlh, 0);
+- if (err && err != ESRCH)
+- {
+- __mutex_unlock (&global_lock);
+- FAIL (err, 17, 0, "cannot remove old default gateway");
+- }
+- err = 0;
+- }
++ /* Delete any existing default route on configured devices */
++ for (in = h->interfaces; in < h->interfaces + h->num_interfaces;
++ in++) {
++ req.nlh.nlmsg_type = RTM_DELROUTE;
++ req.nlh.nlmsg_flags = 0;
++ rta.rta_oif = &in->device->ifindex;
++ tb = fib_get_table (req.rtm.rtm_table);
++ if (tb)
++ {
++ err = - (*tb->tb_delete)
++ (tb, &req.rtm, &rta, &req.nlh, 0);
++ if (err && err != ESRCH)
++ {
++ __mutex_unlock (&global_lock);
++ FAIL (err, 17, 0,
++ "cannot remove old default gateway");
++ }
++ err = 0;
++ }
++ }
+ }
+ else
+ {
+ /* Add a default route, replacing any existing one. */
++ rta.rta_oif = &gw4_in->device->ifindex;
++ rta.rta_gw = &gw4_in->gateway;
+ req.nlh.nlmsg_type = RTM_NEWROUTE;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
+ tb = fib_new_table (req.rtm.rtm_table);
+@@ -467,13 +573,77 @@ parse_opt (int opt, char *arg, struct ar
+ if (!gw6_in || rt6i->rt6i_dev != gw6_in->device
+ || !IN6_ARE_ADDR_EQUAL (&rt6i->rt6i_gateway, &gw6_in->gateway6))
+ {
+- rt6_purge_dflt_routers (0);
++ /* Delete any existing default route on configured devices */
++ for (in = h->interfaces; in < h->interfaces
++ + h->num_interfaces; in++)
++ if (rt6i->rt6i_dev == in->device || gw6_in )
++ rt6_purge_dflt_routers (0);
++
+ if (gw6_in)
+ rt6_add_dflt_router (&gw6_in->gateway6, gw6_in->device);
+ }
+ }
+ #endif
+
++ /* Setup the routing required for DHCP. */
++ for (in = h->interfaces; in < h->interfaces + h->num_interfaces; in++)
++ {
++ struct kern_rta rta;
++ struct
++ {
++ struct nlmsghdr nlh;
++ struct rtmsg rtm;
++ } req;
++ struct fib_table *tb;
++ struct rtentry route;
++ struct sockaddr_in *dst;
++ struct device *dev;
++
++ if (!in->device)
++ continue;
++
++ dst = (struct sockaddr_in *) &route.rt_dst;
++ if (!in->device->name)
++ {
++ __mutex_unlock (&global_lock);
++ FAIL (ENODEV, 17, 0, "unknown device");
++ }
++ dev = dev_get (in->device->name);
++ if (!dev)
++ {
++ __mutex_unlock (&global_lock);
++ FAIL (ENODEV, 17, 0, "unknown device");
++ }
++
++ /* Simulate the SIOCADDRT behavior. */
++ memset (&route, 0, sizeof (struct rtentry));
++ memset (&req.rtm, 0, sizeof req.rtm);
++ memset (&rta, 0, sizeof rta);
++ req.nlh.nlmsg_type = RTM_NEWROUTE;
++
++ /* Append this routing for 0.0.0.0. By this way we can send always
++ dhcp messages (e.g dhcp renew). */
++ req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE
++ | NLM_F_APPEND;
++ req.rtm.rtm_protocol = RTPROT_BOOT;
++ req.rtm.rtm_scope = RT_SCOPE_LINK;
++ req.rtm.rtm_type = RTN_UNICAST;
++ rta.rta_dst = &dst->sin_addr.s_addr;
++ rta.rta_oif = &dev->ifindex;
++
++ tb = fib_new_table (req.rtm.rtm_table);
++ if (tb)
++ err = tb->tb_insert (tb, &req.rtm, &rta, &req.nlh, NULL);
++ else
++ err = ENOBUFS;
++
++ if (err)
++ {
++ __mutex_unlock (&global_lock);
++ FAIL (err, 17, 0, "cannot add route");
++ }
++ }
++
+ __mutex_unlock (&global_lock);
+
+ /* Fall through to free hook. */
+@@ -526,8 +696,9 @@ trivfs_append_args (struct trivfs_contro
+ ADD_ADDR_OPT ("netmask", mask);
+ if (peer != addr)
+ ADD_ADDR_OPT ("peer", peer);
+- key.iif = dev->ifindex;
+- if (! main_table->tb_lookup (main_table, &key, &res))
++ key.oif = dev->ifindex;
++ if (! main_table->tb_lookup (main_table, &key, &res)
++ && FIB_RES_GW(res) != INADDR_ANY)
+ ADD_ADDR_OPT ("gateway", FIB_RES_GW (res));
+
+ #undef ADD_ADDR_OPT
+--- a/pfinet/linux-src/net/ipv4/devinet.c
++++ b/pfinet/linux-src/net/ipv4/devinet.c
+@@ -214,10 +214,12 @@ inet_insert_ifa(struct in_device *in_dev
+ {
+ struct in_ifaddr *ifa1, **ifap, **last_primary;
+
++#ifndef _HURD_
+ if (ifa->ifa_local == 0) {
+ inet_free_ifa(ifa);
+ return 0;
+ }
++#endif
+
+ ifa->ifa_flags &= ~IFA_F_SECONDARY;
+ last_primary = &in_dev->ifa_list;
diff --git a/debian/patches/pflocal.patch b/debian/patches/pflocal.patch
new file mode 100644
index 00000000..3d9b3ac2
--- /dev/null
+++ b/debian/patches/pflocal.patch
@@ -0,0 +1,674 @@
+2005-05-17 Neal H. Walfield <neal@gnu.org>
+
+ * connq.h (struct connq_request): Remove forward.
+ (connq_listen): Wait for a request to be queued not until there is
+ a connection attempt. Remove REQ parameter. Update callers.
+ (connq_request_complete): Remove declaration.
+ (connq_connect): Wait for a slot to queue a request not until
+ there is an acceptor. Remove SOCK parameter. Update callers.
+ (connq_connect_complete): New declaration.
+ (connq_connect_cancel): New declaration.
+
+ * connq.c (struct connq): Remove fields noqueue, queue, length,
+ head and tail. Add fields head, tail, count, max, connectors and
+ num_connectors. That is, replace the circular buffer with a
+ singly linked list.
+ (qnext): Remove function.
+ (struct connq_request): Remove field signal, lock, completed and
+ err. Add field next.
+ (connq_request_init): Rewrite according to new semantics.
+ (connq_request_enqueue): New function.
+ (connq_request_dequeue): New function.
+ (connq_create): Update according to new semantics.
+ (connq_destroy): Likewise.
+ (connq_listen): Rewrite to not block until there is a connector
+ but until there is a request in the queue.
+ (connq_request_complete): Remove function.
+ (connq_connect): Rewrite to not block until there is an acceptor
+ but until there is space for a request.
+ (connq_connect_complete): New function.
+ (connq_connect_cancel): New function.
+ (connq_compress): Remove dead code.
+ (connq_set_length): Rewrite.
+
+ * socket.c (S_socket_connect): Create the server socket here...
+ (S_socket_accept): ... not here.
+
+---
+ pflocal/connq.c | 341 +++++++++++++++++++++++++++++--------------------------
+ pflocal/connq.h | 39 +++---
+ pflocal/io.c | 8 -
+ pflocal/socket.c | 72 +++++------
+ 4 files changed, 245 insertions(+), 215 deletions(-)
+
+--- a/pflocal/connq.c
++++ b/pflocal/connq.c
+@@ -26,31 +26,22 @@
+ /* A queue for queueing incoming connections. */
+ struct connq
+ {
+- /* True if all connection requests should be treated as non-blocking. */
+- int noqueue;
+-
+ /* The connection request queue. */
+- struct connq_request **queue;
+- unsigned length;
+- /* Head is the position in QUEUE of the first request, and TAIL is the
+- first free position in the queue. If HEAD == TAIL, then the queue is
+- empty. Starting at HEAD, successive positions can be calculated by
+- using qnext(). */
+- unsigned head, tail;
++ struct connq_request *head;
++ struct connq_request **tail;
++ unsigned count;
++ unsigned max;
+
+ /* Threads that have done an accept on this queue wait on this condition. */
+ struct condition listeners;
+ unsigned num_listeners;
+
++ /* Threads that have done a connect on this queue wait on this condition. */
++ struct condition connectors;
++ unsigned num_connectors;
++
+ struct mutex lock;
+ };
+-
+-/* Returns the position CQ's queue after POS. */
+-static inline unsigned
+-qnext (struct connq *cq, unsigned pos)
+-{
+- return (pos + 1 == cq->length) ? 0 : pos + 1;
+-}
+
+ /* ---------------------------------------------------------------- */
+
+@@ -58,30 +49,50 @@ qnext (struct connq *cq, unsigned pos)
+ get information from and to the thread. */
+ struct connq_request
+ {
++ struct connq_request *next;
++
+ /* The socket that's waiting to connect. */
+ struct sock *sock;
+-
+- /* What the waiting thread blocks on. */
+- struct condition signal;
+- struct mutex lock;
+-
+- /* Set to true when this request has been dealt with, to guard against
+- spurious conditions being signaled. */
+- int completed;
+-
+- /* After the waiting thread is unblocked, this is the result, either 0 if
+- SOCK has been connected, or an error. */
+- error_t err;
+ };
+
+ static inline void
+ connq_request_init (struct connq_request *req, struct sock *sock)
+ {
+- req->err = 0;
+ req->sock = sock;
+- req->completed = 0;
+- condition_init (&req->signal);
+- mutex_init (&req->lock);
++}
++
++/* Enqueue connection request REQ onto CQ. CQ must be locked. */
++static void
++connq_request_enqueue (struct connq *cq, struct connq_request *req)
++{
++ assert (! mutex_try_lock (&cq->lock));
++
++ req->next = NULL;
++ *cq->tail = req;
++ cq->tail = &req->next;
++
++ cq->count ++;
++}
++
++/* Dequeue a pending request from CQ. CQ must be locked and must not
++ be empty. */
++static struct connq_request *
++connq_request_dequeue (struct connq *cq)
++{
++ struct connq_request *req;
++
++ assert (! mutex_try_lock (&cq->lock));
++ assert (cq->head);
++
++ req = cq->head;
++ cq->head = req->next;
++ if (! cq->head)
++ /* We just dequeued the last element. Fixup the tail pointer. */
++ cq->tail = &cq->head;
++
++ cq->count --;
++
++ return req;
+ }
+
+ /* ---------------------------------------------------------------- */
+@@ -95,16 +106,20 @@ connq_create (struct connq **cq)
+ struct connq *new = malloc (sizeof (struct connq));
+
+ if (!new)
+- return ENOMEM;
++ return ENOBUFS;
++
++ new->head = NULL;
++ new->tail = &new->head;
++ new->count = 0;
++ /* By default, don't queue requests. */
++ new->max = 0;
+
+- new->noqueue = 1; /* By default, don't queue requests. */
+- new->length = 0;
+- new->head = new->tail = 0;
+- new->queue = NULL;
+ new->num_listeners = 0;
++ new->num_connectors = 0;
+
+ mutex_init (&new->lock);
+ condition_init (&new->listeners);
++ condition_init (&new->connectors);
+
+ *cq = new;
+ return 0;
+@@ -116,175 +131,189 @@ connq_destroy (struct connq *cq)
+ {
+ /* Everybody in the queue should hold a reference to the socket
+ containing the queue. */
+- assert (cq->length == 0);
+- /* Nevertheless, malloc(0) or realloc(0) might allocate some small
+- space. */
+- if (cq->queue)
+- free (cq->queue);
++ assert (! cq->head);
++ assert (cq->count == 0);
++
+ free (cq);
+ }
+
+ /* ---------------------------------------------------------------- */
+
+-/* Wait for a connection attempt to be made on CQ, and return the connecting
+- socket in SOCK, and a request tag in REQ. If REQ is NULL, the request is
+- left in the queue, otherwise connq_request_complete must be called on REQ
+- to allow the requesting thread to continue. If NOBLOCK is true,
+- EWOULDBLOCK is returned when there are no immediate connections
+- available. */
++/* Return a connection request on CQ. If SOCK is NULL, the request is
++ left in the queue. If NOBLOCK is true, EWOULDBLOCK is returned
++ when there are no immediate connections available. */
+ error_t
+-connq_listen (struct connq *cq, int noblock,
+- struct connq_request **req, struct sock **sock)
++connq_listen (struct connq *cq, int noblock, struct sock **sock)
+ {
++ error_t err = 0;
++
+ mutex_lock (&cq->lock);
+
+- if (noblock && cq->head == cq->tail)
++ if (noblock && cq->count == 0 && cq->num_connectors == 0)
+ {
+ mutex_unlock (&cq->lock);
+ return EWOULDBLOCK;
+ }
+
++ if (! sock && (cq->count > 0 || cq->num_connectors > 0))
++ /* The caller just wants to know if a connection ready. */
++ {
++ mutex_unlock (&cq->lock);
++ return 0;
++ }
++
+ cq->num_listeners++;
+
+- while (cq->head == cq->tail)
+- if (hurd_condition_wait (&cq->listeners, &cq->lock))
+- {
+- cq->num_listeners--;
+- mutex_unlock (&cq->lock);
+- return EINTR;
+- }
++ if (cq->count == 0)
++ /* The request queue is empty. */
++ {
++ assert (! cq->head);
++
++ if (cq->num_connectors > 0)
++ /* Someone is waiting for an acceptor. Signal that we can
++ service their request. */
++ condition_signal (&cq->connectors);
++
++ do
++ if (hurd_condition_wait (&cq->listeners, &cq->lock))
++ {
++ cq->num_listeners--;
++ err = EINTR;
++ goto out;
++ }
++ while (cq->count == 0);
++ }
++
++ assert (cq->head);
+
+- if (req != NULL)
++ if (sock)
+ /* Dequeue the next request, if desired. */
+ {
+- *req = cq->queue[cq->head];
+- cq->head = qnext (cq, cq->head);
+- if (sock != NULL)
+- *sock = (*req)->sock;
++ struct connq_request *req = connq_request_dequeue (cq);
++ *sock = req->sock;
++ free (req);
+ }
++ else if (cq->num_listeners > 0)
++ /* The caller will not actually process this request but someone
++ else could. (This case is rare but possible: it would require
++ one thread to do a select on the socket and a second to do an
++ accept.) */
++ condition_signal (&cq->listeners);
++ else
++ /* There is no one else to process the request and the connection
++ has now been initiated. This is not actually a problem as even
++ if the current queue limit is 0, the connector will queue the
++ request and another listener (should) eventually come along.
++ (In fact it is very probably as the caller has likely done a
++ select and will now follow up with an accept.) */
++ ;
+
+- cq->num_listeners--;
+-
++ out:
+ mutex_unlock (&cq->lock);
+-
+- return 0;
+-}
+-
+-/* Return the error code ERR to the thread that made the listen request REQ,
+- returned from a previous connq_listen. */
+-void
+-connq_request_complete (struct connq_request *req, error_t err)
+-{
+- mutex_lock (&req->lock);
+- req->err = err;
+- req->completed = 1;
+- condition_signal (&req->signal);
+- mutex_unlock (&req->lock);
++ return err;
+ }
+
+-/* Try to connect SOCK with the socket listening on CQ. If NOBLOCK is true,
+- then return EWOULDBLOCK immediately when there are no immediate
+- connections available. Neither SOCK nor CQ should be locked. */
++/* Try to connect SOCK with the socket listening on CQ. If NOBLOCK is
++ true, then return EWOULDBLOCK if there are no connections
++ immediately available. On success, this call must be followed up
++ either connq_connect_complete or connq_connect_cancel. */
+ error_t
+-connq_connect (struct connq *cq, int noblock, struct sock *sock)
++connq_connect (struct connq *cq, int noblock)
+ {
+- error_t err = 0;
+- unsigned next;
+-
+ mutex_lock (&cq->lock);
+
+ /* Check for listeners after we've locked CQ for good. */
+- if ((noblock || cq->noqueue) && cq->num_listeners == 0)
++
++ if (noblock
++ && cq->count + cq->num_connectors >= cq->max + cq->num_listeners)
++ /* We are in non-blocking mode and would have to wait to secure an
++ entry in the listen queue. */
+ {
+ mutex_unlock (&cq->lock);
+ return EWOULDBLOCK;
+ }
+
+- next = qnext (cq, cq->tail);
+- if (next == cq->tail)
+- /* The queue is full. */
+- err = ECONNREFUSED;
+- else
+- {
+- struct connq_request req;
++ cq->num_connectors ++;
++
++ while (cq->count + cq->num_connectors > cq->max + cq->num_listeners)
++ /* The queue is full and there is no immediate listener to service
++ us. Block until we can get a slot. */
++ if (hurd_condition_wait (&cq->connectors, &cq->lock))
++ {
++ cq->num_connectors --;
++ mutex_unlock (&cq->lock);
++ return EINTR;
++ }
+
+- connq_request_init (&req, sock);
++ mutex_unlock (&cq->lock);
+
+- cq->queue[cq->tail] = &req;
+- cq->tail = next;
++ return 0;
++}
+
+- /* Hold REQ.LOCK before we signal the condition so that we're sure
+- to be woken up. */
+- mutex_lock (&req.lock);
+- condition_signal (&cq->listeners);
+- mutex_unlock (&cq->lock);
++/* Follow up to connq_connect. Completes the connect, SOCK is the new
++ server socket. */
++void
++connq_connect_complete (struct connq *cq, struct sock *sock)
++{
++ struct connq_request *req;
++
++ req = malloc (sizeof (struct connq_request));
++ if (! req)
++ abort ();
++
++ connq_request_init (req, sock);
+
+- while (!req.completed)
+- condition_wait (&req.signal, &req.lock);
+- err = req.err;
++ mutex_lock (&cq->lock);
++
++ assert (cq->num_connectors > 0);
++ cq->num_connectors --;
++
++ connq_request_enqueue (cq, req);
+
+- mutex_unlock (&req.lock);
++ if (cq->num_listeners > 0)
++ /* Wake a listener up. We must consume the listener ref here as
++ someone else might call this function before the listener
++ thread dequeues this request. */
++ {
++ cq->num_listeners --;
++ condition_signal (&cq->listeners);
+ }
+
+- return err;
++ mutex_unlock (&cq->lock);
+ }
+-
+-#if 0
+-/* `Compresses' CQ, by removing any NULL entries. CQ should be locked. */
+-static void
+-connq_compress (struct connq *cq)
++
++/* Follow up to connq_connect. Cancel the connect. */
++void
++connq_connect_cancel (struct connq *cq)
+ {
+- unsigned pos;
+- unsigned comp_tail = cq->head;
++ mutex_lock (&cq->lock);
+
+- /* Now compress the queue to remove any null entries we put in. */
+- for (pos = cq->head; pos != cq->tail; pos = qnext (cq, pos))
+- if (cq->queue[pos] != NULL)
+- /* This position has a non-NULL request, so move it to the end of the
+- compressed queue. */
+- {
+- cq->queue[comp_tail] = cq->queue[pos];
+- comp_tail = qnext (cq, comp_tail);
+- }
++ assert (cq->num_connectors > 0);
++ cq->num_connectors --;
+
+- /* Move back tail to only include what we kept in the queue. */
+- cq->tail = comp_tail;
++ if (cq->count + cq->num_connectors >= cq->max + cq->num_listeners)
++ /* A connector is blocked and could use the spot we reserved. */
++ condition_signal (&cq->connectors);
++
++ mutex_unlock (&cq->lock);
+ }
+-#endif
+
+-/* Set CQ's queue length to LENGTH. Any sockets already waiting for a
+- connections that are past the new length will fail with ECONNREFUSED. */
++/* Set CQ's queue length to LENGTH. */
+ error_t
+-connq_set_length (struct connq *cq, int length)
++connq_set_length (struct connq *cq, int max)
+ {
+- mutex_lock (&cq->lock);
++ int omax;
+
+- if (length > cq->length)
+- /* Growing the queue is simple... */
+- cq->queue = realloc (cq->queue, sizeof (struct connq_request *) * length);
+- else
+- /* Shrinking it less so. */
+- {
+- int i;
+- struct connq_request **new_queue =
+- malloc (sizeof (struct connq_request *) * length);
+-
+- for (i = 0; i < cq->length && cq->head != cq->tail; i++)
+- {
+- if (i < length)
+- /* Keep this connect request in the queue. */
+- new_queue[length - i] = cq->queue[cq->head];
+- else
+- /* Punt this one. */
+- connq_request_complete (cq->queue[cq->head], ECONNREFUSED);
+- cq->head = qnext (cq, cq->head);
+- }
+-
+- free (cq->queue);
+- cq->queue = new_queue;
+- }
++ mutex_lock (&cq->lock);
++ omax = cq->max;
++ cq->max = max;
+
+- cq->noqueue = 0; /* Turn on queueing. */
++ if (max > omax && cq->count >= omax && cq->count < max
++ && cq->num_connectors >= cq->num_listeners)
++ /* This is an increase in the number of connection slots which has
++ made some slots available and there are waiting threads. Wake
++ them up. */
++ condition_broadcast (&cq->listeners);
+
+ mutex_unlock (&cq->lock);
+
+--- a/pflocal/connq.h
++++ b/pflocal/connq.h
+@@ -23,9 +23,8 @@
+
+ #include <errno.h>
+
+-/* Unknown types */
++/* Forward. */
+ struct connq;
+-struct connq_request;
+ struct sock;
+
+ /* Create a new listening queue, returning it in CQ. The resulting queue
+@@ -36,26 +35,26 @@ error_t connq_create (struct connq **cq)
+ /* Destroy a queue. */
+ void connq_destroy (struct connq *cq);
+
+-/* Wait for a connection attempt to be made on CQ, and return the connecting
+- socket in SOCK, and a request tag in REQ. If REQ is NULL, the request is
+- left in the queue, otherwise connq_request_complete must be called on REQ
+- to allow the requesting thread to continue. If NOBLOCK is true,
+- EWOULDBLOCK is returned when there are no immediate connections
+- available. CQ should be unlocked. */
+-error_t connq_listen (struct connq *cq, int noblock,
+- struct connq_request **req, struct sock **sock);
+-
+-/* Return the error code ERR to the thread that made the listen request REQ,
+- returned from a previous connq_listen. */
+-void connq_request_complete (struct connq_request *req, error_t err);
++/* Return a connection request on CQ. If SOCK is NULL, the request is
++ left in the queue. If NOBLOCK is true, EWOULDBLOCK is returned
++ when there are no immediate connections available. */
++error_t connq_listen (struct connq *cq, int noblock, struct sock **sock);
++
++/* Try to connect SOCK with the socket listening on CQ. If NOBLOCK is
++ true, then return EWOULDBLOCK if there are no connections
++ immediately available. On success, this call must be followed up
++ either connq_connect_complete or connq_connect_cancel. */
++error_t connq_connect (struct connq *cq, int noblock);
++
++/* Follow up to connq_connect. Completes the connection, SOCK is the
++ new server socket. */
++void connq_connect_complete (struct connq *cq, struct sock *sock);
++
++/* Follow up to connq_connect. Cancel the connect. */
++void connq_connect_cancel (struct connq *cq);
+
+ /* Set CQ's queue length to LENGTH. Any sockets already waiting for a
+- connections that are past the new length will fail with ECONNREFUSED. */
++ connections that are past the new length remain. */
+ error_t connq_set_length (struct connq *cq, int length);
+
+-/* Try to connect SOCK with the socket listening on CQ. If NOBLOCK is true,
+- then return EWOULDBLOCK immediately when there are no immediate
+- connections available. Neither SOCK nor CQ should be locked. */
+-error_t connq_connect (struct connq *cq, int noblock, struct sock *sock);
+-
+ #endif /* __CONNQ_H__ */
+--- a/pflocal/io.c
++++ b/pflocal/io.c
+@@ -199,16 +199,16 @@ S_io_select (struct sock_user *user,
+
+ if (*select_type & SELECT_READ)
+ {
+- /* Wait for a connect. Passing in NULL for REQ means that the
+- request won't be dequeued. */
+- if (connq_listen (sock->listen_queue, 1, NULL, NULL) == 0)
++ /* Wait for a connect. Passing in NULL for SOCK means that
++ the request won't be dequeued. */
++ if (connq_listen (sock->listen_queue, 1, NULL) == 0)
+ /* We can satisfy this request immediately. */
+ return 0;
+ else
+ /* Gotta wait... */
+ {
+ ports_interrupt_self_on_port_death (user, reply);
+- return connq_listen (sock->listen_queue, 0, NULL, NULL);
++ return connq_listen (sock->listen_queue, 0, NULL);
+ }
+ }
+ }
+--- a/pflocal/socket.c
++++ b/pflocal/socket.c
+@@ -110,7 +110,7 @@ S_socket_connect (struct sock_user *user
+ else if (sock->flags & SOCK_CONNECTED)
+ /* SOCK_CONNECTED is only set for connection-oriented sockets,
+ which can only ever connect once. [If we didn't do this test
+- here, it would eventually fail when it the listening socket
++ here, it would eventually fail when the listening socket
+ tried to accept our connection request.] */
+ err = EISCONN;
+ else
+@@ -118,16 +118,35 @@ S_socket_connect (struct sock_user *user
+ /* Assert that we're trying to connect, so anyone else trying
+ to do so will fail with EALREADY. */
+ sock->connect_queue = cq;
+- mutex_unlock (&sock->lock); /* Unlock SOCK while waiting. */
++ /* Unlock SOCK while waiting. */
++ mutex_unlock (&sock->lock);
+
+- /* Try to connect. */
+- err = connq_connect (cq, sock->flags & SOCK_NONBLOCK, sock);
++ err = connq_connect (peer->listen_queue,
++ sock->flags & SOCK_NONBLOCK);
++ if (!err)
++ {
++ struct sock *server;
++
++ err = sock_clone (peer, &server);
++ if (!err)
++ {
++ err = sock_connect (sock, server);
++ if (!err)
++ connq_connect_complete (peer->listen_queue, server);
++ else
++ sock_free (server);
++ }
+
+- /* We can safely set CONNECT_QUEUE to NULL, as no one else can
++ mutex_lock (&sock->lock);
++ if (err)
++ connq_connect_cancel (peer->listen_queue);
++ }
++
++ /* We must set CONNECT_QUEUE to NULL, as no one else can
+ set it until we've done so. */
+- mutex_lock (&sock->lock);
+ sock->connect_queue = NULL;
+ }
++
+ mutex_unlock (&sock->lock);
+ }
+ else
+@@ -157,42 +176,25 @@ S_socket_accept (struct sock_user *user,
+ err = ensure_connq (sock);
+ if (!err)
+ {
+- struct connq_request *req;
+ struct sock *peer_sock;
+
+- err =
+- connq_listen (sock->listen_queue, sock->flags & SOCK_NONBLOCK,
+- &req, &peer_sock);
++ err = connq_listen (sock->listen_queue, sock->flags & SOCK_NONBLOCK,
++ &peer_sock);
+ if (!err)
+ {
+- struct sock *conn_sock;
+-
+- err = sock_clone (sock, &conn_sock);
++ struct addr *peer_addr;
++ *port_type = MACH_MSG_TYPE_MAKE_SEND;
++ err = sock_create_port (peer_sock, port);
++ if (!err)
++ err = sock_get_addr (peer_sock, &peer_addr);
+ if (!err)
+ {
+- err = sock_connect (conn_sock, peer_sock);
+- if (!err)
+- {
+- struct addr *peer_addr;
+- *port_type = MACH_MSG_TYPE_MAKE_SEND;
+- err = sock_create_port (conn_sock, port);
+- if (!err)
+- err = sock_get_addr (peer_sock, &peer_addr);
+- if (!err)
+- {
+- *peer_addr_port = ports_get_right (peer_addr);
+- *peer_addr_port_type = MACH_MSG_TYPE_MAKE_SEND;
+- ports_port_deref (peer_addr);
+- }
+- else
+- /* TEAR DOWN THE CONNECTION XXX */;
+- }
+- if (err)
+- sock_free (conn_sock);
++ *peer_addr_port = ports_get_right (peer_addr);
++ *peer_addr_port_type = MACH_MSG_TYPE_MAKE_SEND;
++ ports_port_deref (peer_addr);
+ }
+-
+- /* Communicate any error (or success) to the connecting thread. */
+- connq_request_complete (req, err);
++ else
++ /* TEAR DOWN THE CONNECTION XXX */;
+ }
+ }
+
diff --git a/debian/patches/posix-sigcodes.patch b/debian/patches/posix-sigcodes.patch
new file mode 100644
index 00000000..34e089f2
--- /dev/null
+++ b/debian/patches/posix-sigcodes.patch
@@ -0,0 +1,270 @@
+commit 2a54ebafd46a26d537ac38d46dc82568f751cc42
+Author: Jeremie Koenig <jk@jk.fr.eu.org>
+Date: Wed Jun 8 03:00:37 2011 +0000
+
+ proc: send signals with POSIX sigcodes
+
+ * proc/stubs.c (send_signal): Add a sigcode argument.
+ * proc/proc.h (send_signal): Declare the sigcode argument.
+ * proc/pgrp.c (leave_pgrp): Specify a null sigcode.
+ * proc/wait.c (alert_parent): Use CLD_EXITED for SIGCHLD on exit.
+ (S_proc_mark_stop): Use CLD_STOPPED for SIGCHLD on stop.
+
+diff --git a/proc/pgrp.c b/proc/pgrp.c
+index 2d6ca93..72c09ba 100644
+--- a/proc/pgrp.c
++++ b/proc/pgrp.c
+@@ -399,42 +399,42 @@ leave_pgrp (struct proc *p)
+ else if (p->p_parent->p_pgrp != pg
+ && p->p_parent->p_pgrp->pg_session == pg->pg_session
+ && !--pg->pg_orphcnt)
+ {
+ /* We were the last process keeping this from being
+ an orphaned process group -- do the orphaning gook */
+ struct proc *ip;
+ int dosignal = 0;
+
+ for (ip = pg->pg_plist; ip; ip = ip->p_gnext)
+ {
+ if (ip->p_stopped)
+ dosignal = 1;
+ if (ip->p_msgport != MACH_PORT_NULL)
+ nowait_msg_proc_newids (ip->p_msgport, ip->p_task, ip->p_parent->p_pid,
+ ip->p_pid, 1);
+ }
+ if (dosignal)
+ for (ip = pg->pg_plist; ip; ip = ip->p_gnext)
+ {
+- send_signal (ip->p_msgport, SIGHUP, ip->p_task);
+- send_signal (ip->p_msgport, SIGCONT, ip->p_task);
++ send_signal (ip->p_msgport, SIGHUP, 0, ip->p_task);
++ send_signal (ip->p_msgport, SIGCONT, 0, ip->p_task);
+ }
+ }
+ }
+
+ /* Cause process P to join its process group. */
+ void
+ join_pgrp (struct proc *p)
+ {
+ struct pgrp *pg = p->p_pgrp;
+ struct proc *tp;
+ int origorphcnt;
+
+ p->p_gnext = pg->pg_plist;
+ p->p_gprevp = &pg->pg_plist;
+ if (pg->pg_plist)
+ pg->pg_plist->p_gprevp = &p->p_gnext;
+ pg->pg_plist = p;
+
+ origorphcnt = !!pg->pg_orphcnt;
+ if (p->p_parent->p_pgrp != pg
+diff --git a/proc/proc.h b/proc/proc.h
+index 7943e0b..b52ca1d 100644
+--- a/proc/proc.h
++++ b/proc/proc.h
+@@ -192,24 +192,24 @@ void exc_clean (void *);
+
+ struct proc *add_tasks (task_t);
+ int pidfree (pid_t);
+
+ struct proc *create_startup_proc (void);
+ struct proc *allocate_proc (task_t);
+ void proc_death_notify (struct proc *);
+ void complete_proc (struct proc *, pid_t);
+
+ void leave_pgrp (struct proc *);
+ void join_pgrp (struct proc *);
+ void boot_setsid (struct proc *);
+
+ void process_has_exited (struct proc *);
+ void alert_parent (struct proc *);
+ void reparent_zombies (struct proc *);
+ void complete_exit (struct proc *);
+
+ void initialize_version_info (void);
+
+-void send_signal (mach_port_t, int, mach_port_t);
++void send_signal (mach_port_t, int, int, mach_port_t);
+
+
+ #endif
+diff --git a/proc/stubs.c b/proc/stubs.c
+index de3a9b1..ee8e578 100644
+--- a/proc/stubs.c
++++ b/proc/stubs.c
+@@ -59,40 +59,41 @@ blocking_message_send (any_t arg)
+ case MACH_SEND_INTERRUPTED:
+ case MACH_SEND_INVALID_NOTIFY:
+ case MACH_SEND_NO_NOTIFY:
+ case MACH_SEND_NOTIFY_IN_PROGRESS:
+ assert_perror (err);
+ break;
+
+ default: /* Other errors are safe to ignore. */
+ break;
+ }
+
+
+ return 0;
+ }
+
+ /* Send signal SIGNO to MSGPORT with REFPORT as reference. Don't
+ block in any fashion. */
+ void
+ send_signal (mach_port_t msgport,
+ int signal,
++ int sigcode,
+ mach_port_t refport)
+ {
+ error_t err;
+
+ /* This message buffer might be modified by mach_msg in some error cases,
+ so we cannot safely use a shared static buffer. */
+ struct msg_sig_post_request message =
+ {
+ {
+ /* Message header: */
+ (MACH_MSGH_BITS_COMPLEX
+ | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
+ sizeof message, /* msgh_size */
+ msgport, /* msgh_remote_port */
+ MACH_PORT_NULL, /* msgh_local_port */
+ 0, /* msgh_seqno */
+ RPCID_SIG_POST, /* msgh_id */
+ },
+ {
+@@ -101,41 +102,41 @@ send_signal (mach_port_t msgport,
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Signal number */
+ signal,
+ /* Type descriptor for sigcode */
+ {
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Sigcode */
+- 0,
++ sigcode,
+ {
+ /* Type descriptor for refport */
+ MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ refport
+ };
+
+ err = mach_msg ((mach_msg_header_t *)&message,
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
+ MACH_PORT_NULL, 0, MACH_PORT_NULL);
+ switch (err)
+ {
+ case MACH_SEND_TIMED_OUT:
+ /* The send could not complete immediately, and we do not want to
+diff --git a/proc/wait.c b/proc/wait.c
+index 6fc94e8..332aaf6 100644
+--- a/proc/wait.c
++++ b/proc/wait.c
+@@ -127,41 +127,41 @@ sample_rusage (struct proc *p)
+ /* Return nonzero if a `waitpid' on WAIT_PID by a process
+ in MYPGRP cares about the death of PID/PGRP. */
+ static inline int
+ waiter_cares (pid_t wait_pid, pid_t mypgrp,
+ pid_t pid, pid_t pgrp)
+ {
+ return (wait_pid == pid ||
+ wait_pid == -pgrp ||
+ wait_pid == WAIT_ANY ||
+ (wait_pid == WAIT_MYPGRP && pgrp == mypgrp));
+ }
+
+ /* A process is dying. Send SIGCHLD to the parent.
+ Wake the parent if it is waiting for us to exit. */
+ void
+ alert_parent (struct proc *p)
+ {
+ /* We accumulate the aggregate usage stats of all our dead children. */
+ rusage_add (&p->p_parent->p_child_rusage, &p->p_rusage);
+
+- send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task);
++ send_signal (p->p_parent->p_msgport, SIGCHLD, CLD_EXITED, p->p_parent->p_task);
+
+ if (!p->p_exiting)
+ {
+ p->p_status = W_EXITCODE (0, SIGKILL);
+ p->p_sigcode = -1;
+ }
+
+ if (p->p_parent->p_waiting)
+ {
+ condition_broadcast (&p->p_parent->p_wakeup);
+ p->p_parent->p_waiting = 0;
+ }
+ }
+
+ kern_return_t
+ S_proc_wait (struct proc *p,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_port_type,
+ pid_t pid,
+ int options,
+@@ -240,41 +240,41 @@ S_proc_wait (struct proc *p,
+ kern_return_t
+ S_proc_mark_stop (struct proc *p,
+ int signo,
+ int sigcode)
+ {
+ if (!p)
+ return EOPNOTSUPP;
+
+ p->p_stopped = 1;
+ p->p_status = W_STOPCODE (signo);
+ p->p_sigcode = sigcode;
+ p->p_waited = 0;
+
+ if (p->p_parent->p_waiting)
+ {
+ condition_broadcast (&p->p_parent->p_wakeup);
+ p->p_parent->p_waiting = 0;
+ }
+
+ if (!p->p_parent->p_nostopcld)
+- send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task);
++ send_signal (p->p_parent->p_msgport, SIGCHLD, CLD_STOPPED, p->p_parent->p_task);
+
+ return 0;
+ }
+
+ /* Implement proc_mark_exit as described in <hurd/process.defs>. */
+ kern_return_t
+ S_proc_mark_exit (struct proc *p,
+ int status,
+ int sigcode)
+ {
+ if (!p)
+ return EOPNOTSUPP;
+
+ if (WIFSTOPPED (status))
+ return EINVAL;
+
+ sample_rusage (p); /* See comments above sample_rusage. */
+
+ if (p->p_exiting)
+ return EBUSY;
diff --git a/debian/patches/proxy-defpager.diff b/debian/patches/proxy-defpager.diff
new file mode 100644
index 00000000..0ba12dee
--- /dev/null
+++ b/debian/patches/proxy-defpager.diff
@@ -0,0 +1,59 @@
+https://savannah.gnu.org/bugs/?26751
+
+2009-06-07 Zheng Da <zhengda1936@gmail.com>
+
+ * Makefile: Use customized default_pager.defs.
+
+ * proxy-defpager.c: Include customized default_pager header.
+
+---
+ Makefile | 7 +++++--
+ proxy-defpager.c | 5 +++--
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff -u -a -r1.40 -r1.40.10.1
+--- a/trans/Makefile 6 Jun 2007 16:08:56 -0000 1.40
++++ b/trans/Makefile 7 Jun 2009 03:51:49 -0000 1.40.10.1
+@@ -26,13 +26,16 @@
+ fakeroot.c proxy-defpager.c
+ OBJS = $(SRCS:.c=.o) fsysServer.o ifsockServer.o passwordServer.o \
+ crashServer.o crash_replyUser.o msgServer.o \
+- default_pagerServer.o default_pagerUser.o \
++ ourdefault_pagerServer.o ourdefault_pagerUser.o \
+ device_replyServer.o elfcore.o
+ HURDLIBS = threads ports netfs trivfs iohelp fshelp pipe ihash shouldbeinlibc
+ password-LDLIBS = $(LIBCRYPT)
+
+ include ../Makeconf
+
++ourdefault_pager.defs: default_pager.defs
++ $(CPP) $(CPPFLAGS) -x c $< | sed -e '/MACH_MSG_TYPE_MAKE_SEND;/s/MAKE/COPY/' | sed -e '/subsystem/iserverprefix S_;' > $@
++
+ vpath elfcore.c $(top_srcdir)/exec
+
+ symlink: fsysServer.o
+@@ -40,7 +43,7 @@
+ crash: crashServer.o crash_replyUser.o msgServer.o elfcore.o
+ password: passwordServer.o
+ streamio: device_replyServer.o
+-proxy-defpager: default_pagerServer.o default_pagerUser.o
++proxy-defpager: ourdefault_pagerServer.o ourdefault_pagerUser.o
+
+ proxy-defpager crash password streamio: ../libthreads/libthreads.a ../libports/libports.a ../libtrivfs/libtrivfs.a ../libthreads/libthreads.a ../libfshelp/libfshelp.a
+ fifo new-fifo: ../libpipe/libpipe.a
+diff -u -a -r1.5 -r1.5.10.1
+--- a/trans/proxy-defpager.c 6 Jun 2007 16:08:56 -0000 1.5
++++ b/trans/proxy-defpager.c 7 Jun 2009 03:51:49 -0000 1.5.10.1
+@@ -23,9 +23,10 @@
+ #include <error.h>
+ #include <version.h>
+ #include <hurd/paths.h>
++#include <string.h>
+
+-#include "default_pager_S.h"
+-#include "default_pager_U.h"
++#include "ourdefault_pager_S.h"
++#include "ourdefault_pager_U.h"
+
+ static mach_port_t real_defpager, dev_master;
+
diff --git a/debian/patches/random-default-fast.patch b/debian/patches/random-default-fast.patch
new file mode 100644
index 00000000..555b3045
--- /dev/null
+++ b/debian/patches/random-default-fast.patch
@@ -0,0 +1,13 @@
+diff --git a/random/random.c b/random/random.c
+index 0ae31f5..c732356 100644
+--- a/random/random.c
++++ b/random/random.c
+@@ -50,7 +50,7 @@ struct condition select_alert; /* For read and select. */
+ numbers.
+ 2: Strong random numbers with a somewhat guaranteed entropy.
+ */
+-#define DEFAULT_LEVEL 2
++#define DEFAULT_LEVEL 1
+ static int level = DEFAULT_LEVEL;
+
+ /* Name of file to use as seed. */
diff --git a/debian/patches/rc.patch b/debian/patches/rc.patch
new file mode 100644
index 00000000..228bb349
--- /dev/null
+++ b/debian/patches/rc.patch
@@ -0,0 +1,78 @@
+More debianish rc scripts
+---
+ daemons/rc.sh | 43 ++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 32 insertions(+), 11 deletions(-)
+
+--- a/daemons/rc.sh
++++ b/daemons/rc.sh
+@@ -19,14 +19,17 @@ then
+ echo Automatic boot in progress...
+ date
+
+- /sbin/fsck --preen --writable
++ fsysopts / --update --readonly
++ /sbin/fsck -p -A
+
+ case $? in
+ # Successful completion
+ 0)
++ fsysopts / --update --writable
+ ;;
+ # Filesystem modified (but ok now)
+ 1 | 2)
++ fsysopts / --update --writable
+ ;;
+ # Fsck couldn't fix it.
+ 4 | 8)
+@@ -85,7 +88,15 @@ if test -d /tmp; then
+
+ fi
+ if test -d /var/run; then
+- (cd /var/run && { rm -rf -- *; cp /dev/null utmp; chmod 644 utmp; })
++ (cd /var/run && {
++ find . ! -type d ! -name utmp ! -name innd.pid \
++ -exec rm -f -- {} \;
++ cp /dev/null utmp
++ if grep -q ^utmp: /etc/group
++ then
++ chmod 664 utmp
++ chgrp utmp utmp
++ fi; })
+ fi
+ echo done
+
+@@ -104,15 +115,25 @@ touch /var/run/mtab
+
+ chmod 664 /etc/motd
+
+-echo -n starting daemons:
++(
++ trap ":" INT QUIT TSTP
+
+-/sbin/syslogd && echo -n ' syslogd'
+-/sbin/inetd && echo -n ' inetd'
+-
+-if test -x /sbin/sendmail -a -r /etc/sendmail.cf; then
+- /sbin/sendmail -bd -q30m && echo -n ' sendmail'
+-fi
+-
+-echo .
++ if [ -d /etc/rc.boot ]
++ then
++ for i in /etc/rc.boot/S*
++ do
++ [ ! -f $i ] && continue
++ $i start
++ done
++ fi
++ if [ -d /etc/rc2.d ]
++ then
++ for i in /etc/rc2.d/S*
++ do
++ [ ! -f $i ] && continue
++ $i start
++ done
++ fi
++)
+
+ date
diff --git a/debian/patches/runsystem_setup_pflocal.patch b/debian/patches/runsystem_setup_pflocal.patch
new file mode 100644
index 00000000..cd5a79eb
--- /dev/null
+++ b/debian/patches/runsystem_setup_pflocal.patch
@@ -0,0 +1,21 @@
+Automatically setup local sockets if not already done so. Needed early for shell
+pipelines.
+---
+ daemons/runsystem.sh | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/daemons/runsystem.sh
++++ b/daemons/runsystem.sh
+@@ -53,6 +53,12 @@ function singleuser ()
+ }
+
+
++# See whether pflocal is setup already, and do so if not (install case)
++
++if ! test -e /servers/socket/1 && which settrans >/dev/null ; then
++ settrans -c /servers/socket/1 /hurd/pflocal
++fi
++
+ # We expect to be started by console-run, which gives us no arguments and
+ # puts FALLBACK_CONSOLE=file-name in the environment if our console is
+ # other than a normal /dev/console.
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 00000000..85672278
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,34 @@
+console_utf-8.patch
+diskfs_no_inherit_dir_group.patch
+ext2fs_large_stores.patch
+hurd_console_startup.patch
+init_try_runsystem.gnu.patch
+install-msgids.diff
+libpager_update_seqno.patch
+libpthread_stubs.patch
+makedev.diff
+pfinet_dhcp.patch
+pflocal.patch
+rc.patch
+runsystem_setup_pflocal.patch
+startup-usr-support.patch
+tmp_exec_startup.patch
+uptime_w_path_fix.patch
+stat_round.patch
+libports_stability.patch
+libpthread_fix.patch
+extern_inline_fix.patch
+proxy-defpager.diff
+libpthread_procfs.patch
+makedev_keep_options.patch
+makedev_parted_store.patch
+console_ignore_bdf_err.patch
+libpthread_sigmask.patch
+ext2fs_nowait.patch
+libpager_deadlock.patch
+libdiskfs_self-reauth.patch
+libdiskfs_sync.patch
+libpthread_globsigdisp.patch
+posix-sigcodes.patch
+random-default-fast.patch
+libexec.patch
diff --git a/debian/patches/startup-usr-support.patch b/debian/patches/startup-usr-support.patch
new file mode 100644
index 00000000..1d705fc9
--- /dev/null
+++ b/debian/patches/startup-usr-support.patch
@@ -0,0 +1,27 @@
+Debian GNU/Hurd has a real /usr
+---
+ daemons/rc.sh | 2 +-
+ daemons/runsystem.sh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/daemons/rc.sh
++++ b/daemons/rc.sh
+@@ -1,6 +1,6 @@
+ #!/bin/bash
+
+-PATH=/bin:/sbin
++PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+ # Start the default pager. It will bail if there is already one running.
+ /hurd/mach-defpager
+--- a/daemons/runsystem.sh
++++ b/daemons/runsystem.sh
+@@ -11,7 +11,7 @@
+ ### Where to find programs, etc.
+ ###
+
+-PATH=/bin:/sbin
++PATH=/bin:/sbin:/usr/bin:/usr/sbin
+ export PATH
+
+ umask 022
diff --git a/debian/patches/stat_round.patch b/debian/patches/stat_round.patch
new file mode 100644
index 00000000..38454ba6
--- /dev/null
+++ b/debian/patches/stat_round.patch
@@ -0,0 +1,52 @@
+---
+ libdiskfs/file-utimes.c | 4 ++--
+ libdiskfs/node-times.c | 6 +++---
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/libdiskfs/file-utimes.c
++++ b/libdiskfs/file-utimes.c
+@@ -33,7 +33,7 @@ diskfs_S_file_utimes (struct protid *cre
+ else
+ {
+ np->dn_stat.st_atim.tv_sec = atime.seconds;
+- np->dn_stat.st_atim.tv_nsec = atime.microseconds * 1000;
++ np->dn_stat.st_atim.tv_nsec = 0;
+ np->dn_set_atime = 0;
+ }
+
+@@ -42,7 +42,7 @@ diskfs_S_file_utimes (struct protid *cre
+ else
+ {
+ np->dn_stat.st_mtim.tv_sec = mtime.seconds;
+- np->dn_stat.st_mtim.tv_nsec = mtime.microseconds * 1000;
++ np->dn_stat.st_mtim.tv_nsec = 0;
+ np->dn_set_mtime = 0;
+ }
+
+--- a/libdiskfs/node-times.c
++++ b/libdiskfs/node-times.c
+@@ -53,21 +53,21 @@ diskfs_set_node_times (struct node *np)
+ if (np->dn_set_mtime)
+ {
+ np->dn_stat.st_mtim.tv_sec = t.tv_sec;
+- np->dn_stat.st_mtim.tv_nsec = t.tv_usec * 1000;
++ np->dn_stat.st_mtim.tv_nsec = 0;
+ np->dn_stat_dirty = 1;
+ np->dn_set_mtime = 0;
+ }
+ if (np->dn_set_atime)
+ {
+ np->dn_stat.st_atim.tv_sec = t.tv_sec;
+- np->dn_stat.st_atim.tv_nsec = t.tv_usec * 1000;
++ np->dn_stat.st_atim.tv_nsec = 0;
+ np->dn_stat_dirty = 1;
+ np->dn_set_atime = 0;
+ }
+ if (np->dn_set_ctime)
+ {
+ np->dn_stat.st_ctim.tv_sec = t.tv_sec;
+- np->dn_stat.st_ctim.tv_nsec = t.tv_usec * 1000;
++ np->dn_stat.st_ctim.tv_nsec = 0;
+ np->dn_stat_dirty = 1;
+ np->dn_set_ctime = 0;
+ }
diff --git a/debian/patches/tmp_exec_startup.patch b/debian/patches/tmp_exec_startup.patch
new file mode 100644
index 00000000..bd605718
--- /dev/null
+++ b/debian/patches/tmp_exec_startup.patch
@@ -0,0 +1,54 @@
+Also try /tmp/exec as it's used for installation.
+
+TODO: not used by d-i. Is it used by crosshurd?
+---
+ libdiskfs/boot-start.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+--- a/libdiskfs/boot-start.c
++++ b/libdiskfs/boot-start.c
+@@ -126,8 +126,13 @@ diskfs_start_bootstrap ()
+ assert (_hurd_ports);
+ assert (_hurd_ports[INIT_PORT_CRDIR].port != MACH_PORT_NULL);
+ diskfs_exec = file_name_lookup (_SERVERS_EXEC, 0, 0);
+- if (diskfs_exec == MACH_PORT_NULL)
+- error (1, errno, "%s", _SERVERS_EXEC);
++ if (diskfs_exec == MACH_PORT_NULL)
++ {
++ /* Debian specifc work-around for install bootstrapping. */
++ diskfs_exec = file_name_lookup ("/tmp/exec", 0, 0);
++ if (diskfs_exec == MACH_PORT_NULL)
++ error (1, errno, "%s", _SERVERS_EXEC);
++ }
+ else
+ {
+ #ifndef NDEBUG
+@@ -177,8 +182,15 @@ diskfs_start_bootstrap ()
+ &retry, pathbuf, &execnode);
+ if (err)
+ {
+- error (0, err, "cannot set translator on %s", _SERVERS_EXEC);
+- mach_port_deallocate (mach_task_self (), diskfs_exec_ctl);
++ /* If /servers/exec is not available (which is the case during
++ installation, try /tmp/exec as well. */
++ err = dir_lookup (root_pt, "/tmp/exec", O_NOTRANS, 0,
++ &retry, pathbuf, &execnode);
++ if (err)
++ {
++ error (0, err, "cannot set translator on %s", _SERVERS_EXEC);
++ mach_port_deallocate (mach_task_self (), diskfs_exec_ctl);
++ }
+ }
+ else
+ {
+@@ -393,6 +405,10 @@ diskfs_execboot_fsys_startup (mach_port_
+
+ err = dir_lookup (rootport, _SERVERS_EXEC, flags|O_NOTRANS, 0,
+ &retry, pathbuf, real);
++ if (err)
++ /* Try /tmp/exec as well, in case we're installing. */
++ err = dir_lookup (rootport, "/tmp/exec", flags|O_NOTRANS|O_CREAT, 0,
++ &retry, pathbuf, real);
+ assert_perror (err);
+ assert (retry == FS_RETRY_NORMAL);
+ assert (pathbuf[0] == '\0');
diff --git a/debian/patches/uptime_w_path_fix.patch b/debian/patches/uptime_w_path_fix.patch
new file mode 100644
index 00000000..a2e595ef
--- /dev/null
+++ b/debian/patches/uptime_w_path_fix.patch
@@ -0,0 +1,16 @@
+Debian has a real /usr and uses w-hurd file name
+---
+ utils/uptime.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/utils/uptime.sh
++++ b/utils/uptime.sh
+@@ -25,7 +25,7 @@
+ USAGE="Usage: $0 [OPTION...]"
+ DOC="Show system uptime, number of users, and load"
+
+-W=${W-/bin/w}
++W=${W-/usr/bin/w-hurd}
+
+ while :; do
+ case "$1" in
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 00000000..b247fed6
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,63 @@
+#!/usr/bin/make -f
+# -*- mode: makefile; coding: utf-8 -*-
+# Copyright © 2003 Jeff Bailey <jbailey@debian.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+DEB_BUILDDIR = $(DEB_SRCDIR)/build
+
+CC=gcc-4.6
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/autotools.mk
+
+DEB_CONFIGURE_USER_FLAGS := --disable-profile --enable-static-progs='ext2fs,ufs,iso9660fs'
+DEB_MAKE_INSTALL_TARGET = install prefix=$(DEB_DESTDIR) sysconfdir=$(DEB_DESTDIR)/etc localstatedir=$(DEB_DESTDIR)/var
+DEB_DH_STRIP_ARGS := --dbg-package=hurd
+DEB_DH_MAKESHLIBS_ARGS_hurd := --add-udeb="hurd-udeb"
+
+build/hurd::
+ cd $(DEB_BUILDDIR)/doc && texi2html -split chapter ../../doc/hurd.texi
+
+install/hurd::
+ # runsystem is managed by update-alternatives
+ mv debian/tmp/lib/hurd/runsystem debian/tmp/lib/hurd/runsystem.gnu
+
+ # move away fakeroot, ps, uptime, vmstat and w to not conflict with the
+ # ones from other packages
+ mkdir -p debian/tmp/usr/bin
+ mv debian/tmp/bin/fakeroot debian/tmp/usr/bin/fakeroot-hurd
+ mv debian/tmp/bin/ps debian/tmp/bin/ps-hurd
+ mv debian/tmp/bin/uptime debian/tmp/usr/bin/uptime-hurd
+ mv debian/tmp/bin/vmstat debian/tmp/usr/bin/vmstat-hurd
+ mv debian/tmp/bin/w debian/tmp/usr/bin/w-hurd
+
+ install -m664 debian/hurd-console.default debian/hurd/etc/default/hurd-console
+
+ install -m664 $(DEB_SRCDIR)/console/motd.UTF8 debian/hurd/etc/
+ install -m664 $(DEB_SRCDIR)/release/servers.boot debian/hurd/boot/
+
+install/hurd-dev::
+ install -m644 debian/local/soundcard.h debian/tmp/include/sys
+ install -m644 debian/local/cdrom.h debian/tmp/include/sys
+
+SUID_PROGRAMS = /bin/ids /bin/login /bin/ps-hurd /usr/bin/w-hurd
+
+binary-predeb/hurd::
+ chmod u+s $(patsubst %, $(CURDIR)/debian/$(cdbs_curpkg)%, $(SUID_PROGRAMS))
+binary-predeb/hurd-dev::
+ rm -f $(CURDIR)/debian/hurd-dev/lib/*_pic.a
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 00000000..163aaf8d
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/options b/debian/source/options
new file mode 100644
index 00000000..8f04d6dd
--- /dev/null
+++ b/debian/source/options
@@ -0,0 +1 @@
+compression = "bzip2"