Whamcloud - gitweb
Many files:
authorTheodore Ts'o <tytso@mit.edu>
Thu, 21 Oct 1999 19:33:18 +0000 (19:33 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 21 Oct 1999 19:33:18 +0000 (19:33 +0000)
  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

31 files changed:
e2fsck/ChangeLog
e2fsck/e2fsck.c
e2fsck/e2fsck.h
e2fsck/message.c
e2fsck/pass1.c
e2fsck/pass2.c
e2fsck/pass4.c
e2fsck/problem.c
e2fsck/problem.h
e2fsck/problemP.h
include/nonunix/asm/types.h [new file with mode: 0644]
include/nonunix/config.h [new file with mode: 0644]
include/nonunix/dirent.h [new file with mode: 0644]
include/nonunix/getopt.h [new file with mode: 0644]
include/nonunix/grp.h [new file with mode: 0644]
include/nonunix/linux/types.h [new file with mode: 0644]
include/nonunix/pwd.h [new file with mode: 0644]
include/nonunix/sys/file.h [new file with mode: 0644]
include/nonunix/sys/ioctl.h [new file with mode: 0644]
include/nonunix/sys/param.h [new file with mode: 0644]
include/nonunix/sys/resource.h [new file with mode: 0644]
include/nonunix/sys/socket.h [new file with mode: 0644]
include/nonunix/sys/time.h [new file with mode: 0644]
include/nonunix/sys/wait.h [new file with mode: 0644]
include/nonunix/termios.h [new file with mode: 0644]
include/nonunix/unistd.h [new file with mode: 0644]
include/nonunix/utime.h [new file with mode: 0644]
lib/ext2fs/ChangeLog
lib/ext2fs/nt_io.c [new file with mode: 0644]
lib/uuid/ChangeLog
lib/uuid/gen_uuid_nt.c [new file with mode: 0644]

index 28960be..0fc1540 100644 (file)
@@ -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
index 3cfca69..3028c87 100644 (file)
@@ -50,6 +50,10 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                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 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                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
index 86b411c..83f0889 100644 (file)
@@ -143,6 +143,8 @@ struct e2fsck_struct {
        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 */
index 8bb11df..a129f86 100644 (file)
@@ -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 @@ static _INLINE_ void expand_dirent_expression(char ch,
        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);
index cebc82c..c7475f9 100644 (file)
  *
  *     - 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 check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 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 @@ void e2fsck_pass1(e2fsck_t ctx)
                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 @@ void e2fsck_pass1(e2fsck_t ctx)
                                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 @@ void e2fsck_pass1(e2fsck_t ctx)
                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 @@ static void alloc_bb_map(e2fsck_t ctx)
 }
 
 /*
+ * 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 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                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 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                        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;
index 37114e3..2eec914 100644 (file)
  *
  * 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 @@ void e2fsck_pass2(e2fsck_t ctx)
                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 @@ static int check_name(e2fsck_t ctx,
        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 @@ static int check_dir_block(ext2_filsys fs,
                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
index 264b1c7..92721bd 100644 (file)
@@ -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 @@ void e2fsck_pass4(e2fsck_t ctx)
                    (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 @@ void e2fsck_pass4(e2fsck_t ctx)
        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) {
index e7a0dc6..3a54926 100644 (file)
@@ -693,6 +693,16 @@ static const struct e2fsck_problem problem_table[] = {
          "@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 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
                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 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        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) {
index 1e21440..ddbc717 100644 (file)
@@ -411,6 +411,12 @@ struct problem_context {
 /* 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
  */
index ceb7bd3..7c75fc6 100644 (file)
@@ -33,4 +33,5 @@ struct latch_descr {
                                /* 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 (file)
index 0000000..fccb426
--- /dev/null
@@ -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 (file)
index 0000000..cc8ac19
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/include/nonunix/getopt.h b/include/nonunix/getopt.h
new file mode 100644 (file)
index 0000000..33ad46c
--- /dev/null
@@ -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 (file)
index 0000000..4130cb7
--- /dev/null
@@ -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 (file)
index 0000000..8e5bc90
--- /dev/null
@@ -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 (file)
index 0000000..67e05ea
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/include/nonunix/sys/ioctl.h b/include/nonunix/sys/ioctl.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/nonunix/sys/param.h b/include/nonunix/sys/param.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/nonunix/sys/resource.h b/include/nonunix/sys/resource.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/nonunix/sys/socket.h b/include/nonunix/sys/socket.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/nonunix/sys/time.h b/include/nonunix/sys/time.h
new file mode 100644 (file)
index 0000000..91fd187
--- /dev/null
@@ -0,0 +1 @@
+#include <time.h>
diff --git a/include/nonunix/sys/wait.h b/include/nonunix/sys/wait.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/nonunix/termios.h b/include/nonunix/termios.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/include/nonunix/unistd.h b/include/nonunix/unistd.h
new file mode 100644 (file)
index 0000000..5053587
--- /dev/null
@@ -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 (file)
index 0000000..8285f38
--- /dev/null
@@ -0,0 +1 @@
+#include <sys/utime.h>
index 275c6b0..5496f16 100644 (file)
@@ -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 (file)
index 0000000..4b3ce47
--- /dev/null
@@ -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;
+}
+
+
index a913d29..b5536e1 100644 (file)
@@ -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 (file)
index 0000000..56aeecb
--- /dev/null
@@ -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 );
+}