From: Theodore Ts'o Date: Thu, 21 Oct 1999 19:33:18 +0000 (+0000) Subject: Many files: X-Git-Tag: E2FSPROGS-1_16~13 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=aa4115a47c554a936fdf5e6679e72a9329fecf45;p=tools%2Fe2fsprogs.git 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 + + * 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 * 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 @@ 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 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 @@ 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 */ 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 ->name string * %dr ->rec_len * %dl ->name_len + * %dt ->filetype * %D inode number * %g integer * %i 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); 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 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; 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 @@ 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 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 @@ 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) { 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 @@ 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) { 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 @@ 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 */ 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 @@ 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 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 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 diff --git a/include/nonunix/sys/ioctl.h b/include/nonunix/sys/ioctl.h new file mode 100644 index 0000000..e69de29 diff --git a/include/nonunix/sys/param.h b/include/nonunix/sys/param.h new file mode 100644 index 0000000..e69de29 diff --git a/include/nonunix/sys/resource.h b/include/nonunix/sys/resource.h new file mode 100644 index 0000000..e69de29 diff --git a/include/nonunix/sys/socket.h b/include/nonunix/sys/socket.h new file mode 100644 index 0000000..e69de29 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 diff --git a/include/nonunix/sys/wait.h b/include/nonunix/sys/wait.h new file mode 100644 index 0000000..e69de29 diff --git a/include/nonunix/termios.h b/include/nonunix/termios.h new file mode 100644 index 0000000..e69de29 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 +#include +#include + +#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 +#include + + +// 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 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 + + * nt_io.c: New file which supports I/O under Windows NT. + 1999-09-07 * 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 +#include +#include + +#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 + +// +// standard stuff +// + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + + * gen_uuid_nt.c: New file which creates a UUID under Windows NT. + 1999-07-18 Theodore Ts'o * 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 ); +}