Many files:
  pass4.c (e2fsck_pass4): If an inode is set in the inode_imagic_map
  	bitmap, don't check to see if it is disconnected from the inode tree
  	(because it almost certainly will be).  Free inode_imagic_map at the
  	end of pass 4.
  pass2.c (check_dir_block, check_filetype): If the FILETYPE feature is
  	set, check the directory entry's filetype information field, and
  	fix/set it if necessary.  (e2fsck_pass2): Free the inode_reg_map
  	bitmap at the end of pass 2.
  pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
  	information for inode_reg_map and inode_imagic_map, which indicates
  	which inodes are regular files and AFS inodes, respectively.
  	Since only the master superblock is written during a restart, force
  	that superblock to be used after a restart; otherwise changes to the
  	block group descriptors end up getting ignored.
  problem.c, problemP.h: If e2fsck is run -n, make def_yn variable be 0
  	for "no".  Add support for a new flag, PR_NO_NOMSG, which supresses
  	the problem message if e2fsck is run with the -n option.
  problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add new
  	problem codes.
  message.c (expand_dirent_expression): Add support for %dt which prints
  	the dirent type information.
  e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map and
  	inode_imagic_map).
  e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map to the
  	context structure.
ChangeLog, nt_io.c:
  nt_io.c: New file which supports I/O under Windows NT.
ChangeLog, gen_uuid_nt.c:
  gen_uuid_nt.c: New file which creates a UUID under Windows NT.
Many files:
  Add support for non-Unix compiles

diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 28960be..0fc1540 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,43 @@
+1999-10-21    <tytso@valinux.com>
+
+	* pass4.c (e2fsck_pass4): If an inode is set in the
+		inode_imagic_map bitmap, don't check to see if it is
+		disconnected from the inode tree (because it almost
+		certainly will be).  Free inode_imagic_map at the end of
+		pass 4.
+
+	* pass2.c (check_dir_block, check_filetype): If the FILETYPE
+		feature is set, check the directory entry's filetype
+		information field, and fix/set it if necessary.
+		(e2fsck_pass2): Free the inode_reg_map bitmap at the end
+		of pass 2.
+
+	* pass1.c (e2fsck_pass1, alloc_imagic_map): Allocate and fill in
+		information for inode_reg_map and inode_imagic_map, which
+		indicates which inodes are regular files and AFS inodes,
+		respectively.
+		Since only the master superblock is written during a
+		restart, force that superblock to be used after a restart;
+		otherwise changes to the block group descriptors end up
+		getting ignored.
+
+	* problem.c, problemP.h: If e2fsck is run -n, make def_yn variable
+		be 0 for "no".  Add support for a new flag, PR_NO_NOMSG,
+		which supresses the problem message if e2fsck is run with
+		the -n option.
+
+	* problem.c, problem.h (PR_2_SET_FILETYPE, PR_2_BAD_FILETYPE): Add
+		new problem codes.
+
+	* message.c (expand_dirent_expression): Add support for %dt which
+		prints the dirent type information.
+
+	* e2fsck.c (e2fsck_reset_context): Free new bitmaps (inode_reg_map
+		and inode_imagic_map).
+
+	* e2fsck.h (e2fsck_t): Add new inode_reg_map and inode_magic_map
+		to the context structure.
+	
 1999-09-24    <tytso@valinux.com>
 
 	* unix.c (PRS), util.c (ask_yn): Add #ifdef's to make
diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c
index 3cfca69..3028c87 100644
--- a/e2fsck/e2fsck.c
+++ b/e2fsck/e2fsck.c
@@ -50,6 +50,10 @@
 		ext2fs_free_inode_bitmap(ctx->inode_dir_map);
 		ctx->inode_dir_map = 0;
 	}
+	if (ctx->inode_reg_map) {
+		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
+		ctx->inode_dir_map = 0;
+	}
 	if (ctx->block_found_map) {
 		ext2fs_free_block_bitmap(ctx->block_found_map);
 		ctx->block_found_map = 0;
@@ -75,6 +79,10 @@
 		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
 		ctx->inode_bad_map = 0;
 	}
+	if (ctx->inode_imagic_map) {
+		ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
+		ctx->inode_imagic_map = 0;
+	}
 
 	/*
 	 * Clear the array of invalid meta-data flags
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 86b411c..83f0889 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -143,6 +143,8 @@
 	ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
 	ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
 	ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
+	ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
+	ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
 
 	ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
 	ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
diff --git a/e2fsck/message.c b/e2fsck/message.c
index 8bb11df..a129f86 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -20,6 +20,7 @@
  * 	%dn	<dirent>->name		string
  * 	%dr	<dirent>->rec_len
  * 	%dl	<dirent>->name_len
+ * 	%dt	<dirent>->filetype
  * 	%D	<dir> 			inode number
  * 	%g	<group>			integer
  * 	%i	<ino>			inode number
@@ -301,6 +302,9 @@
 	case 'l':
 		printf("%u", dirent->name_len & 0xFF);
 		break;
+	case 't':
+		printf("%u", dirent->name_len >> 8);
+		break;
 	default:
 	no_dirent:
 		printf("%%D%c", ch);
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index cebc82c..c7475f9 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -19,8 +19,10 @@
  *
  * 	- A bitmap of which inodes are in use.		(inode_used_map)
  * 	- A bitmap of which inodes are directories.	(inode_dir_map)
+ * 	- A bitmap of which inodes are regular files.	(inode_reg_map)
  * 	- A bitmap of which inodes have bad fields.	(inode_bad_map)
  * 	- A bitmap of which inodes are in bad blocks.	(inode_bb_map)
+ * 	- A bitmap of which inodes are imagic inodes.	(inode_imagic_map)
  * 	- A bitmap of which blocks are in use.		(block_found_map)
  * 	- A bitmap of which blocks are in use by two inodes	(block_dup_map)
  * 	- The data blocks of the directory inodes.	(dir_map)
@@ -60,6 +62,7 @@
 static void mark_table_blocks(e2fsck_t ctx);
 static void alloc_bad_map(e2fsck_t ctx);
 static void alloc_bb_map(e2fsck_t ctx);
+static void alloc_imagic_map(e2fsck_t ctx);
 static void handle_fs_bad_blocks(e2fsck_t ctx);
 static void process_inodes(e2fsck_t ctx, char *block_buf);
 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
@@ -199,6 +202,15 @@
 		ctx->flags |= E2F_FLAG_ABORT;
 		return;
 	}
+	pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
+						    "regular file inode map",
+					      &ctx->inode_reg_map);
+	if (pctx.errcode) {
+		pctx.num = 6;
+		fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
 	pctx.errcode = ext2fs_allocate_block_bitmap(fs, "in-use block map",
 					      &ctx->block_found_map);
 	if (pctx.errcode) {
@@ -405,14 +417,20 @@
 				alloc_bad_map(ctx);
 			ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
 		}
+		if (inode.i_flags & EXT2_IMAGIC_FL) {
+			if (!ctx->inode_imagic_map)
+				alloc_imagic_map(ctx);
+			ext2fs_mark_inode_bitmap(ctx->inode_imagic_map, ino);
+		}
 		
 		if (LINUX_S_ISDIR(inode.i_mode)) {
 			ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
 			e2fsck_add_dir_info(ctx, ino, 0);
 			ctx->fs_directory_count++;
-		} else if (LINUX_S_ISREG (inode.i_mode))
+		} else if (LINUX_S_ISREG (inode.i_mode)) {
+			ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
 			ctx->fs_regular_count++;
-		else if (LINUX_S_ISCHR (inode.i_mode) &&
+		} else if (LINUX_S_ISCHR (inode.i_mode) &&
 			 e2fsck_pass1_check_device_inode(&inode))
 			ctx->fs_chardev_count++;
 		else if (LINUX_S_ISBLK (inode.i_mode) &&
@@ -485,6 +503,13 @@
 		handle_fs_bad_blocks(ctx);
 
 	if (ctx->flags & E2F_FLAG_RESTART) {
+		/*
+		 * Only the master copy of the superblock and block
+		 * group descriptors are going to be written during a
+		 * restart, so set the superblock to be used to be the
+		 * master superblock.
+		 */
+		ctx->use_superblock = 0;
 		unwind_pass1(fs);
 		goto endit;
 	}
@@ -649,6 +674,26 @@
 }
 
 /*
+ * This procedure will allocate the inode imagic table
+ */
+static void alloc_imagic_map(e2fsck_t ctx)
+{
+	struct		problem_context pctx;
+	
+	clear_problem_context(&pctx);
+	pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
+					      "imagic inode map",
+					      &ctx->inode_imagic_map);
+	if (pctx.errcode) {
+		pctx.num = 5;
+		fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+		/* Should never get here */
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+}
+
+/*
  * Marks a block as in use, setting the dup_map if it's been set
  * already.  Called by process_block and process_bad_block.
  *
@@ -729,6 +774,7 @@
 		inode->i_dtime = time(0);
 		e2fsck_write_inode(ctx, ino, inode, "check_blocks");
 		ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+		ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
 		ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
 		/*
 		 * The inode was probably partially accounted for
@@ -752,6 +798,7 @@
 			inode->i_dtime = time(0);
 			e2fsck_write_inode(ctx, ino, inode, "check_blocks");
 			ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+			ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
 			ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
 			ctx->fs_directory_count--;
 			pb.is_dir = 0;
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 37114e3..2eec914 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -38,11 +38,18 @@
  *
  * Pass 2 frees the following data structures
  * 	- The inode_bad_map bitmap
+ * 	- The inode_reg_map bitmap
  */
 
 #include "e2fsck.h"
 #include "problem.h"
 
+#ifdef NO_INLINE_FUNCS
+#define _INLINE_
+#else
+#define _INLINE_ inline
+#endif
+
 /*
  * Keeps track of how many times an inode is referenced.
  */
@@ -134,6 +141,10 @@
 		ext2fs_free_inode_bitmap(ctx->inode_bad_map);
 		ctx->inode_bad_map = 0;
 	}
+	if (ctx->inode_reg_map) {
+		ext2fs_free_inode_bitmap(ctx->inode_reg_map);
+		ctx->inode_reg_map = 0;
+	}
 #ifdef RESOURCE_TRACK
 	if (ctx->options & E2F_OPT_TIME2) {
 		e2fsck_clear_progbar(ctx);
@@ -268,6 +279,57 @@
 	return ret;
 }
 
+/*
+ * Check the directory filetype (if present)
+ */
+static _INLINE_ int check_filetype(e2fsck_t ctx,
+		      struct ext2_dir_entry *dirent,
+		      ino_t dir_ino, struct problem_context *pctx)
+{
+	int	filetype = dirent->name_len >> 8;
+	int	should_be = EXT2_FT_UNKNOWN;
+	struct ext2_inode	inode;
+
+	if (!(ctx->fs->super->s_feature_incompat &
+	      EXT2_FEATURE_INCOMPAT_FILETYPE))
+		return 0;
+
+	if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
+		should_be = EXT2_FT_DIR;
+	} else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
+					    dirent->inode)) {
+		should_be = EXT2_FT_REG_FILE;
+	} else if (ctx->inode_bad_map &&
+		   ext2fs_test_inode_bitmap(ctx->inode_bad_map,
+					    dirent->inode))
+		should_be = 0;
+	else {
+		e2fsck_read_inode(ctx, dirent->inode, &inode,
+				  "check_filetype");
+		if (LINUX_S_ISCHR (inode.i_mode))
+			should_be = EXT2_FT_CHRDEV;
+		else if (LINUX_S_ISBLK (inode.i_mode))
+			should_be = EXT2_FT_BLKDEV;
+		else if (LINUX_S_ISLNK (inode.i_mode))
+			should_be = EXT2_FT_SYMLINK;
+		else if (LINUX_S_ISFIFO (inode.i_mode))
+			should_be = EXT2_FT_FIFO;
+		else if (LINUX_S_ISSOCK (inode.i_mode))
+			should_be = EXT2_FT_SOCK;
+	}
+	if (filetype == should_be)
+		return 0;
+	pctx->num = should_be;
+
+	if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
+			pctx) == 0)
+		return 0;
+			
+	dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
+	return 1;
+}
+
+
 static int check_dir_block(ext2_filsys fs,
 			   struct ext2_db_entry *db,
 			   void *priv_data)
@@ -465,6 +527,9 @@
 		if (check_name(ctx, dirent, ino, &cd->pctx))
 			dir_modified++;
 
+		if (check_filetype(ctx, dirent, ino, &cd->pctx))
+			dir_modified++;
+
 		/*
 		 * If this is a directory, then mark its parent in its
 		 * dir_info structure.  If the parent field is already
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index 264b1c7..92721bd 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -10,6 +10,7 @@
  *
  * Pass 4 frees the following data structures:
  * 	- A bitmap of which inodes are in bad blocks.	(inode_bb_map)
+ * 	- A bitmap of which inodes are imagic inodes.	(inode_imagic_map)
  */
 
 #include "e2fsck.h"
@@ -117,6 +118,8 @@
 		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
 			continue;
 		if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
+		    (ctx->inode_imagic_map &&
+		     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
 		    (ctx->inode_bb_map &&
 		     ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
 			continue;
@@ -151,6 +154,7 @@
 	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
 	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
 	ext2fs_free_inode_bitmap(ctx->inode_bb_map);
+	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
 	ctx->inode_bb_map = 0;
 #ifdef RESOURCE_TRACK
 	if (ctx->options & E2F_OPT_TIME2) {
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index e7a0dc6..3a54926 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -693,6 +693,16 @@
 	  "@i %i (%Q) is an @I socket.\n",
 	  PROMPT_CLEAR, 0 },
 
+	/* Directory filetype not set */
+	{ PR_2_SET_FILETYPE,
+	  "Setting filetype for @E to %N.\n",
+	  PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
+
+	/* Directory filetype incorrect */
+	{ PR_2_BAD_FILETYPE,
+	  "@E has an incorrect filetype (was %dt, should be %N)\n",
+	  PROMPT_FIX, 0 },
+
 	/* Pass 3 errors */
 
 	/* Pass 3: Checking directory connectivity */
@@ -1038,7 +1048,9 @@
 		printf("Unhandled error code (%d)!\n", code);
 		return 0;
 	}
-	def_yn = (ptr->flags & PR_NO_DEFAULT) ? 0 : 1;
+	def_yn = 1;
+	if ((ptr->flags & PR_NO_DEFAULT) || (ctx->options & E2F_OPT_NO))
+		def_yn= 0;
 
 	/*
 	 * Do special latch processing.  This is where we ask the
@@ -1060,6 +1072,9 @@
 	if ((ptr->flags & PR_PREEN_NOMSG) &&
 	    (ctx->options & E2F_OPT_PREEN))
 		suppress++;
+	if ((ptr->flags & PR_NO_NOMSG) &&
+	    (ctx->options & E2F_OPT_NO))
+		suppress++;
 	if (!suppress) {
 		message = ptr->e2p_description;
 		if (ctx->options & E2F_OPT_PREEN) {
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 1e21440..ddbc717 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -411,6 +411,12 @@
 /* Illegal socket */
 #define PR_2_BAD_SOCKET		0x020026
 
+/* Directory filetype not set */
+#define PR_2_SET_FILETYPE	0x020027
+
+/* Directory filetype incorrect */
+#define PR_2_BAD_FILETYPE	0x020028
+
 /*
  * Pass 3 errors
  */
diff --git a/e2fsck/problemP.h b/e2fsck/problemP.h
index ceb7bd3..7c75fc6 100644
--- a/e2fsck/problemP.h
+++ b/e2fsck/problemP.h
@@ -33,4 +33,5 @@
 				/* ask another */
 #define PR_PREEN_NOMSG	0x0200	/* Don't print a message if we're preening */
 #define PR_NOCOLLATE	0x0400	/* Don't collate answers for this latch */
+#define PR_NO_NOMSG	0x0800	/* Don't print a message if e2fsck -n */
 
diff --git a/include/nonunix/asm/types.h b/include/nonunix/asm/types.h
new file mode 100644
index 0000000..fccb426
--- /dev/null
+++ b/include/nonunix/asm/types.h
@@ -0,0 +1 @@
+#include "../linux/types.h"
\ No newline at end of file
diff --git a/include/nonunix/config.h b/include/nonunix/config.h
new file mode 100644
index 0000000..cc8ac19
--- /dev/null
+++ b/include/nonunix/config.h
@@ -0,0 +1,18 @@
+
+#define _INO_T_DEFINED 1
+
+#define HAVE_STDLIB_H  1
+#define HAVE_STRING_H  1
+#define HAVE_GETOPT_H  1
+#define HAVE_ERRNO_H   1
+#define HAVE_SETJMP_H  1
+
+#define HAVE_STRCASECMP 1
+#define HAVE_CONIO_H   1
+
+#define HAVE_EXT2_INODE_VERSION 1
+
+#define inline __forceinline
+
+#define _CTYPE_DISABLE_MACROS
+
diff --git a/include/nonunix/dirent.h b/include/nonunix/dirent.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/dirent.h
diff --git a/include/nonunix/getopt.h b/include/nonunix/getopt.h
new file mode 100644
index 0000000..33ad46c
--- /dev/null
+++ b/include/nonunix/getopt.h
@@ -0,0 +1,135 @@
+/* Declarations for getopt.
+   Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifndef GETOPT_VARIABLE
+#define GETOPT_VARIABLE
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern GETOPT_VARIABLE char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern GETOPT_VARIABLE int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern GETOPT_VARIABLE int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern GETOPT_VARIABLE int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define	no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+		        const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+			     const char *shortopts,
+		             const struct option *longopts, int *longind,
+			     int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/include/nonunix/grp.h b/include/nonunix/grp.h
new file mode 100644
index 0000000..4130cb7
--- /dev/null
+++ b/include/nonunix/grp.h
@@ -0,0 +1,17 @@
+
+#pragma once
+
+typedef unsigned short __gid_t;
+__inline __gid_t getgid(void){return 0;}
+__inline struct group * getgrnam(char* g){return 0;}
+
+struct group
+  {
+    char *gr_name;	
+    char *gr_passwd;
+    __gid_t gr_gid;	
+    char **gr_mem;	
+  };
+
+#define getgrgid(i) NULL
+
diff --git a/include/nonunix/linux/types.h b/include/nonunix/linux/types.h
new file mode 100644
index 0000000..8e5bc90
--- /dev/null
+++ b/include/nonunix/linux/types.h
@@ -0,0 +1,28 @@
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#ifndef _MSC_VER
+#error  _MSC_VER not defined
+#endif
+
+
+typedef unsigned __int8 __u8;
+typedef signed __int8 __s8;
+
+typedef signed   __int64 __s64;
+typedef unsigned __int64 __u64;
+
+typedef	signed   __int16	__s16;
+typedef	unsigned __int16	__u16;
+
+typedef	signed   __int32	__s32;
+typedef	unsigned __int32	__u32;
+
+typedef	signed   __int64	__s64;
+typedef	unsigned __int64	__u64;
+
+
+typedef __u32 ino_t;
+
+
+#endif /* LINUX_TYPES_H */
diff --git a/include/nonunix/pwd.h b/include/nonunix/pwd.h
new file mode 100644
index 0000000..67e05ea
--- /dev/null
+++ b/include/nonunix/pwd.h
@@ -0,0 +1,22 @@
+
+#pragma once
+
+typedef unsigned short __uid_t;
+__inline __uid_t getuid(void){return 0;}
+__inline int geteuid(void){return 1;}
+__inline struct passwd* getpwnam (char* g){return 0;}
+
+
+struct passwd
+{
+  char *pw_name;		
+  char *pw_passwd;		
+  __uid_t pw_uid;		
+  __gid_t pw_gid;		
+  char *pw_gecos;		
+  char *pw_dir;			
+  char *pw_shell;		
+};
+
+#define getpwuid(i) NULL
+
diff --git a/include/nonunix/sys/file.h b/include/nonunix/sys/file.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/sys/file.h
diff --git a/include/nonunix/sys/ioctl.h b/include/nonunix/sys/ioctl.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/sys/ioctl.h
diff --git a/include/nonunix/sys/param.h b/include/nonunix/sys/param.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/sys/param.h
diff --git a/include/nonunix/sys/resource.h b/include/nonunix/sys/resource.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/sys/resource.h
diff --git a/include/nonunix/sys/socket.h b/include/nonunix/sys/socket.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/sys/socket.h
diff --git a/include/nonunix/sys/time.h b/include/nonunix/sys/time.h
new file mode 100644
index 0000000..91fd187
--- /dev/null
+++ b/include/nonunix/sys/time.h
@@ -0,0 +1 @@
+#include <time.h>
diff --git a/include/nonunix/sys/wait.h b/include/nonunix/sys/wait.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/sys/wait.h
diff --git a/include/nonunix/termios.h b/include/nonunix/termios.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/nonunix/termios.h
diff --git a/include/nonunix/unistd.h b/include/nonunix/unistd.h
new file mode 100644
index 0000000..5053587
--- /dev/null
+++ b/include/nonunix/unistd.h
@@ -0,0 +1,49 @@
+
+
+#pragma once
+
+#include <stdlib.h>
+#include <process.h>
+#include <io.h>
+
+#define EOPNOTSUPP  95
+
+#define O_NONBLOCK  0
+#define O_RDONLY    _O_RDONLY
+#define O_RDWR      _O_RDWR
+
+#define popen   _popen
+#define pclose  _pclose
+#define sleep   _sleep
+#define stat    _stat
+#define open    _open
+#define close   _close
+#define fstat   _fstat
+#define read    _read
+#define write   _write
+#define off_t   _off_t
+#define lseek   _lseek
+#define putenv  _putenv
+#define getpid  _getpid
+#define utimbuf _utimbuf
+#define sys_nerr _sys_nerr
+#define sys_errlist _sys_errlist
+#define isatty _isatty
+#define getch _getch
+
+#include <grp.h>
+#include <pwd.h>
+
+
+// no-oped sync
+__inline void sync(void){};
+
+
+
+#define gettimeofday(p, v) ((p)->tv_sec = (p)->tv_usec = 0)
+
+
+#define strcasecmp _stricmp
+
+
+
diff --git a/include/nonunix/utime.h b/include/nonunix/utime.h
new file mode 100644
index 0000000..8285f38
--- /dev/null
+++ b/include/nonunix/utime.h
@@ -0,0 +1 @@
+#include <sys/utime.h>
diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog
index 275c6b0..5496f16 100644
--- a/lib/ext2fs/ChangeLog
+++ b/lib/ext2fs/ChangeLog
@@ -1,3 +1,7 @@
+1999-09-24    <tytso@valinux.com>
+
+	* nt_io.c: New file which supports I/O under Windows NT.
+
 1999-09-07    <tytso@valinux.com>
 
 	* ext2fs.h: Add new fields for journalling and define new
diff --git a/lib/ext2fs/nt_io.c b/lib/ext2fs/nt_io.c
new file mode 100644
index 0000000..4b3ce47
--- /dev/null
+++ b/lib/ext2fs/nt_io.c
@@ -0,0 +1,1514 @@
+/*
+/*
+ * nt_io.c --- This is the Nt I/O interface to the I/O manager.
+ *
+ * Implements a one-block write-through cache.
+ *
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ * Copyright (C) 1998 Andrey Shedel
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+//
+// I need some warnings to disable...
+//
+
+
+#pragma warning(disable:4514) // unreferenced inline function has been removed
+#pragma warning(push,4)
+
+#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union)
+#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int
+#pragma warning(disable:4115) // named type definition in parentheses
+
+#include <ntddk.h>
+#include <ntdddisk.h>
+#include <ntstatus.h>
+
+#pragma warning(pop)
+
+
+//
+// Some native APIs.
+//
+
+NTSYSAPI
+ULONG
+NTAPI
+RtlNtStatusToDosError(
+    IN NTSTATUS Status
+   );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtClose(
+    IN HANDLE Handle
+   );
+
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtOpenFile(
+    OUT PHANDLE FileHandle,
+    IN ACCESS_MASK DesiredAccess,
+    IN POBJECT_ATTRIBUTES ObjectAttributes,
+    OUT PIO_STATUS_BLOCK IoStatusBlock,
+    IN ULONG ShareAccess,
+    IN ULONG OpenOptions
+    );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtFlushBuffersFile(
+    IN HANDLE FileHandle,
+    OUT PIO_STATUS_BLOCK IoStatusBlock
+   );
+
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtReadFile(
+    IN HANDLE FileHandle,
+    IN HANDLE Event OPTIONAL,
+    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+    IN PVOID ApcContext OPTIONAL,
+    OUT PIO_STATUS_BLOCK IoStatusBlock,
+    OUT PVOID Buffer,
+    IN ULONG Length,
+    IN PLARGE_INTEGER ByteOffset OPTIONAL,
+    IN PULONG Key OPTIONAL
+    );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtWriteFile(
+    IN HANDLE FileHandle,
+    IN HANDLE Event OPTIONAL,
+    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+    IN PVOID ApcContext OPTIONAL,
+    OUT PIO_STATUS_BLOCK IoStatusBlock,
+    IN PVOID Buffer,
+    IN ULONG Length,
+    IN PLARGE_INTEGER ByteOffset OPTIONAL,
+    IN PULONG Key OPTIONAL
+    );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtDeviceIoControlFile(
+    IN HANDLE FileHandle,
+    IN HANDLE Event OPTIONAL,
+    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+    IN PVOID ApcContext OPTIONAL,
+    OUT PIO_STATUS_BLOCK IoStatusBlock,
+    IN ULONG IoControlCode,
+    IN PVOID InputBuffer OPTIONAL,
+    IN ULONG InputBufferLength,
+    OUT PVOID OutputBuffer OPTIONAL,
+    IN ULONG OutputBufferLength
+    );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtFsControlFile(
+    IN HANDLE FileHandle,
+    IN HANDLE Event OPTIONAL,
+    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+    IN PVOID ApcContext OPTIONAL,
+    OUT PIO_STATUS_BLOCK IoStatusBlock,
+    IN ULONG IoControlCode,
+    IN PVOID InputBuffer OPTIONAL,
+    IN ULONG InputBufferLength,
+    OUT PVOID OutputBuffer OPTIONAL,
+    IN ULONG OutputBufferLength
+    );
+
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtDelayExecution(
+    IN BOOLEAN Alertable,
+    IN PLARGE_INTEGER Interval
+    );
+
+
+#define FSCTL_LOCK_VOLUME               CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define FSCTL_UNLOCK_VOLUME             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define FSCTL_DISMOUNT_VOLUME           CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define FSCTL_IS_VOLUME_MOUNTED         CTL_CODE(FILE_DEVICE_FILE_SYSTEM,10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+//
+// useful macros
+//
+
+#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
+
+
+//
+// Include Win32 error codes.
+//
+
+#include <winerror.h>
+
+//
+// standard stuff
+//
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include <linux/types.h>
+#include <linux/ext2_fs.h>
+#include <errno.h>
+
+#include "et/com_err.h"
+#include "ext2fs/ext2fs.h"
+#include "ext2fs/ext2_err.h"
+
+
+
+
+//
+// For checking structure magic numbers...
+//
+
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+	  if ((struct)->magic != (code)) return (code)
+
+#define EXT2_ET_MAGIC_NT_IO_CHANNEL  0x10ed
+
+
+//
+// Private data block
+//
+
+typedef struct _NT_PRIVATE_DATA {
+	int	   magic;
+	HANDLE Handle;
+	int	   Flags;
+	PCHAR  Buffer;
+	__u32  BufferBlockNumber;
+	ULONG  BufferSize;
+	BOOLEAN OpenedReadonly;
+	BOOLEAN Written;
+}NT_PRIVATE_DATA, *PNT_PRIVATE_DATA;
+
+
+
+//
+// Standard interface prototypes
+//
+
+static errcode_t nt_open(const char *name, int flags, io_channel *channel);
+static errcode_t nt_close(io_channel channel);
+static errcode_t nt_set_blksize(io_channel channel, int blksize);
+static errcode_t nt_read_blk(io_channel channel, unsigned long block,
+			       int count, void *data);
+static errcode_t nt_write_blk(io_channel channel, unsigned long block,
+				int count, const void *data);
+static errcode_t nt_flush(io_channel channel);
+
+static struct struct_io_manager struct_nt_manager = {
+	EXT2_ET_MAGIC_IO_MANAGER,
+	"NT I/O Manager",
+	nt_open,
+	nt_close,
+	nt_set_blksize,
+	nt_read_blk,
+	nt_write_blk,
+	nt_flush
+};
+
+
+
+//
+// function to get API
+//
+
+io_manager nt_io_manager()
+{
+	return &struct_nt_manager;
+}
+
+
+
+
+
+//
+// This is a code to convert Win32 errors to unix errno
+//
+
+typedef struct {
+	ULONG WinError;
+	int errnocode;
+}ERROR_ENTRY;
+
+static ERROR_ENTRY ErrorTable[] = {
+        {  ERROR_INVALID_FUNCTION,       EINVAL    },
+        {  ERROR_FILE_NOT_FOUND,         ENOENT    },
+        {  ERROR_PATH_NOT_FOUND,         ENOENT    },
+        {  ERROR_TOO_MANY_OPEN_FILES,    EMFILE    },
+        {  ERROR_ACCESS_DENIED,          EACCES    },
+        {  ERROR_INVALID_HANDLE,         EBADF     },
+        {  ERROR_ARENA_TRASHED,          ENOMEM    },
+        {  ERROR_NOT_ENOUGH_MEMORY,      ENOMEM    },
+        {  ERROR_INVALID_BLOCK,          ENOMEM    },
+        {  ERROR_BAD_ENVIRONMENT,        E2BIG     },
+        {  ERROR_BAD_FORMAT,             ENOEXEC   },
+        {  ERROR_INVALID_ACCESS,         EINVAL    },
+        {  ERROR_INVALID_DATA,           EINVAL    },
+        {  ERROR_INVALID_DRIVE,          ENOENT    },
+        {  ERROR_CURRENT_DIRECTORY,      EACCES    },
+        {  ERROR_NOT_SAME_DEVICE,        EXDEV     },
+        {  ERROR_NO_MORE_FILES,          ENOENT    },
+        {  ERROR_LOCK_VIOLATION,         EACCES    },
+        {  ERROR_BAD_NETPATH,            ENOENT    },
+        {  ERROR_NETWORK_ACCESS_DENIED,  EACCES    },
+        {  ERROR_BAD_NET_NAME,           ENOENT    },
+        {  ERROR_FILE_EXISTS,            EEXIST    },
+        {  ERROR_CANNOT_MAKE,            EACCES    },
+        {  ERROR_FAIL_I24,               EACCES    },
+        {  ERROR_INVALID_PARAMETER,      EINVAL    },
+        {  ERROR_NO_PROC_SLOTS,          EAGAIN    },
+        {  ERROR_DRIVE_LOCKED,           EACCES    },
+        {  ERROR_BROKEN_PIPE,            EPIPE     },
+        {  ERROR_DISK_FULL,              ENOSPC    },
+        {  ERROR_INVALID_TARGET_HANDLE,  EBADF     },
+        {  ERROR_INVALID_HANDLE,         EINVAL    },
+        {  ERROR_WAIT_NO_CHILDREN,       ECHILD    },
+        {  ERROR_CHILD_NOT_COMPLETE,     ECHILD    },
+        {  ERROR_DIRECT_ACCESS_HANDLE,   EBADF     },
+        {  ERROR_NEGATIVE_SEEK,          EINVAL    },
+        {  ERROR_SEEK_ON_DEVICE,         EACCES    },
+        {  ERROR_DIR_NOT_EMPTY,          ENOTEMPTY },
+        {  ERROR_NOT_LOCKED,             EACCES    },
+        {  ERROR_BAD_PATHNAME,           ENOENT    },
+        {  ERROR_MAX_THRDS_REACHED,      EAGAIN    },
+        {  ERROR_LOCK_FAILED,            EACCES    },
+        {  ERROR_ALREADY_EXISTS,         EEXIST    },
+        {  ERROR_FILENAME_EXCED_RANGE,   ENOENT    },
+        {  ERROR_NESTING_NOT_ALLOWED,    EAGAIN    },
+        {  ERROR_NOT_ENOUGH_QUOTA,       ENOMEM    }
+};
+
+
+
+
+static
+unsigned
+_MapDosError (
+    IN ULONG WinError
+   )
+{
+	int i;
+
+	//
+	// Lookup
+	//
+
+	for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i)
+	{
+		if (WinError == ErrorTable[i].WinError)
+		{
+			return ErrorTable[i].errnocode;
+		}
+	}
+
+	//
+	// not in table. Check ranges
+	//
+
+	if ((WinError >= ERROR_WRITE_PROTECT) &&
+		(WinError <= ERROR_SHARING_BUFFER_EXCEEDED))
+	{
+		return EACCES;
+	}
+	else if ((WinError >= ERROR_INVALID_STARTING_CODESEG) &&
+			 (WinError <= ERROR_INFLOOP_IN_RELOC_CHAIN))
+	{
+		return ENOEXEC;
+	}
+	else
+	{
+		return EINVAL;
+	}
+}
+
+
+
+
+
+
+
+//
+// Function to map NT status to dos error.
+//
+
+static
+__inline
+unsigned
+_MapNtStatus(
+    IN NTSTATUS Status
+   )
+{
+	return _MapDosError(RtlNtStatusToDosError(Status));
+}
+
+
+
+
+
+//
+// Helper functions to make things easyer
+//
+
+static
+NTSTATUS
+_OpenNtName(
+    IN PCSTR Name,
+    IN BOOLEAN Readonly,
+    OUT PHANDLE Handle,
+    OUT PBOOLEAN OpenedReadonly OPTIONAL
+   )
+{
+	UNICODE_STRING UnicodeString;
+	ANSI_STRING    AnsiString;
+	WCHAR Buffer[512];
+	NTSTATUS Status;
+	OBJECT_ATTRIBUTES ObjectAttributes;
+	IO_STATUS_BLOCK IoStatusBlock;
+
+	//
+	// Make Unicode name from inlut string
+	//
+
+	UnicodeString.Buffer = &Buffer[0];
+	UnicodeString.Length = 0;
+	UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!!
+
+	RtlInitAnsiString(&AnsiString, Name);
+
+	Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
+
+	if(!NT_SUCCESS(Status))
+	{
+		return Status; // Unpappable character?
+	}
+
+	//
+	// Initialize object
+	//
+
+	InitializeObjectAttributes(&ObjectAttributes,
+							   &UnicodeString,
+							   OBJ_CASE_INSENSITIVE,
+							   NULL,
+							   NULL );
+
+	//
+	// Try to open it in initial mode
+	//
+
+	if(ARGUMENT_PRESENT(OpenedReadonly))
+	{
+		*OpenedReadonly = Readonly;
+	}
+
+
+	Status = NtOpenFile(Handle,
+						SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA),
+						&ObjectAttributes,
+						&IoStatusBlock,
+						FILE_SHARE_WRITE | FILE_SHARE_READ,
+						FILE_SYNCHRONOUS_IO_ALERT);
+
+	if(!NT_SUCCESS(Status))
+	{
+		//
+		// Maybe was just mounted? wait 0.5 sec and retry.
+		//
+
+		LARGE_INTEGER Interval;
+		Interval.QuadPart = -5000000; // 0.5 sec. from now
+
+		NtDelayExecution(FALSE, &Interval);
+
+		Status = NtOpenFile(Handle,
+							SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA),
+							&ObjectAttributes,
+							&IoStatusBlock,
+							FILE_SHARE_WRITE | FILE_SHARE_READ,
+							FILE_SYNCHRONOUS_IO_ALERT);
+
+		//
+		// Try to satisfy mode
+		//
+
+		if((STATUS_ACCESS_DENIED == Status) && !Readonly)
+		{
+			if(ARGUMENT_PRESENT(OpenedReadonly))
+			{
+				*OpenedReadonly = TRUE;
+			}
+
+			Status = NtOpenFile(Handle,
+							SYNCHRONIZE | FILE_READ_DATA,
+							&ObjectAttributes,
+							&IoStatusBlock,
+							FILE_SHARE_WRITE | FILE_SHARE_READ,
+							FILE_SYNCHRONOUS_IO_ALERT);
+		}
+	}
+
+
+
+	//
+	// done
+	//
+
+	return Status;
+}
+
+
+static
+NTSTATUS
+_OpenDriveLetter(
+    IN CHAR Letter,
+    IN BOOLEAN ReadOnly,
+    OUT PHANDLE Handle,
+    OUT PBOOLEAN OpenedReadonly OPTIONAL
+   )
+{
+	CHAR Buffer[100];
+
+	sprintf(Buffer, "\\DosDevices\\%c:", Letter);
+
+	return _OpenNtName(Buffer, ReadOnly, Handle, OpenedReadonly);
+}
+
+
+//
+// Flush device
+//
+
+static
+__inline
+NTSTATUS
+_FlushDrive(
+		IN HANDLE Handle
+		)
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	return NtFlushBuffersFile(Handle, &IoStatusBlock);
+}
+
+
+//
+// lock drive
+//
+
+static
+__inline
+NTSTATUS
+_LockDrive(
+		IN HANDLE Handle
+		)
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_LOCK_VOLUME, 0, 0, 0, 0);
+}
+
+
+//
+// unlock drive
+//
+
+static
+__inline
+NTSTATUS
+_UnlockDrive(
+	IN HANDLE Handle
+	)
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0);
+}
+
+static
+__inline
+NTSTATUS
+_DismountDrive(
+	IN HANDLE Handle
+	)
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0);
+}
+
+
+//
+// is mounted
+//
+
+static
+__inline
+BOOLEAN
+_IsMounted(
+	IN HANDLE Handle
+	)
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	NTSTATUS Status;
+	Status = NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0);
+	return (BOOLEAN)(STATUS_SUCCESS == Status);
+}
+
+
+static
+__inline
+NTSTATUS
+_CloseDisk(
+		IN HANDLE Handle
+		)
+{
+	return NtClose(Handle);
+}
+
+
+
+
+//
+// Make NT name from any recognized name
+//
+
+static
+PCSTR
+_NormalizeDeviceName(
+    IN PCSTR Device,
+    IN PSTR NormalizedDeviceNameBuffer
+   )
+{
+	int PartitionNumber = -1;
+	UCHAR DiskNumber;
+	PSTR p;
+
+
+	//
+	// Do not try to parse NT name
+	//
+
+	if('\\' == *Device)
+		return Device;
+
+
+
+	//
+	// Strip leading '/dev/' if any
+	//
+
+	if(('/' == *(Device)) &&
+		('d' == *(Device + 1)) &&
+		('e' == *(Device + 2)) &&
+		('v' == *(Device + 3)) &&
+		('/' == *(Device + 4)))
+	{
+		Device += 5;
+	}
+
+	if('\0' == *Device)
+	{
+		return NULL;
+	}
+
+
+	//
+	// forms: hda[n], fd[n]
+	//
+
+	if('d' != *(Device + 1))
+	{
+		return NULL;
+	}
+
+	if('h' == *Device)
+	{
+		if((*(Device + 2) < 'a') || (*(Device + 2) > ('a' + 9)) ||
+		   ((*(Device + 3) != '\0') &&
+			((*(Device + 4) != '\0') ||
+			 ((*(Device + 3) < '0') || (*(Device + 3) > '9'))
+			)
+		   )
+		  )
+		{
+			return NULL;
+		}
+
+		DiskNumber = (UCHAR)(*(Device + 2) - 'a');
+
+		if(*(Device + 3) != '\0')
+		{
+			PartitionNumber = (*(Device + 3) - '0');
+		}
+
+	}
+	else if('f' == *Device)
+	{
+		//
+		// 3-d letted should be a digit.
+		//
+
+		if((*(Device + 3) != '\0') ||
+		   (*(Device + 2) < '0') || (*(Device + 2) > '9'))
+		{
+			return NULL;
+		}
+
+		DiskNumber = (UCHAR)(*(Device + 2) - '0');
+
+	}
+	else
+	{
+		//
+		// invalid prefix
+		//
+
+		return NULL;
+	}
+
+
+
+	//
+	// Prefix
+	//
+
+	strcpy(NormalizedDeviceNameBuffer, "\\Device\\");
+
+	//
+	// Media name
+	//
+
+	switch(*Device)
+	{
+
+	case 'f':
+		strcat(NormalizedDeviceNameBuffer, "Floppy0");
+		break;
+
+	case 'h':
+		strcat(NormalizedDeviceNameBuffer, "Harddisk0");
+		break;
+	}
+
+
+	p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1;
+	*p = (CHAR)(*p + DiskNumber);
+
+
+	//
+	// Partition nr.
+	//
+
+	if(PartitionNumber >= 0)
+	{
+		strcat(NormalizedDeviceNameBuffer, "\\Partition0");
+
+		p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1;
+		*p = (CHAR)(*p + PartitionNumber);
+	}
+
+
+	return NormalizedDeviceNameBuffer;
+}
+
+
+
+
+static
+VOID
+_GetDeviceSize(
+    IN HANDLE h,
+    OUT unsigned __int64 *FsSize
+   )
+{
+	PARTITION_INFORMATION pi;
+	DISK_GEOMETRY gi;
+	NTSTATUS Status;
+	IO_STATUS_BLOCK IoStatusBlock;
+
+	//
+	// Zero it
+	//
+
+	*FsSize = 0;
+
+	//
+	// Call driver
+	//
+
+	RtlZeroMemory(&pi, sizeof(PARTITION_INFORMATION));
+
+	Status = NtDeviceIoControlFile(
+		h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_PARTITION_INFO,
+		&pi, sizeof(PARTITION_INFORMATION),
+		&pi, sizeof(PARTITION_INFORMATION));
+
+
+	if(NT_SUCCESS(Status))
+	{
+		*FsSize = pi.PartitionLength.QuadPart;
+	}
+	else if(STATUS_INVALID_DEVICE_REQUEST == Status)
+	{
+		//
+		// No partitions: get device info.
+		//
+
+		RtlZeroMemory(&gi, sizeof(DISK_GEOMETRY));
+
+		Status = NtDeviceIoControlFile(
+				h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+				&gi, sizeof(DISK_GEOMETRY),
+				&gi, sizeof(DISK_GEOMETRY));
+
+
+		if(NT_SUCCESS(Status))
+		{
+			*FsSize =
+				gi.BytesPerSector *
+				gi.SectorsPerTrack *
+				gi.TracksPerCylinder *
+				gi.Cylinders.QuadPart;
+		}
+
+	}
+}
+
+
+
+//
+// Open device by name.
+//
+
+static
+BOOLEAN
+_Ext2OpenDevice(
+    IN PCSTR Name,
+    IN BOOLEAN ReadOnly,
+    OUT PHANDLE Handle,
+    OUT PBOOLEAN OpenedReadonly OPTIONAL,
+    OUT unsigned *Errno OPTIONAL
+   )
+{
+	CHAR NormalizedDeviceName[512];
+	NTSTATUS Status;
+
+	if(NULL == Name)
+	{
+		//
+		// Set not found
+		//
+
+		if(ARGUMENT_PRESENT(Errno))
+			*Errno = ENOENT;
+
+		return FALSE;
+	}
+
+
+	if((((*Name) | 0x20) >= 'a') && (((*Name) | 0x20) <= 'z') &&
+		(':' == *(Name + 1)) && ('\0' == *(Name + 2)))
+	{
+		Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly);
+	}
+	else
+	{
+		//
+		// Make name
+		//
+
+		Name = _NormalizeDeviceName(Name, NormalizedDeviceName);
+
+		if(NULL == Name)
+		{
+			//
+			// Set not found
+			//
+
+			if(ARGUMENT_PRESENT(Errno))
+				*Errno = ENOENT;
+
+			return FALSE;
+		}
+
+		//
+		// Try to open it
+		//
+
+		Status = _OpenNtName(Name, ReadOnly, Handle, OpenedReadonly);
+	}
+
+
+	if(!NT_SUCCESS(Status))
+	{
+		if(ARGUMENT_PRESENT(Errno))
+			*Errno = _MapNtStatus(Status);
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+//
+// Raw block io. Sets dos errno
+//
+
+static
+BOOLEAN
+_BlockIo(
+    IN HANDLE Handle,
+    IN LARGE_INTEGER Offset,
+    IN ULONG Bytes,
+    IN OUT PCHAR Buffer,
+    IN BOOLEAN Read,
+    OUT unsigned* Errno
+   )
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	NTSTATUS Status;
+
+	//
+	// Should be aligned
+	//
+
+	ASSERT(0 == (Bytes % 512));
+	ASSERT(0 == (Offset.LowPart % 512));
+
+
+	//
+	// perform io
+	//
+
+	if(Read)
+	{
+		Status = NtReadFile(Handle, NULL, NULL, NULL,
+			&IoStatusBlock, Buffer, Bytes, &Offset, NULL);
+	}
+	else
+	{
+		Status = NtWriteFile(Handle, NULL, NULL, NULL,
+			&IoStatusBlock, Buffer, Bytes, &Offset, NULL);
+	}
+
+
+	//
+	// translate error
+	//
+
+	if(NT_SUCCESS(Status))
+	{
+		*Errno = 0;
+		return TRUE;
+	}
+
+	*Errno = _MapNtStatus(Status);
+
+	return FALSE;
+}
+
+
+
+__inline
+BOOLEAN
+_RawWrite(
+    IN HANDLE Handle,
+    IN LARGE_INTEGER Offset,
+    IN ULONG Bytes,
+    OUT const CHAR* Buffer,
+    OUT unsigned* Errno
+   )
+{
+	return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno);
+}
+
+__inline
+BOOLEAN
+_RawRead(
+    IN HANDLE Handle,
+    IN LARGE_INTEGER Offset,
+    IN ULONG Bytes,
+    IN PCHAR Buffer,
+    OUT unsigned* Errno
+   )
+{
+	return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno);
+}
+
+
+
+__inline
+BOOLEAN
+_SetPartType(
+    IN HANDLE Handle,
+    IN UCHAR Type
+   )
+{
+	IO_STATUS_BLOCK IoStatusBlock;
+	return STATUS_SUCCESS == NtDeviceIoControlFile(
+												   Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_PARTITION_INFO,
+												   &Type, sizeof(Type),
+												   NULL, 0);
+}
+
+
+
+//--------------------- interface part
+
+//
+// Interface functions.
+// Is_mounted is set to 1 if the device is mounted, 0 otherwise
+//
+
+errcode_t
+ext2fs_check_if_mounted(const char *file, int *mount_flags)
+{
+	HANDLE h;
+	BOOLEAN Readonly;
+
+	*mount_flags = 0;
+
+	if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL))
+	{
+		return 0;
+	}
+
+
+	__try{
+		*mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0;
+	}
+	__finally{
+		_CloseDisk(h);
+	}
+
+	return 0;
+}
+
+
+
+//
+// Returns the number of blocks in a partition
+//
+
+static __int64 FsSize = 0;
+static char knowndevice[1024] = "";
+
+
+errcode_t
+ext2fs_get_device_size(const char *file, int blocksize,
+				 blk_t *retblocks)
+{
+	HANDLE h;
+	BOOLEAN Readonly;
+
+	if((0 == FsSize) || (0 != strcmp(knowndevice, file)))
+	{
+
+		if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL))
+		{
+			return 0;
+		}
+
+
+		__try{
+
+			//
+			// Get size
+			//
+
+			_GetDeviceSize(h, &FsSize);
+			strcpy(knowndevice, file);
+		}
+		__finally{
+			_CloseDisk(h);
+		}
+
+	}
+
+	*retblocks = (blk_t)(unsigned __int64)(FsSize / blocksize);
+	UNREFERENCED_PARAMETER(file);
+	return 0;
+}
+
+
+
+
+
+
+//
+// Table elements
+//
+
+
+static
+errcode_t
+nt_open(const char *name, int flags, io_channel *channel)
+{
+	io_channel      io = NULL;
+	PNT_PRIVATE_DATA NtData = NULL;
+	errcode_t Errno = 0;
+
+	//
+	// Check name
+	//
+
+	if (NULL == name)
+	{
+		return EXT2_ET_BAD_DEVICE_NAME;
+	}
+
+	__try{
+
+		//
+		// Allocate channel handle
+		//
+
+		io = (io_channel) malloc(sizeof(struct struct_io_channel));
+
+		if (NULL == io)
+		{
+			Errno = ENOMEM;
+			__leave;
+		}
+
+		RtlZeroMemory(io, sizeof(struct struct_io_channel));
+		io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+
+		NtData = (PNT_PRIVATE_DATA)malloc(sizeof(NT_PRIVATE_DATA));
+
+		if (NULL == NtData)
+		{
+			Errno = ENOMEM;
+			__leave;
+		}
+
+
+		io->manager = nt_io_manager();
+		io->name = malloc(strlen(name) + 1);
+		if (NULL == io->name)
+		{
+			Errno = ENOMEM;
+			__leave;
+		}
+
+		strcpy(io->name, name);
+		io->private_data = NtData;
+		io->block_size = 1024;
+		io->read_error = 0;
+		io->write_error = 0;
+		io->refcount = 1;
+
+		//
+		// Initialize data
+		//
+
+		RtlZeroMemory(NtData, sizeof(NT_PRIVATE_DATA));
+
+		NtData->magic = EXT2_ET_MAGIC_NT_IO_CHANNEL;
+		NtData->BufferBlockNumber = 0xffffffff;
+		NtData->BufferSize = 1024;
+		NtData->Buffer = malloc(NtData->BufferSize);
+
+		if (NULL == NtData->Buffer)
+		{
+			Errno = ENOMEM;
+			__leave;
+		}
+
+		//
+		// Open it
+		//
+
+		if(!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &NtData->Handle, &NtData->OpenedReadonly, &Errno))
+		{
+			__leave;
+		}
+
+
+		//
+		// get size
+		//
+
+		_GetDeviceSize(NtData->Handle, &FsSize);
+		strcpy(knowndevice, name);
+
+
+		//
+		// Lock/dismount
+		//
+
+		if(!NT_SUCCESS(_LockDrive(NtData->Handle)) || !NT_SUCCESS(_DismountDrive(NtData->Handle)))
+		{
+			NtData->OpenedReadonly = TRUE;
+		}
+
+		//
+		// Done
+		//
+
+		*channel = io;
+
+
+	}
+	__finally{
+
+		if(0 != Errno)
+		{
+			//
+			// Cleanup
+			//
+
+			if (NULL != io)
+			{
+				if(NULL != io->name)
+				{
+					free(io->name);
+				}
+
+				free(io);
+			}
+
+			if (NULL != NtData)
+			{
+				if(NULL != NtData->Handle)
+				{
+					_UnlockDrive(NtData->Handle);
+					_CloseDisk(NtData->Handle);
+				}
+
+				if(NULL != NtData->Buffer)
+				{
+					free(NtData->Buffer);
+				}
+
+				free(NtData);
+			}
+		}
+	}
+
+	return Errno;
+}
+
+
+//
+// Close api
+//
+
+static
+errcode_t
+nt_close(io_channel channel)
+{
+	PNT_PRIVATE_DATA NtData = NULL;
+
+	if(NULL == channel)
+	{
+		return 0;
+	}
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	NtData = (PNT_PRIVATE_DATA) channel->private_data;
+	EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL);
+
+	if (--channel->refcount > 0)
+	{
+		return 0;
+	}
+
+	if(NULL != channel->name)
+	{
+		free(channel->name);
+	}
+
+
+	free(channel);
+
+	if (NULL != NtData)
+	{
+		if(NULL != NtData->Handle)
+		{
+			_DismountDrive(NtData->Handle);
+			_UnlockDrive(NtData->Handle);
+			_CloseDisk(NtData->Handle);
+		}
+
+		if(NULL != NtData->Buffer)
+		{
+			free(NtData->Buffer);
+		}
+
+		free(NtData);
+	}
+
+	return 0;
+}
+
+
+
+//
+// set block size
+//
+
+static
+errcode_t
+nt_set_blksize(io_channel channel, int blksize)
+{
+	PNT_PRIVATE_DATA NtData = NULL;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	NtData = (PNT_PRIVATE_DATA) channel->private_data;
+	EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL);
+
+	if (channel->block_size != blksize)
+	{
+		channel->block_size = blksize;
+
+		free(NtData->Buffer);
+		NtData->BufferBlockNumber = 0xffffffff;
+		NtData->BufferSize = channel->block_size;
+		ASSERT(0 == (NtData->BufferSize % 512));
+
+		NtData->Buffer = malloc(NtData->BufferSize);
+
+		if (NULL == NtData->Buffer)
+		{
+			return ENOMEM;
+		}
+
+	}
+
+	return 0;
+}
+
+
+//
+// read block
+//
+
+static
+errcode_t
+nt_read_blk(io_channel channel, unsigned long block,
+			       int count, void *buf)
+{
+	PVOID BufferToRead;
+	ULONG SizeToRead;
+	ULONG Size;
+	LARGE_INTEGER Offset;
+	PNT_PRIVATE_DATA NtData = NULL;
+	unsigned Errno = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	NtData = (PNT_PRIVATE_DATA) channel->private_data;
+	EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL);
+
+	//
+	// If it's in the cache, use it!
+	//
+
+	if ((1 == count) &&
+		(block == NtData->BufferBlockNumber) &&
+		(NtData->BufferBlockNumber != 0xffffffff))
+	{
+		memcpy(buf, NtData->Buffer, channel->block_size);
+		return 0;
+	}
+
+	Size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size);
+
+	Offset.QuadPart = block * channel->block_size;
+
+	//
+	// If not fit to the block
+	//
+
+	if(Size <= NtData->BufferSize)
+	{
+		//
+		// Update the cache
+		//
+
+		NtData->BufferBlockNumber = block;
+		BufferToRead = NtData->Buffer;
+		SizeToRead = NtData->BufferSize;
+	}
+	else
+	{
+		SizeToRead = Size;
+		BufferToRead = buf;
+		ASSERT(0 == (SizeToRead % channel->block_size));
+	}
+
+	if(!_RawRead(NtData->Handle, Offset, SizeToRead, BufferToRead, &Errno))
+	{
+
+		if (channel->read_error)
+		{
+			return (channel->read_error)(channel, block, count, buf,
+					       Size, 0, Errno);
+		}
+		else
+		{
+			return Errno;
+		}
+	}
+
+
+	if(BufferToRead != buf)
+	{
+		ASSERT(Size <= SizeToRead);
+		memcpy(buf, BufferToRead, Size);
+	}
+
+	return 0;
+}
+
+
+//
+// write block
+//
+
+static
+errcode_t
+nt_write_blk(io_channel channel, unsigned long block,
+				int count, const void *buf)
+{
+	ULONG SizeToWrite;
+	LARGE_INTEGER Offset;
+	PNT_PRIVATE_DATA NtData = NULL;
+	unsigned Errno = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	NtData = (PNT_PRIVATE_DATA) channel->private_data;
+	EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL);
+
+	if(NtData->OpenedReadonly)
+	{
+		return EACCES;
+	}
+
+	if (count == 1)
+	{
+		SizeToWrite = channel->block_size;
+	}
+	else
+	{
+		NtData->BufferBlockNumber = 0xffffffff;
+
+		if (count < 0)
+		{
+			SizeToWrite = (ULONG)(-count);
+		}
+		else
+		{
+			SizeToWrite = (ULONG)(count * channel->block_size);
+		}
+	}
+
+
+	ASSERT(0 == (SizeToWrite % 512));
+	Offset.QuadPart = block * channel->block_size;
+
+	if(!_RawWrite(NtData->Handle, Offset, SizeToWrite, buf, &Errno))
+	{
+		if (channel->write_error)
+		{
+			return (channel->write_error)(channel, block, count, buf,
+						SizeToWrite, 0, Errno);
+		}
+		else
+		{
+			return Errno;
+		}
+	}
+
+
+	//
+	// Stash a copy.
+	//
+
+	if(SizeToWrite >= NtData->BufferSize)
+	{
+		NtData->BufferBlockNumber = block;
+		memcpy(NtData->Buffer, buf, NtData->BufferSize);
+	}
+
+	NtData->Written = TRUE;
+
+	return 0;
+
+}
+
+
+
+//
+// Flush data buffers to disk.  Since we are currently using a
+// write-through cache, this is a no-op.
+//
+
+static
+errcode_t
+nt_flush(io_channel channel)
+{
+	PNT_PRIVATE_DATA NtData = NULL;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	NtData = (PNT_PRIVATE_DATA) channel->private_data;
+	EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL);
+
+	if(NtData->OpenedReadonly)
+	{
+		return 0; // EACCESS;
+	}
+
+
+	//
+	// Flush file buffers.
+	//
+
+	_FlushDrive(NtData->Handle);
+
+
+	//
+	// Test and correct partition type.
+	//
+
+	if(NtData->Written)
+	{
+		_SetPartType(NtData->Handle, 0x83);
+	}
+
+	return 0;
+}
+
+
diff --git a/lib/uuid/ChangeLog b/lib/uuid/ChangeLog
index a913d29..b5536e1 100644
--- a/lib/uuid/ChangeLog
+++ b/lib/uuid/ChangeLog
@@ -1,3 +1,7 @@
+1999-09-24    <tytso@valinux.com>
+
+	* gen_uuid_nt.c: New file which creates a UUID under Windows NT.
+
 1999-07-18  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
 	* Release of E2fsprogs 1.15
diff --git a/lib/uuid/gen_uuid_nt.c b/lib/uuid/gen_uuid_nt.c
new file mode 100644
index 0000000..56aeecb
--- /dev/null
+++ b/lib/uuid/gen_uuid_nt.c
@@ -0,0 +1,25 @@
+
+
+//
+// Use NT api to generate uuid
+//
+
+
+
+#include "uuidP.h"
+
+
+#pragma comment(lib, "ntdll.lib")
+
+unsigned long
+__stdcall
+NtAllocateUuids(
+   void* p1,  // 8 bytes
+   void* p2,  // 4 bytes
+   void* p3   // 4 bytes
+   );
+
+void uuid_generate(uuid_t out)
+{
+	NtAllocateUuids(out, ((char*)out)+8, ((char*)out)+12 );
+}