shithub: drawterm

Download patch

ref: 5d6ebf7a53a2992d56e7403afd5cfce59b15e879
parent: d920d42c8bad0719f8a91f5121d5f7c080e2a332
author: Russ Cox <[email protected]>
date: Mon Oct 31 10:30:23 EST 2005

Merge in Windows port using mingw and make.

--- /dev/null
+++ b/LICENSE
@@ -1,0 +1,258 @@
+The Plan 9 software is provided under the terms of the
+Lucent Public License, Version 1.02, reproduced below,
+with the following exceptions:
+
+1. No right is granted to create derivative works of or
+   to redistribute (other than with the Plan 9 Operating System)
+   the screen imprinter fonts identified in subdirectory
+   /lib/font/bit/lucida and printer fonts (Lucida Sans Unicode, Lucida
+   Sans Italic, Lucida Sans Demibold, Lucida Typewriter, Lucida Sans
+   Typewriter83), identified in subdirectory /sys/lib/postscript/font.
+   These directories contain material copyrights by B&H Inc. and Y&Y Inc.
+
+2. The printer fonts identified in subdirectory /sys/lib/ghostscript/font
+   are subject to the GNU GPL, reproduced in the file /LICENSE.gpl.
+
+3. The ghostscript program in the subdirectory /sys/src/cmd/gs is
+   covered by the Aladdin Free Public License, reproduced in the file
+   /LICENSE.afpl.
+
+===================================================================
+
+Lucent Public License Version 1.02
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+  a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
+     Program, and
+  b. in the case of each Contributor,
+
+     i. changes to the Program, and
+    ii. additions to the Program;
+
+    where such changes and/or additions to the Program were added to the
+    Program by such Contributor itself or anyone acting on such
+    Contributor's behalf, and the Contributor explicitly consents, in
+    accordance with Section 3C, to characterization of the changes and/or
+    additions as Contributions.
+
+"Contributor" means LUCENT and any other entity that has Contributed a
+Contribution to the Program.
+
+"Distributor" means a Recipient that distributes the Program,
+modifications to the Program, or any part thereof.
+
+"Licensed Patents" mean patent claims licensable by a Contributor
+which are necessarily infringed by the use or sale of its Contribution
+alone or when combined with the Program.
+
+"Original Program" means the original version of the software
+accompanying this Agreement as released by LUCENT, including source
+code, object code and documentation, if any.
+
+"Program" means the Original Program and Contributions or any part
+thereof
+
+"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free copyright
+    license to reproduce, prepare derivative works of, publicly display,
+    publicly perform, distribute and sublicense the Contribution of such
+    Contributor, if any, and such derivative works, in source code and
+    object code form.
+    
+ b. Subject to the terms of this Agreement, each Contributor hereby
+    grants Recipient a non-exclusive, worldwide, royalty-free patent
+    license under Licensed Patents to make, use, sell, offer to sell,
+    import and otherwise transfer the Contribution of such Contributor, if
+    any, in source code and object code form. The patent license granted
+    by a Contributor shall also apply to the combination of the
+    Contribution of that Contributor and the Program if, at the time the
+    Contribution is added by the Contributor, such addition of the
+    Contribution causes such combination to be covered by the Licensed
+    Patents. The patent license granted by a Contributor shall not apply
+    to (i) any other combinations which include the Contribution, nor to
+    (ii) Contributions of other Contributors. No hardware per se is
+    licensed hereunder.
+    
+ c. Recipient understands that although each Contributor grants the
+    licenses to its Contributions set forth herein, no assurances are
+    provided by any Contributor that the Program does not infringe the
+    patent or other intellectual property rights of any other entity. Each
+    Contributor disclaims any liability to Recipient for claims brought by
+    any other entity based on infringement of intellectual property rights
+    or otherwise. As a condition to exercising the rights and licenses
+    granted hereunder, each Recipient hereby assumes sole responsibility
+    to secure any other intellectual property rights needed, if any. For
+    example, if a third party patent license is required to allow
+    Recipient to distribute the Program, it is Recipient's responsibility
+    to acquire that license before distributing the Program.
+
+ d. Each Contributor represents that to its knowledge it has sufficient
+    copyright rights in its Contribution, if any, to grant the copyright
+    license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A. Distributor may choose to distribute the Program in any form under
+this Agreement or under its own license agreement, provided that:
+
+ a. it complies with the terms and conditions of this Agreement;
+
+ b. if the Program is distributed in source code or other tangible
+    form, a copy of this Agreement or Distributor's own license agreement
+    is included with each copy of the Program; and
+
+ c. if distributed under Distributor's own license agreement, such
+    license agreement:
+
+      i. effectively disclaims on behalf of all Contributors all warranties
+         and conditions, express and implied, including warranties or
+         conditions of title and non-infringement, and implied warranties or
+         conditions of merchantability and fitness for a particular purpose;
+     ii. effectively excludes on behalf of all Contributors all liability
+         for damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits; and
+    iii. states that any provisions which differ from this Agreement are
+         offered by that Contributor alone and not by any other party.
+
+B. Each Distributor must include the following in a conspicuous
+   location in the Program:
+
+   Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
+   Reserved.
+
+C. In addition, each Contributor must identify itself as the
+originator of its Contribution in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution.
+Also, each Contributor must agree that the additions and/or changes
+are intended to be a Contribution. Once a Contribution is contributed,
+it may not thereafter be revoked.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use
+of the Program, the Distributor who includes the Program in a
+commercial product offering should do so in a manner which does not
+create potential liability for Contributors. Therefore, if a
+Distributor includes the Program in a commercial product offering,
+such Distributor ("Commercial Distributor") hereby agrees to defend
+and indemnify every Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively"Losses") arising from
+claims, lawsuits and other legal actions brought by a third party
+against the Indemnified Contributor to the extent caused by the acts
+or omissions of such Commercial Distributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement.
+In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Distributor in writing of such claim, and b)
+allow the Commercial Distributor to control, and cooperate with the
+Commercial Distributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense.
+
+For example, a Distributor might include the Program in a commercial
+product offering, Product X. That Distributor is then a Commercial
+Distributor. If that Commercial Distributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Distributor's responsibility
+alone. Under this section, the Commercial Distributor would have to
+defend claims against the Contributors related to those performance
+claims and warranties, and if a court requires any Contributor to pay
+any damages as a result, the Commercial Distributor must pay those
+damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement, including but not limited to
+the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, programs or equipment, and
+unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), 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 OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. EXPORT CONTROL
+
+Recipient agrees that Recipient alone is responsible for compliance
+with the United States export administration regulations (and the
+export control laws and regulation of any other countries).
+
+8. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as
+of the date such litigation is filed. In addition, if Recipient
+institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and
+survive.
+
+LUCENT may publish new versions (including revisions) of this
+Agreement from time to time. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to
+distribute the Program (including its Contributions) under the new
+version. No one other than LUCENT has the right to modify this
+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property
+of any Contributor under this Agreement, whether expressly, by
+implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No
+party to this Agreement will bring a legal action under this Agreement
+more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.
+
--- /dev/null
+++ b/Make.config
@@ -1,0 +1,1 @@
+include $(ROOT)/Make.$(CONF)
--- /dev/null
+++ b/Make.unix
@@ -1,0 +1,12 @@
+# Unix
+AR=ar
+CC=gcc
+RANLIB=ranlib
+CFLAGS=-I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -ggdb -D_THREAD_SAFE -pthread # not ready for this yet: -Wall
+O=o
+OS=posix
+GUI=x11
+LDADD=-L/usr/X11R6/lib -lX11 -ggdb
+LDFLAGS=-pthread
+TARG=drawterm
+
--- /dev/null
+++ b/Make.win32
@@ -1,0 +1,30 @@
+# Windows via mingw32
+# MING=mingw32- is necessary if you're cross-compiling
+# on another platform.  Otherwise the binaries are just
+# named gcc, etc.
+
+MING=mingw32-
+#MING=
+AR=$(MING)ar
+CC=$(MING)gcc
+RANLIB=$(MING)ranlib
+CFLAGS=-I$(ROOT)/include -I$(ROOT) -I$(ROOT)/kern -c -D_X86_ -DIS_32 -DWINDOWS
+O=o
+FS=fs-win32
+IP=win32
+OS=win32
+GUI=win32
+LDFLAGS=
+LDADD=-lkernel32 -ladvapi32 -lgdi32 -lmpr -lwsock32
+TARG=drawterm.exe
+
+# Windows via MSVC
+#AR=???
+#CC=cl
+#CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -Iinclude -DWINDOWS
+#O=obj
+#FS=fs-win32
+#IP=win32
+#OS=win32
+#GUI=win32
+
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,13 @@
-TARG=drawterm
-CC=gcc
-CFLAGS=-Iinclude -c -ggdb -D_THREAD_SAFE -pthread # not ready for this yet: -Wall
-O=o
-#CC=cl
-#CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -Iinclude -DWINDOWS
-#O=obj
+ROOT=.
 
+include Make.config
+
 OFILES=\
 	main.$O\
 	cpu.$O\
 	readcons.$O\
 	secstore.$O\
-    latin1.$O\
+	latin1.$O\
 
 LIBS=\
 	kern/libkern.a\
@@ -24,7 +20,7 @@
 	libdraw/libdraw.a\
 	libc/libc.a\
 	kern/libkern.a\
-	gui-x11/libx11.a\
+	gui-$(GUI)/libgui.a\
 	libmemdraw/libmemdraw.a\
 	libdraw/libdraw.a\
 	kern/libkern.a\
@@ -35,13 +31,13 @@
 	libmachdep.a
 
 $(TARG): $(OFILES) $(LIBS)
-	$(CC) -pthread -o $(TARG) $(OFILES) $(LIBS) -L/usr/X11R6/lib -lX11 -ggdb
+	$(CC) $(LDFLAGS) -o $(TARG) $(OFILES) $(LIBS) $(LDADD)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
 
 clean:
-	rm -f *.o */*.o */*.a drawterm  *.a
+	rm -f *.o */*.o */*.a *.a drawterm drawterm.exe
 
 kern/libkern.a:
 	(cd kern; make)
@@ -70,8 +66,8 @@
 libc/libc.a:
 	(cd libc; make)
 
-gui-x11/libx11.a:
-	(cd gui-x11; make)
+gui-$(GUI)/libgui.a:
+	(cd gui-$(GUI); make)
 
 #libmachdep.a:
 #	arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \
--- a/Notes
+++ /dev/null
@@ -1,16 +1,0 @@
-
-Win32 port Notes:
-
-* Issues:
-
-	** ownership questions on files are completely deferred by
-	marking them as unknown.  It works for now, but probably
-	should be handled correctly.
-
-	** No performance measurements have been done.  The interactive
-	response seems faster than old drawterm, but the i/o seems
-	slower.
-
-	** fs functions in devntfs.c need to handle conversions to/from
-	widechar and utf-8.
-
--- /dev/null
+++ b/README
@@ -1,0 +1,31 @@
+INSTALLATION
+--------------
+To build on Unix, run CONF=unix make.
+
+To build on Windows, you need Mingw.  See http://www.mingw.org.
+Edit Make.config to uncomment the Windows section
+and comment out the rest.  Then run CONF=windows make.
+
+(You can download nmake from 
+http://support.microsoft.com/default.aspx?scid=kb;en-us;Q132084
+Rename it to make.exe and put it in your path somewhere.
+)
+
+I haven't tested the Windows build on Windows itself.
+I cross-compile using mingw32 on Linux.
+
+
+BINARIES
+---------
+See http://swtch.com/drawterm/
+
+
+TO DO:
+------
+
+- Drawterm seems to have ssl synchronization problems.
+Specifically, fcp bigfile /mnt/term/tmp reliably wedges it.
+
+- Should clean up the code so that gcc -Wall doesn't print
+any warnings.
+
binary files a/drawterm.ico /dev/null differ
--- a/drawterm.rc
+++ /dev/null
@@ -1,72 +1,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_ICON1               ICON    DISCARDABLE     "drawterm.ico"
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
binary files a/drawterm.res /dev/null differ
--- a/exportfs/Makefile
+++ b/exportfs/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libexportfs.a
-CC=gcc
-CFLAGS=-I../include -I. -I.. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	exportfs.$O\
@@ -8,8 +7,8 @@
 	exportsrv.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/exportfs/mkfile
+++ /dev/null
@@ -1,11 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libexportfs.$L
-
-OFILES=\
-	exportfs.$O\
-	exportsrv.$O
-
-HFILES=\
-	exportfs.h
-
-<$DSRC/mklib-$CONF
--- /dev/null
+++ b/gui-win32/Makefile
@@ -1,0 +1,19 @@
+ROOT=..
+include ../Make.config
+LIB=libgui.a
+
+OFILES=\
+	alloc.$O\
+	cload.$O\
+	draw.$O\
+	load.$O\
+	screen.$O\
+	wstrtoutf.$O
+
+$(LIB): $(OFILES)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
+
+%.$O: %.c
+	$(CC) $(CFLAGS) $*.c
+
--- a/gui-win32/mkfile
+++ /dev/null
@@ -1,14 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libgui.$L
-
-OFILES=\
-	alloc.$O\
-	cload.$O\
-	draw.$O\
-	load.$O\
-	screen.$O\
-	wstrtoutf.$O
-
-HFILES=\
-
-<$DSRC/mklib-$CONF
--- a/gui-win32/screen.c
+++ b/gui-win32/screen.c
@@ -1,5 +1,4 @@
 #include	<windows.h>
-// #include	"winduhz.h"
 
 #undef Rectangle
 #define Rectangle _Rectangle
@@ -564,9 +563,8 @@
 	return p;
 }
 
-
-uchar*
-clipread()
+char*
+clipread(void)
 {
 	HANDLE h;
 	uchar *p;
--- a/gui-x11/Makefile
+++ b/gui-x11/Makefile
@@ -1,7 +1,6 @@
-LIB=libx11.a
-CC=gcc
-CFLAGS=-I../include -I. -I/usr/X11R6/include -I../kern -c -ggdb -D_THREAD_SAFE -pthread
-O=o
+ROOT=..
+include ../Make.config
+LIB=libgui.a
 
 OFILES=\
 	alloc.$O\
@@ -12,8 +11,8 @@
 	keysym2ucs-x11.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- /dev/null
+++ b/include/9windows.h
@@ -1,0 +1,18 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <fcntl.h>
+#include <io.h>
+#include <setjmp.h>
+#include <direct.h>
+#include <process.h>
+#include <time.h>
+#include <assert.h>
+#include <stdarg.h>
+
+/* disable various silly warnings */
+#pragma warning( disable : 4245 4305 4244 4102 4761 4090 4028 4024)
+
+typedef __int64		p9_vlong;
+typedef	unsigned __int64 p9_uvlong;
--- a/include/dtos.h
+++ b/include/dtos.h
@@ -4,7 +4,7 @@
 #		define panic dt_panic
 #	endif
 #elif defined(WINDOWS)
-#	include "winduhz.h"
+#	include "9windows.h"
 #else
 #	error "Define an OS"
 #endif
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -1,10 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libkern.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
-#CC=cl
-#CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -I../include -DWINDOWS
-#O=obj
 
 OFILES=\
 	allocb.$O\
@@ -14,9 +10,9 @@
 	dev.$O\
 	devcons.$O\
 	devdraw.$O\
-	devfs.$O\
+	devfs-$(OS).$O\
 	devip.$O\
-	devip-posix.$O\
+	devip-$(OS).$O\
 	devmnt.$O\
 	devmouse.$O\
 	devpipe.$O\
@@ -26,7 +22,6 @@
 	error.$O\
 	parse.$O\
 	pgrp.$O\
-	posix.$O\
 	procinit.$O\
 	rwlock.$O\
 	sleep.$O\
@@ -39,11 +34,12 @@
 	term.$O\
 	todo.$O\
 	uart.$O\
-	waserror.$O
+	waserror.$O\
+	$(OS).$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/kern/devcons.c
+++ b/kern/devcons.c
@@ -445,12 +445,12 @@
 	 if(c == Kalt){
 		 collecting = 1;
 		 nk = 0;
-		 return;
+		 return 0;
 	 }
 
 	 if(!collecting){
 		 _kbdputc(c);
-		 return;
+		 return 0;
 	 }
 
 	kc[nk++] = c;
@@ -1034,8 +1034,7 @@
 	return randn;
 }
 
-/* static uvlong uvorder = 0x0001020304050607ULL; */
-static uvlong uvorder = (uvlong)0x0001020304050607;
+static uvlong uvorder = (uvlong) 0x0001020304050607ULL;
 
 static uchar*
 le2vlong(vlong *to, uchar *f)
--- /dev/null
+++ b/kern/devfs-posix.c
@@ -1,0 +1,638 @@
+#include	<sys/types.h>
+#include	<sys/stat.h>
+#include	<dirent.h>
+#include	<fcntl.h>
+#include	<errno.h>
+#include	<stdio.h> /* for remove, rename */
+#include	<limits.h>
+
+#ifndef NAME_MAX
+#	define NAME_MAX 256
+#endif
+#include	"u.h"
+#include	"lib.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"error.h"
+
+
+typedef	struct Ufsinfo	Ufsinfo;
+
+enum
+{
+	NUID	= 256,
+	NGID	= 256,
+	MAXPATH	= 1024,
+	MAXCOMP	= 128
+};
+
+struct Ufsinfo
+{
+	int	mode;
+	int	fd;
+	int	uid;
+	int	gid;
+	DIR*	dir;
+	ulong	offset;
+	QLock	oq;
+	char nextname[NAME_MAX];
+};
+
+char	*base = "/";
+
+static	Qid	fsqid(char*, struct stat *);
+static	void	fspath(Chan*, char*, char*);
+static	ulong	fsdirread(Chan*, uchar*, int, ulong);
+static	int	fsomode(int);
+
+/* clumsy hack, but not worse than the Path stuff in the last one */
+static char*
+uc2name(Chan *c)
+{
+	char *s;
+
+	if(c->name == nil)
+		return "/";
+	s = c2name(c);
+	if(s[0]=='#' && s[1]=='U')
+		return s+2;
+	return s;
+}
+
+static char*
+lastelem(Chan *c)
+{
+	char *s, *t;
+
+	s = uc2name(c);
+	if((t = strrchr(s, '/')) == nil)
+		return s;
+	if(t[1] == 0)
+		return t;
+	return t+1;
+}
+	
+static Chan*
+fsattach(char *spec)
+{
+	Chan *c;
+	struct stat stbuf;
+	static int devno;
+	Ufsinfo *uif;
+
+	if(stat(base, &stbuf) < 0)
+		error(strerror(errno));
+
+	c = devattach('U', spec);
+
+	uif = mallocz(sizeof(Ufsinfo), 1);
+	uif->mode = stbuf.st_mode;
+	uif->uid = stbuf.st_uid;
+	uif->gid = stbuf.st_gid;
+
+	c->aux = uif;
+	c->dev = devno++;
+	c->qid.type = QTDIR;
+/*print("fsattach %s\n", c2name(c));*/
+
+	return c;
+}
+
+static Chan*
+fsclone(Chan *c, Chan *nc)
+{
+	Ufsinfo *uif;
+
+	uif = mallocz(sizeof(Ufsinfo), 1);
+	*uif = *(Ufsinfo*)c->aux;
+	nc->aux = uif;
+
+	return nc;
+}
+
+static int
+fswalk1(Chan *c, char *name)
+{
+	struct stat stbuf;
+	char path[MAXPATH];
+	Ufsinfo *uif;
+
+	fspath(c, name, path);
+
+	/*print("** fs walk '%s' -> %s\n", path, name);  */
+
+	if(stat(path, &stbuf) < 0)
+		return 0;
+
+	uif = c->aux;
+
+	uif->mode = stbuf.st_mode;
+	uif->uid = stbuf.st_uid;
+	uif->gid = stbuf.st_gid;
+
+	c->qid = fsqid(path, &stbuf);
+
+	return 1;
+}
+
+extern Cname* addelem(Cname*, char*);
+
+static Walkqid*
+fswalk(Chan *c, Chan *nc, char **name, int nname)
+{
+	int i;
+	Cname *cname;
+	Walkqid *wq;
+
+	if(nc != nil)
+		panic("fswalk: nc != nil");
+	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
+	nc = devclone(c);
+	cname = c->name;
+	incref(&cname->ref);
+
+	fsclone(c, nc);
+	wq->clone = nc;
+	for(i=0; i<nname; i++){
+		nc->name = cname;
+		if(fswalk1(nc, name[i]) == 0)
+			break;
+		cname = addelem(cname, name[i]);
+		wq->qid[i] = nc->qid;
+	}
+	nc->name = nil;
+	cnameclose(cname);
+	if(i != nname){
+		cclose(nc);
+		wq->clone = nil;
+	}
+	wq->nqid = i;
+	return wq;
+}
+	
+static int
+fsstat(Chan *c, uchar *buf, int n)
+{
+	Dir d;
+	struct stat stbuf;
+	char path[MAXPATH];
+
+	if(n < BIT16SZ)
+		error(Eshortstat);
+
+	fspath(c, 0, path);
+	if(stat(path, &stbuf) < 0)
+		error(strerror(errno));
+
+	d.name = lastelem(c);
+	d.uid = "unknown";
+	d.gid = "unknown";
+	d.muid = "unknown";
+	d.qid = c->qid;
+	d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
+	d.atime = stbuf.st_atime;
+	d.mtime = stbuf.st_mtime;
+	d.length = stbuf.st_size;
+	d.type = 'U';
+	d.dev = c->dev;
+	return convD2M(&d, buf, n);
+}
+
+static Chan*
+fsopen(Chan *c, int mode)
+{
+	char path[MAXPATH];
+	int m, isdir;
+	Ufsinfo *uif;
+
+/*print("fsopen %s\n", c2name(c));*/
+	m = mode & (OTRUNC|3);
+	switch(m) {
+	case 0:
+		break;
+	case 1:
+	case 1|16:
+		break;
+	case 2:	
+	case 0|16:
+	case 2|16:
+		break;
+	case 3:
+		break;
+	default:
+		error(Ebadarg);
+	}
+
+	isdir = c->qid.type & QTDIR;
+
+	if(isdir && mode != OREAD)
+		error(Eperm);
+
+	m = fsomode(m & 3);
+	c->mode = openmode(mode);
+
+	uif = c->aux;
+
+	fspath(c, 0, path);
+	if(isdir) {
+		uif->dir = opendir(path);
+		if(uif->dir == 0)
+			error(strerror(errno));
+	}	
+	else {
+		if(mode & OTRUNC)
+			m |= O_TRUNC;
+		uif->fd = open(path, m, 0666);
+
+		if(uif->fd < 0)
+			error(strerror(errno));
+	}
+	uif->offset = 0;
+
+	c->offset = 0;
+	c->flag |= COPEN;
+	return c;
+}
+
+static void
+fscreate(Chan *c, char *name, int mode, ulong perm)
+{
+	int fd, m;
+	char path[MAXPATH];
+	struct stat stbuf;
+	Ufsinfo *uif;
+
+	m = fsomode(mode&3);
+
+	fspath(c, name, path);
+
+	uif = c->aux;
+
+	if(perm & DMDIR) {
+		if(m)
+			error(Eperm);
+
+		if(mkdir(path, perm & 0777) < 0)
+			error(strerror(errno));
+
+		fd = open(path, 0);
+		if(fd >= 0) {
+			chmod(path, perm & 0777);
+			chown(path, uif->uid, uif->uid);
+		}
+		close(fd);
+
+		uif->dir = opendir(path);
+		if(uif->dir == 0)
+			error(strerror(errno));
+	}
+	else {
+		fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+		if(fd >= 0) {
+			if(m != 1) {
+				close(fd);
+				fd = open(path, m);
+			}
+			chmod(path, perm & 0777);
+			chown(path, uif->uid, uif->gid);
+		}
+		if(fd < 0)
+			error(strerror(errno));
+		uif->fd = fd;
+	}
+
+	if(stat(path, &stbuf) < 0)
+		error(strerror(errno));
+	c->qid = fsqid(path, &stbuf);
+	c->offset = 0;
+	c->flag |= COPEN;
+	c->mode = openmode(mode);
+}
+
+static void
+fsclose(Chan *c)
+{
+	Ufsinfo *uif;
+
+	uif = c->aux;
+
+	if(c->flag & COPEN) {
+		if(c->qid.type & QTDIR)
+			closedir(uif->dir);
+		else
+			close(uif->fd);
+	}
+
+	free(uif);
+}
+
+static long
+fsread(Chan *c, void *va, long n, vlong offset)
+{
+	int fd, r;
+	Ufsinfo *uif;
+
+/*print("fsread %s\n", c2name(c));*/
+	if(c->qid.type & QTDIR)
+		return fsdirread(c, va, n, offset);
+
+	uif = c->aux;
+	qlock(&uif->oq);
+	if(waserror()) {
+		qunlock(&uif->oq);
+		nexterror();
+	}
+	fd = uif->fd;
+	if(uif->offset != offset) {
+		r = lseek(fd, offset, 0);
+		if(r < 0)
+			error(strerror(errno));
+		uif->offset = offset;
+	}
+
+	n = read(fd, va, n);
+	if(n < 0)
+		error(strerror(errno));
+
+	uif->offset += n;
+	qunlock(&uif->oq);
+	poperror();
+
+	return n;
+}
+
+static long
+fswrite(Chan *c, void *va, long n, vlong offset)
+{
+	int fd, r;
+	Ufsinfo *uif;
+
+	uif = c->aux;
+
+	qlock(&uif->oq);
+	if(waserror()) {
+		qunlock(&uif->oq);
+		nexterror();
+	}
+	fd = uif->fd;
+	if(uif->offset != offset) {
+		r = lseek(fd, offset, 0);
+		if(r < 0)
+			error(strerror(errno));
+		uif->offset = offset;
+	}
+
+	n = write(fd, va, n);
+	if(n < 0)
+		error(strerror(errno));
+
+	uif->offset += n;
+	qunlock(&uif->oq);
+	poperror();
+
+	return n;
+}
+
+static void
+fsremove(Chan *c)
+{
+	int n;
+	char path[MAXPATH];
+
+	fspath(c, 0, path);
+	if(c->qid.type & QTDIR)
+		n = rmdir(path);
+	else
+		n = remove(path);
+	if(n < 0)
+		error(strerror(errno));
+}
+
+int
+fswstat(Chan *c, uchar *buf, int n)
+{
+	Dir d;
+	struct stat stbuf;
+	char old[MAXPATH], new[MAXPATH], dir[MAXPATH];
+	char strs[MAXPATH*3], *p;
+	Ufsinfo *uif;
+
+	if(convM2D(buf, n, &d, strs) != n)
+		error(Ebadstat);
+	
+	fspath(c, 0, old);
+	if(stat(old, &stbuf) < 0)
+		error(strerror(errno));
+
+	uif = c->aux;
+
+	if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
+		fspath(c, 0, old);
+		strcpy(new, old);
+		p = strrchr(new, '/');
+		strcpy(p+1, d.name);
+		if(rename(old, new) < 0)
+			error(strerror(errno));
+	}
+
+	fspath(c, 0, old);
+	if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
+		if(chmod(old, d.mode&0777) < 0)
+			error(strerror(errno));
+		uif->mode &= ~0777;
+		uif->mode |= d.mode&0777;
+	}
+/*
+	p = name2pass(gid, d.gid);
+	if(p == 0)
+		error(Eunknown);
+
+	if(p->id != stbuf.st_gid) {
+		if(chown(old, stbuf.st_uid, p->id) < 0)
+			error(strerror(errno));
+
+		uif->gid = p->id;
+	}
+*/
+	return n;
+}
+
+static Qid
+fsqid(char *p, struct stat *st)
+{
+	Qid q;
+	int dev;
+	ulong h;
+	static int nqdev;
+	static uchar *qdev;
+
+	if(qdev == 0)
+		qdev = mallocz(65536U, 1);
+
+	q.type = 0;
+	if((st->st_mode&S_IFMT) ==  S_IFDIR)
+		q.type = QTDIR;
+
+	dev = st->st_dev & 0xFFFFUL;
+	if(qdev[dev] == 0)
+		qdev[dev] = ++nqdev;
+
+	h = 0;
+	while(*p != '\0')
+		h += *p++ * 13;
+	
+	q.path = (vlong)qdev[dev]<<32;
+	q.path |= h;
+	q.vers = st->st_mtime;
+
+	return q;
+}
+
+static void
+fspath(Chan *c, char *ext, char *path)
+{
+	int i, n;
+	char *comp[MAXCOMP];
+
+	strcpy(path, base);
+	strcat(path, "/");
+	strcat(path, uc2name(c));
+	if(ext){
+		strcat(path, "/");
+		strcat(path, ext);
+	}
+	cleanname(path);
+}
+
+static int
+isdots(char *name)
+{
+	if(name[0] != '.')
+		return 0;
+	if(name[1] == '\0')
+		return 1;
+	if(name[1] != '.')
+		return 0;
+	if(name[2] == '\0')
+		return 1;
+	return 0;
+}
+
+static int
+p9readdir(char *name, Ufsinfo *uif)
+{
+	struct dirent *de;
+	
+	if(uif->nextname[0]){
+		strcpy(name, uif->nextname);
+		uif->nextname[0] = 0;
+		return 1;
+	}
+
+	de = readdir(uif->dir);
+	if(de == NULL)
+		return 0;
+		
+	strcpy(name, de->d_name);
+	return 1;
+}
+
+static ulong
+fsdirread(Chan *c, uchar *va, int count, ulong offset)
+{
+	int i;
+	Dir d;
+	long n;
+	char de[NAME_MAX];
+	struct stat stbuf;
+	char path[MAXPATH], dirpath[MAXPATH];
+	Ufsinfo *uif;
+
+/*print("fsdirread %s\n", c2name(c));*/
+	i = 0;
+	uif = c->aux;
+
+	errno = 0;
+	if(uif->offset != offset) {
+		if(offset != 0)
+			error("bad offset in fsdirread");
+		uif->offset = offset;  /* sync offset */
+		uif->nextname[0] = 0;
+		rewinddir(uif->dir);
+	}
+
+	fspath(c, 0, dirpath);
+
+	while(i+BIT16SZ < count) {
+		if(!p9readdir(de, uif))
+			break;
+
+		if(de[0]==0 || isdots(de))
+			continue;
+
+		d.name = de;
+		sprint(path, "%s/%s", dirpath, de);
+		memset(&stbuf, 0, sizeof stbuf);
+
+		if(stat(path, &stbuf) < 0) {
+			/* fprint(2, "dir: bad path %s\n", path); */
+			/* but continue... probably a bad symlink */
+		}
+
+		d.uid = "unknown";
+		d.gid = "unknown";
+		d.qid = fsqid(path, &stbuf);
+		d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
+		d.atime = stbuf.st_atime;
+		d.mtime = stbuf.st_mtime;
+		d.length = stbuf.st_size;
+		d.type = 'U';
+		d.dev = c->dev;
+		n = convD2M(&d, (char*)va+i, count-i);
+		if(n == BIT16SZ){
+			strcpy(uif->nextname, de);
+			break;
+		}
+		i += n;
+	}
+/*print("got %d\n", i);*/
+	uif->offset += i;
+	return i;
+}
+
+static int
+fsomode(int m)
+{
+	switch(m) {
+	case 0:			/* OREAD */
+	case 3:			/* OEXEC */
+		return 0;
+	case 1:			/* OWRITE */
+		return 1;
+	case 2:			/* ORDWR */
+		return 2;
+	}
+	error(Ebadarg);
+	return 0;
+}
+
+Dev fsdevtab = {
+	'U',
+	"fs",
+
+	devreset,
+	devinit,
+	devshutdown,
+	fsattach,
+	fswalk,
+	fsstat,
+	fsopen,
+	fscreate,
+	fsclose,
+	fsread,
+	devbread,
+	fswrite,
+	devbwrite,
+	fsremove,
+	fswstat,
+};
--- /dev/null
+++ b/kern/devfs-win32.c
@@ -1,0 +1,704 @@
+#include	<windows.h>
+#include	<sys/types.h>
+#include	<sys/stat.h>
+#include	<fcntl.h>
+
+#ifndef NAME_MAX
+#	define NAME_MAX 256
+#endif
+#include	"u.h"
+#include	"lib.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"error.h"
+
+typedef struct DIR	DIR;
+typedef	struct Ufsinfo	Ufsinfo;
+
+enum
+{
+	NUID	= 256,
+	NGID	= 256,
+	MAXPATH	= 1024,
+	MAXCOMP	= 128
+};
+
+struct DIR
+{
+	HANDLE	handle;
+	char*	path;
+	int	index;
+	WIN32_FIND_DATA	wfd;
+};
+
+struct Ufsinfo
+{
+	int	mode;
+	int	fd;
+	int	uid;
+	int	gid;
+	DIR*	dir;
+	ulong	offset;
+	QLock	oq;
+	char nextname[NAME_MAX];
+};
+
+DIR*	opendir(char*);
+int	readdir(char*, DIR*);
+void	closedir(DIR*);
+void	rewinddir(DIR*);
+
+char	*base = "c:/.";
+
+static	Qid	fsqid(char*, struct stat *);
+static	void	fspath(Chan*, char*, char*);
+// static	void	fsperm(Chan*, int);
+static	ulong	fsdirread(Chan*, uchar*, int, ulong);
+static	int	fsomode(int);
+static  int	chown(char *path, int uid, int);
+static	int	link(char *path, char *next);
+
+/* clumsy hack, but not worse than the Path stuff in the last one */
+static char*
+uc2name(Chan *c)
+{
+	char *s;
+
+	if(c->name == nil)
+		return "/";
+	s = c2name(c);
+	if(s[0]=='#' && s[1]=='U')
+		return s+2;
+	return s;
+}
+
+static char*
+lastelem(Chan *c)
+{
+	char *s, *t;
+
+	s = uc2name(c);
+	if((t = strrchr(s, '/')) == nil)
+		return s;
+	if(t[1] == 0)
+		return t;
+	return t+1;
+}
+	
+static Chan*
+fsattach(char *spec)
+{
+	Chan *c;
+	struct stat stbuf;
+	static int devno;
+	Ufsinfo *uif;
+
+	if(stat(base, &stbuf) < 0)
+		error(strerror(errno));
+
+	c = devattach('U', spec);
+
+	uif = mallocz(sizeof(Ufsinfo), 1);
+	uif->gid = stbuf.st_gid;
+	uif->uid = stbuf.st_uid;
+	uif->mode = stbuf.st_mode;
+
+	c->aux = uif;
+	c->dev = devno++;
+	c->qid.type = QTDIR;
+/*print("fsattach %s\n", c2name(c));*/
+
+	return c;
+}
+
+static Chan*
+fsclone(Chan *c, Chan *nc)
+{
+	Ufsinfo *uif;
+
+	uif = mallocz(sizeof(Ufsinfo), 1);
+	*uif = *(Ufsinfo*)c->aux;
+	nc->aux = uif;
+
+	return nc;
+}
+
+static int
+fswalk1(Chan *c, char *name)
+{
+	struct stat stbuf;
+	char path[MAXPATH];
+	Ufsinfo *uif;
+
+	fspath(c, name, path);
+
+	/*	print("** fs walk '%s' -> %s\n", path, name); /**/
+
+	if(stat(path, &stbuf) < 0)
+		return 0;
+
+	uif = c->aux;
+
+	uif->gid = stbuf.st_gid;
+	uif->uid = stbuf.st_uid;
+	uif->mode = stbuf.st_mode;
+
+	c->qid = fsqid(path, &stbuf);
+
+	return 1;
+}
+
+extern Cname* addelem(Cname*, char*);
+
+static Walkqid*
+fswalk(Chan *c, Chan *nc, char **name, int nname)
+{
+	int i;
+	Cname *cname;
+	Walkqid *wq;
+
+	if(nc != nil)
+		panic("fswalk: nc != nil");
+	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
+	nc = devclone(c);
+	cname = c->name;
+	incref(&cname->ref);
+
+	fsclone(c, nc);
+	wq->clone = nc;
+	for(i=0; i<nname; i++){
+		nc->name = cname;
+		if(fswalk1(nc, name[i]) == 0)
+			break;
+		cname = addelem(cname, name[i]);
+		wq->qid[i] = nc->qid;
+	}
+	nc->name = nil;
+	cnameclose(cname);
+	if(i != nname){
+		cclose(nc);
+		wq->clone = nil;
+	}
+	wq->nqid = i;
+	return wq;
+}
+	
+static int
+fsstat(Chan *c, uchar *buf, int n)
+{
+	Dir d;
+	struct stat stbuf;
+	char path[MAXPATH];
+
+	if(n < BIT16SZ)
+		error(Eshortstat);
+
+	fspath(c, 0, path);
+	if(stat(path, &stbuf) < 0)
+		error(strerror(errno));
+
+	d.name = lastelem(c);
+	d.uid = "unknown";
+	d.gid = "unknown";
+	d.muid = "unknown";
+	d.qid = c->qid;
+	d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
+	d.atime = stbuf.st_atime;
+	d.mtime = stbuf.st_mtime;
+	d.length = stbuf.st_size;
+	d.type = 'U';
+	d.dev = c->dev;
+	return convD2M(&d, buf, n);
+}
+
+static Chan*
+fsopen(Chan *c, int mode)
+{
+	char path[MAXPATH];
+	int m, isdir;
+	Ufsinfo *uif;
+
+/*print("fsopen %s\n", c2name(c));*/
+	m = mode & (OTRUNC|3);
+	switch(m) {
+	case 0:
+		break;
+	case 1:
+	case 1|16:
+		break;
+	case 2:	
+	case 0|16:
+	case 2|16:
+		break;
+	case 3:
+		break;
+	default:
+		error(Ebadarg);
+	}
+
+	isdir = c->qid.type & QTDIR;
+
+	if(isdir && mode != OREAD)
+		error(Eperm);
+
+	m = fsomode(m & 3);
+	c->mode = openmode(mode);
+
+	uif = c->aux;
+
+	fspath(c, 0, path);
+	if(isdir) {
+		uif->dir = opendir(path);
+		if(uif->dir == 0)
+			error(strerror(errno));
+	}	
+	else {
+		if(mode & OTRUNC)
+			m |= O_TRUNC;
+		uif->fd = open(path, m|_O_BINARY, 0666);
+
+		if(uif->fd < 0)
+			error(strerror(errno));
+	}
+	uif->offset = 0;
+
+	c->offset = 0;
+	c->flag |= COPEN;
+	return c;
+}
+
+static void
+fscreate(Chan *c, char *name, int mode, ulong perm)
+{
+	int fd, m;
+	char path[MAXPATH];
+	struct stat stbuf;
+	Ufsinfo *uif;
+
+	m = fsomode(mode&3);
+
+	fspath(c, name, path);
+
+	uif = c->aux;
+
+	if(perm & DMDIR) {
+		if(m)
+			error(Eperm);
+
+		if(mkdir(path) < 0)
+			error(strerror(errno));
+
+		fd = open(path, 0);
+		if(fd >= 0) {
+			chmod(path, perm & 0777);
+			chown(path, uif->uid, uif->uid);
+		}
+		close(fd);
+
+		uif->dir = opendir(path);
+		if(uif->dir == 0)
+			error(strerror(errno));
+	}
+	else {
+		fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
+		if(fd >= 0) {
+			if(m != 1) {
+				close(fd);
+				fd = open(path, m|_O_BINARY);
+			}
+			chmod(path, perm & 0777);
+			chown(path, uif->uid, uif->gid);
+		}
+		if(fd < 0)
+			error(strerror(errno));
+		uif->fd = fd;
+	}
+
+	if(stat(path, &stbuf) < 0)
+		error(strerror(errno));
+	c->qid = fsqid(path, &stbuf);
+	c->offset = 0;
+	c->flag |= COPEN;
+	c->mode = openmode(mode);
+}
+
+static void
+fsclose(Chan *c)
+{
+	Ufsinfo *uif;
+
+	uif = c->aux;
+
+	if(c->flag & COPEN) {
+		if(c->qid.type & QTDIR)
+			closedir(uif->dir);
+		else
+			close(uif->fd);
+	}
+
+	free(uif);
+}
+
+static long
+fsread(Chan *c, void *va, long n, vlong offset)
+{
+	int fd, r;
+	Ufsinfo *uif;
+
+/*print("fsread %s\n", c2name(c));*/
+	if(c->qid.type & QTDIR)
+		return fsdirread(c, va, n, offset);
+
+	uif = c->aux;
+	qlock(&uif->oq);
+	if(waserror()) {
+		qunlock(&uif->oq);
+		nexterror();
+	}
+	fd = uif->fd;
+	if(uif->offset != offset) {
+		r = lseek(fd, offset, 0);
+		if(r < 0)
+			error(strerror(errno));
+		uif->offset = offset;
+	}
+
+	n = read(fd, va, n);
+	if(n < 0)
+		error(strerror(errno));
+
+	uif->offset += n;
+	qunlock(&uif->oq);
+	poperror();
+
+	return n;
+}
+
+static long
+fswrite(Chan *c, void *va, long n, vlong offset)
+{
+	int fd, r;
+	Ufsinfo *uif;
+
+	uif = c->aux;
+
+	qlock(&uif->oq);
+	if(waserror()) {
+		qunlock(&uif->oq);
+		nexterror();
+	}
+	fd = uif->fd;
+	if(uif->offset != offset) {
+		r = lseek(fd, offset, 0);
+		if(r < 0)
+			error(strerror(errno));
+		uif->offset = offset;
+	}
+
+	n = write(fd, va, n);
+	if(n < 0)
+		error(strerror(errno));
+
+	uif->offset += n;
+	qunlock(&uif->oq);
+	poperror();
+
+	return n;
+}
+
+static void
+fsremove(Chan *c)
+{
+	int n;
+	char path[MAXPATH];
+
+	fspath(c, 0, path);
+	if(c->qid.type & QTDIR)
+		n = rmdir(path);
+	else
+		n = remove(path);
+	if(n < 0)
+		error(strerror(errno));
+}
+
+static int
+fswstat(Chan *c, uchar *buf, int n)
+{
+	Dir d;
+	struct stat stbuf;
+	char old[MAXPATH], new[MAXPATH];
+	char strs[MAXPATH*3], *p;
+	Ufsinfo *uif;
+
+	if (convM2D(buf, n, &d, strs) != n)
+		error(Ebadstat);
+	
+	fspath(c, 0, old);
+	if(stat(old, &stbuf) < 0)
+		error(strerror(errno));
+
+	uif = c->aux;
+
+//	if(uif->uid != stbuf.st_uid)
+//		error(Eowner);
+
+	if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
+		fspath(c, 0, old);
+		strcpy(new, old);
+		p = strrchr(new, '/');
+		strcpy(p+1, d.name);
+		if(rename(old, new) < 0)
+			error(strerror(errno));
+	}
+
+	fspath(c, 0, old);
+	if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
+		if(chmod(old, d.mode&0777) < 0)
+			error(strerror(errno));
+		uif->mode &= ~0777;
+		uif->mode |= d.mode&0777;
+	}
+/*
+	p = name2pass(gid, d.gid);
+	if(p == 0)
+		error(Eunknown);
+
+	if(p->id != stbuf.st_gid) {
+		if(chown(old, stbuf.st_uid, p->id) < 0)
+			error(sys_errlist[errno]);
+
+		uif->gid = p->id;
+	}
+*/
+	return n;
+}
+
+static Qid
+fsqid(char *p, struct stat *st)
+{
+	Qid q;
+	int dev;
+	ulong h;
+	static int nqdev;
+	static uchar *qdev;
+
+	if(qdev == 0)
+		qdev = mallocz(65536U, 1);
+
+	q.type = 0;
+	if((st->st_mode&S_IFMT) ==  S_IFDIR)
+		q.type = QTDIR;
+
+	dev = st->st_dev & 0xFFFFUL;
+	if(qdev[dev] == 0)
+		qdev[dev] = ++nqdev;
+
+	h = 0;
+	while(*p != '\0')
+		h += *p++ * 13;
+	
+	q.path = (vlong)qdev[dev]<<32;
+	q.path |= h;
+	q.vers = st->st_mtime;
+
+	return q;
+}
+
+static void
+fspath(Chan *c, char *ext, char *path)
+{
+	strcpy(path, base);
+	strcat(path, "/");
+	strcat(path, uc2name(c));
+	if(ext) {
+		strcat(path, "/");
+		strcat(path, ext);
+	}
+	cleanname(path);
+}
+
+static int
+isdots(char *name)
+{
+	if(name[0] != '.')
+		return 0;
+	if(name[1] == '\0')
+		return 1;
+	if(name[1] != '.')
+		return 0;
+	if(name[2] == '\0')
+		return 1;
+	return 0;
+}
+
+static int
+p9readdir(char *name, Ufsinfo *uif)
+{
+	if(uif->nextname[0]){
+		strcpy(name, uif->nextname);
+		uif->nextname[0] = 0;
+		return 1;
+	}
+
+	return readdir(name, uif->dir);
+}
+
+static ulong
+fsdirread(Chan *c, uchar *va, int count, ulong offset)
+{
+	int i;
+	Dir d;
+	long n;
+	char de[NAME_MAX];
+	struct stat stbuf;
+	char path[MAXPATH], dirpath[MAXPATH];
+	Ufsinfo *uif;
+
+/*print("fsdirread %s\n", c2name(c));*/
+	i = 0;
+	uif = c->aux;
+
+	errno = 0;
+	if(uif->offset != offset) {
+		if(offset != 0)
+			error("bad offset in fsdirread");
+		uif->offset = offset;  /* sync offset */
+		uif->nextname[0] = 0;
+		rewinddir(uif->dir);
+	}
+
+	fspath(c, 0, dirpath);
+
+	while(i+BIT16SZ < count) {
+		if(!p9readdir(de, uif))
+			break;
+
+		if(de[0]==0 || isdots(de))
+			continue;
+
+		d.name = de;
+		sprint(path, "%s/%s", dirpath, de);
+		memset(&stbuf, 0, sizeof stbuf);
+
+		if(stat(path, &stbuf) < 0) {
+			print("dir: bad path %s\n", path);
+			/* but continue... probably a bad symlink */
+		}
+
+		d.uid = "unknown";
+		d.gid = "unknown";
+		d.muid = "unknown";
+		d.qid = fsqid(path, &stbuf);
+		d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
+		d.atime = stbuf.st_atime;
+		d.mtime = stbuf.st_mtime;
+		d.length = stbuf.st_size;
+		d.type = 'U';
+		d.dev = c->dev;
+		n = convD2M(&d, (char*)va+i, count-i);
+		if(n == BIT16SZ){
+			strcpy(uif->nextname, de);
+			break;
+		}
+		i += n;
+	}
+/*print("got %d\n", i);*/
+	uif->offset += i;
+	return i;
+}
+
+static int
+fsomode(int m)
+{
+	switch(m) {
+	case 0:			/* OREAD */
+	case 3:			/* OEXEC */
+		return 0;
+	case 1:			/* OWRITE */
+		return 1;
+	case 2:			/* ORDWR */
+		return 2;
+	}
+	error(Ebadarg);
+	return 0;
+}
+void
+closedir(DIR *d)
+{
+	FindClose(d->handle);
+	free(d->path);
+}
+
+int
+readdir(char *name, DIR *d)
+{
+	if(d->index != 0) {
+		if(FindNextFile(d->handle, &d->wfd) == FALSE)
+			return 0;
+	}
+	strcpy(name, d->wfd.cFileName);
+	d->index++;
+
+	return 1;
+}
+
+void
+rewinddir(DIR *d)
+{
+	FindClose(d->handle);
+	d->handle = FindFirstFile(d->path, &d->wfd);
+	d->index = 0;
+}
+
+static int
+chown(char *path, int uid, int perm)
+{
+/*	panic("chown"); */
+	return 0;
+}
+
+DIR*
+opendir(char *p)
+{
+	DIR *d;
+	char path[MAX_PATH];
+
+	
+	snprint(path, sizeof(path), "%s/*.*", p);
+
+	d = mallocz(sizeof(DIR), 1);
+	if(d == 0)
+		return 0;
+
+	d->index = 0;
+
+	d->handle = FindFirstFile(path, &d->wfd);
+	if(d->handle == INVALID_HANDLE_VALUE) {
+		free(d);
+		return 0;
+	}
+
+	d->path = strdup(path);
+	return d;
+}
+
+Dev fsdevtab = {
+	'U',
+	"fs",
+
+	devreset,
+	devinit,
+	devshutdown,
+	fsattach,
+	fswalk,
+	fsstat,
+	fsopen,
+	fscreate,
+	fsclose,
+	fsread,
+	devbread,
+	fswrite,
+	devbwrite,
+	fsremove,
+	fswstat,
+};
--- a/kern/devfs.c
+++ /dev/null
@@ -1,638 +1,0 @@
-#include	<sys/types.h>
-#include	<sys/stat.h>
-#include	<dirent.h>
-#include	<fcntl.h>
-#include	<errno.h>
-#include	<stdio.h> /* for remove, rename */
-#include	<limits.h>
-
-#ifndef NAME_MAX
-#	define NAME_MAX 256
-#endif
-#include	"u.h"
-#include	"lib.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"error.h"
-
-
-typedef	struct Ufsinfo	Ufsinfo;
-
-enum
-{
-	NUID	= 256,
-	NGID	= 256,
-	MAXPATH	= 1024,
-	MAXCOMP	= 128
-};
-
-struct Ufsinfo
-{
-	int	mode;
-	int	fd;
-	int	uid;
-	int	gid;
-	DIR*	dir;
-	ulong	offset;
-	QLock	oq;
-	char nextname[NAME_MAX];
-};
-
-char	*base = "/";
-
-static	Qid	fsqid(char*, struct stat *);
-static	void	fspath(Chan*, char*, char*);
-static	ulong	fsdirread(Chan*, uchar*, int, ulong);
-static	int	fsomode(int);
-
-/* clumsy hack, but not worse than the Path stuff in the last one */
-static char*
-uc2name(Chan *c)
-{
-	char *s;
-
-	if(c->name == nil)
-		return "/";
-	s = c2name(c);
-	if(s[0]=='#' && s[1]=='U')
-		return s+2;
-	return s;
-}
-
-static char*
-lastelem(Chan *c)
-{
-	char *s, *t;
-
-	s = uc2name(c);
-	if((t = strrchr(s, '/')) == nil)
-		return s;
-	if(t[1] == 0)
-		return t;
-	return t+1;
-}
-	
-static Chan*
-fsattach(char *spec)
-{
-	Chan *c;
-	struct stat stbuf;
-	static int devno;
-	Ufsinfo *uif;
-
-	if(stat(base, &stbuf) < 0)
-		error(strerror(errno));
-
-	c = devattach('U', spec);
-
-	uif = mallocz(sizeof(Ufsinfo), 1);
-	uif->mode = stbuf.st_mode;
-	uif->uid = stbuf.st_uid;
-	uif->gid = stbuf.st_gid;
-
-	c->aux = uif;
-	c->dev = devno++;
-	c->qid.type = QTDIR;
-/*print("fsattach %s\n", c2name(c));*/
-
-	return c;
-}
-
-static Chan*
-fsclone(Chan *c, Chan *nc)
-{
-	Ufsinfo *uif;
-
-	uif = mallocz(sizeof(Ufsinfo), 1);
-	*uif = *(Ufsinfo*)c->aux;
-	nc->aux = uif;
-
-	return nc;
-}
-
-static int
-fswalk1(Chan *c, char *name)
-{
-	struct stat stbuf;
-	char path[MAXPATH];
-	Ufsinfo *uif;
-
-	fspath(c, name, path);
-
-	/*print("** fs walk '%s' -> %s\n", path, name);  */
-
-	if(stat(path, &stbuf) < 0)
-		return 0;
-
-	uif = c->aux;
-
-	uif->mode = stbuf.st_mode;
-	uif->uid = stbuf.st_uid;
-	uif->gid = stbuf.st_gid;
-
-	c->qid = fsqid(path, &stbuf);
-
-	return 1;
-}
-
-extern Cname* addelem(Cname*, char*);
-
-static Walkqid*
-fswalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	int i;
-	Cname *cname;
-	Walkqid *wq;
-
-	if(nc != nil)
-		panic("fswalk: nc != nil");
-	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
-	nc = devclone(c);
-	cname = c->name;
-	incref(&cname->ref);
-
-	fsclone(c, nc);
-	wq->clone = nc;
-	for(i=0; i<nname; i++){
-		nc->name = cname;
-		if(fswalk1(nc, name[i]) == 0)
-			break;
-		cname = addelem(cname, name[i]);
-		wq->qid[i] = nc->qid;
-	}
-	nc->name = nil;
-	cnameclose(cname);
-	if(i != nname){
-		cclose(nc);
-		wq->clone = nil;
-	}
-	wq->nqid = i;
-	return wq;
-}
-	
-static int
-fsstat(Chan *c, uchar *buf, int n)
-{
-	Dir d;
-	struct stat stbuf;
-	char path[MAXPATH];
-
-	if(n < BIT16SZ)
-		error(Eshortstat);
-
-	fspath(c, 0, path);
-	if(stat(path, &stbuf) < 0)
-		error(strerror(errno));
-
-	d.name = lastelem(c);
-	d.uid = "unknown";
-	d.gid = "unknown";
-	d.muid = "unknown";
-	d.qid = c->qid;
-	d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
-	d.atime = stbuf.st_atime;
-	d.mtime = stbuf.st_mtime;
-	d.length = stbuf.st_size;
-	d.type = 'U';
-	d.dev = c->dev;
-	return convD2M(&d, buf, n);
-}
-
-static Chan*
-fsopen(Chan *c, int mode)
-{
-	char path[MAXPATH];
-	int m, isdir;
-	Ufsinfo *uif;
-
-/*print("fsopen %s\n", c2name(c));*/
-	m = mode & (OTRUNC|3);
-	switch(m) {
-	case 0:
-		break;
-	case 1:
-	case 1|16:
-		break;
-	case 2:	
-	case 0|16:
-	case 2|16:
-		break;
-	case 3:
-		break;
-	default:
-		error(Ebadarg);
-	}
-
-	isdir = c->qid.type & QTDIR;
-
-	if(isdir && mode != OREAD)
-		error(Eperm);
-
-	m = fsomode(m & 3);
-	c->mode = openmode(mode);
-
-	uif = c->aux;
-
-	fspath(c, 0, path);
-	if(isdir) {
-		uif->dir = opendir(path);
-		if(uif->dir == 0)
-			error(strerror(errno));
-	}	
-	else {
-		if(mode & OTRUNC)
-			m |= O_TRUNC;
-		uif->fd = open(path, m, 0666);
-
-		if(uif->fd < 0)
-			error(strerror(errno));
-	}
-	uif->offset = 0;
-
-	c->offset = 0;
-	c->flag |= COPEN;
-	return c;
-}
-
-static void
-fscreate(Chan *c, char *name, int mode, ulong perm)
-{
-	int fd, m;
-	char path[MAXPATH];
-	struct stat stbuf;
-	Ufsinfo *uif;
-
-	m = fsomode(mode&3);
-
-	fspath(c, name, path);
-
-	uif = c->aux;
-
-	if(perm & DMDIR) {
-		if(m)
-			error(Eperm);
-
-		if(mkdir(path, perm & 0777) < 0)
-			error(strerror(errno));
-
-		fd = open(path, 0);
-		if(fd >= 0) {
-			chmod(path, perm & 0777);
-			chown(path, uif->uid, uif->uid);
-		}
-		close(fd);
-
-		uif->dir = opendir(path);
-		if(uif->dir == 0)
-			error(strerror(errno));
-	}
-	else {
-		fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-		if(fd >= 0) {
-			if(m != 1) {
-				close(fd);
-				fd = open(path, m);
-			}
-			chmod(path, perm & 0777);
-			chown(path, uif->uid, uif->gid);
-		}
-		if(fd < 0)
-			error(strerror(errno));
-		uif->fd = fd;
-	}
-
-	if(stat(path, &stbuf) < 0)
-		error(strerror(errno));
-	c->qid = fsqid(path, &stbuf);
-	c->offset = 0;
-	c->flag |= COPEN;
-	c->mode = openmode(mode);
-}
-
-static void
-fsclose(Chan *c)
-{
-	Ufsinfo *uif;
-
-	uif = c->aux;
-
-	if(c->flag & COPEN) {
-		if(c->qid.type & QTDIR)
-			closedir(uif->dir);
-		else
-			close(uif->fd);
-	}
-
-	free(uif);
-}
-
-static long
-fsread(Chan *c, void *va, long n, vlong offset)
-{
-	int fd, r;
-	Ufsinfo *uif;
-
-/*print("fsread %s\n", c2name(c));*/
-	if(c->qid.type & QTDIR)
-		return fsdirread(c, va, n, offset);
-
-	uif = c->aux;
-	qlock(&uif->oq);
-	if(waserror()) {
-		qunlock(&uif->oq);
-		nexterror();
-	}
-	fd = uif->fd;
-	if(uif->offset != offset) {
-		r = lseek(fd, offset, 0);
-		if(r < 0)
-			error(strerror(errno));
-		uif->offset = offset;
-	}
-
-	n = read(fd, va, n);
-	if(n < 0)
-		error(strerror(errno));
-
-	uif->offset += n;
-	qunlock(&uif->oq);
-	poperror();
-
-	return n;
-}
-
-static long
-fswrite(Chan *c, void *va, long n, vlong offset)
-{
-	int fd, r;
-	Ufsinfo *uif;
-
-	uif = c->aux;
-
-	qlock(&uif->oq);
-	if(waserror()) {
-		qunlock(&uif->oq);
-		nexterror();
-	}
-	fd = uif->fd;
-	if(uif->offset != offset) {
-		r = lseek(fd, offset, 0);
-		if(r < 0)
-			error(strerror(errno));
-		uif->offset = offset;
-	}
-
-	n = write(fd, va, n);
-	if(n < 0)
-		error(strerror(errno));
-
-	uif->offset += n;
-	qunlock(&uif->oq);
-	poperror();
-
-	return n;
-}
-
-static void
-fsremove(Chan *c)
-{
-	int n;
-	char path[MAXPATH];
-
-	fspath(c, 0, path);
-	if(c->qid.type & QTDIR)
-		n = rmdir(path);
-	else
-		n = remove(path);
-	if(n < 0)
-		error(strerror(errno));
-}
-
-int
-fswstat(Chan *c, uchar *buf, int n)
-{
-	Dir d;
-	struct stat stbuf;
-	char old[MAXPATH], new[MAXPATH], dir[MAXPATH];
-	char strs[MAXPATH*3], *p;
-	Ufsinfo *uif;
-
-	if(convM2D(buf, n, &d, strs) != n)
-		error(Ebadstat);
-	
-	fspath(c, 0, old);
-	if(stat(old, &stbuf) < 0)
-		error(strerror(errno));
-
-	uif = c->aux;
-
-	if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
-		fspath(c, 0, old);
-		strcpy(new, old);
-		p = strrchr(new, '/');
-		strcpy(p+1, d.name);
-		if(rename(old, new) < 0)
-			error(strerror(errno));
-	}
-
-	fspath(c, 0, old);
-	if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
-		if(chmod(old, d.mode&0777) < 0)
-			error(strerror(errno));
-		uif->mode &= ~0777;
-		uif->mode |= d.mode&0777;
-	}
-/*
-	p = name2pass(gid, d.gid);
-	if(p == 0)
-		error(Eunknown);
-
-	if(p->id != stbuf.st_gid) {
-		if(chown(old, stbuf.st_uid, p->id) < 0)
-			error(strerror(errno));
-
-		uif->gid = p->id;
-	}
-*/
-	return n;
-}
-
-static Qid
-fsqid(char *p, struct stat *st)
-{
-	Qid q;
-	int dev;
-	ulong h;
-	static int nqdev;
-	static uchar *qdev;
-
-	if(qdev == 0)
-		qdev = mallocz(65536U, 1);
-
-	q.type = 0;
-	if((st->st_mode&S_IFMT) ==  S_IFDIR)
-		q.type = QTDIR;
-
-	dev = st->st_dev & 0xFFFFUL;
-	if(qdev[dev] == 0)
-		qdev[dev] = ++nqdev;
-
-	h = 0;
-	while(*p != '\0')
-		h += *p++ * 13;
-	
-	q.path = (vlong)qdev[dev]<<32;
-	q.path |= h;
-	q.vers = st->st_mtime;
-
-	return q;
-}
-
-static void
-fspath(Chan *c, char *ext, char *path)
-{
-	int i, n;
-	char *comp[MAXCOMP];
-
-	strcpy(path, base);
-	strcat(path, "/");
-	strcat(path, uc2name(c));
-	if(ext){
-		strcat(path, "/");
-		strcat(path, ext);
-	}
-	cleanname(path);
-}
-
-static int
-isdots(char *name)
-{
-	if(name[0] != '.')
-		return 0;
-	if(name[1] == '\0')
-		return 1;
-	if(name[1] != '.')
-		return 0;
-	if(name[2] == '\0')
-		return 1;
-	return 0;
-}
-
-static int
-p9readdir(char *name, Ufsinfo *uif)
-{
-	struct dirent *de;
-	
-	if(uif->nextname[0]){
-		strcpy(name, uif->nextname);
-		uif->nextname[0] = 0;
-		return 1;
-	}
-
-	de = readdir(uif->dir);
-	if(de == NULL)
-		return 0;
-		
-	strcpy(name, de->d_name);
-	return 1;
-}
-
-static ulong
-fsdirread(Chan *c, uchar *va, int count, ulong offset)
-{
-	int i;
-	Dir d;
-	long n;
-	char de[NAME_MAX];
-	struct stat stbuf;
-	char path[MAXPATH], dirpath[MAXPATH];
-	Ufsinfo *uif;
-
-/*print("fsdirread %s\n", c2name(c));*/
-	i = 0;
-	uif = c->aux;
-
-	errno = 0;
-	if(uif->offset != offset) {
-		if(offset != 0)
-			error("bad offset in fsdirread");
-		uif->offset = offset;  /* sync offset */
-		uif->nextname[0] = 0;
-		rewinddir(uif->dir);
-	}
-
-	fspath(c, 0, dirpath);
-
-	while(i+BIT16SZ < count) {
-		if(!p9readdir(de, uif))
-			break;
-
-		if(de[0]==0 || isdots(de))
-			continue;
-
-		d.name = de;
-		sprint(path, "%s/%s", dirpath, de);
-		memset(&stbuf, 0, sizeof stbuf);
-
-		if(stat(path, &stbuf) < 0) {
-			print("dir: bad path %s\n", path);
-			/* but continue... probably a bad symlink */
-		}
-
-		d.uid = "unknown";
-		d.gid = "unknown";
-		d.qid = fsqid(path, &stbuf);
-		d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
-		d.atime = stbuf.st_atime;
-		d.mtime = stbuf.st_mtime;
-		d.length = stbuf.st_size;
-		d.type = 'U';
-		d.dev = c->dev;
-		n = convD2M(&d, (char*)va+i, count-i);
-		if(n == BIT16SZ){
-			strcpy(uif->nextname, de);
-			break;
-		}
-		i += n;
-	}
-/*print("got %d\n", i);*/
-	uif->offset += i;
-	return i;
-}
-
-static int
-fsomode(int m)
-{
-	switch(m) {
-	case 0:			/* OREAD */
-	case 3:			/* OEXEC */
-		return 0;
-	case 1:			/* OWRITE */
-		return 1;
-	case 2:			/* ORDWR */
-		return 2;
-	}
-	error(Ebadarg);
-	return 0;
-}
-
-Dev fsdevtab = {
-	'U',
-	"fs",
-
-	devreset,
-	devinit,
-	devshutdown,
-	fsattach,
-	fswalk,
-	fsstat,
-	fsopen,
-	fscreate,
-	fsclose,
-	fsread,
-	devbread,
-	fswrite,
-	devbwrite,
-	fsremove,
-	fswstat,
-};
--- a/kern/devip-win.c
+++ /dev/null
@@ -1,208 +1,0 @@
-#include <windows.h>
-#include "winduhz.h"
-#include "u.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-
-#include "devip.h"
-
-#pragma comment(lib, "wsock32.lib")
-
-#undef listen
-#undef accept
-#undef bind
-
-void
-osipinit(void)
-{
-	WSADATA wasdat;
-	char buf[1024];
-
-	if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0)
-		panic("no winsock.dll");
-
-	gethostname(buf, sizeof(buf));
-	kstrdup(&sysname, buf);
-}
-
-int
-so_socket(int type)
-{
-	int fd, one;
-
-	switch(type) {
-	default:
-		error("bad protocol type");
-	case S_TCP:
-		type = SOCK_STREAM;
-		break;
-	case S_UDP:
-		type = SOCK_DGRAM;
-		break;
-	}
-
-	fd = socket(AF_INET, type, 0);
-	if(fd < 0)
-		error(sys_errlist[errno]);
-
-	one = 1;
-	if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0)
-		print("setsockopt: %s", sys_errlist[errno]);
-
-
-	return fd;
-}
-
-
-void
-so_connect(int fd, unsigned long raddr, unsigned short rport)
-{
-	struct sockaddr_in sin;
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	hnputs(&sin.sin_port, rport);
-	hnputl(&sin.sin_addr.s_addr, raddr);
-
-	if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
-		error(sys_errlist[errno]);
-}
-
-void
-so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
-{
-	int len;
-	struct sockaddr_in sin;
-
-	len = sizeof(sin);
-	if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
-		error(sys_errlist[errno]);
-
-	if(sin.sin_family != AF_INET || len != sizeof(sin))
-		error("not AF_INET");
-
-	*laddr = nhgetl(&sin.sin_addr.s_addr);
-	*lport = nhgets(&sin.sin_port);
-}
-
-void
-so_listen(int fd)
-{
-	if(listen(fd, 5) < 0)
-		error(sys_errlist[errno]);
-}
-
-int
-so_accept(int fd, unsigned long *raddr, unsigned short *rport)
-{
-	int nfd, len;
-	struct sockaddr_in sin;
-
-	len = sizeof(sin);
-	nfd = accept(fd, (struct sockaddr*)&sin, &len);
-	if(nfd < 0)
-		error(sys_errlist[errno]);
-
-	if(sin.sin_family != AF_INET || len != sizeof(sin))
-		error("not AF_INET");
-
-	*raddr = nhgetl(&sin.sin_addr.s_addr);
-	*rport = nhgets(&sin.sin_port);
-	return nfd;
-}
-
-void
-so_bind(int fd, int su, unsigned short port)
-{
-	int i, one;
-	struct sockaddr_in sin;
-
-	one = 1;
-	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0)
-		print("setsockopt: %s", sys_errlist[errno]);
-
-	if(su) {
-		for(i = 600; i < 1024; i++) {
-			memset(&sin, 0, sizeof(sin));
-			sin.sin_family = AF_INET;
-			sin.sin_port = i;
-
-			if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)	
-				return;
-		}
-		error(sys_errlist[errno]);
-	}
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	hnputs(&sin.sin_port, port);
-
-	if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
-		error(sys_errlist[errno]);
-}
-
-int
-so_gethostbyname(char *host, char**hostv, int n)
-{
-	int i;
-	char buf[32];
-	unsigned char *p;
-	struct hostent *hp;
-
-	hp = gethostbyname(host);
-	if(hp == 0)
-		return 0;
-
-	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
-		p = (unsigned char*)hp->h_addr_list[i];
-		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-		hostv[i] = strdup(buf);
-		if(hostv[i] == 0)
-			break;
-	}
-	return i;
-}
-
-char*
-hostlookup(char *host)
-{
-	char buf[100];
-	uchar *p;
-	HOSTENT *he;
-
-	he = gethostbyname(host);
-	if(he != 0 && he->h_addr_list[0]) {
-		p = he->h_addr_list[0];
-		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
-	} else
-		strcpy(buf, host);
-
-	return strdup(buf);
-}
-
-int
-so_getservbyname(char *service, char *net, char *port)
-{
-	struct servent *s;
-
-	s = getservbyname(service, net);
-	if(s == 0)
-		return -1;
-
-	sprint(port, "%d", nhgets(&s->s_port));
-	return 0;
-}
-
-int
-so_send(int fd, void *d, int n, int f)
-{
-	return send(fd, d, n, f);
-}
-
-int
-so_recv(int fd, void *d, int n, int f)
-{
-	return recv(fd, d, n, f);
-}
--- /dev/null
+++ b/kern/devip-win32.c
@@ -1,0 +1,207 @@
+#include <windows.h>
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+#include "devip.h"
+
+#pragma comment(lib, "wsock32.lib")
+
+#undef listen
+#undef accept
+#undef bind
+
+void
+osipinit(void)
+{
+	WSADATA wasdat;
+	char buf[1024];
+
+	if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0)
+		panic("no winsock.dll");
+
+	gethostname(buf, sizeof(buf));
+	kstrdup(&sysname, buf);
+}
+
+int
+so_socket(int type)
+{
+	int fd, one;
+
+	switch(type) {
+	default:
+		error("bad protocol type");
+	case S_TCP:
+		type = SOCK_STREAM;
+		break;
+	case S_UDP:
+		type = SOCK_DGRAM;
+		break;
+	}
+
+	fd = socket(AF_INET, type, 0);
+	if(fd < 0)
+		error(sys_errlist[errno]);
+
+	one = 1;
+	if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0)
+		print("setsockopt: %s", sys_errlist[errno]);
+
+
+	return fd;
+}
+
+
+void
+so_connect(int fd, unsigned long raddr, unsigned short rport)
+{
+	struct sockaddr_in sin;
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	hnputs(&sin.sin_port, rport);
+	hnputl(&sin.sin_addr.s_addr, raddr);
+
+	if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
+		error(sys_errlist[errno]);
+}
+
+void
+so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
+{
+	int len;
+	struct sockaddr_in sin;
+
+	len = sizeof(sin);
+	if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
+		error(sys_errlist[errno]);
+
+	if(sin.sin_family != AF_INET || len != sizeof(sin))
+		error("not AF_INET");
+
+	*laddr = nhgetl(&sin.sin_addr.s_addr);
+	*lport = nhgets(&sin.sin_port);
+}
+
+void
+so_listen(int fd)
+{
+	if(listen(fd, 5) < 0)
+		error(sys_errlist[errno]);
+}
+
+int
+so_accept(int fd, unsigned long *raddr, unsigned short *rport)
+{
+	int nfd, len;
+	struct sockaddr_in sin;
+
+	len = sizeof(sin);
+	nfd = accept(fd, (struct sockaddr*)&sin, &len);
+	if(nfd < 0)
+		error(sys_errlist[errno]);
+
+	if(sin.sin_family != AF_INET || len != sizeof(sin))
+		error("not AF_INET");
+
+	*raddr = nhgetl(&sin.sin_addr.s_addr);
+	*rport = nhgets(&sin.sin_port);
+	return nfd;
+}
+
+void
+so_bind(int fd, int su, unsigned short port)
+{
+	int i, one;
+	struct sockaddr_in sin;
+
+	one = 1;
+	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0)
+		print("setsockopt: %s", sys_errlist[errno]);
+
+	if(su) {
+		for(i = 600; i < 1024; i++) {
+			memset(&sin, 0, sizeof(sin));
+			sin.sin_family = AF_INET;
+			sin.sin_port = i;
+
+			if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)	
+				return;
+		}
+		error(sys_errlist[errno]);
+	}
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	hnputs(&sin.sin_port, port);
+
+	if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
+		error(sys_errlist[errno]);
+}
+
+int
+so_gethostbyname(char *host, char**hostv, int n)
+{
+	int i;
+	char buf[32];
+	unsigned char *p;
+	struct hostent *hp;
+
+	hp = gethostbyname(host);
+	if(hp == 0)
+		return 0;
+
+	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
+		p = (unsigned char*)hp->h_addr_list[i];
+		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+		hostv[i] = strdup(buf);
+		if(hostv[i] == 0)
+			break;
+	}
+	return i;
+}
+
+char*
+hostlookup(char *host)
+{
+	char buf[100];
+	uchar *p;
+	HOSTENT *he;
+
+	he = gethostbyname(host);
+	if(he != 0 && he->h_addr_list[0]) {
+		p = he->h_addr_list[0];
+		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
+	} else
+		strcpy(buf, host);
+
+	return strdup(buf);
+}
+
+int
+so_getservbyname(char *service, char *net, char *port)
+{
+	struct servent *s;
+
+	s = getservbyname(service, net);
+	if(s == 0)
+		return -1;
+
+	sprint(port, "%d", nhgets(&s->s_port));
+	return 0;
+}
+
+int
+so_send(int fd, void *d, int n, int f)
+{
+	return send(fd, d, n, f);
+}
+
+int
+so_recv(int fd, void *d, int n, int f)
+{
+	return recv(fd, d, n, f);
+}
--- a/kern/devmnt.c
+++ b/kern/devmnt.c
@@ -477,8 +477,10 @@
 	r->request.fid = c->fid;
 	mountrpc(m, r);
 
-	if(r->reply.nstat >= 1<<(8*BIT16SZ))
+/* r->reply.nstat is 16 bits
+	if(r->reply.nstat >= 1<<16)
 		error("returned stat buffer count too large");
+*/
 
 	if(r->reply.nstat > n){
 		/*
--- a/kern/devntfs.c
+++ /dev/null
@@ -1,704 +1,0 @@
-#include	<windows.h>
-#include	<sys/types.h>
-#include	<sys/stat.h>
-#include	<fcntl.h>
-
-#ifndef NAME_MAX
-#	define NAME_MAX 256
-#endif
-#include	"u.h"
-#include	"lib.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"error.h"
-
-typedef struct DIR	DIR;
-typedef	struct Ufsinfo	Ufsinfo;
-
-enum
-{
-	NUID	= 256,
-	NGID	= 256,
-	MAXPATH	= 1024,
-	MAXCOMP	= 128
-};
-
-struct DIR
-{
-	HANDLE	handle;
-	char*	path;
-	int	index;
-	WIN32_FIND_DATA	wfd;
-};
-
-struct Ufsinfo
-{
-	int	mode;
-	int	fd;
-	int	uid;
-	int	gid;
-	DIR*	dir;
-	ulong	offset;
-	QLock	oq;
-	char nextname[NAME_MAX];
-};
-
-DIR*	opendir(char*);
-int	readdir(char*, DIR*);
-void	closedir(DIR*);
-void	rewinddir(DIR*);
-
-char	*base = "c:/.";
-
-static	Qid	fsqid(char*, struct stat *);
-static	void	fspath(Chan*, char*, char*);
-// static	void	fsperm(Chan*, int);
-static	ulong	fsdirread(Chan*, uchar*, int, ulong);
-static	int	fsomode(int);
-static  int	chown(char *path, int uid, int);
-static	int	link(char *path, char *next);
-
-/* clumsy hack, but not worse than the Path stuff in the last one */
-static char*
-uc2name(Chan *c)
-{
-	char *s;
-
-	if(c->name == nil)
-		return "/";
-	s = c2name(c);
-	if(s[0]=='#' && s[1]=='U')
-		return s+2;
-	return s;
-}
-
-static char*
-lastelem(Chan *c)
-{
-	char *s, *t;
-
-	s = uc2name(c);
-	if((t = strrchr(s, '/')) == nil)
-		return s;
-	if(t[1] == 0)
-		return t;
-	return t+1;
-}
-	
-static Chan*
-fsattach(void *spec)
-{
-	Chan *c;
-	struct stat stbuf;
-	static int devno;
-	Ufsinfo *uif;
-
-	if(stat(base, &stbuf) < 0)
-		error(strerror(errno));
-
-	c = devattach('U', spec);
-
-	uif = mallocz(sizeof(Ufsinfo), 1);
-	uif->gid = stbuf.st_gid;
-	uif->uid = stbuf.st_uid;
-	uif->mode = stbuf.st_mode;
-
-	c->aux = uif;
-	c->dev = devno++;
-	c->qid.type = QTDIR;
-/*print("fsattach %s\n", c2name(c));*/
-
-	return c;
-}
-
-static Chan*
-fsclone(Chan *c, Chan *nc)
-{
-	Ufsinfo *uif;
-
-	uif = mallocz(sizeof(Ufsinfo), 1);
-	*uif = *(Ufsinfo*)c->aux;
-	nc->aux = uif;
-
-	return nc;
-}
-
-static int
-fswalk1(Chan *c, char *name)
-{
-	struct stat stbuf;
-	char path[MAXPATH];
-	Ufsinfo *uif;
-
-	fspath(c, name, path);
-
-	/*	print("** fs walk '%s' -> %s\n", path, name); /**/
-
-	if(stat(path, &stbuf) < 0)
-		return 0;
-
-	uif = c->aux;
-
-	uif->gid = stbuf.st_gid;
-	uif->uid = stbuf.st_uid;
-	uif->mode = stbuf.st_mode;
-
-	c->qid = fsqid(path, &stbuf);
-
-	return 1;
-}
-
-extern Cname* addelem(Cname*, char*);
-
-static Walkqid*
-fswalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	int i;
-	Cname *cname;
-	Walkqid *wq;
-
-	if(nc != nil)
-		panic("fswalk: nc != nil");
-	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
-	nc = devclone(c);
-	cname = c->name;
-	incref(&cname->ref);
-
-	fsclone(c, nc);
-	wq->clone = nc;
-	for(i=0; i<nname; i++){
-		nc->name = cname;
-		if(fswalk1(nc, name[i]) == 0)
-			break;
-		cname = addelem(cname, name[i]);
-		wq->qid[i] = nc->qid;
-	}
-	nc->name = nil;
-	cnameclose(cname);
-	if(i != nname){
-		cclose(nc);
-		wq->clone = nil;
-	}
-	wq->nqid = i;
-	return wq;
-}
-	
-static int
-fsstat(Chan *c, uchar *buf, int n)
-{
-	Dir d;
-	struct stat stbuf;
-	char path[MAXPATH];
-
-	if(n < BIT16SZ)
-		error(Eshortstat);
-
-	fspath(c, 0, path);
-	if(stat(path, &stbuf) < 0)
-		error(strerror(errno));
-
-	d.name = lastelem(c);
-	d.uid = "unknown";
-	d.gid = "unknown";
-	d.muid = "unknown";
-	d.qid = c->qid;
-	d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
-	d.atime = stbuf.st_atime;
-	d.mtime = stbuf.st_mtime;
-	d.length = stbuf.st_size;
-	d.type = 'U';
-	d.dev = c->dev;
-	return convD2M(&d, buf, n);
-}
-
-static Chan*
-fsopen(Chan *c, int mode)
-{
-	char path[MAXPATH];
-	int m, isdir;
-	Ufsinfo *uif;
-
-/*print("fsopen %s\n", c2name(c));*/
-	m = mode & (OTRUNC|3);
-	switch(m) {
-	case 0:
-		break;
-	case 1:
-	case 1|16:
-		break;
-	case 2:	
-	case 0|16:
-	case 2|16:
-		break;
-	case 3:
-		break;
-	default:
-		error(Ebadarg);
-	}
-
-	isdir = c->qid.type & QTDIR;
-
-	if(isdir && mode != OREAD)
-		error(Eperm);
-
-	m = fsomode(m & 3);
-	c->mode = openmode(mode);
-
-	uif = c->aux;
-
-	fspath(c, 0, path);
-	if(isdir) {
-		uif->dir = opendir(path);
-		if(uif->dir == 0)
-			error(strerror(errno));
-	}	
-	else {
-		if(mode & OTRUNC)
-			m |= O_TRUNC;
-		uif->fd = open(path, m|_O_BINARY, 0666);
-
-		if(uif->fd < 0)
-			error(strerror(errno));
-	}
-	uif->offset = 0;
-
-	c->offset = 0;
-	c->flag |= COPEN;
-	return c;
-}
-
-static void
-fscreate(Chan *c, char *name, int mode, ulong perm)
-{
-	int fd, m;
-	char path[MAXPATH];
-	struct stat stbuf;
-	Ufsinfo *uif;
-
-	m = fsomode(mode&3);
-
-	fspath(c, name, path);
-
-	uif = c->aux;
-
-	if(perm & DMDIR) {
-		if(m)
-			error(Eperm);
-
-		if(mkdir(path) < 0)
-			error(strerror(errno));
-
-		fd = open(path, 0);
-		if(fd >= 0) {
-			chmod(path, perm & 0777);
-			chown(path, uif->uid, uif->uid);
-		}
-		close(fd);
-
-		uif->dir = opendir(path);
-		if(uif->dir == 0)
-			error(strerror(errno));
-	}
-	else {
-		fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
-		if(fd >= 0) {
-			if(m != 1) {
-				close(fd);
-				fd = open(path, m|_O_BINARY);
-			}
-			chmod(path, perm & 0777);
-			chown(path, uif->uid, uif->gid);
-		}
-		if(fd < 0)
-			error(strerror(errno));
-		uif->fd = fd;
-	}
-
-	if(stat(path, &stbuf) < 0)
-		error(strerror(errno));
-	c->qid = fsqid(path, &stbuf);
-	c->offset = 0;
-	c->flag |= COPEN;
-	c->mode = openmode(mode);
-}
-
-static void
-fsclose(Chan *c)
-{
-	Ufsinfo *uif;
-
-	uif = c->aux;
-
-	if(c->flag & COPEN) {
-		if(c->qid.type & QTDIR)
-			closedir(uif->dir);
-		else
-			close(uif->fd);
-	}
-
-	free(uif);
-}
-
-static long
-fsread(Chan *c, void *va, long n, ulong offset)
-{
-	int fd, r;
-	Ufsinfo *uif;
-
-/*print("fsread %s\n", c2name(c));*/
-	if(c->qid.type & QTDIR)
-		return fsdirread(c, va, n, offset);
-
-	uif = c->aux;
-	qlock(&uif->oq);
-	if(waserror()) {
-		qunlock(&uif->oq);
-		nexterror();
-	}
-	fd = uif->fd;
-	if(uif->offset != offset) {
-		r = lseek(fd, offset, 0);
-		if(r < 0)
-			error(strerror(errno));
-		uif->offset = offset;
-	}
-
-	n = read(fd, va, n);
-	if(n < 0)
-		error(strerror(errno));
-
-	uif->offset += n;
-	qunlock(&uif->oq);
-	poperror();
-
-	return n;
-}
-
-static long
-fswrite(Chan *c, void *va, long n, ulong offset)
-{
-	int fd, r;
-	Ufsinfo *uif;
-
-	uif = c->aux;
-
-	qlock(&uif->oq);
-	if(waserror()) {
-		qunlock(&uif->oq);
-		nexterror();
-	}
-	fd = uif->fd;
-	if(uif->offset != offset) {
-		r = lseek(fd, offset, 0);
-		if(r < 0)
-			error(strerror(errno));
-		uif->offset = offset;
-	}
-
-	n = write(fd, va, n);
-	if(n < 0)
-		error(strerror(errno));
-
-	uif->offset += n;
-	qunlock(&uif->oq);
-	poperror();
-
-	return n;
-}
-
-static void
-fsremove(Chan *c)
-{
-	int n;
-	char path[MAXPATH];
-
-	fspath(c, 0, path);
-	if(c->qid.type & QTDIR)
-		n = rmdir(path);
-	else
-		n = remove(path);
-	if(n < 0)
-		error(strerror(errno));
-}
-
-static int
-fswstat(Chan *c, uchar *buf, int n)
-{
-	Dir d;
-	struct stat stbuf;
-	char old[MAXPATH], new[MAXPATH];
-	char strs[MAXPATH*3], *p;
-	Ufsinfo *uif;
-
-	if (convM2D(buf, n, &d, strs) != n)
-		error(Ebadstat);
-	
-	fspath(c, 0, old);
-	if(stat(old, &stbuf) < 0)
-		error(strerror(errno));
-
-	uif = c->aux;
-
-//	if(uif->uid != stbuf.st_uid)
-//		error(Eowner);
-
-	if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
-		fspath(c, 0, old);
-		strcpy(new, old);
-		p = strrchr(new, '/');
-		strcpy(p+1, d.name);
-		if(rename(old, new) < 0)
-			error(strerror(errno));
-	}
-
-	fspath(c, 0, old);
-	if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
-		if(chmod(old, d.mode&0777) < 0)
-			error(strerror(errno));
-		uif->mode &= ~0777;
-		uif->mode |= d.mode&0777;
-	}
-/*
-	p = name2pass(gid, d.gid);
-	if(p == 0)
-		error(Eunknown);
-
-	if(p->id != stbuf.st_gid) {
-		if(chown(old, stbuf.st_uid, p->id) < 0)
-			error(sys_errlist[errno]);
-
-		uif->gid = p->id;
-	}
-*/
-	return n;
-}
-
-static Qid
-fsqid(char *p, struct stat *st)
-{
-	Qid q;
-	int dev;
-	ulong h;
-	static int nqdev;
-	static uchar *qdev;
-
-	if(qdev == 0)
-		qdev = mallocz(65536U, 1);
-
-	q.type = 0;
-	if((st->st_mode&S_IFMT) ==  S_IFDIR)
-		q.type = QTDIR;
-
-	dev = st->st_dev & 0xFFFFUL;
-	if(qdev[dev] == 0)
-		qdev[dev] = ++nqdev;
-
-	h = 0;
-	while(*p != '\0')
-		h += *p++ * 13;
-	
-	q.path = (vlong)qdev[dev]<<32;
-	q.path |= h;
-	q.vers = st->st_mtime;
-
-	return q;
-}
-
-static void
-fspath(Chan *c, char *ext, char *path)
-{
-	strcpy(path, base);
-	strcat(path, "/");
-	strcat(path, uc2name(c));
-	if(ext) {
-		strcat(path, "/");
-		strcat(path, ext);
-	}
-	cleanname(path);
-}
-
-static int
-isdots(char *name)
-{
-	if(name[0] != '.')
-		return 0;
-	if(name[1] == '\0')
-		return 1;
-	if(name[1] != '.')
-		return 0;
-	if(name[2] == '\0')
-		return 1;
-	return 0;
-}
-
-static int
-p9readdir(char *name, Ufsinfo *uif)
-{
-	if(uif->nextname[0]){
-		strcpy(name, uif->nextname);
-		uif->nextname[0] = 0;
-		return 1;
-	}
-
-	return readdir(name, uif->dir);
-}
-
-static ulong
-fsdirread(Chan *c, uchar *va, int count, ulong offset)
-{
-	int i;
-	Dir d;
-	long n;
-	char de[NAME_MAX];
-	struct stat stbuf;
-	char path[MAXPATH], dirpath[MAXPATH];
-	Ufsinfo *uif;
-
-/*print("fsdirread %s\n", c2name(c));*/
-	i = 0;
-	uif = c->aux;
-
-	errno = 0;
-	if(uif->offset != offset) {
-		if(offset != 0)
-			error("bad offset in fsdirread");
-		uif->offset = offset;  /* sync offset */
-		uif->nextname[0] = 0;
-		rewinddir(uif->dir);
-	}
-
-	fspath(c, 0, dirpath);
-
-	while(i+BIT16SZ < count) {
-		if(!p9readdir(de, uif))
-			break;
-
-		if(de[0]==0 || isdots(de))
-			continue;
-
-		d.name = de;
-		sprint(path, "%s/%s", dirpath, de);
-		memset(&stbuf, 0, sizeof stbuf);
-
-		if(stat(path, &stbuf) < 0) {
-			print("dir: bad path %s\n", path);
-			/* but continue... probably a bad symlink */
-		}
-
-		d.uid = "unknown";
-		d.gid = "unknown";
-		d.muid = "unknown";
-		d.qid = fsqid(path, &stbuf);
-		d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
-		d.atime = stbuf.st_atime;
-		d.mtime = stbuf.st_mtime;
-		d.length = stbuf.st_size;
-		d.type = 'U';
-		d.dev = c->dev;
-		n = convD2M(&d, (char*)va+i, count-i);
-		if(n == BIT16SZ){
-			strcpy(uif->nextname, de);
-			break;
-		}
-		i += n;
-	}
-/*print("got %d\n", i);*/
-	uif->offset += i;
-	return i;
-}
-
-static int
-fsomode(int m)
-{
-	switch(m) {
-	case 0:			/* OREAD */
-	case 3:			/* OEXEC */
-		return 0;
-	case 1:			/* OWRITE */
-		return 1;
-	case 2:			/* ORDWR */
-		return 2;
-	}
-	error(Ebadarg);
-	return 0;
-}
-void
-closedir(DIR *d)
-{
-	FindClose(d->handle);
-	free(d->path);
-}
-
-int
-readdir(char *name, DIR *d)
-{
-	if(d->index != 0) {
-		if(FindNextFile(d->handle, &d->wfd) == FALSE)
-			return 0;
-	}
-	strcpy(name, d->wfd.cFileName);
-	d->index++;
-
-	return 1;
-}
-
-void
-rewinddir(DIR *d)
-{
-	FindClose(d->handle);
-	d->handle = FindFirstFile(d->path, &d->wfd);
-	d->index = 0;
-}
-
-static int
-chown(char *path, int uid, int perm)
-{
-/*	panic("chown"); */
-	return 0;
-}
-
-DIR*
-opendir(char *p)
-{
-	DIR *d;
-	char path[MAX_PATH];
-
-	
-	snprint(path, sizeof(path), "%s/*.*", p);
-
-	d = mallocz(sizeof(DIR), 1);
-	if(d == 0)
-		return 0;
-
-	d->index = 0;
-
-	d->handle = FindFirstFile(path, &d->wfd);
-	if(d->handle == INVALID_HANDLE_VALUE) {
-		free(d);
-		return 0;
-	}
-
-	d->path = strdup(path);
-	return d;
-}
-
-Dev fsdevtab = {
-	'U',
-	"fs",
-
-	devreset,
-	devinit,
-	devshutdown,
-	fsattach,
-	fswalk,
-	fsstat,
-	fsopen,
-	fscreate,
-	fsclose,
-	fsread,
-	devbread,
-	fswrite,
-	devbwrite,
-	fsremove,
-	fswstat,
-};
--- a/kern/devssl.c
+++ b/kern/devssl.c
@@ -1025,7 +1025,7 @@
 	{ "rc4_40", 1, RC4, initRC4key_40, },
 	{ 0 }
 };
-#endif NOSPOOKS
+#endif /* NOSPOOKS */
 
 static int
 parseencryptalg(char *p, Dstate *s)
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -196,6 +196,7 @@
 int		nrand(int);
 int		okaddr(ulong, ulong, int);
 int		openmode(ulong);
+void		oserrstr(void);
 Block*		packblock(Block*);
 Block*		padblock(Block*, int);
 void		pagechainhead(Page*);
--- a/kern/mkfile
+++ /dev/null
@@ -1,47 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libkern.$L
-
-OFILES=\
-	allocb.$O\
-	cache.$O\
-	chan.$O\
-	data.$O\
-	dev.$O\
-	devcons.$O\
-	devdraw.$O\
-	devip.$O\
-	devmnt.$O\
-	devmouse.$O\
-	devpipe.$O\
-	devroot.$O\
-	devssl.$O\
-	devtab.$O\
-	error.$O\
-	parse.$O\
-	pgrp.$O\
-	procinit.$O\
-	rwlock.$O\
-	sleep.$O\
-	smalloc.$O\
-	stub.$O\
-	sysfile.$O\
-	sysproc.$O\
-	qio.$O\
-	qlock.$O\
-	term.$O\
-	todo.$O\
-	uart.$O\
-	waserror.$O\
-	$DEVIP.$O\
-	$OSHOOKS.$O\
-	$DEVFS.$O
-
-HFILE=\
-	dat.h\
-	devip.h\
-	error.h\
-	fns.h\
-	netif.h\
-	screen.h
-
-<$DSRC/mklib-$CONF
--- a/kern/os-windows.c
+++ /dev/null
@@ -1,184 +1,0 @@
-#include <windows.h>
-#include "u.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-
-typedef struct Oproc Oproc;
-struct Oproc {
-	int tid;
-	HANDLE	*sema;
-};
-
-char	*argv0;
-_declspec(thread)       Proc *CT;
-
-Proc*
-_getproc(void)
-{
-	return CT;
-}
-
-void
-_setproc(Proc *p)
-{
-	CT = p;
-}
-
-void
-oserrstr(void)
-{
-	char *p;
-	char buf[ERRMAX];
-
-	if((p = strerror(errno)) != nil)
-		strecpy(up->errstr, up->errstr+ERRMAX, p);
-	else
-		snprint(up->errstr, ERRMAX, "unix error %d", errno);
-}
-
-void
-oserror(void)
-{
-	oserrstr();
-	nexterror();
-}
-
-void
-osinit(void)
-{
-	Oproc *t;
-	static Proc firstprocCTstore;
-
-	CT = &firstprocCTstore;
-	t = (Oproc*) CT->oproc;
-	assert(t != 0);
-
-	t->tid = GetCurrentThreadId();
-	t->sema = CreateSemaphore(0, 0, 1000, 0);
-	if(t->sema == 0) {
-		oserror();
-		fatal("could not create semaphore: %r");
-	}
-}
-
-void
-osnewproc(Proc *p)
-{
-	Oproc *op;
-
-	op = (Oproc*)p->oproc;
-	op->sema = CreateSemaphore(0, 0, 1000, 0);
-	if (op->sema == 0) {
-		oserror();
-		fatal("could not create semaphore: %r");
-	}
-}
-
-void
-osmsleep(int ms)
-{
-	Sleep((DWORD) ms);
-}
-
-void
-osyield(void)
-{
-	Sleep(0);
-}
-
-static DWORD WINAPI tramp(LPVOID vp);
-
-void
-osproc(Proc *p)
-{
-	int tid;
-
-	if(CreateThread(0, 0, tramp, p, 0, &tid) == 0) {
-		oserror();
-		fatal("osproc: %r");
-	}
-
-	Sleep(0);
-}
-
-static DWORD WINAPI
-tramp(LPVOID vp)
-{
-	Proc *p = (Proc *) vp;
-	Oproc *op = (Oproc*) p->oproc;
-
-	CT = p;
-	op->tid = GetCurrentThreadId();
-	op->sema = CreateSemaphore(0, 0, 1000, 0);
-	if(op->sema == 0) {
-		oserror();
-		fatal("could not create semaphore: %r");
-	}
-
- 	(*p->fn)(p->arg);
-	ExitThread(0);
-	return 0;
-}
-
-void
-procsleep(void)
-{
-	Proc *p;
-	Oproc *op;
-
-	p = up;
-	op = (Oproc*)p->oproc;
-	WaitForSingleObject(op->sema, INFINITE);}
-
-void
-procwakeup(Proc *p)
-{
-	Oproc *op;
-
-	op = (Oproc*)p->oproc;
-	ReleaseSemaphore(op->sema, 1, 0);
-}
-
-void
-randominit(void)
-{
-	srand(seconds());
-}
-
-ulong
-randomread(void *v, ulong n)
-{
-	int m, i, *r;
-
-	m = (n / sizeof(int)) * sizeof(int);
-	for (i = 0, r = (int*)v; i < m; i += sizeof(int)) {
-		*r = rand();
-		r += sizeof(int);
-	}
-
-	return m;
-}
-
-long
-seconds(void)
-{
-	return time(0);
-}
-
-int
-ticks(void)
-{
-	return GetTickCount();
-}
-
-extern int	main(int, char*[]);
-static int	args(char *argv[], int n, char *p);
-
-int PASCAL
-WinMain(HANDLE hInst, HANDLE hPrev, LPSTR arg, int nshow)
-{
-	main(__argc, __argv);
-	ExitThread(0);
-	return 0;
-}
--- a/kern/uart.c
+++ b/kern/uart.c
@@ -8,7 +8,7 @@
 void
 uartputs(char *s, int n)
 {
-	write(1, s, n); 
+//	write(1, s, n); 
 }
 
 
--- /dev/null
+++ b/kern/win32.c
@@ -1,0 +1,284 @@
+#include <windows.h>
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+
+typedef struct Oproc Oproc;
+struct Oproc {
+	int tid;
+	HANDLE	*sema;
+};
+
+static int tlsx = TLS_OUT_OF_INDEXES;
+
+char	*argv0;
+
+Proc*
+_getproc(void)
+{
+	if(tlsx == TLS_OUT_OF_INDEXES)
+		return nil;
+	return TlsGetValue(tlsx);
+}
+
+void
+_setproc(Proc *p)
+{
+	if(tlsx == TLS_OUT_OF_INDEXES){
+		tlsx = TlsAlloc();
+		if(tlsx == TLS_OUT_OF_INDEXES)
+			panic("out of indexes");
+	}
+	TlsSetValue(tlsx, p);
+}
+
+void
+oserror(void)
+{
+	oserrstr();
+	nexterror();
+}
+
+void
+osinit(void)
+{
+	Oproc *t;
+	static Proc firstprocCTstore;
+
+	_setproc(&firstprocCTstore);
+	t = (Oproc*)firstprocCTstore.oproc;
+	assert(t != 0);
+
+	t->tid = GetCurrentThreadId();
+	t->sema = CreateSemaphore(0, 0, 1000, 0);
+	if(t->sema == 0) {
+		oserror();
+		fatal("could not create semaphore: %r");
+	}
+}
+
+void
+osnewproc(Proc *p)
+{
+	Oproc *op;
+
+	op = (Oproc*)p->oproc;
+	op->sema = CreateSemaphore(0, 0, 1000, 0);
+	if (op->sema == 0) {
+		oserror();
+		fatal("could not create semaphore: %r");
+	}
+}
+
+void
+osmsleep(int ms)
+{
+	Sleep((DWORD) ms);
+}
+
+void
+osyield(void)
+{
+	Sleep(0);
+}
+
+static DWORD WINAPI tramp(LPVOID vp);
+
+void
+osproc(Proc *p)
+{
+	DWORD tid;
+
+	if(CreateThread(0, 0, tramp, p, 0, &tid) == 0) {
+		oserror();
+		fatal("osproc: %r");
+	}
+
+	Sleep(0);
+}
+
+static DWORD WINAPI
+tramp(LPVOID vp)
+{
+	Proc *p = (Proc *) vp;
+	Oproc *op = (Oproc*) p->oproc;
+
+	_setproc(p);
+	op->tid = GetCurrentThreadId();
+	op->sema = CreateSemaphore(0, 0, 1000, 0);
+	if(op->sema == 0) {
+		oserror();
+		fatal("could not create semaphore: %r");
+	}
+
+ 	(*p->fn)(p->arg);
+	ExitThread(0);
+	return 0;
+}
+
+void
+procsleep(void)
+{
+	Proc *p;
+	Oproc *op;
+
+	p = up;
+	op = (Oproc*)p->oproc;
+	WaitForSingleObject(op->sema, INFINITE);}
+
+void
+procwakeup(Proc *p)
+{
+	Oproc *op;
+
+	op = (Oproc*)p->oproc;
+	ReleaseSemaphore(op->sema, 1, 0);
+}
+
+void
+randominit(void)
+{
+	srand(seconds());
+}
+
+ulong
+randomread(void *v, ulong n)
+{
+	int m, i, *r;
+
+	m = (n / sizeof(int)) * sizeof(int);
+	for (i = 0, r = (int*)v; i < m; i += sizeof(int)) {
+		*r = rand();
+		r += sizeof(int);
+	}
+
+	return m;
+}
+
+long
+seconds(void)
+{
+	return time(0);
+}
+
+int
+ticks(void)
+{
+	return GetTickCount();
+}
+
+#if 0
+uvlong
+fastticks(uvlong *v)
+{
+	uvlong n;
+
+	n = GetTickCount() * 1000 * 1000;
+	if(v)
+		*v = n;
+	return n;
+}
+#endif
+
+extern int	main(int, char*[]);
+static int	args(char *argv[], int n, char *p);
+
+int APIENTRY
+WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR arg, int nshow)
+{
+	main(__argc, __argv);
+	ExitThread(0);
+	return 0;
+}
+
+/*
+ * Windows socket error messages
+ * There must be a way to get these strings out of the library.
+ * This table is derived from the MSDN online help.
+ */
+static struct {
+	int e;
+	char *s;
+} tab[] = {
+	{ 10004, "interrupted function call" },
+	{ 10013, "permission denied" },
+	{ 10014, "bad address" },
+	{ 10022, "invalid argument" },
+	{ 10024, "too many open files" },
+	{ 10035, "resource temporarily unavailable" },
+	{ 10036, "operation now in progress" },
+	{ 10037, "operation already in progress" },
+	{ 10038, "socket operation on nonsocket" },
+	{ 10039, "destination address required" },
+	{ 10040, "message too long" },
+	{ 10041, "protocol wrong type for socket" },
+	{ 10042, "bad protocol option" },
+	{ 10043, "protocol not supported" },
+	{ 10044, "socket type not supported" },
+	{ 10045, "operation not supported" },
+	{ 10046, "protocol family not supported" },
+	{ 10047, "address family not supported by protocol family" },
+	{ 10048, "address already in use" },
+	{ 10049, "cannot assign requested address" },
+	{ 10050, "network is down" },
+	{ 10051, "network is unreachable" },
+	{ 10052, "network dropped connection on reset" },
+	{ 10053, "software caused connection abort" },
+	{ 10054, "connection reset by peer" },
+	{ 10055, "no buffer space available" },
+	{ 10056, "socket is already connected" },
+	{ 10057, "socket is not connected" },
+	{ 10058, "cannot send after socket shutdown" },
+	{ 10060, "connection timed out" },
+	{ 10061, "connection refused" },
+	{ 10064, "host is down" },
+	{ 10065, "no route to host" },
+	{ 10067, "too many processes" },
+	{ 10091, "network subsystem is unavailable" },
+	{ 10092, "winsock.dll version out of range" },
+	{ 10093, "wsastartup not called" },
+	{ 10101, "graceful shutdown in progress" },
+	{ 10109, "class type not found" },
+	{ 11001, "host name not found" },
+	{ 11002, "host not found (non-authoritative)" },
+	{ 11003, "nonrecoverable error" },
+	{ 11004, "valid name, but no data record of requested type" },
+};
+
+void
+osrerrstr(char *buf, uint nbuf)
+{
+	char *p, *q;
+	int e, i, r;
+
+	e = GetLastError();
+	r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
+		0, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		buf, nbuf, 0);
+	if(r == 0){
+		for(i=0; i<nelem(tab); i++)
+			if(tab[i].e == e){
+				strecpy(buf, buf+nbuf, tab[i].s);
+				break;
+			}
+		if(i==nelem(tab))
+			snprint(buf, nbuf, "windows error %d", e);
+	}
+
+	for(p=q=buf; *p; p++) {
+		if(*p == '\r')
+			continue;
+		if(*p == '\n')
+			*q++ = ' ';
+		else
+			*q++ = *p;
+	}
+	*q = '\0';
+}
+
+void
+oserrstr(void)
+{
+	osrerrstr(up->errstr, ERRMAX);
+}
--- a/kern/winduhz.h
+++ /dev/null
@@ -1,18 +1,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <fcntl.h>
-#include <io.h>
-#include <setjmp.h>
-#include <direct.h>
-#include <process.h>
-#include <time.h>
-#include <assert.h>
-#include <stdarg.h>
-
-/* disable various silly warnings */
-#pragma warning( disable : 4245 4305 4244 4102 4761 4090 4028 4024)
-
-typedef __int64		p9_vlong;
-typedef	unsigned __int64 p9_uvlong;
--- a/libauthsrv/Makefile
+++ b/libauthsrv/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libauthsrv.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	_asgetticket.$O\
@@ -20,8 +19,8 @@
 	readnvram.$O\
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libauthsrv/mkfile
+++ /dev/null
@@ -1,25 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libauthsrv.$L
-
-OFILES=\
-	_asgetticket.$O\
-	_asrdresp.$O\
-	convA2M.$O\
-	convM2A.$O\
-	convM2PR.$O\
-	convM2T.$O\
-	convM2TR.$O\
-	convPR2M.$O\
-	convT2M.$O\
-	convTR2M.$O\
-	nvcsum.$O\
-	opasstokey.$O\
-	passtokey.$O\
-	readnvram.$O\
-
-HFILE=\
-
-
-TARGOBJ=${OFILES:%=$TARG(%)}
-
-<$DSRC/mklib-$CONF
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libc.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	charstod.$O\
@@ -81,8 +80,8 @@
 	vsnprint.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libc/fcallfmt.c
+++ b/libc/fcallfmt.c
@@ -209,7 +209,7 @@
 	if(count > DUMPL)
 		count = DUMPL;
 	for(i=0; i<count && printable; i++)
-		if((buf[i]<32 && buf[i] !='\n' && buf[i] !='\t') || buf[i]>127)
+		if((buf[i]<32 && buf[i] !='\n' && buf[i] !='\t') || (uchar)buf[i]>127)
 			printable = 0;
 	p = ans;
 	*p++ = '\'';
--- a/libc/mkfile
+++ /dev/null
@@ -1,90 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libc.$L
-
-OFILES=\
-	charstod.$O\
-	cleanname.$O\
-	convD2M.$O\
-	convM2D.$O\
-	convM2S.$O\
-	convS2M.$O\
-	crypt.$O\
-	dial.$O\
-	dirfstat.$O\
-	dirfwstat.$O\
-	dirmodefmt.$O\
-	dirstat.$O\
-	dirwstat.$O\
-	dofmt.$O\
-	dorfmt.$O\
-	fcallfmt.$O\
-	fltfmt.$O\
-	fmt.$O\
-	fmtfd.$O\
-	fmtlock.$O\
-	fmtprint.$O\
-	fmtquote.$O\
-	fmtrune.$O\
-	fmtstr.$O\
-	fmtvprint.$O\
-	fprint.$O\
-	frand.$O\
-	getfields.$O\
-	getpid.$O\
-	lnrand.$O\
-	lock.$O\
-	lrand.$O\
-	mallocz.$O\
-	nan64.$O\
-	netmkaddr.$O\
-	nrand.$O\
-	nsec.$O\
-	pow10.$O\
-	pushssl.$O\
-	read9pmsg.$O\
-	readn.$O\
-	rune.$O\
-	runefmtstr.$O\
-	runeseprint.$O\
-	runesmprint.$O\
-	runesnprint.$O\
-	runesprint.$O\
-	runetype.$O\
-	runevseprint.$O\
-	runevsmprint.$O\
-	runevsnprint.$O\
-	seprint.$O\
-	smprint.$O\
-	snprint.$O\
-	sprint.$O\
-	strecpy.$O\
-	strtod.$O\
-	strtoll.$O\
-	sysfatal.$O\
-	time.$O\
-	tokenize.$O\
-	truerand.$O\
-	u16.$O\
-	u32.$O\
-	u64.$O\
-	utfecpy.$O\
-	utflen.$O\
-	utfnlen.$O\
-	utfrrune.$O\
-	utfrune.$O\
-	utfutf.$O\
-	vfprint.$O\
-	vseprint.$O\
-	vsmprint.$O\
-	vsnprint.$O
-
-HFILES=../include/libc.h\
-	fmt.h\
-	fmtdef.h\
-	nan.h\
-	strtod.h\
-	utf.h\
-	utfdef.h
-
-<$DSRC/mklib-$CONF
-
--- a/libc/nan64.c
+++ b/libc/nan64.c
@@ -12,9 +12,9 @@
 // typedef unsigned long long uvlong;
 // typedef unsigned long ulong;
 
-static uvlong uvnan    = 0x7FF0000000000001;
-static uvlong uvinf    = 0x7FF0000000000000;
-static uvlong uvneginf = 0xFFF0000000000000;
+static uvlong uvnan    = 0x7FF0000000000001ULL;
+static uvlong uvinf    = 0x7FF0000000000000ULL;
+static uvlong uvneginf = 0xFFF0000000000000ULL;
 
 double
 __NaN(void)
--- a/libc/nsec.c
+++ b/libc/nsec.c
@@ -1,8 +1,7 @@
 #include <u.h>
 #include <libc.h>
 
-
-static uvlong order = (uvlong) 0x0001020304050607;
+static uvlong order = (uvlong) 0x0001020304050607ULL;
 
 static void
 be2vlong(vlong *to, uchar *f)
--- a/libdraw/Makefile
+++ b/libdraw/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libdraw.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	alloc.$O\
@@ -16,8 +15,8 @@
 	rgb.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libdraw/mkfile
+++ /dev/null
@@ -1,18 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libdraw.$L
-
-OFILES=\
-	alloc.$O\
-	arith.$O\
-	bytesperline.$O\
-	chan.$O\
-	defont.$O\
-	drawrepl.$O\
-	icossin.$O\
-	icossin2.$O\
-	rectclip.$O\
-	rgb.$O
-
-HFILES=\
-
-<$DSRC/mklib-$CONF
--- a/libmemdraw/Makefile
+++ b/libmemdraw/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libmemdraw.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	alloc.$O\
@@ -25,8 +24,8 @@
 	write.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libmemdraw/fillpoly.c
+++ b/libmemdraw/fillpoly.c
@@ -20,9 +20,9 @@
 };
 
 static	void	zsort(Seg **seg, Seg **ep);
-static	int	ycompare(void*, void*);
-static	int	xcompare(void*, void*);
-static	int	zcompare(void*, void*);
+static	int	ycompare(const void*, const void*);
+static	int	xcompare(const void*, const void*);
+static	int	zcompare(const void*, const void*);
 static	void	xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int, int, int);
 static	void	yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int);
 
@@ -469,13 +469,13 @@
 }
 
 static int
-ycompare(void *a, void *b)
+ycompare(const void *a, const void *b)
 {
 	Seg **s0, **s1;
 	long y0, y1;
 
-	s0 = a;
-	s1 = b;
+	s0 = (Seg**)a;
+	s1 = (Seg**)b;
 	y0 = (*s0)->p0.y;
 	y1 = (*s1)->p0.y;
 
@@ -487,13 +487,13 @@
 }
 
 static int
-xcompare(void *a, void *b)
+xcompare(const void *a, const void *b)
 {
 	Seg **s0, **s1;
 	long x0, x1;
 
-	s0 = a;
-	s1 = b;
+	s0 = (Seg**)a;
+	s1 = (Seg**)b;
 	x0 = (*s0)->p0.x;
 	x1 = (*s1)->p0.x;
 
@@ -505,13 +505,13 @@
 }
 
 static int
-zcompare(void *a, void *b)
+zcompare(const void *a, const void *b)
 {
 	Seg **s0, **s1;
 	long z0, z1;
 
-	s0 = a;
-	s1 = b;
+	s0 = (Seg**)a;
+	s1 = (Seg**)b;
 	z0 = (*s0)->z;
 	z1 = (*s1)->z;
 
--- a/libmemdraw/mkfile
+++ /dev/null
@@ -1,27 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libmemdraw.$L
-
-OFILES=\
-	alloc.$O\
-	arc.$O\
-	cload.$O\
-	cmap.$O\
-	cread.$O\
-	defont.$O\
-	draw.$O\
-	ellipse.$O\
-	fillpoly.$O\
-	hwdraw.$O\
-	line.$O\
-	load.$O\
-	openmemsubfont.$O\
-	poly.$O\
-	read.$O\
-	string.$O\
-	subfont.$O\
-	unload.$O\
-	write.$O
-
-HFILE=\
-
-<$DSRC/mklib-$CONF
--- a/libmemlayer/Makefile
+++ b/libmemlayer/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libmemlayer.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	draw.$O\
@@ -18,8 +17,8 @@
 	unload.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libmemlayer/mkfile
+++ /dev/null
@@ -1,23 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libmemlayer.$L
-
-OFILES=\
-	draw.$O\
-	lalloc.$O\
-	layerop.$O\
-	ldelete.$O\
-	lhide.$O\
-	line.$O\
-	load.$O\
-	lorigin.$O\
-	lsetrefresh.$O\
-	ltofront.$O\
-	ltorear.$O\
-	unload.$O\
-
-HFILES=\
-	../include/memlayer.h\
-	../include/memdraw.h\
-	../include/draw.h
-
-<$DSRC/mklib-$CONF
--- a/libmp/Makefile
+++ b/libmp/Makefile
@@ -1,9 +1,8 @@
+ROOT=..
+include ../Make.config
 # N.B.  This is used only for secstore.  It needn't be fast.
 
 LIB=libmp.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	betomp.$O\
@@ -38,8 +37,8 @@
 	strtomp.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libmp/mkfile
+++ /dev/null
@@ -1,40 +1,0 @@
-TARG=libmp.$L
-<$DSRC/mkfile-$CONF
-
-OFILES=\
-	betomp.$O\
-	crt.$O\
-	letomp.$O\
-	mpadd.$O\
-	mpaux.$O\
-	mpcmp.$O\
-	mpdigdiv.$O\
-	mpdiv.$O\
-	mpeuclid.$O\
-	mpexp.$O\
-	mpextendedgcd.$O\
-	mpfmt.$O\
-	mpinvert.$O\
-	mpleft.$O\
-	mpmod.$O\
-	mpmul.$O\
-	mprand.$O\
-	mpright.$O\
-	mpsub.$O\
-	mptobe.$O\
-	mptoi.$O\
-	mptole.$O\
-	mptoui.$O\
-	mptouv.$O\
-	mptov.$O\
-	mpvecadd.$O\
-	mpveccmp.$O\
-	mpvecdigmuladd.$O\
-	mpvecsub.$O\
-	strtomp.$O
-
-HFILE=\
-	dat.h\
-	os.h
-
-<$DSRC/mklib-$CONF
--- a/libsec/Makefile
+++ b/libsec/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=libsec.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	aes.$O\
@@ -52,8 +51,8 @@
 	smallprimes.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/libsec/mkfile
+++ /dev/null
@@ -1,55 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libsec.$L
-
-OFILES=\
-	aes.$O\
-	blowfish.$O\
-	decodepem.$O\
-	des.$O\
-	des3CBC.$O\
-	des3ECB.$O\
-	desCBC.$O\
-	desECB.$O\
-	desmodes.$O\
-	dsaalloc.$O\
-	dsagen.$O\
-	dsaprimes.$O\
-	dsaprivtopub.$O\
-	dsasign.$O\
-	dsaverify.$O\
-	egalloc.$O\
-	egdecrypt.$O\
-	egencrypt.$O\
-	eggen.$O\
-	egprivtopub.$O\
-	egsign.$O\
-	egverify.$O\
-	fastrand.$O\
-	genprime.$O\
-	genrandom.$O\
-	gensafeprime.$O\
-	genstrongprime.$O\
-	hmac.$O\
-	md4.$O\
-	md5.$O\
-	md5block.$O\
-	md5pickle.$O\
-	nfastrand.$O\
-	prng.$O\
-	probably_prime.$O\
-	rc4.$O\
-	rsaalloc.$O\
-	rsadecrypt.$O\
-	rsaencrypt.$O\
-	rsafill.$O\
-	rsagen.$O\
-	rsaprivtopub.$O\
-	sha1.$O\
-	sha1block.$O\
-	sha1pickle.$O\
-	smallprimes.$O
-
-HFILE=\
-	os.h
-
-<$DSRC/mklib-$CONF
--- a/mkfile
+++ /dev/null
@@ -1,95 +1,0 @@
-#CONF=FreeBSD
-#CONF=FreeBSD-power	# MAC OSX
-#CONF=Irix
-CONF=posix
-#CONF=OSF1
-#CONF=Solaris
-#CONF=Solaris-386
-#CONF=Solaris-sparc
-#CONF=Windows
-
-<mkfile-$CONF
-TARG=drawterm
-
-OFILES=\
-	main.$O\
-	cpu.$O\
-	readcons.$O\
-	secstore.$O
-
-DIRS=	kern exportfs libauthsrv libsec libmp libmemdraw libmemlayer libdraw libc
-LIBS=\
-	kern/libkern.$L\
-	exportfs/libexportfs.$L\
-	libauthsrv/libauthsrv.$L\
-	libsec/libsec.$L\
-	libmp/libmp.$L\
-	libmemdraw/libmemdraw.$L\
-	libmemlayer/libmemlayer.$L\
-	libdraw/libdraw.$L\
-	libc/libc.$L\
-	$SYS-$objtype/libmachdep.$L \
-	gui-win32/libgui.$L\
-#	gui-x11/libx11.$L\
-
-$TARG: $OFILES $LIBS
-	$LD $LDFLAGS $prereq $OSLIBS 
-
-# $TARG: $OFILES $LIBS
-#	$CC -o $TARG $OFILES $LIBS $LDFLAGS
-
-%.$O: %.c
-	$CC $CFLAGS $stem.c
-
-clean:
-	rm -f *.$O */*.$O */*.$L drawterm  *.$L
-
-#$LIBS:
-#	for (i in $DIRS) {
-#		cd $i
-#		mk
-#	}
-
-kern/libkern.$L:
-	cd kern; mk
-
-exportfs/libexportfs.$L:
-	cd exportfs; mk
-
-libauthsrv/libauthsrv.$L:
-	cd libauthsrv; mk
-
-libmp/libmp.$L:
-	cd libmp; mk
-
-libsec/libsec.$L:
-	cd libsec; mk
-
-libmemdraw/libmemdraw.$L:
-	cd libmemdraw; mk
-
-libmemlayer/libmemlayer.$L:
-	cd libmemlayer; mk
-
-libdraw/libdraw.$L:
-	cd libdraw; mk
-
-libc/libc.$L:
-	cd libc; mk
-
-gui-x11/libx11.$L:
-	cd gui-x11; mk
-
-gui-win32/libgui.$L:
-	cd gui-win32; mk
-
-drawterm.res:\
-	drawterm.ico\
-
-$SYS-$objtype/libmachdep.$L:
-	arch=$SYS-$objtype
-	cd $arch; mk
-
-#libmachdep.$L:
-#	arch=`{uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'}
-#	cd gcc$$arch mk
--- a/mkfile-Windows
+++ /dev/null
@@ -1,54 +1,0 @@
-WIN=win
-SYS=win32
-OS=WinXP
-objtype=386
-BIN=$9pm/bin
-DSRC=C:/src/dt2k
-
-# compiler, linker, librarian
-CC=cl
-LD=link
-AR=lib
-AS=ml
-RC=rc
-
-# file extensions
-O=obj
-L=lib
-CPUS=
-CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -I. -I$DSRC -I$DSRC/include -I$DSRC/kern -DWINDOWS
-# -nologo	a little less verbose
-# -W3		level 3 warning - u.h contains pragma's that inhibit some of the very silly warnings
-# -YX		use precompiled headers (.PCH files)
-# -G5		generate code that runs best on Pentiums - has bugs on 4.2
-# -Zi		generate debug info (.PDB files)
-# -MT		Link with LIBCMT.LIB (multi thread static)
-# -Zl 		don't include libcmt.lib and oldnames.lib in object files
-# -Oi		enable intrinic function, i.e abs, sin, sqrt, etc
-# -FAs		generate asm listing with source
-# -G5		Pentium code
-# -Ob2		Let the compiler inline function -O2 only inlines functions marked inline
-# -Fr or -FR	generate .SBR files (browsing information) without or with local symbols
-
-OSLIBS=\
-	drawterm.res\
-	libcmt.lib\
-	oldnames.lib\
-	user32.lib\
-	advapi32.lib\
-	kernel32.lib\
-	gdi32.lib\
-
-LDFLAGS=-entry:mainCRTStartup -debug -nologo -incremental:no
-#-nodefaultlib:libcmt.lib -nodefaultlib:oldnames.lib 
-#TARG=drawterm.exe
-LDFLAGS=-nologo -incremental:no -debug -subsystem:windows -out:drawterm.exe
-ARFLAGS=-nologo
-
-# System specific targets
-DEVFS=devntfs
-DEVIP=devip-win
-OSHOOKS=os-windows
-
-%.res:	%.rc
-	$RC $RCFLAGS $stem.rc
--- a/mkfile-posix
+++ /dev/null
@@ -1,9 +1,0 @@
-CC=gcc
-objtype=`{uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'}
-CFLAGS=-I$DSRC/include -c -ggdb -D_THREAD_SAFE -pthread # not ready for this yet: -Wall
-LDFLAGS=-pthread -L/usr/X11R6/lib -lX11 -ggdb
-O=o
-L=a
-SYS=posix
-#OS=FreeBSD
-OSHOOKS=posix
--- a/mklib-Windows
+++ /dev/null
@@ -1,22 +1,0 @@
-TARGOBJ=${OFILES:%=$TARG(%)}
-
-all:V:	$TARG.all
-
-inc:V:	$TARG
-
-$TARG:	$TARGOBJ
-	$AR $ARFLAGS -out:$TARG $newmember
-
-$TARG.all:V: $OFILES
-	rm -f $TARG
-	$AR $ARFLAGS -out:$TARG $OFILES
-
-%.$O:	$HFILES			# don't combine with following %.$O rules
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	%.s
-	$AS $AFLAGS $stem.s
-
-$TARG(%.$O):N:	%.$O
--- a/mkone
+++ /dev/null
@@ -1,50 +1,0 @@
-LDFLAGS=
-YFLAGS=-d
-AFLAGS=
-
-default:V:	$O.out
-
-all:V:	$O.out
-
-$O.out:	$OFILES $LIB
-	$LD $LDFLAGS -o $target $prereq
-
-%.$O:	$HFILES		# don't combine with following %.$O rules
-
-%.$O:	%.c
-	$CC $CFLAGS $stem.c
-
-%.$O:	%.s
-	$AS $AFLAGS $stem.s
-
-y.tab.h y.tab.c:	$YFILES
-	$YACC $YFLAGS $prereq
-
-install:V:	$BIN/$TARG
-
-$BIN/$TARG:	$O.out
-	cp $prereq $BIN/$TARG
-
-installall:V:
-	for(objtype in $CPUS)
-		mk install
-
-nuke:V:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output *.acid $TARG
-
-clean:V:
-	rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG
-
-safeinstall:V: $O.out
-	test -e $BIN/$TARG && mv $BIN/$TARG $BIN/_$TARG
-	cp $prereq $BIN/$TARG
-
-update:V:
-	update $UPDATEFLAGS $UPDATE
-
-safeinstallall:V:
-	for (objtype in $CPUS)
-		mk safeinstall
-
-%.acid: %.$O $HFILES
-	$CC $CFLAGS -a $stem.c >$target
--- a/posix-386/Makefile
+++ b/posix-386/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=../libmachdep.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	getcallerpc.$O\
@@ -8,8 +7,8 @@
 	tas.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/posix-power/Makefile
+++ b/posix-power/Makefile
@@ -1,7 +1,6 @@
+ROOT=..
+include ../Make.config
 LIB=../libmachdep.a
-CC=gcc
-CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
-O=o
 
 OFILES=\
 	getcallerpc.$O\
@@ -8,8 +7,8 @@
 	tas.$O
 
 $(LIB): $(OFILES)
-	ar r $(LIB) $(OFILES)
-	ranlib $(LIB)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
 
 %.$O: %.c
 	$(CC) $(CFLAGS) $*.c
--- a/win32-386/mkfile
+++ /dev/null
@@ -1,10 +1,0 @@
-<$DSRC/mkfile-$CONF
-TARG=libmachdep.$L
-
-OFILES=\
-	getcallerpc.$O\
-	tas.$O
-
-HFILES=\
-
-<$DSRC/mklib-$CONF