aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore4
-rw-r--r--COPYING341
-rw-r--r--Makefile94
-rw-r--r--README53
-rw-r--r--TODO21
-rw-r--r--arclib/Makefile20
-rw-r--r--arclib/arc.c226
-rw-r--r--arclib/arc.h262
-rw-r--r--arclib/spb.h96
-rw-r--r--arclib/stddef.h11
-rw-r--r--arclib/stdio.c281
-rw-r--r--arclib/stdio.h31
-rw-r--r--arclib/stdlib.c118
-rw-r--r--arclib/stdlib.h16
-rw-r--r--arclib/string.c126
-rw-r--r--arclib/string.h23
-rw-r--r--arclib/types.h14
-rw-r--r--common/.cvsignore1
-rw-r--r--common/Makefile16
-rw-r--r--common/print_loadaddr.c30
-rwxr-xr-xcommon/print_outputformat9
-rw-r--r--common/subarch.h51
-rw-r--r--common/version.h1
-rw-r--r--debian/.cvsignore5
-rw-r--r--debian/README.Debian8
-rw-r--r--debian/arcboot.868
-rw-r--r--debian/arcboot.manpages1
-rw-r--r--debian/changelog243
-rw-r--r--debian/compat1
-rw-r--r--debian/config17
-rw-r--r--debian/control27
-rw-r--r--debian/copyright13
-rw-r--r--debian/dirs3
-rw-r--r--debian/docs2
-rw-r--r--debian/po/POTFILES.in1
-rw-r--r--debian/po/cs.po40
-rw-r--r--debian/po/da.po40
-rw-r--r--debian/po/de.po43
-rw-r--r--debian/po/es.po51
-rw-r--r--debian/po/fr.po40
-rw-r--r--debian/po/ja.po40
-rw-r--r--debian/po/nl.po34
-rw-r--r--debian/po/pt.po41
-rw-r--r--debian/po/pt_BR.po42
-rw-r--r--debian/po/sv.po40
-rw-r--r--debian/po/templates.pot38
-rw-r--r--debian/po/vi.po29
-rw-r--r--debian/postinst41
-rwxr-xr-xdebian/rules104
-rw-r--r--debian/templates7
-rw-r--r--debian/tip22.826
-rw-r--r--debian/tip22.docs2
-rw-r--r--debian/tip22.manpages2
-rw-r--r--debian/tip32.827
-rw-r--r--e2fslib/.cvsignore3
-rw-r--r--e2fslib/ChangeLog2274
-rw-r--r--e2fslib/MCONFIG199
-rw-r--r--e2fslib/Makefile642
-rw-r--r--e2fslib/Makefile.in477
-rw-r--r--e2fslib/alloc.c178
-rw-r--r--e2fslib/alloc.obin0 -> 17532 bytes
-rw-r--r--e2fslib/alloc_tables.c120
-rw-r--r--e2fslib/alloc_tables.obin0 -> 13672 bytes
-rw-r--r--e2fslib/badblocks.c236
-rw-r--r--e2fslib/badblocks.obin0 -> 11932 bytes
-rw-r--r--e2fslib/bb_compat.c63
-rw-r--r--e2fslib/bb_compat.obin0 -> 7600 bytes
-rw-r--r--e2fslib/bb_inode.c287
-rw-r--r--e2fslib/bb_inode.obin0 -> 18316 bytes
-rw-r--r--e2fslib/bitmaps.c213
-rw-r--r--e2fslib/bitmaps.obin0 -> 18880 bytes
-rw-r--r--e2fslib/bitops.c91
-rw-r--r--e2fslib/bitops.h718
-rw-r--r--e2fslib/bitops.obin0 -> 13556 bytes
-rw-r--r--e2fslib/block.c496
-rw-r--r--e2fslib/block.obin0 -> 23588 bytes
-rw-r--r--e2fslib/bmap.c237
-rw-r--r--e2fslib/bmap.obin0 -> 20372 bytes
-rw-r--r--e2fslib/bmove.c160
-rw-r--r--e2fslib/brel.h86
-rw-r--r--e2fslib/brel_ma.c197
-rw-r--r--e2fslib/check_desc.c68
-rw-r--r--e2fslib/check_desc.obin0 -> 11564 bytes
-rw-r--r--e2fslib/closefs.c291
-rw-r--r--e2fslib/closefs.obin0 -> 18440 bytes
-rw-r--r--e2fslib/cmp_bitmaps.c72
-rw-r--r--e2fslib/cmp_bitmaps.obin0 -> 12996 bytes
-rw-r--r--e2fslib/com_err.h40
-rw-r--r--e2fslib/dblist.c254
-rw-r--r--e2fslib/dblist.obin0 -> 19188 bytes
-rw-r--r--e2fslib/dblist_dir.c77
-rw-r--r--e2fslib/dblist_dir.obin0 -> 13940 bytes
-rw-r--r--e2fslib/dir_iterate.c137
-rw-r--r--e2fslib/dir_iterate.obin0 -> 15556 bytes
-rw-r--r--e2fslib/dirblock.c100
-rw-r--r--e2fslib/dirblock.obin0 -> 14216 bytes
-rw-r--r--e2fslib/dll/jump.funcs178
-rw-r--r--e2fslib/dll/jump.import166
-rw-r--r--e2fslib/dll/jump.params6
-rw-r--r--e2fslib/dll/jump.undefs2
-rw-r--r--e2fslib/dll/jump.vars6
-rw-r--r--e2fslib/dosio.c456
-rw-r--r--e2fslib/dosio.h153
-rw-r--r--e2fslib/dupfs.c92
-rw-r--r--e2fslib/dupfs.obin0 -> 13864 bytes
-rw-r--r--e2fslib/e2image.h51
-rw-r--r--e2fslib/e2p/e2p.h39
-rw-r--r--e2fslib/et/.cvsignore1
-rw-r--r--e2fslib/et/ChangeLog210
-rw-r--r--e2fslib/et/Makefile334
-rw-r--r--e2fslib/et/Makefile.in129
-rw-r--r--e2fslib/et/com_err.c120
-rw-r--r--e2fslib/et/com_err.h40
-rw-r--r--e2fslib/et/com_err.obin0 -> 7844 bytes
-rw-r--r--e2fslib/et/com_err.texinfo579
-rwxr-xr-xe2fslib/et/compile_et31
-rw-r--r--e2fslib/et/compile_et.sh.in31
-rw-r--r--e2fslib/et/error_message.c88
-rw-r--r--e2fslib/et/error_message.obin0 -> 6312 bytes
-rw-r--r--e2fslib/et/error_table.h42
-rw-r--r--e2fslib/et/et_c.awk187
-rw-r--r--e2fslib/et/et_h.awk159
-rw-r--r--e2fslib/et/et_name.c43
-rw-r--r--e2fslib/et/et_name.obin0 -> 3192 bytes
-rw-r--r--e2fslib/et/init_et.c63
-rw-r--r--e2fslib/et/init_et.obin0 -> 5184 bytes
-rw-r--r--e2fslib/et/internal.h30
-rw-r--r--e2fslib/et/libcom_err.abin0 -> 23006 bytes
-rw-r--r--e2fslib/et/vfprintf.c49
-rw-r--r--e2fslib/expanddir.c132
-rw-r--r--e2fslib/expanddir.obin0 -> 15012 bytes
-rw-r--r--e2fslib/ext2_err.c140
-rw-r--r--e2fslib/ext2_err.et276
-rw-r--r--e2fslib/ext2_err.et.in276
-rw-r--r--e2fslib/ext2_err.h106
-rw-r--r--e2fslib/ext2_err.obin0 -> 9224 bytes
-rw-r--r--e2fslib/ext2_ext_attr.h58
-rw-r--r--e2fslib/ext2_fs.h624
-rw-r--r--e2fslib/ext2_io.h100
-rw-r--r--e2fslib/ext2_types.h53
-rw-r--r--e2fslib/ext2_types.h.in53
-rw-r--r--e2fslib/ext2fs.h976
-rw-r--r--e2fslib/ext2fsP.h93
-rw-r--r--e2fslib/ext_attr.c100
-rw-r--r--e2fslib/ext_attr.obin0 -> 15324 bytes
-rw-r--r--e2fslib/fileio.c336
-rw-r--r--e2fslib/fileio.obin0 -> 20788 bytes
-rw-r--r--e2fslib/finddev.c208
-rw-r--r--e2fslib/finddev.obin0 -> 9920 bytes
-rw-r--r--e2fslib/flushb.c76
-rw-r--r--e2fslib/flushb.obin0 -> 4588 bytes
-rw-r--r--e2fslib/freefs.c137
-rw-r--r--e2fslib/freefs.obin0 -> 16244 bytes
-rw-r--r--e2fslib/gen_bitmap.c48
-rw-r--r--e2fslib/gen_bitmap.obin0 -> 12052 bytes
-rw-r--r--e2fslib/get_pathname.c158
-rw-r--r--e2fslib/get_pathname.obin0 -> 16440 bytes
-rw-r--r--e2fslib/getsize.c157
-rw-r--r--e2fslib/getsize.obin0 -> 6848 bytes
-rw-r--r--e2fslib/icount.c482
-rw-r--r--e2fslib/icount.obin0 -> 27388 bytes
-rw-r--r--e2fslib/imager.c380
-rw-r--r--e2fslib/imager.obin0 -> 20904 bytes
-rw-r--r--e2fslib/initialize.c326
-rw-r--r--e2fslib/initialize.obin0 -> 18024 bytes
-rw-r--r--e2fslib/inline.c32
-rw-r--r--e2fslib/inline.obin0 -> 30228 bytes
-rw-r--r--e2fslib/inode.c724
-rw-r--r--e2fslib/inode.obin0 -> 30508 bytes
-rw-r--r--e2fslib/irel.h114
-rw-r--r--e2fslib/irel_ma.c373
-rw-r--r--e2fslib/ismounted.c261
-rw-r--r--e2fslib/ismounted.obin0 -> 10124 bytes
-rw-r--r--e2fslib/jfs_dat.h64
-rw-r--r--e2fslib/jfs_user.h9
-rw-r--r--e2fslib/libcom_err.abin0 -> 23006 bytes
-rw-r--r--e2fslib/libext2fs.abin0 -> 800092 bytes
-rw-r--r--e2fslib/link.c121
-rw-r--r--e2fslib/link.obin0 -> 13500 bytes
-rw-r--r--e2fslib/linux/jfs.h682
-rw-r--r--e2fslib/linux/jfs_compat.h64
-rw-r--r--e2fslib/linux/list.h108
-rw-r--r--e2fslib/llseek.c132
-rw-r--r--e2fslib/llseek.obin0 -> 3716 bytes
-rw-r--r--e2fslib/lookup.c69
-rw-r--r--e2fslib/lookup.obin0 -> 12716 bytes
-rw-r--r--e2fslib/mkdir.c154
-rw-r--r--e2fslib/mkdir.obin0 -> 14556 bytes
-rw-r--r--e2fslib/mkjournal.c408
-rw-r--r--e2fslib/mkjournal.obin0 -> 23812 bytes
-rw-r--r--e2fslib/namei.c205
-rw-r--r--e2fslib/namei.obin0 -> 19168 bytes
-rw-r--r--e2fslib/native.c27
-rw-r--r--e2fslib/native.obin0 -> 3960 bytes
-rw-r--r--e2fslib/newdir.c72
-rw-r--r--e2fslib/newdir.obin0 -> 12464 bytes
-rw-r--r--e2fslib/nt_io.c1513
-rw-r--r--e2fslib/openfs.c240
-rw-r--r--e2fslib/openfs.obin0 -> 16392 bytes
-rw-r--r--e2fslib/read_bb.c95
-rw-r--r--e2fslib/read_bb.obin0 -> 12856 bytes
-rw-r--r--e2fslib/read_bb_file.c96
-rw-r--r--e2fslib/read_bb_file.obin0 -> 13552 bytes
-rw-r--r--e2fslib/rs_bitmap.c107
-rw-r--r--e2fslib/rs_bitmap.obin0 -> 13908 bytes
-rw-r--r--e2fslib/rw_bitmaps.c302
-rw-r--r--e2fslib/rw_bitmaps.obin0 -> 20296 bytes
-rw-r--r--e2fslib/swapfs.c145
-rw-r--r--e2fslib/swapfs.obin0 -> 15372 bytes
-rw-r--r--e2fslib/test_io.c265
-rw-r--r--e2fslib/test_io.obin0 -> 15060 bytes
-rw-r--r--e2fslib/tst_badblocks.c237
-rw-r--r--e2fslib/tst_bitops.c44
-rw-r--r--e2fslib/tst_byteswap.c92
-rw-r--r--e2fslib/tst_getsize.c44
-rw-r--r--e2fslib/tst_iscan.c218
-rw-r--r--e2fslib/unix_io.c556
-rw-r--r--e2fslib/unix_io.obin0 -> 21784 bytes
-rw-r--r--e2fslib/unlink.c80
-rw-r--r--e2fslib/unlink.obin0 -> 12960 bytes
-rw-r--r--e2fslib/util/.cvsignore1
-rw-r--r--e2fslib/util/ChangeLog132
-rw-r--r--e2fslib/util/Makefile231
-rw-r--r--e2fslib/util/Makefile.in39
-rw-r--r--e2fslib/util/gcc-wall-cleanup17
-rw-r--r--e2fslib/util/libecho.c78
-rwxr-xr-xe2fslib/util/substbin0 -> 80037 bytes
-rw-r--r--e2fslib/util/subst.c374
-rw-r--r--e2fslib/util/subst.conf16
-rw-r--r--e2fslib/util/subst.conf.in16
-rw-r--r--e2fslib/util/subst.obin0 -> 16392 bytes
-rw-r--r--e2fslib/valid_blk.c45
-rw-r--r--e2fslib/valid_blk.obin0 -> 5856 bytes
-rw-r--r--e2fslib/version.c50
-rw-r--r--e2fslib/version.h10
-rw-r--r--e2fslib/version.obin0 -> 5492 bytes
-rw-r--r--e2fslib/write_bb_file.c34
-rw-r--r--e2fslib/write_bb_file.obin0 -> 5300 bytes
-rw-r--r--etc/arcboot.conf13
-rw-r--r--ext2load/.cvsignore2
-rw-r--r--ext2load/Makefile48
-rw-r--r--ext2load/arcboot.h26
-rw-r--r--ext2load/conffile.c172
-rw-r--r--ext2load/ext2io.c781
-rw-r--r--ext2load/ld.script.in73
-rw-r--r--ext2load/loader.c564
-rw-r--r--scripts/arcboot42
-rw-r--r--tip22/.cvsignore6
-rw-r--r--tip22/Makefile73
-rw-r--r--tip22/README32
-rw-r--r--tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff88
-rw-r--r--tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff172
-rw-r--r--tip22/ld.kernel.script.in11
-rw-r--r--tip22/ld.ramdisk.script.in11
-rw-r--r--tip22/ld.script.in78
-rw-r--r--tip22/tftpload.c353
-rw-r--r--tip22/tip2251
-rwxr-xr-xtip22/tip3251
258 files changed, 30560 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..90638bf
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,4 @@
+arcboot.ip22
+arcboot.ip32
+build-stamp
+configure-stamp
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a52b16e
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,341 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1c880d5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,94 @@
+#
+# Copyright 1999 Silicon Graphics, Inc.
+# Copyright 2002-2004 Guido Guenther <agx@sigxcpu.org>
+# Copyright (C) 2004 by Thiemo Seufer
+#
+
+# default subarch
+SUBARCH ?= IP22
+
+# these contain subarch independent files
+SUBARCH_INDEP_DIRS= \
+ arclib \
+ tip22
+
+# these contain subarch dependent files
+SUBARCH_DIRS= \
+ common \
+ ext2load
+
+define indep-tgt
+$(foreach sd,$(SUBARCH_INDEP_DIRS),$(1)-subarch-indep-$(sd))
+endef
+
+define dep-tgt
+$(foreach sd,$(SUBARCH_DIRS),$(1)-subarch-dep-$(sd))
+endef
+
+define build-indep-tgt
+$(call indep-tgt,build)
+endef
+
+define build-dep-tgt
+$(call dep-tgt,build)
+endef
+
+define install-indep-tgt
+$(call indep-tgt,install)
+endef
+
+define install-dep-tgt
+$(call dep-tgt,install)
+endef
+
+define clean-indep-tgt
+$(call indep-tgt,clean)
+endef
+
+define clean-dep-tgt
+$(call dep-tgt,clean)
+endef
+
+define submake
+@$(MAKE) -C $(1) SUBARCH=$(SUBARCH) $(2)
+endef
+
+
+all: build
+
+build: build-subarch-indep build-subarch-dep
+build-subarch-indep: $(build-indep-tgt)
+build-subarch-dep: $(build-dep-tgt)
+
+$(build-indep-tgt):
+ $(call submake,$(patsubst build-subarch-indep-%,%,$@),all)
+
+$(build-dep-tgt):
+ $(call submake,$(patsubst build-subarch-dep-%,%,$@),all)
+
+install: install-subarch-indep install-subarch-dep
+install-subarch-indep: $(install-indep-tgt)
+install-subarch-dep: $(install-dep-tgt)
+
+$(install-indep-tgt):
+ $(call submake,$(patsubst install-subarch-indep-%,%,$@),install)
+
+$(install-dep-tgt):
+ $(call submake,$(patsubst install-subarch-dep-%,%,$@),install)
+
+clean: clean-subarch-indep clean-subarch-dep
+clean-subarch-indep: $(clean-indep-tgt)
+clean-subarch-dep: $(clean-dep-tgt)
+
+$(clean-indep-tgt):
+ $(call submake,$(patsubst clean-subarch-indep-%,%,$@),clean)
+
+$(clean-dep-tgt):
+ $(call submake,$(patsubst clean-subarch-dep-%,%,$@),clean)
+
+
+.PHONY: all \
+ build build-subarch-indep build-subarch-dep \
+ $(build-indep-tgt) $(build-dep-tgt) \
+ clean clean-subarch-indep clean-subarch-dep \
+ $(clean-indep-tgt) $(clean-dep-tgt)
diff --git a/README b/README
new file mode 100644
index 0000000..4128fc1
--- /dev/null
+++ b/README
@@ -0,0 +1,53 @@
+Arcboot is the bootloader used on SGI IP22 machines (Indy and Indigo2) and
+the SGI IP32 (O2) to boot Linux from an Ext{2,3}-filesystem.
+
+To install arcboot type:
+
+"/usr/sbin/arcboot <name_of_disk>" as root.
+
+where <name_of_disk> is the disk on which arcboot will be installed. To let
+this work the disk *must* have an SGI disklabel. Afterwards copy arcboot.conf
+into /etc/ and adjust it to your needs.
+
+Arcboot parses the PROM variable OSLoadPartition to find arcboot.conf therefore
+/etc/ has to be on the same partition as the kernel.
+It boots the label given in OSLoadFilename or on the command line (see below).
+
+If it can't fine the label in arcboot.conf it tries to boot the file
+OSLoadPartition/OSLoadFilename, allowing you to boot any file on an ext2
+filesystem by adjusting OSLoadPartition accordingly (this might be helpful if
+your freshly installed kernel doesn't boot).
+
+Besides the append="..." line in /etc/arcboot.conf arcboot also appends the
+value of the prom variable OSLoadOptions to the kernel's command line. This
+allows you to override the arcboot.conf's kernel command line.
+
+If you enter the prom and boot via the "boot" command you can pass additional
+parameters to the kernel. E.g.:
+
+boot linux single console=ttyS0 root=/dev/sda2
+
+will boot the label "linux" from arcboot.conf and append to additional
+arguments given above. Or
+
+boot /boot/vmlinux single console=ttyS0 root=/dev/sda2
+
+will boot the file with the absolute path OSLoadPartition/boot/vmlinux with the
+same arguments as above. Note that OSLoadPartition must be an partition name
+as understood by ARCS (like scsi(0)disk(1)rdisk(0)partition(0)).
+
+Note: arcboot can only load ELF kernels. ECOFF is (and will not be) supported.
+
+For tftpbooting please refer to the tip22 package.
+
+Acknowledgements:
+ - arcboot is based on the arc-bootloader for SGI visual workstations written
+ by Ralf Baechle
+ - the e2fslib dir is basically a stripped down verion of e2fsprogs 1.25 as
+ found on http://sourceforge.net/projects/e2fsprogs and written by Theodore
+ T'so <tytso@thunk.org> compiled with -nopic.
+ - most of the config file parsing is borrowed from delo by Florian Lohoff
+ <flo@rfc822.org>. Additional thanks to him for a weekend of input, testing
+ & patches.
+
+ -- Guido Guenther <agx@sigxcpu.org>, Sun, 26 Apr 2003 20:29:43 +0100
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..8ec983d
--- /dev/null
+++ b/TODO
@@ -0,0 +1,21 @@
+common:
+-------
+ - add gzip decompression
+ - add iso9660 suport
+ - teach arcboot about sgi disklabels
+ - add support for other OSs (NetBSD,IRIX)
+ - split out code common to arcboot and tip22
+ - relink to proper loadaddr on install
+ - determine kernel's loaddr from system type during boot
+
+arclib:
+-------
+
+arcboot:
+--------
+ - add support for initrd
+
+tip22:
+------
+
+ -- Guido Guenther <agx@sigxcpu.org> Thu, 15 May 2002 19:57:00 +0200
diff --git a/arclib/Makefile b/arclib/Makefile
new file mode 100644
index 0000000..4a53c26
--- /dev/null
+++ b/arclib/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright 1999 Silicon Graphics, Inc.
+#
+CFLAGS += -O2 -Werror -Wall -mno-abicalls -G 0 -fno-pic
+
+TARGETS = libarc.a
+OBJECTS = arc.o stdio.o stdlib.o string.o
+
+all: $(TARGETS)
+
+$(TARGETS): $(OBJECTS)
+ rm -f $@
+ $(AR) -crs $@ $(OBJECTS)
+
+install: $(TARGETS)
+ install -d ${PREFIX}/${LIBDIR}
+ install -m 644 $< ${PREFIX}/${LIBDIR}
+
+clean:
+ rm -f libarc.a $(OBJECTS) *~ tags
diff --git a/arclib/arc.c b/arclib/arc.c
new file mode 100644
index 0000000..957f012
--- /dev/null
+++ b/arclib/arc.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#include "types.h"
+#include "arc.h"
+#include "spb.h"
+
+
+LONG ArcLoad(CHAR * Path, ULONG TopAddr, ULONG * ExecAddr, ULONG * LowAddr)
+{
+ return FVector->Load(Path, TopAddr, ExecAddr, LowAddr);
+}
+
+
+LONG
+ArcInvoke(ULONG ExecAddr,
+ ULONG StackAddr, ULONG Argc, CHAR * Argv[], CHAR * Envp[]
+ )
+{
+ return FVector->Invoke(ExecAddr, StackAddr, Argc, Argv, Envp);
+}
+
+
+LONG ArcExecute(CHAR * Path, ULONG Argc, CHAR * Argv[], CHAR * Envp[])
+{
+ return FVector->Execute(Path, Argc, Argv, Envp);
+}
+
+
+VOID ArcHalt(VOID)
+{
+ FVector->Halt();
+}
+
+
+VOID ArcPowerDown(VOID)
+{
+ FVector->PowerDown();
+}
+
+
+VOID ArcRestart(VOID)
+{
+ FVector->Restart();
+}
+
+
+VOID ArcReboot(VOID)
+{
+ FVector->Reboot();
+}
+
+
+VOID ArcEnterInteractiveMode(VOID)
+{
+ FVector->EnterInteractiveMode();
+}
+
+
+COMPONENT *ArcGetPeer(COMPONENT * Current)
+{
+ return FVector->GetPeer(Current);
+}
+
+
+COMPONENT *ArcGetChild(COMPONENT * Current)
+{
+ return FVector->GetChild(Current);
+}
+
+
+COMPONENT *ArcGetParent(COMPONENT * Current)
+{
+ return FVector->GetParent(Current);
+}
+
+
+LONG
+ArcGetConfigurationData(VOID * ConfigurationData, COMPONENT * Component)
+{
+ return FVector->GetConfigurationData(ConfigurationData, Component);
+}
+
+
+COMPONENT *ArcAddChild(COMPONENT * Current, COMPONENT * Template,
+ VOID * ConfigurationData)
+{
+ return FVector->AddChild(Current, Template, ConfigurationData);
+}
+
+
+LONG ArcDeleteComponent(COMPONENT * ComponentToDelete)
+{
+ return FVector->DeleteComponent(ComponentToDelete);
+}
+
+
+COMPONENT *ArcGetComponent(CHAR * Path)
+{
+ return FVector->GetComponent(Path);
+}
+
+
+LONG ArcSaveConfiguration(VOID)
+{
+ return FVector->SaveConfiguration();
+}
+
+
+SYSTEMID *ArcGetSystemId(VOID)
+{
+ return FVector->GetSystemId();
+}
+
+
+MEMORYDESCRIPTOR *ArcGetMemoryDescriptor(MEMORYDESCRIPTOR * Current)
+{
+ return FVector->GetMemoryDescriptor(Current);
+}
+
+
+TIMEINFO *ArcGetTime(VOID)
+{
+ return FVector->GetTime();
+}
+
+
+ULONG ArcGetRelativeTime(VOID)
+{
+ return FVector->GetRelativeTime();
+}
+
+
+LONG
+ArcGetDirectoryEntry(ULONG FileID,
+ DIRECTORYENTRY * Buffer, ULONG N, ULONG * Count)
+{
+ return FVector->GetDirectoryEntry(FileID, Buffer, N, Count);
+}
+
+
+LONG ArcOpen(CHAR * Path, OPENMODE OpenMode, ULONG * FileID)
+{
+ return FVector->Open(Path, OpenMode, FileID);
+}
+
+
+LONG ArcClose(ULONG FileID)
+{
+ return FVector->Close(FileID);
+}
+
+
+LONG ArcRead(ULONG FileID, VOID * Buffer, ULONG N, ULONG * Count)
+{
+ return FVector->Read(FileID, Buffer, N, Count);
+}
+
+
+LONG ArcGetReadStatus(ULONG FileID)
+{
+ return FVector->GetReadStatus(FileID);
+}
+
+
+LONG ArcWrite(ULONG FileID, VOID * Buffer, ULONG N, ULONG * Count)
+{
+ return FVector->Write(FileID, Buffer, N, Count);
+}
+
+
+LONG ArcSeek(ULONG FileID, LARGEINTEGER * Position, SEEKMODE SeekMode)
+{
+ return FVector->Seek(FileID, Position, SeekMode);
+}
+
+
+LONG ArcMount(CHAR * Path, MOUNTOPERATION Operation)
+{
+ return FVector->Mount(Path, Operation);
+}
+
+
+CHAR *ArcGetEnvironmentVariable(CHAR * Name)
+{
+ return FVector->GetEnvironmentVariable(Name);
+}
+
+
+LONG ArcSetEnvironmentVariable(CHAR * Name, CHAR * Value)
+{
+ return FVector->SetEnvironmentVariable(Name, Value);
+}
+
+
+LONG ArcGetFileInformation(ULONG FileID, FILEINFORMATION * Information)
+{
+ return FVector->GetFileInformation(FileID, Information);
+}
+
+
+LONG
+ArcSetFileInformation(ULONG FileID, ULONG AttributeFlags,
+ ULONG AttributeMask)
+{
+ return FVector->SetFileInformation(FileID, AttributeFlags,
+ AttributeMask);
+}
+
+
+VOID ArcFlushAllCaches(VOID)
+{
+ FVector->FlushAllCaches();
+}
+
+
+LONG ArcTestUnicodeCharacter(ULONG FileID, USHORT UnicodeCharacter)
+{
+ return FVector->TestUnicodeCharacter(FileID, UnicodeCharacter);
+}
+
+
+DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID)
+{
+ return FVector->GetDisplayStatus(FileID);
+}
diff --git a/arclib/arc.h b/arclib/arc.h
new file mode 100644
index 0000000..2920276
--- /dev/null
+++ b/arclib/arc.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ * 2001-03 Guido Guenther <agx@sixcpu.org>
+ */
+#ifndef _ARC_H_
+#define _ARC_H_
+
+#include "types.h"
+
+#define ESUCCESS 0 /* No error */
+#define E2BIG 1 /* Argument list too long */
+#define EACCES 2 /* Permission denied */
+#define EAGAIN 3 /* Resource temporarily unavailable */
+#define EBADF 4 /* Bad file descriptor */
+#define EBUSY 5 /* Resource busy */
+#define EFAULT 6 /* Bad address */
+#define EINVAL 7 /* Invalid argument */
+#define EIO 8 /* Input/output error */
+#define EISDIR 9 /* Is a directory */
+#define EMFILE 10 /* Too many open files */
+#define EMLINK 11 /* Too many links */
+#define ENAMETOOLONG 12 /* Filename too long */
+#define ENODEV 13 /* No such device */
+#define ENOENT 14 /* No such file or directory */
+#define ENOEXEC 15 /* Execute format error */
+#define ENOMEM 16 /* Not enough space */
+#define ENOSPC 17 /* No space left on device */
+#define ENOTDIR 18 /* Not a directory */
+#define ENOTTY 19 /* Inappropriate I/O control operation */
+#define ENXIO 20 /* Media not loaded */
+#define EROFS 21 /* Read-only file system */
+
+
+typedef enum {
+ SystemClass = 0,
+ ProcessorClass = 1,
+ CacheClass = 2,
+ AdapterClass = 3,
+ ControllerClass = 4,
+ PeripheralClass = 5,
+ MemoryClass = 6
+} COMPONENT_CLASS;
+
+typedef enum {
+ ARC = 0,
+ CPU = 1,
+ FPU = 2,
+ PrimaryICache = 3,
+ PrimaryDCache = 4,
+ SecondaryICache = 5,
+ SecondaryDCache = 6,
+ SecondaryCache = 7,
+ EISAAdapter = 8,
+ TCAdapter = 9,
+ SCSIAdapter = 10,
+ DTIAdapter = 11,
+ MultiFunctionAdapter = 12,
+ DiskController = 13,
+ TapeController = 14,
+ CDROMController = 15,
+ WORMController = 16,
+ SerialController = 17,
+ NetworkController = 18,
+ DisplayController = 19,
+ ParallelController = 20,
+ PointerController = 21,
+ KeyboardController = 22,
+ AudioController = 23,
+ OtherController = 24,
+ DiskPeripheral = 25,
+ FloppyDiskPeripheral = 26,
+ TapePeripheral = 27,
+ ModemPeripheral = 28,
+ MonitorPeripheral = 29,
+ PrinterPeripheral = 30,
+ PointerPeripheral = 31,
+ KeyboardPeripheral = 32,
+ TerminalPeripheral = 33,
+ OtherPeripheral = 34,
+ LinePeripheral = 35,
+ NetworkPeripheral = 36,
+ MemoryUnit = 37
+} COMPONENT_TYPE;
+
+typedef enum {
+ Failed = 1,
+ ReadOnly = 2,
+ Removable = 4,
+ ConsoleIn = 8,
+ ConsoleOut = 16,
+ Input = 32,
+ Output = 64
+} COMPONENT_FLAGS;
+
+typedef struct {
+ COMPONENT_CLASS Class;
+ COMPONENT_TYPE Type;
+ COMPONENT_FLAGS Flags;
+ USHORT Version;
+ USHORT Revision;
+ ULONG Key;
+ ULONG AffinityMask;
+ ULONG ConfigurationDataSize;
+ ULONG IdentifierLength;
+ CHAR *Identifier;
+} COMPONENT;
+
+typedef struct {
+ CHAR VendorId[8];
+ UCHAR ProductId[8];
+} SYSTEMID;
+
+/* This is ARCS not ARC */
+typedef enum {
+ ExceptionBlock,
+ SystemParameterBlock,
+ FreeContiguous,
+ FreeMemory,
+ BadMemory,
+ LoadedProgram,
+ FirmwareTemporary,
+ FirmwarePermanent,
+} MEMORYTYPE;
+
+typedef struct {
+ MEMORYTYPE Type;
+ ULONG BasePage;
+ ULONG PageCount;
+} MEMORYDESCRIPTOR;
+
+typedef struct {
+ USHORT Year;
+ USHORT Month;
+ USHORT Day;
+ USHORT Hour;
+ USHORT Minutes;
+ USHORT Seconds;
+ USHORT Milliseconds;
+} TIMEINFO;
+
+#define ARC_NAME_MAX 32
+
+typedef struct {
+ ULONG FileNameLength;
+ ULONG FileAttribute;
+ ULONG FileName[ARC_NAME_MAX];
+} DIRECTORYENTRY;
+
+typedef enum {
+ OpenReadOnly,
+ OpenWriteOnly,
+ OpenReadWrite,
+ CreateWriteOnly,
+ CreateReadWrite,
+ SupersedeWriteOnly,
+ SupersedeReadWrite,
+ OpenDirectory,
+ CreateDirectory
+} OPENMODE;
+
+typedef struct {
+#ifdef __MIPSEL__
+ ULONG LowPart;
+ *LONG HighPart;
+#else /* !(__MIPSEL__) */
+ LONG HighPart;
+ ULONG LowPart;
+#endif
+} LARGEINTEGER;
+
+typedef enum {
+ SeekAbsolute,
+ SeekRelative
+} SEEKMODE;
+
+typedef enum {
+ LoadMedia,
+ UnloadMedia
+} MOUNTOPERATION;
+
+typedef struct {
+ LARGEINTEGER StartingAddress;
+ LARGEINTEGER EndingAddress;
+ LARGEINTEGER CurrentAddress;
+ COMPONENT_TYPE Type;
+ ULONG FileNameLength;
+ UCHAR Attributes;
+ CHAR Filename[ARC_NAME_MAX];
+} FILEINFORMATION;
+
+typedef enum {
+ ReadOnlyFile = 1,
+ HiddenFile = 2,
+ SystemFile = 4,
+ ArchiveFile = 8,
+ DirectoryFile = 16,
+ DeleteFile = 32
+} FILEATTRIBUTES;
+
+typedef struct {
+ USHORT CursorXPosition;
+ USHORT CursorYPosition;
+ USHORT CursorMaxXPosition;
+ USHORT CursorMaxYPosition;
+ UCHAR ForegroundColor;
+ UCHAR BackgroundColor;
+ UCHAR HighIntensity;
+ UCHAR Underscored;
+ UCHAR ReverseVideo;
+} DISPLAY_STATUS;
+
+
+#define ARC_STDIN 0
+#define ARC_STDOUT 1
+
+extern LONG ArcLoad(CHAR * Path, ULONG TopAddr, ULONG * ExecAddr,
+ ULONG * LowAddr);
+extern LONG ArcInvoke(ULONG ExecAddr, ULONG StackAddr, ULONG Argc,
+ CHAR * Argv[], CHAR * Envp[]);
+extern LONG ArcExecute(CHAR * Path, ULONG Argc, CHAR * Argv[],
+ CHAR * Envp[]);
+extern VOID ArcHalt(VOID);
+extern VOID ArcPowerDown(VOID);
+extern VOID ArcRestart(VOID);
+extern VOID ArcReboot(VOID);
+extern VOID ArcEnterInteractiveMode(VOID);
+extern COMPONENT *ArcGetPeer(COMPONENT * Current);
+extern COMPONENT *ArcGetChild(COMPONENT * Current);
+extern COMPONENT *ArcGetParent(COMPONENT * Current);
+extern LONG ArcGetConfigurationData
+ (VOID * ConfigurationData, COMPONENT * Component);
+extern COMPONENT *ArcAddChild
+ (COMPONENT * Current, COMPONENT * Template, VOID * ConfigurationData);
+extern LONG ArcDeleteComponent(COMPONENT * ComponentToDelete);
+extern COMPONENT *ArcGetComponent(CHAR * Path);
+extern LONG ArcSaveConfiguration(VOID);
+extern SYSTEMID *ArcGetSystemId(VOID);
+extern MEMORYDESCRIPTOR *ArcGetMemoryDescriptor(MEMORYDESCRIPTOR *
+ Current);
+extern TIMEINFO *ArcGetTime(VOID);
+extern ULONG ArcGetRelativeTime(VOID);
+extern LONG ArcGetDirectoryEntry
+ (ULONG FileID, DIRECTORYENTRY * Buffer, ULONG N, ULONG * Count);
+extern LONG ArcOpen(CHAR * Path, OPENMODE OpenMode, ULONG * FileID);
+extern LONG ArcClose(ULONG FileID);
+extern LONG ArcRead(ULONG FileID, VOID * Buffer, ULONG N, ULONG * Count);
+extern LONG ArcGetReadStatus(ULONG FileID);
+extern LONG ArcWrite(ULONG FileID, VOID * Buffer, ULONG N, ULONG * Count);
+extern LONG ArcSeek(ULONG FileID, LARGEINTEGER * Position,
+ SEEKMODE SeekMode);
+extern LONG ArcMount(CHAR * Path, MOUNTOPERATION Operation);
+extern CHAR *ArcGetEnvironmentVariable(CHAR * Name);
+extern LONG ArcSetEnvironmentVariable(CHAR * Name, CHAR * Value);
+extern LONG ArcGetFileInformation(ULONG FileID,
+ FILEINFORMATION * Information);
+extern LONG ArcSetFileInformation(ULONG FileID, ULONG AttributeFlags,
+ ULONG AttributeMask);
+extern VOID ArcFlushAllCaches(VOID);
+extern LONG ArcTestUnicodeCharacter(ULONG FileID, USHORT UnicodeCharacter);
+extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID);
+
+#endif /* _ARC_H_ */
diff --git a/arclib/spb.h b/arclib/spb.h
new file mode 100644
index 0000000..fffc20a
--- /dev/null
+++ b/arclib/spb.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 1999, 2001 Silicon Graphics, Inc.
+ * Copyright 2001 Ralf Baechle
+ */
+#ifndef _SPB_H_
+#define _SPB_H_
+
+#include "types.h"
+#include "arc.h"
+
+typedef struct {
+ LONG(*Load) (CHAR *, ULONG, ULONG *, ULONG *);
+ LONG(*Invoke) (ULONG, ULONG, ULONG, CHAR *[], CHAR *[]);
+ LONG(*Execute) (CHAR *, ULONG, CHAR *[], CHAR *[]);
+ VOID(*Halt) (VOID);
+ VOID(*PowerDown) (VOID);
+ VOID(*Restart) (VOID);
+ VOID(*Reboot) (VOID);
+ VOID(*EnterInteractiveMode) (VOID);
+ VOID *reserved1;
+ COMPONENT *(*GetPeer) (COMPONENT *);
+ COMPONENT *(*GetChild) (COMPONENT *);
+ COMPONENT *(*GetParent) (COMPONENT *);
+ LONG(*GetConfigurationData) (VOID *, COMPONENT *);
+ COMPONENT *(*AddChild) (COMPONENT *, COMPONENT *, VOID *);
+ LONG(*DeleteComponent) (COMPONENT *);
+ COMPONENT *(*GetComponent) (CHAR *);
+ LONG(*SaveConfiguration) (VOID);
+ SYSTEMID *(*GetSystemId) (VOID);
+ MEMORYDESCRIPTOR *(*GetMemoryDescriptor) (MEMORYDESCRIPTOR *);
+ VOID *reserved2;
+ TIMEINFO *(*GetTime) (VOID);
+ ULONG(*GetRelativeTime) (VOID);
+ LONG(*GetDirectoryEntry) (ULONG, DIRECTORYENTRY *, ULONG, ULONG *);
+ LONG(*Open) (CHAR *, OPENMODE, ULONG *);
+ LONG(*Close) (ULONG);
+ LONG(*Read) (ULONG, VOID *, ULONG, ULONG *);
+ LONG(*GetReadStatus) (ULONG);
+ LONG(*Write) (ULONG, VOID *, ULONG, ULONG *);
+ LONG(*Seek) (ULONG, LARGEINTEGER *, SEEKMODE);
+ LONG(*Mount) (CHAR *, MOUNTOPERATION);
+ CHAR *(*GetEnvironmentVariable) (CHAR *);
+ LONG(*SetEnvironmentVariable) (CHAR *, CHAR *);
+ LONG(*GetFileInformation) (ULONG, FILEINFORMATION *);
+ LONG(*SetFileInformation) (ULONG, ULONG, ULONG);
+ VOID(*FlushAllCaches) (VOID);
+ LONG(*TestUnicodeCharacter) (ULONG, USHORT);
+ DISPLAY_STATUS *(*GetDisplayStatus) (ULONG);
+} FIRMWAREVECTOR;
+
+#define RSTB_SIGNATURE 0x42545352
+
+typedef struct _rstb {
+ ULONG RSTBSignature;
+ ULONG RSTBLength;
+ USHORT Version;
+ USHORT Revision;
+ struct _rstb *NextRSTB;
+ VOID *RestartAddress;
+ ULONG BootMasterID;
+ ULONG ProcessorID;
+ ULONG BootStatus;
+ ULONG Checksum;
+ ULONG SaveAreaLength;
+ ULONG SavedStateArea[1];
+} RESTARTBLOCK;
+
+typedef struct {
+ ULONG AdapterType;
+ ULONG AdapterVectorLength;
+ VOID *AdapterVector;
+} ADAPTER;
+
+#define SPB_SIGNATURE 0x53435241
+
+typedef struct {
+ ULONG SPBSignature;
+ ULONG SPBLength;
+ USHORT Version;
+ USHORT Revision;
+ RESTARTBLOCK *RestartBlock;
+ VOID *DebugBlock;
+ VOID *GEVector;
+ VOID *UTLBMissVector;
+ ULONG FirmwareVectorLength;
+ FIRMWAREVECTOR *FirmwareVector;
+ ULONG PrivateVectorLength;
+ VOID *PrivateVector;
+ ULONG AdapterCount;
+ ADAPTER Adapters[1];
+} SPB;
+
+#define SystemParameterBlock ((SPB *) 0xA0001000UL)
+#define FVector (SystemParameterBlock->FirmwareVector)
+
+#endif /* _SPB_H_ */
diff --git a/arclib/stddef.h b/arclib/stddef.h
new file mode 100644
index 0000000..97ee87f
--- /dev/null
+++ b/arclib/stddef.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _STDDEF_H_
+#define _STDDEF_H_
+
+typedef unsigned int size_t;
+
+#define NULL ((void *) 0)
+
+#endif /* _STDDEF_H_ */
diff --git a/arclib/stdio.c b/arclib/stdio.c
new file mode 100644
index 0000000..9825594
--- /dev/null
+++ b/arclib/stdio.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#include "arc.h"
+#include "string.h"
+
+#include "stdio.h"
+
+#include <stdarg.h>
+
+static FILE arc_stdin = ARC_STDIN;
+FILE *stdin = &arc_stdin;
+
+static FILE arc_stdout = ARC_STDOUT;
+FILE *stdout = &arc_stdout;
+
+
+int fputs(const char *s, FILE * stream)
+{
+ LONG status;
+ ULONG count;
+
+ if (strlen(s) > 0) {
+ status = ArcWrite(*stream, (char *) s, strlen(s), &count);
+ if ((status != ESUCCESS) || (count != strlen(s)))
+ return EOF;
+ }
+ return 0;
+}
+
+
+int puts(const char *s)
+{
+ int status = fputs(s, stdout);
+
+ if (status != EOF)
+ status = fputs("\n\r", stdout);
+ return status;
+}
+
+
+int fgetc(FILE * stream)
+{
+ LONG status;
+ CHAR ch;
+ ULONG count;
+
+ status = ArcRead(*stream, &ch, sizeof(CHAR), &count);
+ if ((status != ESUCCESS) || (count != sizeof(CHAR)))
+ return EOF;
+ return (int) ch;
+}
+
+
+static const char *numtostr(unsigned int num, unsigned int base)
+{
+ static char str[33];
+ static char digits[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ int pos = 32;
+
+ str[pos] = '\0';
+ do {
+ str[--pos] = digits[num % base];
+ num /= base;
+ } while (num > 0);
+
+ return &str[pos];
+}
+
+
+int vfprintf(FILE * stream, const char *format, va_list ap)
+{
+ int count = 0;
+ const char *str;
+ unsigned int uint;
+ char tmp[2];
+
+ if (format != NULL) {
+ while (*format != '\0') {
+ str = strchr(format, '%');
+ if (str == NULL) {
+ count += strlen(format);
+ fputs(format, stream);
+ break;
+ } else {
+ if (format < str) {
+ LONG status;
+ ULONG count;
+ ULONG len = str - format;
+
+ status =
+ ArcWrite(*stream,
+ (char *) format, len,
+ &count);
+ if ((status != ESUCCESS)
+ || (count != len))
+ return EOF;
+ count += len;
+ }
+
+ format = str + 1;
+ if(*format == 'l')
+ format = str + 2;
+
+ switch (*format) {
+ case 'u':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 10);
+ if (fputs(str, stream) == EOF)
+ return EOF;
+ count += strlen(str);
+ break;
+
+ case 'p':
+ case 'x':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 16);
+ if (fputs(str, stream) == EOF)
+ return EOF;
+ count += strlen(str);
+ break;
+
+ case 's':
+ str = va_arg(ap, const char *);
+ if( !str )
+ str = "(NULL)";
+ if (fputs(str, stream) == EOF)
+ return EOF;
+ count += strlen(str);
+ break;
+
+ case 'c':
+ tmp[0] = (char)va_arg(ap, int);
+ tmp[1] = '\0';
+ if (fputs(tmp, stream) == EOF)
+ return EOF;
+ count++;
+ break;
+
+ case '%':
+ if (fputs("%", stream) == EOF)
+ return EOF;
+ count += 1;
+ break;
+
+ case '\0': /* format error */
+ default:
+ return EOF;
+ }
+
+ format += 1;
+ }
+ }
+ }
+
+ return count;
+}
+
+
+int vprintf(const char *format, va_list ap)
+{
+ return vfprintf(stdout, format, ap);
+}
+
+
+int fprintf(FILE * stream, const char *format, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, format);
+ result = vfprintf(stream, format, ap);
+ va_end(ap);
+
+ return result;
+}
+
+
+int printf(const char *format, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, format);
+ result = vfprintf(stdout, format, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int vsprintf(char* string, const char *format, va_list ap)
+{
+ int count = 0;
+ const char *str;
+ unsigned int uint;
+ char tmp[2];
+
+ if (format != NULL) {
+ while (*format != '\0') {
+ str = strchr(format, '%');
+ if (str == NULL) {
+ strcpy(&string[count], format);
+ count += strlen(format);
+ break;
+ } else {
+ if (format < str) {
+ ULONG len = str - format;
+
+ strncpy(&string[count],
+ (char *) format, len);
+ count += len;
+ }
+
+ format = str + 1;
+ if(*format == 'l')
+ format = str + 2;
+
+ switch (*format) {
+ case 'u':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 10);
+ strcpy(&string[count], str);
+ count += strlen(str);
+ break;
+
+ case 'p':
+ case 'x':
+ uint = va_arg(ap, unsigned int);
+ str = numtostr(uint, 16);
+ strcpy(&string[count], str);
+ count += strlen(str);
+ break;
+
+ case 's':
+ str = va_arg(ap, const char *);
+ if( !str )
+ str = "(NULL)";
+ strcpy(&string[count], str);
+ count += strlen(str);
+ break;
+
+ case 'c':
+ tmp[0] = (char)va_arg(ap, int);
+ tmp[1] = '\0';
+ strcpy(&string[count], tmp);
+ count++;
+ break;
+
+ case '%':
+ strcpy(&string[count], "%");
+ count++;
+ break;
+
+ case '\0': /* format error */
+ default:
+ return EOF;
+ }
+
+ format += 1;
+ }
+ }
+ }
+ string[count]='\0';
+ return count;
+}
+
+
+int sprintf(char* str, const char *format, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, format);
+ result = vsprintf(str, format, ap);
+ va_end(ap);
+
+ return result;
+}
diff --git a/arclib/stdio.h b/arclib/stdio.h
new file mode 100644
index 0000000..4a29336
--- /dev/null
+++ b/arclib/stdio.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _STDIO_H_
+#define _STDIO_H_
+
+#include "types.h"
+#include <stdarg.h>
+
+typedef ULONG FILE;
+
+#define EOF (-1)
+
+extern FILE *stdin;
+extern FILE *stdout;
+
+extern int fputs(const char *s, FILE * stream);
+extern int puts(const char *s);
+
+extern int fgetc(FILE * stream);
+#define getc(stream) fgetc(stream)
+#define getchar() getc(stdin)
+
+extern int printf(const char *format, ...);
+extern int fprintf(FILE * stream, const char *format, ...);
+extern int sprintf(char* string, const char* format, ...);
+extern int vprintf(const char *format, va_list ap);
+extern int vfprintf(FILE * stream, const char *format, va_list ap);
+extern int vsprtinf(char* string, const char* format, va_list ap);
+
+#endif /* _STDIO_H_ */
diff --git a/arclib/stdlib.c b/arclib/stdlib.c
new file mode 100644
index 0000000..1377ff0
--- /dev/null
+++ b/arclib/stdlib.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#include "stdlib.h"
+#include "string.h"
+#include "arc.h"
+
+
+typedef struct _Node {
+ size_t size;
+ struct _Node *next;
+} Node;
+
+static Node *freeList = NULL;
+
+
+void *malloc(size_t size)
+{
+ Node **free, *mem;
+
+ size +=
+ /* header */ sizeof(Node) + /* round up */ (sizeof(Node) - 1);
+ size -= size % sizeof(Node);
+
+ free = &freeList;
+ while ((*free != NULL) && ((*free)->size < size))
+ free = &((*free)->next);
+
+ mem = *free;
+ if (mem != NULL) {
+ if (mem->size > size) {
+ Node *split = mem + (size / sizeof(Node));
+
+ split->size = mem->size - size;
+ split->next = mem->next;
+ mem->size = size;
+ mem->next = split;
+ }
+ *free = mem->next;
+ mem += 1;
+ }
+
+ return ((void *) mem);
+}
+
+
+void free(void *ptr)
+{
+ if (ptr != NULL) {
+ Node *mem = ((Node *) ptr) - 1;
+ Node **free = &freeList;
+
+ while ((*free != NULL) && (*free < mem)) {
+ if (mem ==
+ (*free + ((*free)->size / sizeof(Node)))) {
+ (*free)->size += mem->size;
+ mem = *free;
+ break;
+ }
+ free = &((*free)->next);
+ }
+
+ if (mem != *free) {
+ mem->next = *free;
+ *free = mem;
+ }
+
+ if (mem->next == (mem + (mem->size / sizeof(Node)))) {
+ mem->size += mem->next->size;
+ mem->next = mem->next->next;
+ }
+ }
+}
+
+
+void *realloc(void *ptr, size_t size)
+{
+ if (ptr == NULL) {
+ ptr = malloc(size);
+ } else {
+ Node *mem = ((Node *) ptr) - 1;
+
+ size +=
+ /* header */ sizeof(Node) +
+ /* round up */ (sizeof(Node) - 1);
+ size -= size % sizeof(Node);
+
+ if (size > mem->size) {
+ /* Should try to grow */
+ void *optr = ptr;
+
+ ptr = malloc(size);
+ if (ptr != NULL) {
+ memcpy(ptr, optr,
+ mem->size - sizeof(Node));
+ free(optr);
+ }
+ } else if (size < mem->size) {
+ Node *split = mem + (size / sizeof(Node));
+
+ split->size = mem->size - size;
+ split->next = mem->next;
+ mem->size = size;
+ free((void *) (split + 1));
+ }
+ }
+
+ return ptr;
+}
+
+
+void arclib_malloc_add(ULONG start, ULONG size)
+{
+ Node *node = (Node *) start;
+
+ node->size = size - (size % sizeof(Node));
+ free((void *) (node + 1));
+}
diff --git a/arclib/stdlib.h b/arclib/stdlib.h
new file mode 100644
index 0000000..7fb829f
--- /dev/null
+++ b/arclib/stdlib.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _STDLIB_H_
+#define _STDLIB_H_
+
+#include "stddef.h"
+#include "types.h"
+
+extern void *malloc(size_t size);
+extern void free(void *ptr);
+extern void *realloc(void *ptr, size_t size);
+
+extern void arclib_malloc_add(ULONG start, ULONG size);
+
+#endif /* _STDLIB_H_ */
diff --git a/arclib/string.c b/arclib/string.c
new file mode 100644
index 0000000..6ff3cfb
--- /dev/null
+++ b/arclib/string.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 1999, 2001 Silicon Graphics, Inc.
+ * Copyright 2001 Ralf Baechle
+ * 2001 Guido Guenther <agx@sgixcpu.org>
+ */
+#include "string.h"
+
+#include "stdlib.h"
+
+size_t strlen(const char *s)
+{
+ size_t len = 0;
+
+ while (*(s++) != '\0')
+ len += 1;
+
+ return len;
+}
+
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+ while (n-- > 0) {
+ if (*s1 < *s2)
+ return -1;
+ else if (*s1 > *s2)
+ return 1;
+ else if (*s1 == '\0')
+ return 0;
+ s1 += 1;
+ s2 += 1;
+ }
+
+ return 0;
+}
+
+/* from lib/string.c in the kernel sources */
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+
+char *strchr(const char *s, int c)
+{
+ while ((*s != (char) c) && (*s != '\0'))
+ s += 1;
+ return (char *) ((*s == '\0') ? NULL : s);
+}
+
+
+char *strcpy(char *s1, const char *s2)
+{
+ char *s = s1;
+
+ do {
+ *(s1++) = *(s2);
+ } while(*s2++ != 0x0);
+
+ return s;
+}
+
+
+char *strncpy(char *s1, const char *s2, size_t n)
+{
+ char *s = s1;
+
+ while (n-- > 0) {
+ if ((*(s1++) = *(s2++)) == '\0')
+ break;
+ }
+
+ return s;
+}
+
+
+char *strdup(const char *s1)
+{
+ char *str = malloc(strlen(s1) + 1);
+
+ if (str != NULL)
+ strcpy(str, s1);
+ return str;
+}
+
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ signed char res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+
+void *memcpy(void *s1, const void *s2, size_t n)
+{
+ char *c1 = (char *) s1;
+ const char *c2 = (const char *) s2;
+
+ while (n-- > 0)
+ *(c1++) = *(c2++);
+ return s1;
+}
+
+
+void *memset(void *s, int c, size_t n)
+{
+ char *mem = (char *) s;
+
+ while (n-- > 0)
+ *(mem++) = (char) c;
+ return s;
+}
+
+void __bzero(char *p, int len)
+{
+ memset(p, 0, len);
+}
diff --git a/arclib/string.h b/arclib/string.h
new file mode 100644
index 0000000..53bf111
--- /dev/null
+++ b/arclib/string.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ * 2001 Guido Guenther <agx@sigxcpu.org>
+ */
+#ifndef _STRING_H_
+#define _STRING_H_
+
+#include "stddef.h"
+
+extern size_t strlen(const char *s);
+extern int strcmp(const char *s1,const char *s2);
+extern int strncmp(const char *s1, const char *s2, size_t n);
+extern char *strchr(const char *s, int c);
+extern char *strcpy(char *s1, const char *s2);
+extern char *strncpy(char *s1, const char *s2, size_t n);
+extern char *strdup(const char *s1);
+
+extern void *memcpy(void *s1, const void *s2, size_t n);
+extern void *memset(void *s, int c, size_t n);
+int memcmp(const void * cs,const void * ct,size_t count);
+extern void __bzero(char *p, int len);
+
+#endif /* _STRING_H_ */
diff --git a/arclib/types.h b/arclib/types.h
new file mode 100644
index 0000000..6467169
--- /dev/null
+++ b/arclib/types.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+typedef unsigned short USHORT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef void VOID;
+typedef char CHAR;
+typedef unsigned char UCHAR;
+
+#endif /* _TYPES_H_ */
diff --git a/common/.cvsignore b/common/.cvsignore
new file mode 100644
index 0000000..d2b1118
--- /dev/null
+++ b/common/.cvsignore
@@ -0,0 +1 @@
+print_loadaddr
diff --git a/common/Makefile b/common/Makefile
new file mode 100644
index 0000000..2f160e3
--- /dev/null
+++ b/common/Makefile
@@ -0,0 +1,16 @@
+SUBARCH ?= IP22
+
+CFLAGS += -Wall -O2 -I. -I../arclib -DSUBARCH=${SUBARCH}
+
+HOSTCC = $(CC)
+HOSTCFLAGS += -Wall -O2 -DSUBARCH=$(SUBARCH)
+
+all: print_loadaddr
+
+print_loadaddr: print_loadaddr.c subarch.h version.h
+ $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
+
+install: print_loadaddr
+
+clean:
+ rm -f print_loadaddr *~ tags
diff --git a/common/print_loadaddr.c b/common/print_loadaddr.c
new file mode 100644
index 0000000..17d648d
--- /dev/null
+++ b/common/print_loadaddr.c
@@ -0,0 +1,30 @@
+/* small helper to get the current subarch's loaddr */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <strings.h>
+
+#include "subarch.h"
+
+int main(int argc, char *argv[])
+{
+ int subarch = SUBARCH;
+
+ if (argc == 2) {
+ if (!strcasecmp(argv[1], "ip22"))
+ subarch = IP22;
+ else if (!strcasecmp(argv[1], "ip32"))
+ subarch = IP32;
+ else {
+ fprintf(stderr,
+ "Unknown subarchitecture %s requested\n",
+ argv[1]);
+ return 1;
+ }
+ }
+
+ printf("%#08x\n", kernel_load[subarch].base
+ + kernel_load[subarch].reserved);
+
+ return 0;
+}
diff --git a/common/print_outputformat b/common/print_outputformat
new file mode 100755
index 0000000..5593a3c
--- /dev/null
+++ b/common/print_outputformat
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# default to ecoff
+
+case $1 in
+ ip32 | IP32) echo "elf32-tradbigmips" ;;
+ ip22 | IP22) echo "ecoff-bigmips" ;;
+ *) echo "ecoff-bigmips" ;;
+esac
diff --git a/common/subarch.h b/common/subarch.h
new file mode 100644
index 0000000..eba5ef0
--- /dev/null
+++ b/common/subarch.h
@@ -0,0 +1,51 @@
+/*
+ * subarch specific definitions
+ */
+
+#ifndef SUBARCH_H
+#define SUBARCH_H
+
+#include <stdint.h>
+
+#define PAGE_SIZE 4096
+#define STACK_PAGES 16
+
+/* supported subarches */
+#define IP22 0
+#define IP32 1
+
+/*
+ * Reserve this memory for loading kernel
+ * Don't put loader structures there because they would be overwritten
+ *
+ * We put the loader right after the kernel so you won't have the
+ * full reserved space since the prom puts the stack right below
+ * the loader.
+ */
+struct kernel_load_block {
+ uint32_t base;
+ uint32_t reserved;
+};
+
+struct kernel_load_block kernel_load[] = {
+ { /* IP22 */
+ .base = 0x88002000,
+ .reserved = 0x800000,
+ },
+ { /* IP32 */
+ .base = 0x80004000,
+ .reserved = 0x1400000,
+ },
+};
+
+/* we filter these out of the command line */
+char* env_vars[] = { "ConsoleIn=",
+ "ConsoleOut=",
+ "OSLoader=",
+ "OSLoadPartition=",
+ "OSLoadFilename=",
+ "OSLoadOptions=",
+ };
+#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
+
+#endif
diff --git a/common/version.h b/common/version.h
new file mode 100644
index 0000000..c144648
--- /dev/null
+++ b/common/version.h
@@ -0,0 +1 @@
+#define __ARCSBOOT_VERSION__ "0.3.8.8"
diff --git a/debian/.cvsignore b/debian/.cvsignore
new file mode 100644
index 0000000..9dd94e8
--- /dev/null
+++ b/debian/.cvsignore
@@ -0,0 +1,5 @@
+arcboot
+arcboot.postrm.debhelper
+arcboot.substvars
+files
+tip22
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644
index 0000000..ed4bb5f
--- /dev/null
+++ b/debian/README.Debian
@@ -0,0 +1,8 @@
+arcboot for Debian
+------------------
+
+You can check out arcboot's source from linux-mips.org's cvs archive:
+
+cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs login
+(password is "cvs")
+cvs -d :pserver:cvs@ftp.linux-mips.org:/home/cvs co arcboot
diff --git a/debian/arcboot.8 b/debian/arcboot.8
new file mode 100644
index 0000000..533c412
--- /dev/null
+++ b/debian/arcboot.8
@@ -0,0 +1,68 @@
+.TH "ARCBOOT" "8" "10 February 2002" "" ""
+.SH NAME
+arcboot \- bootloader for SGI/MIPS IP22 machines
+.SH SYNOPSIS
+
+\fB/usr/sbin/arcboot\fR <device>
+
+.SH "DESCRIPTION"
+.PP
+\fBarcboot\fR is the bootloader used on SGI/MIPS IP22 machines. It currently
+supports booting the kernel from an ext{2,3} filesystem and usually resides in
+the volume header of a disk with a SGI disklabel.
+.SH "USAGE"
+.PP
+<device> is the device name of the disk containing the volume header
+\fBarcboot\fR should go into. To use \fBarcboot\fR you have to modify
+the following PROM variables:
+.P
+\fIsetenv OSLoader arcboot\fR
+.P
+\fIsetenv SystemPartition scsi(0)disk(X)rdisk(0)partition(8)\fR
+.P
+\fIsetenv OSLoadPartition scsi(0)disk(Y)rdisk(0)partition(Z)\fR
+.P
+\fIsetenv OSLoadFilename label_or_filename
+.P
+(where "X" is the scsi ID of the disk \fBarcboot\fR resides on and "Y" and "Z"
+are the scsi ID and partition number of the partition \fB/etc/arcboot.conf\fR
+resides on). Note that \fB/etc/arcboot.conf\fR and the directory your kernels
+are in (usually /boot/) have to be on the same partition. On boot
+\fBarcboot\fR looks at the \fIOSLoadFilename\fR PROM variable and tries to find
+a label with the same name in \fB/etc/arcboot.conf\fR.
+
+.SH "Configuration File"
+An entry in \fB/etc/arcboot.conf\fR has the following format:
+.P
+label=<label>
+ image=<kernel>
+ append=<boot options>
+
+<label> is referenced by \fIOSLoadFilename\fR, <image> is the path to the
+kernel(again relative to \fIOSLoadPartition\fR) and <boot options> are the
+options appended to the kernel's command line.
+
+.SH "Example"
+label=linux
+ image=/boot/vmlinux-2.4.17
+ append="root=/dev/sda1 console=ttyS0"
+
+.SH "Notes"
+arcboot only loads ELF kernels. It doesn't handle ECOFF kernels to keep arcboot
+as small as possible and because ECOFF kernels on mips don't contain any symbol
+information which makes debugging more difficult.
+
+.SH "Files"
+.BR /etc/arcboot.conf
+\fBarcboot\fR's configuration file
+.P
+.BR /usr/share/doc/arcboot/README
+more details on howto setup arcboot
+.PP
+.SH "SEE ALSO"
+.PP
+dvhtool(1), elf2ecoff(8), tip22(8)
+.SH "AUTHORS"
+Arcboot is based on the arc bootloader for SGI Visual workstations written
+by Ralf Bächle <ralf@gnu.org>. Modifications for IP22 by Guido Günther
+<agx@sigxcpu.org>.
diff --git a/debian/arcboot.manpages b/debian/arcboot.manpages
new file mode 100644
index 0000000..b52d639
--- /dev/null
+++ b/debian/arcboot.manpages
@@ -0,0 +1 @@
+debian/arcboot.8
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..bd77615
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,243 @@
+arcboot (0.3.8.8) unstable; urgency=low
+
+ * Non-Maintainer Upload, with maintainer consent.
+ * scripts/arcboot:
+ + Fix syntax error when $IMAGE isn't found (closes: #329111).
+ * debian/control:
+ + Bumped Standards-Version to 3.7.2 (no changes).
+ + Added ${misc:Depends} to arcboot's Depends, to get the debconf
+ dependency.
+ * Added spanish debconf translation, courtesy of César Gómez Martín
+ (closes: #333875).
+ * Added swedish debconf translation, courtesy of Daniel Nylander
+ (closes: #331295).
+ * Fixed po/ja.po Content-Type (seems to be UTF-8 instead of EUC-JP ?)
+
+ -- Julien BLACHE <jblache@debian.org> Mon, 14 Aug 2006 11:34:48 +0000
+
+arcboot (0.3.8.7) unstable; urgency=low
+
+ * Add vietnamese translation, thanks Clytie Siddall (Closes: #313114).
+ * Add czech translation, thanks Miroslav Kure (Closes: #317662).
+ * Switch from the local e2fslib to the up-to-date libext2fs-nopic.a
+ in Debian, but don't delete the old version for now.
+ * Avoid inclusion of kernel headers.
+
+ -- Thiemo Seufer <ths@debian.org> Sat, 17 Sep 2005 20:15:35 +0200
+
+arcboot (0.3.8.6) unstable; urgency=low
+
+ * Allow ELF64 kernels for tip22/tip32.
+
+ -- Thiemo Seufer <ths@debian.org> Sun, 06 Feb 2005 01:51:01 +0100
+
+arcboot (0.3.8.5) unstable; urgency=low
+
+ * Add da debconf translation by Morten Brix Pedersen, thanks
+ (Closes: #276691).
+ * Add tip32 for IP32 machines.
+ * Rework build system.
+ * Vastly improved loader performance, thanks Keith Wesolowski.
+
+ -- Thiemo Seufer <ths@debian.org> Mon, 31 Jan 2005 21:24:00 +0100
+
+arcboot (0.3.8.4) unstable; urgency=low
+
+ * fix compilation with gcc-3.3 for tip22 also (Closes: #273951)
+ * mention IP32 in arcboots package description
+
+ -- Guido Guenther <agx@debian.org> Mon, 27 Sep 2004 16:45:11 +0200
+
+arcboot (0.3.8.3) unstable; urgency=low
+
+ * fix IP32/O2 subarch detection again, I hate /proc/cpuinfo changes
+ * the 'de' debconf translation was in the last upload already
+ (Closes: #250572)
+ * finally tested it on IP32 myself and it work{s,ed}
+ * fixup linker script to work with gcc-3.3 too
+
+ -- Guido Guenther <agx@debian.org> Sat, 25 Sep 2004 23:32:38 +0200
+
+arcboot (0.3.8.2) unstable; urgency=low
+
+ * /usr/sbin/arcboot uses file so depend on it (Closes: #236970)
+ * add nl debconf translation by Luk Claes, thanks (Closes: #244632)
+
+ -- Guido Guenther <agx@debian.org> Tue, 20 Apr 2004 10:30:14 +0200
+
+arcboot (0.3.8.1) unstable; urgency=low
+
+ * correct subarch detection for IP32
+
+ -- Guido Guenther <agx@debian.org> Tue, 2 Mar 2004 12:01:14 +0100
+
+arcboot (0.3.8) unstable; urgency=low
+
+ * add support to load 64bit kernels (by Vivien Chappelier and Ilya Volynets)
+ * hack up makefile to allow for easier per subarch builds
+ * debian/rules: build and include arcboot.ip32 in the package.
+ * modify arcboot script to select the correct arcboot.subarch when
+ putting the loader in the volume header
+ * use ext2_fs.h from e2fslib instead of linux/ext2fs.h to not depend
+ on kernel headers
+ * add pt translation by Bruno Rodrigues, thanks (Closes: #216392)
+ * add pt_BR translation by Andre Luis Lopes, thanks (Closes: #228285)
+ * add ja translaton by Hideki Yamane, thanks (Closes: #234087)
+
+ -- Guido Guenther <agx@debian.org> Mon, 1 Mar 2004 12:42:06 +0100
+
+arcboot (0.3.7) unstable; urgency=low
+
+ * postinst: call arcboot after arcboot.conf was created
+ * /usr/sbin/arcboot: abort if we don't find a configuration file
+ * fix typo in control file, thanks to Julien Blache <jblache at debian.org>,
+ (Closes: #192810)
+ * use po-debconf, patch by Christian Perrier <bubulle at ebian.org>, thanks!
+ (Closes: #205819)
+ * add French translation, thanks again Christian! (Closes: #206586)
+ * fix "Upstream Authors(s)" in copyright file
+ * reformat debian/control to 80 characters
+ * bump Standards-Version to 3.6.1
+
+ -- Guido Guenther <agx@debian.org> Sun, 31 Aug 2003 22:53:20 +0200
+
+arcboot (0.3.6) unstable; urgency=low
+
+ * fix command line handling, now things like
+ boot linux root=/dev/sda1 single
+ should work as expected, no need to mess with OSLoadOptions
+ * fix booting arbitrary files
+ boot /vmlinux root=/dev/sda1
+ will now properly boot OSLoadPartition/vmlinux
+ * search for OSLoadPartition if the envvar is bogus
+ * add missing prototypes, cleanup printf length modifiers
+ * move some common definitions to subarch.h
+ * use gcc-2.95
+ * adding other 32bit IPs to arcboot is now a two line change
+ in common/subarch.h
+ * arcboot script now prints what it's doing
+ * postrm: silent grep on new installs
+ * echo 4 > debian/compat
+ * Build-Depend: on debhelper (>=4)
+ * Bump Standards Version to 3.5.9
+ * add ${misc:Depends}
+
+ -- Guido Guenther <agx@debian.org> Sat, 26 Apr 2003 22:01:14 +0200
+
+arcboot (0.3.5) unstable; urgency=low
+
+ * relax arcboots ELF check to make it recongnize kernels built with
+ newer binutils
+ * make strcpy copy the trailing '\0', thanks to Florian Lohoff for the patch
+ * compile version number from changelog into arcsboot/tip22
+ * spelling fixes
+ * minor debian/rules cleanup
+
+ -- Guido Guenther <agx@debian.org> Fri, 27 Sep 2002 14:06:36 +0200
+
+arcboot (0.3.4) unstable; urgency=low
+
+ * don't let ext2fs errors crash the loader
+ * remove dead code (larc.c)
+ * Fix description, thanks Joey! (Closes: #153084)
+
+ -- Guido Guenther <agx@debian.org> Tue, 16 Jul 2002 01:05:49 +0200
+
+arcboot (0.3.3) unstable; urgency=low
+
+ * tip22 calculated the highest address of the kernel's memory image
+ wrong - fixed
+ * tip22 now passes everything in an append="...." statement on to the kernel's
+ commandline
+ * improve {s,f}printf (handle "%p","%lx", be more graceful on unimplemented
+ format specifiers)
+ * make tip22 script more failsafe
+ * removed all printing of version numbers/dates on startup
+ * typo fixes, minor doc updates
+
+ -- Guido Guenther <agx@debian.org> Thu, 16 May 2002 00:49:28 +0200
+
+arcboot (0.3.2) unstable; urgency=low
+
+ * implemented "tip22" bootloader. It embeds kernel and initrd in one
+ ECOFF binary. This can be used for either tftp- or CD-booting and makes
+ addinitrd in the mips-tools package obselete.
+ * update package built to include tip22
+ * add snprintf() to arclib (needed by tip22)
+ * remove snprintf() stub from ext2io.c
+ * Makefile and docu cleanups
+ * add a rudimentary manpage for tip22
+
+ -- Guido Guenther <agx@debian.org> Thu, 9 May 2002 22:01:11 +0200
+
+arcboot (0.3.1) unstable; urgency=low
+
+ * move arcboot's load address 1MB upwards to let more room for larger
+ kernels
+ * check if the kernels in /etc/arcboot.conf are really ELF (Closes: #144728)
+ * add some logic to determine the vh arcboot should go into in arcboot.config
+ * update TODO
+
+ -- Guido Guenther <agx@debian.org> Sat, 23 Feb 2002 20:21:50 +0100
+
+arcboot (0.3) unstable; urgency=low
+
+ * update manpage, README and package description
+ * disable debugging output
+
+ -- Guido Guenther <agx@debian.org> Sun, 10 Feb 2002 20:04:55 +0100
+
+arcboot (0.2) unstable; urgency=low
+
+ * close ITP (Closes: #119163)
+ * the diff was far larger than the .orig.tar.gz so make this a
+ debian native package
+ * add debconf dependency
+ * update manpage
+ * apply patch from Flo <flo@rfc822.org> with an updated linker scipt
+ removing the mips-tools dependency
+ * generate /etc/arcboot.conf if it doesn't exist
+
+ -- Guido Guenther <agx@debian.org> Sat, 9 Feb 2002 02:30:04 +0100
+
+arcboot (0.1-3) experimental; urgency=low
+
+ * replace "\n" by "\n\r" for proper output on serial consoles
+ * apply patch from Florian Lohoff to fix bad OSLoadFilename
+ and formatting
+ * use elf2ecoff to convert arcboot into an ecoff image
+ * if OSLoadOptions starts with "/" it's a kernel name otherwise
+ a label in arcboot.conf
+ * remove shlibs from Depends in control file
+ * change loadaddress of the bootloader 0x8820f000
+ * add cacheflush before jumping into the kernel
+ * add debconf frontend
+ * add missing -d in dvhtool call to /usr/sbin/arcboot
+ * finally remove run.S and disable larc build
+
+ -- Guido Guenther <agx@debian.org> Fri, 8 Feb 2002 23:42:18 +0100
+
+arcboot (0.1-2) unstable; urgency=low
+
+ * added config file parsing (an example is in /u/s/d/arcboot/examples)
+ * added a small script to move arcboot into the volume header
+
+ -- Guido Guenther <agx@debian.org> Sun, 18 Nov 2001 18:09:49 +0100
+
+arcboot (0.1-1) unstable; urgency=low
+
+ * Initial Release.
+ * warning fixes
+ * make memset & free return the same values as the libc versions
+ * build with -mno-abicalls -G 0 -fno-pic, so the prom can deal with it
+ * use basically the kernel's linker script to link arcboot
+ * move all addresses into KSEG0
+ * IP22 is ARCS not ARC (MEMORYTYPE in arc.h)
+ * IP22 is big endian (LARGEINTEGER in arc.h)
+ * remove run.S and call the kernel entry via a C function call
+ * add everything that is needed from e2fsprogs so we can build
+ a libe2fs with -fnopic -mno-abicalls -G 0
+ * make sure arcboot doesn't use the system ext2fs header files
+
+ -- Guido Guenther <agx@debian.org> Mon, 12 Nov 2001 00:21:31 +0100
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+4
diff --git a/debian/config b/debian/config
new file mode 100644
index 0000000..db1136d
--- /dev/null
+++ b/debian/config
@@ -0,0 +1,17 @@
+#!/bin/sh -e
+#$Id: config,v 1.1 2004/11/29 10:39:38 ladis Exp $
+
+# Source debconf library.
+. /usr/share/debconf/confmodule
+
+# Already seen?
+db_fget arcboot/boot_device seen
+if [ "$RET" = "false" ]; then
+ # what about devfs?
+ ROOTDEVICE=`mount | grep '[[:space:]]/[[:space:]]' | cut -d' ' -f 1`
+ BOOTDEVICE=`echo $ROOTDEVICE | sed 's/[12345678]*$//'`
+ db_set arcboot/boot_device $BOOTDEVICE
+fi
+
+db_input medium arcboot/boot_device || true
+db_go
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..448b5fd
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,27 @@
+Source: arcboot
+Section: admin
+Priority: optional
+Maintainer: Guido Guenther <agx@debian.org>
+Uploaders: Thiemo Seufer <ths@debian.org>
+Build-Depends: debhelper (>=4.1.16), e2fslibs-dev
+Standards-Version: 3.7.2
+
+Package: arcboot
+Architecture: mips
+Depends: dvhtool, ${misc:Depends}
+Description: Bootloader for SGI/MIPS IP22 and IP32 machines
+ arcboot is a bootloader for SGI/MIPS IP22 and IP32 machines like the Indy,
+ Indigo2 and O2. It is able to boot the Linux kernel from ext2 and ext3
+ filesystems. Support for other ARCS based subarchitectures can easily be
+ added. It is currently not capable of booting IRIX or to boot from iso9660
+ CDROMs though.
+
+Package: tip22
+Architecture: mips
+Depends: binutils | binutils-multiarch, file
+Description: Tftp boot image builder for SGI/MIPS IP22 and IP32 machines
+ tip22 is used to merge kernel and initrd into one bootable image. This
+ image also contains a small loader stub that copies the kernel to its
+ load address and appends the ramdisk. This is useful for booting via tftp or
+ from a CDROM. It is currently targeted for the IP22 and IP32 subarchitectures
+ but support for other ARCS based subarchitectures can easily be added.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..33d84f0
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,13 @@
+This package was debianized by Guido Guenther <agx@debian.org> on
+Wed, 24 Oct 2001 19:28:10 +0200.
+
+Arcboot was downloaded from oss.sgi.com's cvs repository. See README.Debian for
+details. tip22 was added later as native debian part.
+
+Upstream Authors: Ralf Baechle, Guido Günther
+
+Copyright:
+
+ You are free to distribute this software under the terms of the GNU General
+ Public License. The full text of this license can be found in the file
+ /usr/share/common-licenses/GPL
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..1555bc9
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,3 @@
+usr/lib/arcboot
+usr/sbin
+etc/
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..724e084
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
+README
+TODO
diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in
new file mode 100644
index 0000000..cef83a3
--- /dev/null
+++ b/debian/po/POTFILES.in
@@ -0,0 +1 @@
+[type: gettext/rfc822deb] templates
diff --git a/debian/po/cs.po b/debian/po/cs.po
new file mode 100644
index 0000000..2c9825d
--- /dev/null
+++ b/debian/po/cs.po
@@ -0,0 +1,40 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2005-07-10 16:11+0200\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Kam chcete arcboot nainstalovat?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"Arcboot se musí nainstalovat do hlaviÄky svazku na disk obsahující SGI "
+"disklabel. Obvykle se používá /dev/sda. Zadejte prosím jméno zařízení "
+"disku, na který chcete arcboot nainstalovat."
diff --git a/debian/po/da.po b/debian/po/da.po
new file mode 100644
index 0000000..65ae6c4
--- /dev/null
+++ b/debian/po/da.po
@@ -0,0 +1,40 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot 0.3.8.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2004-10-15 18:02+0200\n"
+"Last-Translator: Morten Brix Pedersen <morten@wtf.dk>\n"
+"Language-Team: Danish <dansk@klid.dk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Hvor skal arcboot placeres?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"Arcoot skal placeres i 'volume' hovedet af en disk med et SGI-diskmærke. "
+"Normalt er 'volume' hovedet på /dev/sda brugt. Angiv enhedsnavnet på den "
+"disk du gerne vil placere arcboot på."
diff --git a/debian/po/de.po b/debian/po/de.po
new file mode 100644
index 0000000..8b6f233
--- /dev/null
+++ b/debian/po/de.po
@@ -0,0 +1,43 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+# Developers do not need to manually edit POT or PO files.
+# Erik Schanze <mail@erikschanze.de>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot_0.3.8.1_de\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2004-05-23 22:29+0200\n"
+"Last-Translator: Erik Schanze <mail@erikschanze.de>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.3.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Wo soll arcboot abgelegt werden?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"Arcboot muss in den Volume-Header einer Festplatte mit einem SGI Disk-Label "
+"abgelegt werden. Normalerweise wird der Volume-Header von /dev/sda "
+"benutzt. Bitte geben Sie den Gerätenamen der Festplatte ein, wo arcboot "
+"abgelegt werden soll."
+
diff --git a/debian/po/es.po b/debian/po/es.po
new file mode 100644
index 0000000..d64bf6a
--- /dev/null
+++ b/debian/po/es.po
@@ -0,0 +1,51 @@
+# arcboot po-debconf translation to Spanish
+# Copyright (C) 2005 Software in the Public Interest
+# This file is distributed under the same license as the arcboot package.
+#
+# Changes:
+# - Initial translation
+# César Gómez Martín <cesar.gomez@gmail.com>
+#
+# Traductores, si no conoce el formato PO, merece la pena leer la
+# documentación de gettext, especialmente las secciones dedicadas a este
+# formato, por ejemplo ejecutando:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Equipo de traducción al español, por favor, lean antes de traducir
+# los siguientes documentos:
+#
+# - El proyecto de traducción de Debian al español
+# http://www.debian.org/intl/spanish/
+# especialmente las notas de traducción en
+# http://www.debian.org/intl/spanish/notas
+#
+# - La guía de traducción de po's de debconf:
+# /usr/share/doc/po-debconf/README-trans
+# o http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2005-10-03 18:36+0100\n"
+"Last-Translator: César Gómez Martín <cesar.gomez@gmail.com>\n"
+"Language-Team: Debian l10n spanish <debian-l10n-spanish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Spanish\n"
+"X-Poedit-Country: SPAIN\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "¿Dónde desea poner arcboot?"
+
+#. Description
+#: ../templates:4
+msgid "Arcboot must be put into the volume header of a disk with a SGI disklabel. Usually the volume header of /dev/sda is used. Please give the device name of the disk you want to put arcboot onto."
+msgstr "Se debe poner arcboot en la cabecera del volumen de un disco con una etiqueta SGI. Normalmente la cabecera del volumen de /dev/sda está usada. Por favor, especifique el nombre del dispositivo del disco en el que quiere poner arcboot."
+
+
diff --git a/debian/po/fr.po b/debian/po/fr.po
new file mode 100644
index 0000000..a425407
--- /dev/null
+++ b/debian/po/fr.po
@@ -0,0 +1,40 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot (0.3.6)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2003-08-05 09:41+0100\n"
+"Last-Translator: Christian Perrier <bubulle@debian.org>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Où faut-il installer arcboot ?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"Arcboot doit être installé sur la partition de démarrage d'un disque comportant "
+"une étiquette de disque SGI (« SGI disklabel »). Veuillez indiquer le nom de "
+"périphérique du disque où vous souhaitez installer arcboot."
diff --git a/debian/po/ja.po b/debian/po/ja.po
new file mode 100644
index 0000000..7436ef3
--- /dev/null
+++ b/debian/po/ja.po
@@ -0,0 +1,40 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot 0.3.7\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2004-01-12 22:02+0900\n"
+"Last-Translator: Hideki Yamane <henrich@samba.gr.jp>\n"
+"Language-Team: Japanese <debian-japanese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "¤É¤³¤Ë arcboot ¤ò½ñ¤­¹þ¤ß¤Þ¤¹¤«?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr "arcboot ¤à SGI ¥Ç¥£¥¹¥¯¥é¥Ù¥ë¤ò»ý¤Ã¤Æ¤¤¤ë¥Ç¥£¥¹¥¯¤Î¥Ü¥ê¥å¡¼¥à¥Ø¥Ã¥À¤Ë½ñ¤­¹þ¤Þ¤Ã¤Ã¤Ê¤ê¤Þ¤»¤ó¡£"
+"Ä̾/dev/sda ¤Î¥Ü¥ê¥å¡¼¥à¥Ø¥Ã¥À¤¬»ÈÃѤµ¤ì¤Þ¤¹¡£arcboot ¤òÇÛÃÖ¤·¤¿¤¤¥Ç¥Ã¥¤¥¹Ì¾¤òÆþÎ䷤Ƥ¯¤À¤µ¤¤¡£"
+
diff --git a/debian/po/nl.po b/debian/po/nl.po
new file mode 100644
index 0000000..aa7c739
--- /dev/null
+++ b/debian/po/nl.po
@@ -0,0 +1,34 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot 0.3.8.1\n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2004-04-16 11:04+0100\n"
+"Last-Translator: Luk Claes <luk.claes@ugent.be>\n"
+"Language-Team: Debian l10n Dutch <debian-l10n-dutch@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Waar moet arcboot geplaatst worden?"
+
+#. Description
+#: ../templates:4
+msgid "Arcboot must be put into the volume header of a disk with a SGI disklabel. Usually the volume header of /dev/sda is used. Please give the device name of the disk you want to put arcboot onto."
+msgstr "Arcboot moet geplaatst worden in een volumehoofding van een schijf met een SGI-schijflabel. Gewoonlijk wordt de volumehoofding van /dev/sda gebruikt. Geef de toestelnaam van de schijf waar u arcboot wilt op plaatsen."
+
diff --git a/debian/po/pt.po b/debian/po/pt.po
new file mode 100644
index 0000000..5386be7
--- /dev/null
+++ b/debian/po/pt.po
@@ -0,0 +1,41 @@
+# translation of arcboot_0.3.7_pt.po to Portuguese
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+# Developers do not need to manually edit POT or PO files.
+# Bruno Rodrigues <bruno.rodrigues@litux.org>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot_0.3.7_pt\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2003-10-18 13:43+0100\n"
+"Last-Translator: Bruno Rodrigues <bruno.rodrigues@litux.org>\n"
+"Language-Team: Portuguese <debian-l10n-portuguese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.2\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Qual o dispositivo para instalar o arcboot?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"O arcboot deverá ser instalado no início de um disco marcado como SGI. "
+"Geralmente o dispositivo padrão é /dev/sda. Introduza o nome do dispositivo:"
+
diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po
new file mode 100644
index 0000000..ccbd732
--- /dev/null
+++ b/debian/po/pt_BR.po
@@ -0,0 +1,42 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot_0.3.7\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2004-01-17 21:15-0300\n"
+"Last-Translator: André Luís Lopes <andrelop@debian.org>\n"
+"Language-Team: Debian-BR Project <debian-l10n-portuguese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Onde colocar o arcboot ?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"O arcboor deve ser colocado dentro de um cabeçalho de volume de um disco "
+"com um disklabel SGI. Normalmente o cabeçalho de volume de /dev/sda é "
+"usado. Por favor, informe o nome do dispositivo do disco onde você deseja "
+"colocar o arcboot."
diff --git a/debian/po/sv.po b/debian/po/sv.po
new file mode 100644
index 0000000..bfc2a1a
--- /dev/null
+++ b/debian/po/sv.po
@@ -0,0 +1,40 @@
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+# Developers do not need to manually edit POT or PO files.
+# , fuzzy
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot 0.3.8-7\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2005-10-03 23:09+0200\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <sv@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Var ska arcboot ligga?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
+"Arcboot måste läggas i volymhuvudet på en disk med en SGI-disketikett. "
+"Normalt är volymhuvudet i /dev/sda använt. Vänligen ange enhetsnamnet "
+"på den disk du vill lägga arcboot på."
+
diff --git a/debian/po/templates.pot b/debian/po/templates.pot
new file mode 100644
index 0000000..97e4a9a
--- /dev/null
+++ b/debian/po/templates.pot
@@ -0,0 +1,38 @@
+#
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+# Developers do not need to manually edit POT or PO files.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr ""
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr ""
diff --git a/debian/po/vi.po b/debian/po/vi.po
new file mode 100644
index 0000000..7bb52c2
--- /dev/null
+++ b/debian/po/vi.po
@@ -0,0 +1,29 @@
+# Vietnamese translation for arcboot.
+# Copyright © 2005 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: arcboot 0.3.8.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-05 09:42+0200\n"
+"PO-Revision-Date: 2005-06-12 11:33+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <gnomevi-list@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. Description
+#: ../templates:4
+msgid "Where to put arcboot?"
+msgstr "Bạn có muốn để trình arcboot vào chỗ nào?"
+
+#. Description
+#: ../templates:4
+msgid ""
+"Arcboot must be put into the volume header of a disk with a SGI disklabel. "
+"Usually the volume header of /dev/sda is used. Please give the device name "
+"of the disk you want to put arcboot onto."
+msgstr "Phải để trình arcboot vào phần đầu khối tin của má»™t Ä‘Ä©a có nhãn Ä‘Ä©a SGI. ThÆ°á»ng dùng phần đầu khối tin của «/dev/sda». Hãy nhập tên thiết bị của Ä‘Ä©a nÆ¡i bạn muốn để trình arcboot."
diff --git a/debian/postinst b/debian/postinst
new file mode 100644
index 0000000..71e956d
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,41 @@
+#!/bin/bash
+# $Id: postinst,v 1.1 2004/11/29 10:39:38 ladis Exp $
+
+set -e
+
+# Source debconf library.
+. /usr/share/debconf/confmodule
+
+case "$1" in
+ configure)
+ db_get arcboot/boot_device || true
+
+ if [ ! -f /etc/arcboot.conf ]; then
+ # create /etc/arcboot.conf
+ ROOTDEVICE=`mount | grep -s '[[:space:]]/[[:space:]]' | cut -d' ' -f 1`
+
+cat << EOF > /etc/arcboot.conf
+# arcboot.conf
+#
+label=linux
+ image=/vmlinux
+ append="root=$ROOTDEVICE"
+EOF
+ fi
+ /usr/sbin/arcboot $RET
+
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..a66ac72
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,104 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+realver := $(shell dpkg-parsechangelog | awk -F' ' '/^Version:/ {print $$2}' | awk -F- '{print $$1}')
+
+PREFIX_ARCB=${CURDIR}/debian/arcboot
+BIN_ARCB=usr/sbin
+LIB_ARCB=usr/lib/arcboot
+
+PREFIX_TIP22=${CURDIR}/debian/tip22
+BIN_TIP22=usr/sbin
+LIB_TIP22=usr/lib/tip22
+
+architecture=$(dpkg --print-architecture)
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+
+ touch configure-stamp
+
+build: configure-stamp build-stamp
+build-stamp:
+ dh_testdir
+
+ # update the version string
+ echo "#define __ARCSBOOT_VERSION__ \"${realver}\"" > common/version.h
+ # build the package
+ $(MAKE) build-subarch-indep
+ $(MAKE) clean-subarch-dep
+ $(MAKE) SUBARCH=IP32 build-subarch-dep
+ cp ext2load/ext2load arcboot.ip32
+ $(MAKE) clean-subarch-dep
+ $(MAKE) SUBARCH=IP22 build-subarch-dep
+ cp ext2load/ext2load arcboot.ip22
+ touch build-stamp
+
+clean:
+ dh_testdir
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ -$(MAKE) clean
+ -rm -f arcboot.ip22 arcboot.ip32
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # install arcboot into debian/arcboot
+ install -m 644 arcboot.ip22 ${PREFIX_ARCB}/${LIB_ARCB}/arcboot.ip22
+ install -m 644 arcboot.ip32 ${PREFIX_ARCB}/${LIB_ARCB}/arcboot.ip32
+ install -m 755 scripts/arcboot ${PREFIX_ARCB}/${BIN_ARCB}/arcboot
+
+ # install tip22 into debian/tip22
+ $(MAKE) PREFIX=${PREFIX_TIP22} BINDIR=${BIN_TIP22} LIBDIR=${LIB_TIP22} -C arclib install
+ $(MAKE) PREFIX=${PREFIX_TIP22} BINDIR=${BIN_TIP22} LIBDIR=${LIB_TIP22} -C tip22 install
+
+# Build architecture-independent files here.
+binary-indep: build install
+# nothing to do
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdebconf
+ dh_installdocs
+ dh_installexamples etc/arcboot.conf -parcboot
+ dh_installexamples tip22/kernel/ -ptip22
+ dh_installmenu
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_installinit
+ dh_installcron
+ dh_installman
+ dh_installinfo
+# dh_undocumented
+ dh_installchangelogs
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+# dh_makeshlibs
+ dh_installdeb
+# dh_perl
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/templates b/debian/templates
new file mode 100644
index 0000000..b6b36db
--- /dev/null
+++ b/debian/templates
@@ -0,0 +1,7 @@
+Template: arcboot/boot_device
+Type: string
+Default: /dev/sda
+_Description: Where to put arcboot?
+ Arcboot must be put into the volume header of a disk with a SGI disklabel.
+ Usually the volume header of /dev/sda is used. Please give the device name
+ of the disk you want to put arcboot onto.
diff --git a/debian/tip22.8 b/debian/tip22.8
new file mode 100644
index 0000000..0791425
--- /dev/null
+++ b/debian/tip22.8
@@ -0,0 +1,26 @@
+.TH "TIP22" "8" "09 May 2002" "" ""
+.SH NAME
+tip22 \- create "piggyback" style boot images for SGI/MIPS IP22 machines
+.SH SYNOPSIS
+
+\fB/usr/sbin/tip22\fR <vmlinux> <initrd> <outfile>
+
+.SH "DESCRIPTION"
+.PP
+\fBtip22\fR is used on SGI/MIPS IP22 machines to embed kernel and initial
+ramdisk into one ECOFF image which can then be booted by the ARCS PROM. This is
+usually used to create tftp boot images.
+.SH "USAGE"
+.PP
+<vmlinux> is the ELF kernel you want to embed into the bootimage
+.P
+<initrd> is the (optionally gzip compressed) initial ramdisk
+.P
+<outfile> is the resulting tftpboot image
+
+.SH "SEE ALSO"
+.PP
+arcboot(8).
+.SH "AUTHORS"
+Tip22 was written by Guido Günther <agx@sigxcpu.org> and borrows heavily
+from arcboot written by Ralf Bächle <ralf@gnu.org> and Guido Günther.
diff --git a/debian/tip22.docs b/debian/tip22.docs
new file mode 100644
index 0000000..3e803b6
--- /dev/null
+++ b/debian/tip22.docs
@@ -0,0 +1,2 @@
+TODO
+tip22/README
diff --git a/debian/tip22.manpages b/debian/tip22.manpages
new file mode 100644
index 0000000..76b3ad8
--- /dev/null
+++ b/debian/tip22.manpages
@@ -0,0 +1,2 @@
+debian/tip22.8
+debian/tip32.8
diff --git a/debian/tip32.8 b/debian/tip32.8
new file mode 100644
index 0000000..1c3916b
--- /dev/null
+++ b/debian/tip32.8
@@ -0,0 +1,27 @@
+.TH "TIP32" "8" "17 November 2004" "" ""
+.SH NAME
+tip32 \- create "piggyback" style boot images for SGI/MIPS IP32 machines
+.SH SYNOPSIS
+
+\fB/usr/sbin/tip32\fR <vmlinux> <initrd> <outfile>
+
+.SH "DESCRIPTION"
+.PP
+\fBtip32\fR is used on SGI/MIPS IP32 machines (SGI O2) to embed kernel and
+initial ramdisk into one ELF image which can then be booted by the ARCS PROM.
+This is usually used to create tftp boot images.
+.SH "USAGE"
+.PP
+<vmlinux> is the ELF kernel you want to embed into the bootimage
+.P
+<initrd> is the (optionally gzip compressed) initial ramdisk
+.P
+<outfile> is the resulting tftpboot image
+
+.SH "SEE ALSO"
+.PP
+arcboot(8).
+.SH "AUTHORS"
+Tip32 is an adaption of tip22, which is the equivalent for SGI IP22 machines.
+Tip22 was written by Guido Günther <agx@sigxcpu.org> and borrows heavily
+from arcboot written by Ralf Bächle <ralf@gnu.org> and Guido Günther.
diff --git a/e2fslib/.cvsignore b/e2fslib/.cvsignore
new file mode 100644
index 0000000..66923b2
--- /dev/null
+++ b/e2fslib/.cvsignore
@@ -0,0 +1,3 @@
+ext2_err.c
+ext2_err.et
+ext2_err.h
diff --git a/e2fslib/ChangeLog b/e2fslib/ChangeLog
new file mode 100644
index 0000000..19b6825
--- /dev/null
+++ b/e2fslib/ChangeLog
@@ -0,0 +1,2274 @@
+2001-09-20 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.25
+
+2001-09-16 Theodore Tso <tytso@valinux.com>
+
+ * ext2_ext_attr.h: Remove unneeded #include of <linux/config.h>
+ which was breaking the build on the Hurd. (Addresses
+ Debian bug #112414).
+
+2001-09-13 Theodore Ts'o <tytso@valinux.com>
+
+ * ismounted.c (check_mntent_file): We now validate the entry in
+ /etc/mtab to make sure the filesystem is really mounted,
+ since some broken distributions (read: Slackware) have
+ buggy boot scripts that don't initialize /etc/mtab before
+ checking non-root filesystems. (Slackware also doesn't
+ check the root filesystem separately, and reboot if the
+ root filesystem had changes applied to it, which is
+ dangerous and broken.)
+
+2001-09-02 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.24a
+
+2001-08-30 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.24
+
+2001-08-30 Theodore Tso <tytso@valinux.com>
+
+ * getsize.c (ext2fs_get_device_size): Back out BLKGETSIZE64
+ changes, since the ioctl number has been reused by another
+ unofficial patch.
+
+2001-08-15 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.23
+
+2001-08-05 Theodore Tso <tytso@valinux.com>
+
+ * alloc.c (ext2fs_new_inode, ext2fs_new_block): Use the fast
+ version of the bitmap test routines to speed up these
+ routines. (At some point I may want to make these
+ routines use the find_first_bit functions, but that will
+ add a lot of complexity since it means that these
+ functions will have to break the bitmap abstraction
+ boundary. It's not clear it's worth it.)
+
+ * mkjournal.c (mkjournal_proc): Remember the last block allocated
+ to speed up ext2fs_new_block().
+
+2001-07-29 Theodore Tso <tytso@valinux.com>
+
+ * finddev.c (scan_dir): Fix memory leak; we weren't calling
+ closedir() when exiting the function in all cases.
+
+2001-07-27 Theodore Tso <tytso@valinux.com>
+
+ * mkjournal.c (ext2fs_create_journal_superblock): Set the first
+ block usable in the journal for external journals to be 2
+ or 3, depending on the blocksize, so that the existing
+ kernel code does the right thing.
+
+ * getsize.c (ext2fs_get_device_size): Add support for the
+ BLKGETSIZE64 ioctl. (Ioctl defined by unofficial patches
+ from Ben LaHaise, but it's likely this interface won't
+ change.)
+
+ * mkjournal.c (ext2fs_add_journal_device): Use the correct block
+ when writing the journal superblock, too. (Oops! Needed
+ to make 1k filesystems with external journal to work.)
+
+2001-07-26 Theodore Tso <tytso@valinux.com>
+
+ * mkjournal.c (ext2fs_add_journal_device): Use the correct block
+ to find the journal superblock if the blocksize is 1024.
+
+2001-07-21 Theodore Tso <tytso@valinux.com>
+
+ * ext2_err.et.in (EXT2_ET_LOAD_EXT_JOURNAL): Add new error code
+
+2001-07-20 Theodore Tso <tytso@valinux.com>
+
+ * ext_attr.c (ext2fs_write_ext_attr): When writing the extended
+ attribute block, set the filesystem changed bit.
+
+ * bitops.h (ext2fs_find_first_bit_set, ext2fs_find_next_bit_set):
+ Comment out these functions since we're not using them.
+
+2001-07-10 Theodore Tso <tytso@valinux.com>
+
+ * closefs.c (write_primary_superblock): After writing changes to
+ the primary superblock, update the original superblock
+ copy so we don't have to re-write those changes in the
+ future.
+ (ext2fs_flush): Clear the superblock dirty flag after
+ we've flushed out changes to disk.
+
+2001-07-07 Theodore Tso <tytso@valinux.com>
+
+ * bitops.h (ext2fs_find_first_bit_set): Use %esi instead of %ebx
+ to avoid register conflicts when compiling in PIC mode.
+
+2001-07-04 Theodore Tso <tytso@valinux.com>
+
+ * bitops.h (ext2fs_find_first_bit_set, ext2fs_find_next_bit_set):
+ Add new functions (C and in i386 assembler) which quickly
+ find bits set in a bitmask.
+
+2001-06-23 Theodore Tso <tytso@valinux.com>
+
+ * Makefile.in, ext_attr.c, ext2_attr.c, ext2fs.h: Add new files
+ ext2_ext_attr.h and ext_attr.c for extended attributes
+ support.
+
+ * Release of E2fsprogs 1.22
+
+2001-06-22 Theodore Tso <tytso@valinux.com>
+
+ * mkjournal.c (ext2fs_add_journal_inode): Move close of file
+ descriptor so that adding a journal to a mounted
+ filesystem doesn't die. (Fixes a bug accidentally
+ introduced in e2fsprogs 1.21.)
+
+ * mkjournal.c (ext2fs_add_journal_inode): Only use fchflags if
+ HAVE_CHFLAGS and UF_NODUMP are defined, since the Hurd has
+ fchflags without defining UF_NODUMP. (Addresses Debian
+ bug #101361)
+
+ * flushb.c: Use platform independent method of defining the
+ BLKFLSBUF and FDFLUSH ioctl's. Also include sys/mount.h
+ since on newer glibc's BLKFLSBUF is defined there.
+
+ * bitops.h: The C language versions of ext2fs_swab16/32 need to be
+ included if EXT2FS_ENABLE_SWAPFS is defined, since we need
+ to support byte swapping even if we don't support the
+ conversion functions. (Fixes Debian bug #101686).
+
+ * dirblock.c (ext2fs_read_dir_block): Remove use of dir_entry_2
+ since the byte-swapping code all assumes the
+ ext2_dir_entry structure. (It's a question of whether or
+ not name_len should be byte-swapped or not, and whether
+ it's a 16 bit or 8 bit field.)
+
+2001-06-15 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.21
+
+2001-06-15 Theodore Tso <tytso@valinux.com>
+
+ * Makefile.in: Fix bug in installation of ext2_types.h. It is a
+ file which is generated and is therefore found in the
+ build directory, not source directory.
+
+ * ismounted.c (check_mntent_file): Use a test file in / to check
+ to see if the root filesystem is mounted read-only. This
+ protects against the case where /etc might not be on /, as
+ well as the case where /etc/mtab doesn't exist. (Both are
+ should-never happen scenarios, but you never know...)
+
+2001-06-14 Theodore Tso <tytso@valinux.com>
+
+ * ismounted.c (ext2fs_check_if_mounted): Fix grammer in comment.
+ Remove unneeded #pragma argsused, since the arguments are
+ always used.
+
+2001-06-13 Theodore Tso <tytso@valinux.com>
+
+ * ext2_types.h.in: If linux/types.h has been defined, then don't
+ try to redefine the typedefs.
+
+ * Makefile.in (HFILES): Add ext2_types.h to the list of files
+ which should be installed.
+
+ * ismounted.c (check_mntent_file): Work around GNU hurd brain
+ damage. Addresses Debian bug #100304.
+
+ * Makefile.in: Limit some .o files from being included into the
+ library if --disable-debugfs, --disable-swapfs,
+ --disable-imager, or --disable-resizer are used.
+
+2001-06-12 Theodore Tso <tytso@valinux.com>
+
+ * inode.c, tst_iscan.c: Stop using the compatibility badblocks
+ function, and use the ext2fs_badblocks_* functions
+ instead.
+
+2001-06-11 Theodore Tso <tytso@valinux.com>
+
+ * Makefile.in, gen_bitmap.c, bitops.h: Move inline functions
+ ext2fs_mark_generic_bitmap and
+ ext2fs_unmark_generic_bitmap to gen_bitmap.c as normal
+ functions. (This saves space and doesn't significantly
+ change the speed of e2fsck on a P-III.)
+
+ * ext2fs.h, bitops.h, block.c, bmap.c, closefs.c, dirblock.c,
+ inode.c, native.c, openfs.c, rw_bitmaps.c, swapfs.c: Only
+ include the byte-swapping logic if ENABLE_SWAPFS is turned
+ on or if we're on a big-endian machine.
+
+ * initialize.c (ext2fs_initialize):Use WORDS_BIGENDIAN directly to
+ set EXT2_FLAG_SWAP_BYTES, instead of using
+ ext2fs_native_flag.
+
+ * native.c (ext2fs_native_flag): Use WORDS_BIGENDIAN provided by
+ autoconf to determine whether or not return
+ EXT2_FLAG_SWAP_BYTES.
+
+2001-06-10 Theodore Tso <tytso@valinux.com>
+
+ * Makefile.in: Remove the dependence on the libe2p library.
+
+ * mkjournal.c (ext2fs_add_journal_inode): Replace use of fsetflags
+ with direct usage of the ioctl/fchflags so that we don't
+ have to depend on the libe2p library.
+
+2001-06-08 Theodore Tso <tytso@valinux.com>
+
+ * ext2_types.h.in: Use unsigned ints in favor of unsigned longs
+ when trying to find a 32-bit wide type.
+
+ * icount.c (insert_icount_el): Fix the code used to estimate the
+ size of the new icount array to be more intelligent, to
+ avoid reallocating the array too many times. Thanks to
+ Enrique Perez-Terron for pointing this out.
+
+2001-06-02 Theodore Tso <tytso@valinux.com>
+
+ * valid_blk.c (ext2fs_inode_has_valid_blocks): Only check i_blocks
+ for a symlink to determine whether it is a fast symlink.
+
+2001-06-01 Theodore Tso <tytso@valinux.com>
+
+ * Makefile.in, dosio.c, ext2_fs.h, ext2_types.h.in, ext2fs.h:
+ Move include/asm/types.h.in to lib/ext2fs/ext2_types.h.in.
+
+2001-05-25 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.20
+
+2001-05-25 Theodore Tso <tytso@valinux.com>
+
+ * ismounted.c: More cleanups for ismounted.c, some from Andreas,
+ some to clean up Andreas's patches. Use strncpy instead
+ of strcpy to save the root's mountpoint. Clean up #ifdef
+ structure. Remove uneeded variable in testing/debug driver.
+
+2001-05-24 Andreas Dilger <adilger@turbolinux.com>
+
+ * ismounted.c: Add check for root device which doesn't depend on
+ /etc/fstab or /proc/mounts to be correct. Don't call
+ endmntent() before we are done with mnt struct.
+
+2001-05-23 Theodore Tso <tytso@valinux.com>
+
+ * ext2_err.et.in (EXT2_ET_JOURNAL_UNSUPP_VERSION): Added new error
+ code.
+
+2001-05-21 Theodore Tso <tytso@valinux.com>
+
+ * ext2_fs.h: Change assignment of EXT2_FEATURE_COMPAT_DIR_INDEX to
+ make room for pre-existing usage of
+ EXT2_FEATURE_COMPAT_EXT_ATTR. Add flag EXT2_INDEX_FL with
+ the same codepoint as EXT2_BTREE_FL.
+
+2001-05-20 Theodore Tso <tytso@valinux.com>
+
+ * ext2fs.h: #include <> instead of "" for ext2fs and et header
+ files, since they will be installed in /usr/include
+
+2001-05-14 Theodore Tso <tytso@valinux.com>
+
+ * alloc.c, alloc_tables.c, badblocks.c, bb_compat.c, bb_inode.c,
+ bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
+ check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
+ dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c,
+ expanddir.c, ext2_fs.h, fileio.c, finddev.c, flushb.c,
+ freefs.c, get_pathname.c, getsize.c, icount.c, imager.c,
+ initialize.c, inline.c, inode.c, irel_ma.c, ismounted.c,
+ link.c, lookup.c, mkdir.c, mkjournal.c, namei.c, native.c,
+ newdir.c, nt_io.c, openfs.c, read_bb.c, read_bb_file.c,
+ rs_bitmap.c, rw_bitmaps.c, swapfs.c, test_io.c,
+ tst_badblocks.c, tst_byteswap.c, tst_getsize.c,
+ tst_iscan.c, unix_io.c, unlink.c, valid_blk.c, version.c,
+ write_bb_file.c, ext2_fs.h: Moved file from include/linux.
+ Adjust all files in this directroy to include this file.
+
+ * mkjournal.c (ext2fs_create_journal_superblock): Remove redundant
+ code.
+
+2001-05-05 Theodore Tso <tytso@valinux.com>
+
+ * fileio.c (ext2fs_file_read): Factored out common code and
+ cleaned up function. Fixed a bug where if there was an
+ error reading from the disk, the number of bytes read
+ wasn't reliably set. (Fixes Debian bug #79163)
+ (ext2fs_file_write): Factored out common code and made
+ function more efficient; if writing a full block, don't
+ bother to do a read-modify-write cycle.
+
+2001-05-04 Theodore Tso <tytso@valinux.com>
+
+ * dirblock.c (ext2fs_read_dir_block): Check for an directory
+ record length which isn't a multiple four, and treat that
+ as an invalid. Scan the directory and return an error
+ (EXT2_ET_DIR_CORRUPTED) if the directory records are
+ corrupted.
+ (ext2fs_write_dir_block): If while byte-swapping the
+ directory block, if there's an error, abort and return
+ EXT2_ET_DIR_CORRUPTED.
+
+2001-05-02 Theodore Tso <tytso@valinux.com>
+
+ * ext2fs.h (EXT2_FLAG_IMAGE_FILE): Add new flag, and add
+ image_header field in the ext2_filsys structure
+
+ * block.c (block_iterate_ind, block_iterate_dind, block_iterate_tind):
+ * inode.c (ext2fs_read_inode):
+ * rw_bitmaps.c (read_bitmaps):
+ * openfs.c (ext2fs_open): Add support for EXT2_FLAG_IMAGE_FILE
+
+ * imager.c (ext2fs_image_bitmap_read): Fix bug in imager to make
+ sure the full bitmap is saved.
+
+2001-05-01 Theodore Tso <tytso@valinux.com>
+
+ * e2image.h (struct ext2_image_hdr): Add space for the device name
+ in the image header.
+
+ * dir_iterate.c (ext2fs_process_dir_block): Add a double-check to
+ make sure the rec_len is a multiple of 4, to prevent
+ bus-errors on architectures which care about mis-aligned
+ pointer references.
+
+2001-04-25 Theodore Tso <tytso@valinux.com>
+
+ * getsize.c (ext2fs_get_device_size): Use an unsigned long to
+ query the device sizes using the BLKGETSIZE ioctl.
+
+2001-04-16 Theodore Tso <tytso@valinux.com>
+
+ * ismounted.c (check_mntent): Check /proc/mounts on Linux systems
+ before checking /etc/mtab. The EXT2_MF_READONLY flag is
+ now set from the /etc/mtab options field for all
+ filesystems, not just the root filesystem. Add debugging
+ code to make it easier to test ext2fs_check_if_mounted().
+
+ * mkjournal.c (ext2fs_create_journal_superblock): Add safety
+ check; return an error if there's an attempt to create a
+ journal less than 1024 filesystem blocks.
+
+ * ext2_err.et.in, mkjournal.c: Change EXT2_JOURNAL_NOT_BLOCK and
+ EXT2_NO_JOURNAL_SB to be EXT2_ET_*.
+
+2001-02-20 Theodore Tso <tytso@valinux.com>
+
+ * bitops.h (ext2fs_swab16, ext2fs_swab32): Add i386 assembly
+ inline functions.
+
+ * tst_byteswap.c: New function to test the byteswap functions.
+ Add to regression test suite.
+
+2001-02-08 Theodore Tso <tytso@valinux.com>
+
+ * e2image.h (struct ext2_image_hdr): Fix type for fs_hostname
+
+2001-02-07 Theodore Tso <tytso@valinux.com>
+
+ * mkjournal.c (ext2fs_create_journal_superblock): Fix the setting
+ of s_first for external devices to always be 1, since
+ jsb->s_first is always relative to the start of the
+ journal superblock. Use htonl(1) when setting s_nr_users.
+
+2001-01-17 Theodore Ts'o <tytso@valinux.com>
+
+ * mkjournal.c (ext2fs_add_journal_device): Fix bug where the
+ device number of the filesystem (instead of the journal)
+ was being dropped into s_journal_dev.
+
+2001-01-15 Theodore Ts'o <tytso@valinux.com>
+
+ * initialize.c (ext2fs_initialize): Add support for initializing
+ the ext2 superblock for external journal devices. This
+ basically means we don't bother to allocate any block
+ group descriptors.
+
+ * openfs.c (ext2fs_open): Only open external journal devices if
+ the new flag EXT2_FLAG_JOURNAL_DEV_OK is passed to
+ ext2fs_open. When opening such devices, don't try to read
+ the block group descriptors, since they're not there.
+
+ * ext2_err.et.in (EXT2_NO_JOURNAL_SB): Add new error code
+
+ * mkjournal.c: Export a new function,
+ ext2fs_create_journal_superblock(), which allocates and
+ returns a buffer containing a journal superblock. This is
+ needed by mke2fs to create an external journal. Rewrote
+ ext2fs_add_journal_device() so that it no longer creates
+ the external journal, but rather adds a filesystem to an
+ existing external journal. It handles all of the UUID
+ manipulation.
+
+ * ext2fs.h: List the EXT3_FEATURE_JOURNAL_DEV as a flag supported
+ by the library. Define the EXT2_FLAG_JOURNAL_DEV_OK.
+ Changed function prototype for ext2fs_add_journal_device().
+
+2001-01-14 Theodore Ts'o <tytso@valinux.com>
+
+ * closefs.c (ext2fs_flush): Don't write out anything beyond the
+ primary superblock if EXT2_INCOMPAT_JOURNAL_DEV is
+ listed.
+
+2001-01-12 Theodore Ts'o <tytso@valinux.com>
+
+ * imager.c: Fix gcc -Wall complaints and a series of bugs where
+ retval wasn't set correctly. (Thanks to Andreas Dilger
+ for pointing this out.)
+
+2001-01-11 <tytso@snap.thunk.org>
+
+ * flushb.c (ext2fs_sync_device): New function which centralizes
+ all of the places which might try to use the BLKFLSBUF
+ or FDFLUSH ioctls (and usually failing to define them
+ since the system header files don't usually do this for
+ us, and we're trying to avoid usage of kernel include
+ files now).
+
+2001-01-10 <tytso@snap.thunk.org>
+
+ * alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c,
+ bmove.c, brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c,
+ dir_iterate.c, expanddir.c, ext2fs.h, ext2fsP.h, fileio.c,
+ finddev.c, get_pathname.c, icount.c, inode.c, irel.h,
+ irel_ma.c, ismounted.c, link.c, lookup.c, mkdir.c,
+ mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
+ tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to
+ ext2_ino_t, to protect applications that attempt to
+ compile -D_FILE_OFFSET_BITS=64, since this inexplicably
+ changes ino_t(!?). So we use ext2_ino_t to avoid an
+ unexpected ABI change.
+
+2001-01-05 <tytso@snap.thunk.org>
+
+ * dirblock.c (ext2fs_read_dir_block): Fix a potential case where
+ we may overrun allocated memory in case of a corrupted
+ filesystem (or an e2fsck test case :-) when byte-swapping
+ the directory block.
+
+ * ext2fs.h: Indent the #warning to fix gcc -Wall complaint.
+
+ * mkjournal.c (ext2fs_add_journal_device): Fix various gcc -Wall
+ complaints including a missing return 0 at the end of
+ ext2fs_add_journal_device.
+
+2001-01-03 <tytso@snap.thunk.org>
+
+ * Makefile.in: Link in libe2p when creating libext2fs as a shared
+ library, since mkjournal.c now references fsetflags().
+
+ * mkjournal.c (ext2fs_add_journal_inode): Folded in Andreas
+ Dilger's changes (with fixups) to allow on-line creation
+ of a journal file.
+
+ * ext2fs.h, closefs.c (ext2fs_flush): Add new flag,
+ EXT2_FLAG_SUPER_ONLY, which the close routines to only
+ update the superblock, and not the group descriptors.
+
+2000-12-30 Andreas Dilger <adilger@turbolinux.com>
+
+ * ismounted.c: add ext2fs_check_mount_point() function, which will
+ optionally return the mount point of a device if mounted
+
+2000-12-14 Andreas Dilger <adilger@turbolinux.com>
+
+ * mkjournal.c: rename ext2fs_add_journal_fs() to the more descriptive
+ ext2fs_add_journal_inode()
+
+2001-01-01 <tytso@snap.thunk.org>
+
+ * ext2fs.h: Remove definition of ext2fs_sb. Note: this may break
+ source (but not binary) compatibility of some users of the
+ ext2 library. They should just simply do a global search
+ and replace of struct ext2fs_sb with struct
+ ext2_super_block, and use their own private copy of
+ ext2_fs.h if they aren't already.
+
+ * closefs.c, initialize.c, link.c, newdir.c, openfs.c, swapfs.c:
+ Replace use of ext2fs_sb with ext2_super_block.
+
+2000-12-31 <tytso@snap.thunk.org>
+
+ * ext2fs.h: Cleaned up header file by removing definitions of
+ feature flags that might not have been defined in older
+ ext2 header files. Now that we're using our own
+ include/linux/ext2fs.h header file, this can never happen.
+
+ * jfs_dat.h: Removed old header file which is no longer needed.
+
+2000-12-13 Theodore Ts'o <tytso@valinux.com>
+
+ * closefs.c (ext2fs_update_dynamic_rev): New function suggested
+ by Andreas Dilger to update the filesystem revision to
+ EXT2_DYNAMIC_REV.
+
+ * swapfs.c (ext2fs_swap_super): Add byte swapping for the journal
+ fields.
+
+2000-12-09 <tytso@snap.thunk.org>
+
+ * ext2fs.h, mkjournal.c (ext2fs_add_journal_inode,
+ ext2fs_add_journal_device): Add a new argument to the APIs
+ of these function, which is a flags word. This is used to
+ allow the creation of a V1 superblock for those folks who
+ are using ext3 0.3b in production. Note, the user-land
+ interface for getting at this flag won't be documented, as
+ the V1 superblock is deprecated.
+
+ * mkjournal.c (init_journal_superblock): Sync Stephen's changes
+ which creates a V2 superblock instead of a V1 superblock.
+
+2000-11-21 <tytso@snap.thunk.org>
+
+ * test_io.c (test_write_blk, test_write_byte): Fix typos pointed
+ out by Andreas Dilger.
+
+2000-11-05 <tytso@snap.thunk.org>
+
+ * imager.c (ext2fs_image_{inode,super,bitmap}_{read,write},
+ ext2_fs.h, Makefile.in: New file that has routines that
+ save ext2fs metadata to a file.
+
+ * ext2_err.et.in (EXT2_ET_MAGIC_E2IMAGE): New error code assigned.
+
+ * e2image.h: New file which defines the file format for the ext2
+ image file. (Saved copy of ext2 metadata to a file as a
+ saving throw against worst-case damage.)
+
+2000-11-01 <tytso@snap.thunk.org>
+
+ * inode.c (ext2fs_flush_icache): Add new function
+ ext2fs_flush_icache() which flushes the internal inode
+ cache. Applications which modify the inode table blocks
+ directly must call this function.
+
+2000-10-26 <tytso@snap.thunk.org>
+
+ * mkjournal.c: Add #include of netinet/in.h, since Solaris
+ requires it for ntohl().
+
+ * ext2_io.h (io_channel_write_byte): Add new interface to allow
+ callers to write specific byte ranges. This is an
+ optional interface, which not all IO channels may
+ implement.
+
+ * unix_io.c (unix_write_byte):
+ * test_io.c (test_write_byte): Add implementation of the
+ write_byte function.
+
+ * closefs.c (write_primary_superblock, ext2fs_flush): Add a new
+ function which writes the primary superblock. If the IO
+ channel supports writing raw bytes directly, only fields
+ which were modified are written to the disk. This makes
+ it safe(r) to use utilities like tune2fs on a mounted
+ filesystem.
+
+ * freefs.c (ext2fs_free): Free the original superblock if it is
+ available.
+
+ * openfs.c (ext2fs_open): Store a copy of the original superblock
+ when opening it.
+
+ * ext2fs.h: Add a field to store the original superblock in the
+ ext2 context structure.
+
+2000-10-24 <tytso@snap.thunk.org>
+
+ * llseek.c: Add #ifdef's for IA64 (it's a 64-bit platform, so we
+ don't need to use llseek).
+
+2000-10-24 <tytso@valinux.com>
+
+ * Makefile.in, ext2fs.h, jfs_dat.h, mkjournal.c: Add functions for
+ creating an ext3 journal on a filesystem.
+
+2000-08-21 <tytso@valinux.com>
+
+ * ext2_err.et.in (EXT2_JOURNAL_NOT_BLOCK): Add new error code.
+
+2000-08-22 <tytso@valinux.com>
+
+ * unix_io.c: Make massive changes to support a multiple block
+ writethrough cacheing.
+
+ * ext2_io.h: Added flags field to the io_channel structure.
+
+2000-08-19 <tytso@valinux.com>
+
+ * finddev.c, ext2fs.h, Makefile.in: Add new file, finddev.c, which
+ provides the function ext2fs_find_block_device(). This
+ function returns the pathname to a block device, given its
+ device number.
+
+2000-07-13 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.19
+
+2000-07-07 Theodore Ts'o <tytso@valinux.com>
+
+ * ext2fs.h (EXT2_LIB_FEATURE_INCOMPAT_SUPP): Add
+ EXT3_FEATURE_INCOMPAT_RECOVER (aka needs_recovery) to the
+ list of filesystem flags supported by the library.
+
+2000-07-04 Theodore Ts'o <tytso@valinux.com>
+
+ * ext2fs.h: Update to include latest journalling additions to the
+ superblock.
+
+ * dll/jump.funcs: Add new jumptable entries for
+ ext2fs_write_bb_FILE, ext2fs_read_bb_FILE2, and
+ ext2fs_badblocks_equal.
+
+ * tst_badblocks.c: Update test program to test
+ ext2fs_read_bb_FILE2 and ext2fs_write_FILE.
+
+ * write_bb_file.c (ext2fs_write_bb_FILE): New function which
+ writes out bad blocks list to a file.
+
+ * read_bb_file.c (ext2fs_read_bb_FILE2): Add new function which
+ changes the callback function to take two additional
+ arguments; a private blind pointer supplied by the caller,
+ and pointer to a char * containing a pointer to the
+ invalid string.
+
+ * badblocks.c (ext2fs_badblocks_equal): Add new function which
+ returns true if two badblocks list are equal.
+
+ * Makefile.in: Remove explicit link of -lc in the shared library.
+ (It shouldn't be necessary, and is harmful in some cases).
+
+2000-06-10 Theodore Ts'o <tytso@valinux.com>
+
+ * getsize.c (main): Add debugging code under #ifdef DEBUG
+
+2000-05-27 Theodore Ts'o <tytso@valinux.com>
+
+ * mkdir.c (ext2fs_mkdir): Read the parent directory's inode
+ earlier, so that if there's an error reading it, we can
+ more cleanly back out of the operation.
+
+2000-05-25 <tytso@snap.thunk.org>
+
+ * getsize.c (ext2fs_get_device_size): Use open64() instead of
+ open() if it exists. Under linux, manually define the
+ ioctl for BLKGETSIZE if it isn't already defined and it's
+ safe to do so.
+
+ * unix_io.c (unix_open): Use open64() instead of open() if it
+ exists.
+
+ * llseek.c: Simplify header includes of unistd.h. If lseek64 is
+ available (and prototypes are defined) use it in
+ preference to llseek.
+
+ * Makefile: Add hack dependency rule so that parallel makes work
+ correctly.
+
+2000-05-18 Theodore Ts'o <tytso@valinux.com>
+
+ * ext2fs.h: Add appropriate ifdef's to support C++ compilation.
+
+2000-04-03 Theodore Ts'o <tytso@valinux.com>
+
+ * block.c: Readibility tweak in conditionals involving
+ ctx->fs->flags.
+
+ * ext2fs.h: Use AUTOCONF SIZEOF_* macros if available to determine
+ how to define __s64 and __u64. Turn off "compression is
+ experimental" warning if the cpp macro
+ I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL is defined.
+
+2000-02-11 <tytso@snap.thunk.org>
+
+ * ext2fs.h: Define EXT2FS_COMPRESSED_BLKADDR and HOLE_BLKADDR.
+ Conditionally include Compression as a supported type if
+ ENABLE_COMPRESSION (via --enable-compression) is turned on.
+
+ * swapfs.c (ext2fs_swap_super): Swap the compression usage bitmap.
+
+2000-02-08 <tytso@snap.thunk.org>
+
+ * bitops.h (ext2fs_mark_generic_bitmap, ext2fs_unmark_generic_bitmap,
+ ext2fs_mark_block_bitmap, ext2fs_unmark_block_bitmap,
+ ext2fs_mark_inode_bitmap, ext2fs_unmark_inode_bitmap):
+ Change to return the previous state of the bit that is
+ being marked or unmarked. For speed optimization.
+
+2000-02-02 Theodore Ts'o <tytso@valinux.com>
+
+ * getsize.c, ismounted.c: Remove unneeded include of linux/fs.h
+
+ * swapfs.c: Remove #ifdef HAVE_EXT2_INODE_VERSION since it's not
+ needed any more; we know it will always be i_generation.
+ Add support for swapping the high bits of the uid and gid.
+
+1999-11-19 <tytso@valinux.com>
+
+ * mkdir.c (ext2fs_mkdir): Only update the parent's inode link
+ counts if the link was successful. Patch suggested by
+ jeremy@goop.org.
+
+ * Makefile.in (distclean): Remove TAGS and Makefile.in.old from
+ the source directory.
+
+1999-11-10 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.18
+
+1999-11-08 <tytso@valinux.com>
+
+ * Makefile.in (tst_badblocks): Add freefs.o to the object list,
+ since ext2fs_badblocks_list_free was moved to freefs.c.
+
+ * tst_badblocks.c: Use the newer badblocks API names. Add
+ duplicate blocks to the test inputs to test dealing with
+ adding blocks which are already in the badblocks list.
+
+ * badblocks.c (ext2fs_badblocks_list_add): If appending to the end
+ of the list, use a shortcut O(1) operations instead of an
+ O(n) operation. (Idea suggested by David Beattie.)
+
+ * freefs.c (ext2fs_free): Use ext2fs_badblocks_list_free() instead
+ of badblocks_list_free(), to save a procedure call.
+
+1999-10-26 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.17
+
+1999-10-26 <tytso@valinux.com>
+
+ * ext2fs.h: Add kludge to deal with the fact that egcs cpp doesn't
+ seem to handle ~0UL the same way as they used to.
+
+1999-10-25 <tytso@valinux.com>
+
+ * nt_io.c (_OpenNtName): Open the device using
+ FILE_SYNCHRONOUS_IO_NONALERT instead of
+ FILE_SYNCHRONOUS_IO_ALERT
+ (nt_open): At the end of the device open routine, unlock
+ the drive but do not dismount it.
+
+ * initialize.c (CREATOR_OS): Use __GNU__ instead of __gnu__ to
+ detect the Hurd OS.
+
+1999-10-22 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.16
+
+1999-10-22 <tytso@valinux.com>
+
+ * mkdir.c (ext2fs_mkdir): Pass EXT2_FT_DIR flag to ext2fs_link().
+
+ * link.c (ext2fs_link): This call now uses the low three bits of
+ the flags parameter to pass the directory filetype
+ information; it will set the directory entry FILETYPE
+ information if the filesystem supports it.
+
+ * newdir.c (ext2fs_new_dir_block): If the FILETYPE superblock
+ option is set, then create the '.' and '..' entries with
+ the filetype set to EXT2_FT_DIR.
+
+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
+ feature bits used by newer filesystems: IMAGIC_INODES,
+ HAS_JOURNAL, RECOVER.
+
+ * expanddir.c (ext2fs_expand_dir, expand_dir_proc): Change where
+ we update the inode block count and size files so that the
+ block count field is updated correctly when we create an
+ indirect block.
+
+1999-07-18 Theodore Ts'o <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.15
+
+1999-06-23 <tytso@valinux.com>
+
+ * swapfs.c (ext2fs_swap_inode): Add compatibility for Linux 2.3
+ kernels that use i_generation instead of i_version. Patch
+ supplied by Jon Bright <sircus@sircus.demon.co.uk>.
+
+1999-06-21 <tytso@valinux.com>
+
+ * dir_iterate.c (ext2fs_process_dir_block): Check for corrupted
+ directory entry before calling the callback function.
+ This should prevent some core dumps of insufficiently
+ paranoid callback functions.
+
+1999-05-29 <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Add feature definition for AFS IMAGIC inodes.
+
+ * fileio.c (ext2fs_file_open): Remove obsolete comment stating
+ that we don't handle writing yet (we do). Fixed bug where
+ we weren't allocating a big enough buffer for ext2_bmap.
+
+1999-05-03 <tytso@rsts-11.mit.edu>
+
+ * openfs.c (ext2fs_open): Check to make sure that the number of
+ blocks per group is not zero --- if so, it must be a bad
+ superblock!
+
+1999-01-09 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.14
+
+1999-01-07 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_read_inode, ext2fs_write_inode): Check to see if
+ the inode number is zero; if it's zero, return
+ EXT2_ET_BAD_INODE_NUM.
+
+1998-12-30 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Use EXT2_FIRST_INODE instead
+ of EXT2_FIRST_INO to ensure compatibility with Linux 1.2
+ header files.
+
+Mon Jan 4 02:32:09 1999 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * llseek.c (ext2fs_llseek): Change ext2fs_llseek() in the
+ non-Linux case to use EINVAL by default, unless it isn't
+ defined, in which case we use EXT2_ET_INVALID_ARGUMENT
+ instead.
+
+1998-12-15 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.13
+
+1998-12-03 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in: Updated dependencies.
+
+1998-09-22 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Make sure that we allocate
+ enough inodes so that we can make a valid filesystem.
+
+1998-09-02 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * rw_bitmaps.c: Fixed signed/unsigned warnings.
+
+ * fileio.c (ext2fs_file_set_size): Remove unneeded extern from the
+ function declaration.
+
+ * dblist.c (make_dblist): Add safety check in case the dblist
+ pointer passed in is null (in which case, assign it to
+ fs->dblist). Fixed some signed/unsigned warnings.
+
+ * bmap.c: Make addr_per_block be of type blk_t to avoid
+ signed/unsigned warnings.
+
+ * namei.c (ext2fs_follow_link): Remove uneeded extern from the
+ function declaration.
+
+ * get_pathname.c (get_pathname_proc): Use return value from
+ ext2fs_get_mem, instead of checking if &gp->name is
+ NULL.
+
+ * dir_iterate.c (ext2fs_process_dir_block):
+ * dblist_dir.c (ext2fs_dblist_dir_iterate): Remove uneeded extern
+ from the function declaration.
+
+ * block.c (ext2fs_block_iterate2): If the read_inode call fails,
+ return the error directly instead of jumping to the
+ cleanup routine, since we don't need to do any cleanup.
+
+ * alloc_table.c (ext2fs_allocate_group_table): Make this
+ function take a dgrp_t for its group argument.
+
+ * ext2fs.h: Make dgrp_t an __u32 type, and make
+ fs->desc_group_count be of type dgrp_t.
+
+1998-07-27 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * badblocks.c (ext2fs_badblocks_list_add): Use a bigger increment
+ than 10 blocks when we need to expand the size of the
+ badblocks list.
+
+1998-07-09 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.12
+
+1998-06-30 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * closefs.c (ext2fs_flush): Update the s_block_group_nr field as
+ appropriate for all of the block group copies, so that
+ it's clear where the beginning of the filesystem is on the
+ disk. (For when the partition table gets scrod.)
+
+ * ext2fs.h: Change the name of the feature from
+ EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE to
+ EXT2_FEATURE_INCOMPAT_FILESIZE (to match with the kernel).
+
+1998-06-18 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (get_next_blockgroup): Fix bug where if
+ get_next_blockgroup() is called early because of a missing
+ inode table in a block group, the current_inode counter
+ wasn't incremented correctly.
+
+1998-06-16 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * read_bb.c (ext2fs_read_bb_inode): Make function more robust
+ against a completely trashed bad block inode.
+
+1998-06-10 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc_tables.c (ext2fs_allocate_group_table): Fix bug so that if
+ the stride length hits a bad value, we retry the block
+ allocation starting at the beginning of the block group.
+
+ * ext2fs.h, bb_inode.c, block.c, bmove.c, dir_iterate.c,
+ expanddir.c, ext2fsP.h, read_bb.c: Change blkcnt_t to be
+ e2_blkcnt_t to avoid collision with LFS API.
+
+1998-05-01 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Initialize s_inodes_count in a
+ way that avoids overflows on disk sizes greater than 4GB.
+
+1998-04-28 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Define EXT2_QSORT_TYPE appropriately for the
+ return type for comparison functions for qsort.
+
+ * dblist.c (dir_block_cmp): Use EXT2_QSORT_TYPE in function
+ declaration.
+
+1998-04-26 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h, bitops.h: Add support for the Watcom C compiler to do
+ inline functions.
+
+ * ext2fs.h, dosio.c: Use asm/types.h instead of linux/types.h to
+ evade a potential problem with glibc's header files trying
+ to spike out linux/types.h.
+
+ * ext2fs.h (ext2fs_resize_mem): Change the function prototype to
+ include the old size of the memory, which is needed for
+ some braindamaged memory allocation systems that don't
+ support realloc().
+
+ * badblocks.c (ext2fs_badblocks_list_add):
+ bb_inode.c (clear_bad_block_proc):
+ dblist.c (ext2fs_add_dir_block):
+ icount.c (insert_icount_el):
+ irel_ma.c (ima_put):
+ rs_bitmap.c (ext2fs_resize_generic_bitmap): Update functions to
+ pass the old size of the memory to be resized to
+ ext2fs_resize_mem().
+
+1998-03-30 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in: Change to use new installation directory variables
+ convention. Fix uninstall rules to take $(DESTDIR) into
+ account.
+
+1998-03-29 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: If __STRICT_ANSI__ is defined and we're on a platform
+ with 32 bit longs, then we need to manually define __s64
+ and __u64, since the current kernel header files don't
+ define these if __STRICT_ANSI__ is defined. This is a
+ problem if we are compiling with full GCC warnings, since
+ we do need 64 bit support.
+
+ * Makefile.in (OBJS): Remove bmove.o from files to be built,
+ since we're not using ext2fs_move_blocks() and there
+ is some question as to its usefulness in its current
+ form.
+
+ * bmap.c (block_bmap): Remove unused function.
+
+ * bmove.c (process_block): Fix -Wall warning.
+
+1998-03-23 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * block.c (ext2fs_block_iterate3): Make the ref_offset field
+ contain the offset into the inode.i_blocks array when
+ ref_block is zero. Since we haven't done a formal
+ release of e2fsprogs since block_iterate2 was first
+ introduced, I removed block_iterate2, and renamed
+ block_iterate3 to be block_iterate2.
+
+ * bb_inode.c, bmove.c, dblist_dir.c, dir_iterate.c,
+ expanddir.c, ext2fs.h, ext2fsP.h, read_bb.c: Change
+ use of block_iterate and block_iterate2 to
+ block_iterate2 with the new prototype for the
+ interator function. (using blkcnt_t forr blockcount)
+
+1998-03-21 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Add new superblock fields (s_algorithm_usage_bitmap,
+ s_prealloc_blocks, s_prealloc_dir_blocks). Added
+ conditional defines of new features COMPAT_DIR_PREALLOC,
+ RO_COMPAT_LARGE_FILE RO_COMPAT_BTREE_DIR,
+ INCOMPAT_COMPRESSION, INCOMPAT_DIRNAME_SIZE. Changed
+ the library to declare that we support COMPAT_DIR_PREALLOC,
+ INCOMPAT_DIRNAME_SIZE, RO_COMPAT_LARGE_FILE.
+
+ * fileio.c: Rename function ext2fs_file_llseek to be
+ ext2fs_file_lseek, which is more accurate.
+
+ * block.c: Add new function ext2fs_block_iterate3 which calls
+ the iterator function with the blockcount argument of
+ type blkcnt_t. This version of the function is
+ allowed to handle large files; the other fucntions are
+ not.
+
+ * ext2fs.h: Add new type blkcnt_t
+
+ * ext2_err.et.in: Add error code EXT2_ET_FILE_TOO_BIG
+
+ * block.c (ext2fs_block_iterate2): Fix bug where the block count
+ field wasn't getting correctly incremented for sparse
+ files when the indirect or doubly-indirect block
+ specified in the inode was zero.
+
+Sun Mar 8 22:42:47 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * unlink.c (unlink_proc):
+ * lookup.c (lookup_proc):
+ * link.c (link_proc):
+ * get_pathname.c (get_pathname_proc):
+ * dir_iterate.c (ext2fs_process_dir_block): Mask off high 8 bits
+ from dirent->name_len, so it can be used for other
+ purposes.
+
+ * ext2fs.h: Add definition of EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE,
+ and indicate that we have support for this incompatible
+ option.
+
+Mon Feb 23 08:46:33 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2_err.et.in: Added new error code, EXT2_ET_CANCEL_REQUESTED.
+
+Fri Feb 20 23:58:01 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_get_num_dirs): Improve the estimation of the
+ number of directories when the block group information is
+ unreliable.
+
+1998-02-20 Theodore Y. Ts'o <tytso@edt.mit.edu>
+
+ * inode.c (ext2fs_get_next_inode): Always do the check to see if the
+ inode table is missing so that we catch the case where the
+ first block group is missing.
+
+ * getsize.c, ismounted.c, unix_io.c: #include errno.h since it's
+ needed.
+
+Mon Feb 16 16:16:00 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2_io.h, ext2fs.h: Protect against being included multiple times.
+
+ * bmove.c: #include ext2fsP.h instead of "ext2fs/ext2fs.h"
+
+ * test_io.c (test_flush): Add a debugging printf when the flush
+ method is called.
+
+ * rw_bitmaps.c (ext2fs_read_bitmaps): If the bitmaps are already
+ read in, return right away.
+
+Sun Feb 1 08:20:24 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * bitops.h: Don't try to do i386 inline asm functions if the
+ compiler isn't GCC.
+
+ * ext2fs.h: If EXT2_FLAT_INCLUDES is defined, #include e2_types.h,
+ instead of linux/types.h, and e2_bitops.h instead of
+ ext2fs/bitops.h.
+
+ * icount.c, version.c: Don't #include <et/com_err.h>, as it isn't
+ necessary.
+
+Sat Jan 17 13:13:31 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_open_inode_scan): Initialize the group variables
+ so that we don't need to call get_next_blockgroup() the
+ first time around. Saves a bit of time, and prevents us
+ from needing to assign -1 to current_group (which is an
+ unsigned value).
+
+ * icount.c (insert_icount_el): Cast the estimated number of inodes
+ from a float to an ino_t.
+
+ * alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
+ bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
+ check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
+ dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c,
+ expanddir.c, ext2fs.h, fileio.c, freefs.c,
+ get_pathname.c, getsize.c, icount.c, initialize.c,
+ inline.c, inode.c, irel_ma.c, ismounted.c, link.c,
+ lookup.c, mkdir.c, namei.c, native.c, newdir.c,
+ openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
+ rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
+ tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c,
+ valid_blk.c, version.c: If EXT2_FLAT_INCLUDES is
+ defined, then assume all of the
+ ext2-specific header files are in a flat directory.
+
+ * block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
+ all assignments from void * to be compatible with C++.
+
+Tue Jan 6 11:28:15 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
+ make sure the contents of the disk are flushed to disk.
+
+Mon Dec 29 14:39:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
+ avoid C++ namespace clash.
+
+ * bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
+ avoid C++ namespace clash.
+
+ * ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
+ irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
+ ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
+ unlink.c: Change private to be priv_data (to avoid C++
+ namespace clash)
+
+Fri Nov 28 09:26:31 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_get_num_dirs): Make ext2fs_get_num_dirs more
+ paranoid about validating the directory counts from the
+ block group information.
+
+ * all files: Don't include stdlib.h anymore; include it in
+ ext2_fs.h, since that file requires stdlib.h
+
+Thu Nov 20 16:07:38 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * expanddir.c (ext2fs_expand_dir): Check to make sure the block
+ bitmap is loaded, and return an error if it is not.
+ (expand_dir_proc): Only use ext2fs_write_dir_block when
+ writing a directory block, not when writing out a fresh
+ indirect block.
+
+Tue Nov 11 22:46:45 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in, tst_getsize.c: Added new file which is used to test
+ the ext2fs_get_device_size function.
+
+ * ext2_err.et.in (EXT2_ET_UNIMPLEMENTED): Added new error code.
+
+Sun Nov 2 20:36:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Make ext2fs_get_mem take an unsigned argument.
+
+ * fileio.c (ext2fs_file_get_size, ext2fs_file_set_size,
+ ext2fs_file_get_fs): New functions added.
+
+
+Fri Oct 31 12:16:52 1997 <tytso@EDT.MIT.EDU>
+
+ * bitops.c (ext2fs_warn_bitmap, ext2fs_warn_bitmap2): Don't call
+ com_err if OMIT_COM_ERR is defined.
+
+Thu Oct 30 11:33:57 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Rename new error codes to _ET_ in them for consistency.
+
+Sat Oct 25 00:06:58 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * [all files, basically]: Added definition of ext2fs_get_mem,
+ ext2fs_free_mem, and ext2fs_resize_mem in ext2fs.h, and
+ changed all library routines to use these wrapper functions.
+
+ * dblist.c, mkdir.c: use EXT2_DIR_EXISTS and EXT2_DB_NOT_FOUND
+ instead of the system error messages.
+
+ * ext2_err.et.in: Added new error messages EXT2_DIR_EXISTS and
+ EXT2_DB_NOT_FOUND
+
+ * ext2fs.h: Added function declarations and constants for bmap.c
+ and fileio.c.
+
+ * ext2_err.et.in: Added new error messages EXT2_FILE_RO and
+ EXT2_ET_MAGIC_EXT2_FILE
+
+ * Makefile.in: Added files bmap.c and fileio.c, and temporarily
+ commented out brel_ma.c and irel_ma.c
+
+ * bmap.c: New file which maps a file's logical block number to its
+ physical block number.
+
+ * fileio.c: New file which implements simple file reading and
+ writing primitives.
+
+ * alloc.c (ext2fs_alloc_block): New function which allocates a
+ block, zeros it, and updates the filesystem accounting
+ records appropriately.
+
+Wed Oct 22 16:47:27 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2_err.et.in: Added new error codes: EXT2_NO_MEMORY,
+ EXT2_INVALID_ARGUMENT, EXT2_BLOCK_ALLOC_FAIL,
+ EXT2_INODE_ALLOC_FAIL, EXT2_NOT_DIRECTORY
+
+ * Change various library files to use these functions instead of
+ EINVAL, ENOENT, etc.
+
+Mon Oct 20 19:32:40 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * llseek.c: Check HAVE_LLSEEK_PROTOTYPE to see whether or not we
+ need to declare llseek().
+
+Sun Oct 19 18:56:22 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Rename io.h to be ext2_io.h (avoid namespace collisions)
+
+ * Add #ifdef's for HAVE_SYS_STAT_H and HAVE_SYS_TYPES_H
+
+Fri Oct 3 13:35:59 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * llseek.c (ext2fs_llseek): Fix type error for ext2fs_llseek()
+
+ * icount.c (ext2fs_icount_validate):
+ * bmove.c (process_block): Fix lint error in type for fprintf().
+
+Mon Sep 15 11:45:09 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_check_directory): Add support for the callback
+ to return the error code EXT2_ET_CALLBACK_NOTHANDLED.
+
+Thu Sep 4 12:28:22 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * bitmaps.c (ext2fs_set_bitmap_padding): New function which sets the
+ padding of the bitmap to be all one's.
+
+Wed Sep 3 14:27:30 1997 Theodore Y. Ts'o <tytso@edt.mit.edu>
+
+ * llseek.c: Added missing semicolon to glibc fixup declaration of
+ llseek().
+
+ * bmove.c: Add #include of errno.h
+
+Sat Aug 23 22:47:46 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in (ELF_SO_VERSION): Bump version to be 2.4 since we've
+ added a new field to the io_channel (app_data).
+
+ * io.h: Add a new element to the io_channel structure, app_data.
+
+ * initialize.c, openfs.c: Set io->app_data to point at the
+ filesystem handle.
+
+Thu Aug 14 08:14:17 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * io.h: Change the prototype of ext2fs_llseek() to use int's
+ instead of unsigned int's.
+
+ * llseek.c: Change to allow PIC and !HAVE_LLSEEK. Add a prototype
+ to make life easer for GNU Libc 2.
+
+ * rw_bitmaps.c: On the PowerPC, the big-endian variant of the ext2
+ filesystem has its bitmaps stored as 32-bit words with bit
+ 0 as the LSB of each word. Thus a bitmap with only bit 0
+ set would be, as a string of bytes, 00 00 00 01 00 ... To
+ cope with this, we byte-reverse each word of a bitmap if
+ we have a big-endian filesystem, that is, if we are *not*
+ byte-swapping other word-sized numbers.
+
+Mon Aug 11 03:30:48 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dosio.c: New file to do DOS/BIOS disk accesses.
+
+ * namei.c (open_namei): Make pathlen be of type size_t.
+
+ * llseek.c: Always #include stdlib.h since it's need to define
+ size_t.
+
+ * io.h: Use errcode_t for magic numbers.
+
+ * icount.c (get_icount_el): Use size_t where appropriate
+
+ * dupfs.c (ext2fs_dup_handle):
+ * dblist.c (dir_block_cmp): Use size_t where appropriate.
+
+ * read_bb.c (ext2fs_read_bb_inode):
+ * cmp_bitmaps.c (ext2fs_compare_inode_bitmap): Use blk_t, ino_t
+ and size_t where appropriate.
+
+ * closefs.c (ext2fs_flush): Use dgrp_t instead of int where
+ appropriate.
+
+ * openfs.c (ext2fs_open):
+ * check_desc.c (ext2fs_check_desc): Use blk_t instead of int where
+ appropriate.
+
+ * rw_bitmaps.c (read_bitmaps):
+ * irel_ma.c:
+ * inode.c (ext2fs_write_inode):
+ * initialize.c (ext2fs_initialize):
+ * brel_ma.c: Fix to make be 16-bit safe.
+
+ * link.c (ext2fs_link):
+ * unlink.c (ext2fs_unlink):
+ * lookup.c (lookup_proc):
+ * ismounted.c (ext2fs_check_if_mounted):
+ * block.c (xlate_func): Add #pragma argsused for Turbo C.
+
+Sun Aug 10 10:05:22 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * block.c (ext2fs_block_iterate2): Use retval which is a errcode_t
+ type.
+
+ * bitmaps.c (make_bitmap): Use size_t instead of int where
+ appropriate.
+
+ * bb_inode.c (set_bad_block_proc): Add #pragma argsused for Turbo C.
+
+ * alloc.c (ext2fs_new_inode): Use ino_t instead of int for the
+ group number.
+
+ * get_pathname.c: Use ino_t instead of int where appropriate.
+
+ * ext2fs.h: Make the magic structure element be errcode_t instead
+ of int.
+
+ * alloc.c alloc_tables.c badblocks.c bb_compat.c bb_inode.c
+ bitmaps.c block.c bmove.c brel_ma.c check_desc.c closefs.c
+ cmp_bitmaps.c dblist.c dblist_dir.c dir_iterate.c
+ dirblock.c dupfs.c expanddir.c freefs.c get_pathname.c
+ icount.c initialize.c inline.c inode.c irel_ma.c link.c
+ llseek.c lookup.c mkdir.c namei.c newdir.c read_bb.c
+ read_bb_file.c rs_bitmap.c rw_bitmaps.c swapfs.c
+ test_io.c tst_badblocks.c tst_iscan.c unix_io.c unlink.c
+ valid_blk.c version.c: Add an #ifdef for HAVE_UNISTD_H
+
+Tue Jun 17 01:33:20 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * unix_io.c (unix_read_blk): If ext2fs_llseek() fails, but errno
+ is zero, then return EXT2_IO_LLSEEK_FAILED.
+
+ * ext2_err.et.in: Add a new error code, EXT2_IO_LLSEEK_FAILED.
+
+ * Release of E2fsprogs 1.11
+
+Mon Jun 16 23:53:06 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_dblist_count): Added new function which returns
+ the number of directory blocks in dblist.
+
+Sat Jun 14 01:39:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * unix_io.c (unix_flush): Make the io_channel flush function do a
+ fsync to flush the kernel buffers to disk.
+
+Wed Jun 11 18:25:31 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_inode_scan_goto_blockgroup): Fix bug; the
+ current inode number wasn't being set by the
+ goto_blockgroup function.
+
+Mon Jun 9 10:45:48 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * bmove.c (ext2fs_move_blocks): New function which takes a bitmap
+ of blocks which need to be moved, and moves those blocks
+ to another location in the filesystem.
+
+ * rs_bitmap.c (ext2fs_resize_generic_bitmap): When expanding a
+ bitmap, make sure all of the new parts of the bitmap are
+ zero.
+
+Sun Jun 8 16:24:39 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * bitmaps.c (ext2fs_copy_bitmap): Fix bug; the destination bitmap
+ wasn't being returned to the caller.
+
+ * alloc_tables.c (ext2fs_allocate_group_table): Add new function
+ ext2fs_allocate_group_table() which sets the group tables
+ for a particular block group. The relevant code was
+ factored out of ext2fs_allocate_tables().
+
+ * dblist.c (make_dblist): Adjust the initial size of the directory
+ block list to be a bit more realistic (ten plus twice the
+ number of directories in the filesystem).
+
+Thu May 8 22:19:09 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * badblocks.c (ext2fs_badblocks_list_test): Fix bug where
+ ext2fs_badblocks_list_test would test the list (and exceed
+ array boundaries) if there were no bad blocks on the bad
+ blocks list. (Showed up when user tried: mke2fs -c -b 4096).
+
+Thu Apr 24 12:16:42 1997 Theodre Ts'o <tytso@localhost.mit.edu>
+
+ * Release of E2fsprogs version 1.10
+
+Thu Apr 24 10:13:42 1997 Theodre Ts'o <tytso@localhost.mit.edu>
+
+ * alloc_tables.c (ext2fs_allocate_tables): Correctly place the
+ inode and block bitmaps based on the RAID 0 stride
+ parameter (which is passed by mke2fs).
+
+ * ext2fs.h: Add "stride" parameter to ext2_filsys, to be used by
+ mke2fs to communicate the stride length to
+ ext2fs_allocate_tables()
+
+Wed Apr 23 21:50:42 1997 Theodre Ts'o <tytso@localhost.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Fix to compile under Linux 1.2
+ systems. (We can't assume that the new filesystem types
+ are supported.)
+
+Wed Apr 23 18:40:53 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc_tables.c (ext2fs_allocate_tables): Make sure that we
+ allocate the inode and block bitmaps inside block group at
+ all times.
+
+Mon Apr 21 00:06:28 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc.c (ext2fs_new_block): Fix bug where if goal==0 and the
+ filesystem has no free blocks, ext2fs_new_block would loop
+ forever.
+
+ * dupfs.c (ext2fs_dup_handle): Duplicate an ext2 filesystem handle
+
+ * freefs.c (ext2fs_free_inode_cache): Decrement refcount and only
+ free if refcount goes to zero.
+
+ * inode.c (create_icache): Initialize refcount to 1.
+
+ * ext2fsP.h: Added refcount to ext2_inode_cache
+
+ * dblist.c (ext2fs_copy_dblist): New function to copy a directory
+ block list.
+
+ * badblocks.c (ext2fs_badblocks_copy): New function to copy a
+ badblocks structure.
+
+Sun Apr 20 23:19:51 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * bitmaps.c (ext2fs_copy_bitmap): New function to copy a bitmap.
+
+ * unix_io.c, test_io.c (unix_open, test_open): Initialize the
+ refcount to 1.
+ (unix_close, test_close): Decrement the refcount and only
+ close the io_channel if the refcount goes to 0.
+
+ * io.h: Add refcount to the io_channel structure. Add new macro
+ interface io_channel_bumpcount() to bump the refcount.
+
+Thu Apr 17 20:25:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_read_inode, ext2fs_write_inode): Use the inode
+ cache in the filesystem handle, instead of the inode cache
+ in a static variable.
+
+ * freefs.c: Added static function to free the inode cache (called by
+ ext2fs_free).
+
+ * ext2fsP.h: Added definition of the ext2_inode_cache structures.
+
+ * ext2fs.h: Added pointer to the inode_cache structure.
+
+ * block.c (block_iterate_ind, block_iterate_dind,
+ block_iterate_tind): If there are holes in the indirect,
+ doubly indirect, or triply indirect blocks, increment the
+ block count field automatically.
+
+Thu Apr 17 12:23:38 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.09
+
+Mon Apr 14 20:38:56 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * version.c (ext2fs_parse_version_string): Check the passed in
+ version string (instead of the hard-coded one).
+
+ * alloc_tables.c (ext2fs_allocate_tables): If the last block is
+ greater filesystem size, clamp it to prevent allocating a
+ block or inode bitmap beyond the filesystem.
+
+ * initialize.c (ext2fs_initialize): Fix bug where the metatdata
+ overhead calculation was accidentally removed.
+
+Fri Apr 11 18:56:26 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.08
+
+Thu Apr 10 13:15:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_set_dir_block): New function which sets the
+ block of a dblist entry, given the directory inode and
+ blockcnt.
+
+Sat Apr 5 12:42:42 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc_tables.c (ext2fs_allocate_tables): Allocate the bitmap and
+ inode bitmaps at staggered locations across the block
+ groups, to avoid concentrating the bitmaps on a small
+ number of disks when using striped RAID arrays.
+
+ * initialize.c (ext2fs_initialize): By default, choose the maximum
+ possible number of blocks per group (based on the size of
+ the bitmaps in the blocksize).
+
+Fri Apr 4 11:28:16 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Add support for
+ EXT2_COMPAT_SPARSE_SUPER feature.
+
+ * closefs.c (ext2fs_bg_has_super): New function to determine
+ whether or a particular block group should have a
+ superblock and block group descriptor. Used for the
+ EXT2_COMPAT_SPARSE_SUPER feature is turned on.
+ (ext2fs_flush): Check ext2fs_bg_has_super to see whether
+ or not the superblock should be written out for the block
+ group.
+
+ * ext2fs.h (EXT2_COMPAT_SPARSE_SUPER): Define compatibility flag
+ for sparse duplicate superblocks.
+
+ * version.c (ext2fs_get_library_version): New function which
+ returns the library version.
+
+ * version.c (ext2fs_parse_version_string): New function which
+ parses a version string and returns a version number,
+ so application programs can compare version numbers as
+ integers.
+
+Wed Mar 26 00:43:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * icount.c (ext2fs_create_icount): Change function so that it also
+ takes a new argument which contains a "hint" icount
+ structure. This "hint" icount allows the create function
+ to set up the sorted list in advance. This reduces
+ significantly the amount of data moving needed to insert
+ these inodes into the list later.
+
+ * icount.c (ext2fs_icount_validate): New function which validates
+ that the icount structure's rep invariant.
+
+ * icount.c (get_icount_el): Completely revamped implementation
+ to subsume put_icount_el(). Put_icount_el() used to
+ use an O(N) implementation to insert in the middle
+ of the icount list. It now uses a O(ln N) to search
+ for where the icount should be inserted, and then uses
+ a memcpy to move the list down (instead of a for loop).
+
+ * icount.c (ext2fs_icount_fetch, ext2fs_icount_store,
+ ext2fs_icount_increment, ext2fs_icount_decrement): Check
+ to see if the inode is within bounds; if it isn't, return
+ EINVAL.
+
+ * bitops.h (ext2fs_test_generic_bitmap): Fix error message given
+ when a bad inode number is passed to test_generic_bitmap
+ to be EXT2FS_TEST_ERROR instead of the wrong
+ EXT2FS_UNMARK_ERROR.
+
+Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * Release of E2fsprogs version 1.07
+
+Sun Mar 2 16:46:18 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in (ELF_VERSION): Change version to be 2.2
+
+Tue Feb 11 14:54:02 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc.c (ext2fs_get_free_blocks): Change routine to use
+ ext2fs_fast_test_block_bitmap_range().
+
+ * bitops.h (ext2fs_fast_test_block_bitmap_range,
+ ext2fs_test_block_bitmap_range: New inline functions which
+ test to see whether a contiguous range of blocks is
+ available.
+
+Thu Feb 6 10:00:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * badblocks.c (ext2fs_badblocks_list_create): Rename sybmols to use
+ use ext2fs_badblocks_* instead of badblocks_*
+
+ * bb_compat.c: New file which translates between old badblocks_*()
+ names to ext2fs_badblocks_*()
+
+ * unlink.c (ext2fs_unlink): New file, moved ext2fs_unlink() from
+ link.c (since e2fsck doesn't use ext2fs_unlink()).
+
+ * rs_bitmap.c (ext2fs_resize_generic_bitmap): New file, contains
+ bitmap resizing routine moved from bitmaps.c, since e2fsck
+ doesn't need to use this function.
+
+ * lookup.c (ext2fs_lookup): Moved ext2fs_lookup to its own file,
+ since e2fsck only needs ext2fs_lookup.
+
+Mon Feb 3 10:11:40 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_open_inode_scan): Set fs->badblocks if it is not
+ already set; this is needed so that programs like dump
+ which use the inode scan functions will deal with
+ filesystems that have bad blocks in the inode table.
+
+Sun Feb 2 00:17:36 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h (struct_badblocks_list, struct_badblocks_iterate):
+ Moved to ext2fsP.h, since it doesn't need to be part of
+ the public interface.
+
+ * dir_iterate.c: Move ext2_dir_iterate out of namei.c.
+
+Sat Feb 1 10:14:55 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_get_num_dirs): New file, which implements a
+ directory block list abstraction. (Code moved from
+ e2fsck).
+
+ * ext2fs.h, inode.c: Moved definition of ext2_struct_inode_scan to
+ to inode.c (since no one else should be peeking inside it!)
+
+ * valid_blk.c (ext2_inode_has_valid_blocks): New function.
+
+ * openfs.c (ext2fs_open): Check the feature set in the ext2
+ superblock, and refuse to open filesystems if they contain
+ incompatible features. (Can be overriden with the
+ EXT2_FLAG_FORCE
+
+Sun Jan 12 11:31:46 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * block.c (ext2fs_block_iterate2): Added new function
+ ext2fs_block_iterate2 which changes the function
+ signature of the callback function to include the
+ referencing block and offset.
+
+ * inode.c (ext2fs_inode_scan_goto_blockgroup): Added new function
+ ext2fs_inode_scan_goto_blockgroup which allows an
+ application to jump to a particular block group while
+ doing an inode scan.
+
+Wed Jan 1 23:50:12 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dirblock.c: Include string.h, since we use memcpy().
+
+Tue Dec 3 12:27:29 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * getsize.c (ext2fs_get_device_size): The ioctl BLKGETSIZE returns
+ a long not an int; this doesn't matter on i386 machines,
+ but it does on Alpha's.
+
+Fri Nov 29 20:57:37 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_write_inode, ext2fs_read_inode): If the inode
+ table pointer is NULL, then return an error indicating
+ that the inode table is missing.
+ (get_next_blockgroup, get_next_blocks,
+ ext2fs_get_next_inode): Don't treat a missing inode table
+ as permanent error. Return MISSING_INODE_TABLE, but as an
+ advisory error code, much like BAD_BLOCK_IN_INODE_TABLE.
+
+ * rw_bitmaps.c (ext2fs_write_block_bitmap,
+ ext2fs_write_inode_bitmap): If the inode or block bitmap
+ block is zero, then don't write out the inode or block
+ bitmap. The idea here is to avoid stomping on the
+ superblock.
+ (read_bitmaps): If the inode or block bitmap block is
+ zero, then fill in that portion of the inode or block
+ bitmap with all zeros.
+
+ * inode.c (ext2fs_get_next_inode): Fix bug in handling of bad
+ blocks in inode table when the inode table size is
+ non-standard (and can therefore span blocks).
+
+Tue Oct 29 20:13:14 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc.c (ext2fs_new_block): Fix fencepost error in
+ ext2fs_new_block; make sure we don't try to allocate the
+ first block beyond the end of the filesystem.
+
+Mon Oct 14 11:00:48 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (check_for_inode_bad_blocks): New function called by
+ get_next_blocks() to avoid reading in bad blocks marked in
+ fs->badblocks. Inodes located in bad blocks are returned
+ by ext2fs_get_next_inode() returns the error code
+ EXT2_ET_BAD_BLOCK_IN_INODE_TABLE.
+
+ * alloc_tables.c (ext2fs_allocate_tables): New function which
+ performs the part of mke2fs's job of allocating the
+ filesystem tables.
+
+ * test_io.c (test_close): IO manager which is used for testing
+ purposes.
+
+Sun Oct 13 04:31:57 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_get_next_inode): Separate out the function of
+ setting up for a new block group to get_next_blockgroup().
+ Separate out the function of reading in blocks of the
+ inode table to get_next_blocks().
+
+ * ext2fs.h: Add the badblocks list to the ext2_filsys entry
+
+ * badblocks.c (badblocks_list_add, badblocks_list_test): Add
+ blocks to the badblock list in sorted order. This allows
+ badblocks_list_test to be coded using a binary search for
+ speed.
+
+Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.06
+
+Mon Oct 7 00:44:17 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h, block.c, closefs.c, dirblock.c, inode.c, native.c,
+ open.c: Change EXT2_SWAP to EXT2_FLAG_SWAP for
+ consistency's sake.
+
+ * closefs.c (ext2fs_flush): If the flag EXT2_MASTER_SB_ONLY is
+ set, then only write out the master superblock.
+
+Sun Oct 6 21:45:26 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * block.c (ext2fs_block_iterate): Fixed bug which caused
+ block_iterate to fail to handle HURD created filesystems;
+ it tested the inode translator field before the inode was
+ loaded.
+
+Tue Sep 17 14:08:24 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Make sure the description for
+ the inode bitmap is set correctly.
+
+ * bitmaps.c (ext2fs_allocate_generic_bitmap): Fix minor type typo.
+
+Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.05
+
+Sat Sep 7 07:36:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c: Override the kernel's idea of default
+ checkinterval from 0 (never) to 180 days.
+
+Wed Aug 28 03:20:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * namei.c (ext2fs_namei_follow): New function which follows
+ symbolic link (if any) at the target.
+
+Tue Aug 27 01:48:43 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_read_inode, ext2fs_write_inode): Add support
+ for shortcut function fs->read_inode() and fs->write_inode().
+ Added inode_cache to reduce CPU time spent in doing
+ byte swapping.
+
+ * swapfs.c (ext2fs_swap_super): Swap the new fields in a V2
+ superblock.
+
+ * namei.c (ext2fs_follow_link): New function.
+ (ext2fs_namei): Extended to have support for chasing
+ symbolic links. ext2fs_namei() still returns an inode
+ which is a symbolic link. Symbolic links are only chased
+ while resolving the containing directory. To chase
+ symbolic links of the final result, use
+ ext2fs_follow_link().
+
+Mon Aug 26 23:46:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2_err.et.in: Added new error code EXT2_ET_SYMLINK_LOOP.
+
+ * bitops.h (ext2fs_set_bit, ext2fs_celar_bit): Use asm inlines
+ provided by Pete A. Zaitcev (zaitcev@lab.sun.mcst.ru).
+
+Thu Aug 22 00:40:18 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): On systems where the byte
+ order is not i386 compatible, set the swap_byte flag.
+
+ * inode.c (inocpy_with_swap): Check to see if inode contains a
+ fast symlink before swapping the inode block fields. This
+ required adding a new argument to inocpy_with_swap to
+ determine whether the mode field is in host order or not.
+
+Wed Aug 21 00:45:42 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * bitops.h (ext2fs_set_bit, ext2fs_clear_bit, ext2fs_test_bit): On
+ the sparc, if EXT2_STD_BITOPS set, use the standard
+ i386-compatible bitmask operations, instead on the
+ non-standard native bitmask operators.
+
+Fri Aug 9 11:11:35 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * block.c (ext2fs_block_iterate): Cause block iterator to return
+ the HURD translator block (along with everything else).
+ If the flag BLOCK_FLAG_DATA_ONLY is passed to the block
+ iterator, then don't return any meta data blocks
+ (including the HURD translator).
+
+Wed Jul 17 17:13:34 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * gen_uuid.c: New file, which generates DCE-compatible UUIDs.
+
+ * uuid.c: New file, containing UUID utility functions.
+
+Tue Jul 16 10:19:16 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Add a definition of the "real" ext2 superblock.
+
+Fri May 24 14:54:55 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * ext2fs.h: Fix erroneous ino_t type used in block_bitmap type.
+
+Sun May 19 15:39:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * openfs.c (ext2fs_open): If the blocksize in the superblock is
+ zero, return the error EXT2_ET_CORRUPT_SUPERBLOCK, since
+ that's a basic value that must be correct for the rest of
+ the library to work.
+
+ * ext2_err.et.in (EXT2_ET_CORRUPT_SUPERBLOCK): Added new error
+ code.
+
+Thu May 16 11:12:30 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.04
+
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
+Tue Mar 26 12:06:32 1996 <tytso@rsts-11.mit.edu>
+
+ * bitops.h (ext2fs_set_bit, ext2fs_clear_bit, ext2fs_test_bit):
+ Change the m68k bit numbering for bitmasks to match with
+ the bit numbering used by all other ext2 implementations.
+
+Thu Mar 7 03:37:00 1996 <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_get_next_inode, ext2fs_close_inode_scan,
+ ext2fs_open_inode_scan): Support dynamically-sized inodes.
+
+Wed Mar 6 12:26:29 1996 <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_read_inode, ext2fs_write_inode): Support
+ dynamically-sized inodes.
+
+ * openfs.c (ext2fs_open): Allow dynamic revision filesystem to be
+ loaded.
+
+Tue Mar 5 03:49:37 1996 <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Catch an error condition where
+ the passed in size is *really* too small.
+
+ * alloc.c (ext2fs_new_inode):
+ * ext2fs.h (EXT2_FIRST_INODE): Add support for dynamic revision to
+ get first inode.
+
+Wed Feb 21 15:56:17 1996 <tytso@rsts-11.mit.edu>
+
+ * getsize.c (ext2fs_get_device_size): Open the device read-only
+ when trying to determine its size.
+
+Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.02
+
+Sat Dec 9 09:57:50 1995 <tytso@rsts-11.mit.edu>
+
+ * rw_bitops.c (ext2fs_write_block_bitmap):
+ * bitops.c (ext2fs_test_bit, ext2fs_clear_bit, ext2fs_set_bit):
+ * bitops.h (ext2fs_test_bit, ext2fs_clear_bit, ext2fs_set_bit):
+ Rename {test,set,clear}_bit to ext2fs_{test,set,clear}_bit,
+ to avoid conflicts with with kernel include files. Also
+ rename ADDR and CONST_ADDR to EXT2FS_ADDR and
+ EXT2FS_CONST_ADDR.
+
+Thu Oct 26 12:09:16 1995 <tytso@rsts-11.mit.edu>
+
+ * ext2_err.et: Updated message in EXT2_ET_BASE to say version 0.5c
+
+ * swapfs.c (ext2fs_swap_super): Put an #ifdef check around
+ s_def_resuid and s_def_resgid for backwards compatibility.
+
+Fri Oct 20 23:33:31 1995 <tytso@rsts-11.mit.edu>
+
+ * bitops.h: Added #ifdef's for Sparc.
+
+Wed Sep 6 22:14:46 1995 <tytso@rsts-11.mit.edu>
+
+ * getsize.c: #include <sys/ioctl.h> under Linux to pick up ioctl()
+ declaration
+
+ * closefs.c: #include <string.h> to pick up memset() declaration
+
+Mon Sep 4 21:45:29 1995 Remy Card <card@bbj>
+
+ * Makefile.in: Added support for BSD shared libraries.
+
+ * initialize.c (ext2fs_initialize): Correctly set the s_creator_os
+ flag.
+
+Mon Sep 4 09:55:30 1995 <tytso@rsts-11.mit.edu>
+
+ * unix_io.c (unix_open): Add a double check; if the passed in name
+ is NULL, return EXT2_ET_BAD_DEVICE_NAME.
+
+ * ext2_err.et (EXT2_ET_BAD_DEVICE_NAME): Added new error code
+
+Wed Aug 16 15:44:10 1995 <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_check_directory): Use LINUX_S_ISDIR instead of
+ S_ISDIR.
+
+Tue Aug 15 13:08:36 1995 <tytso@rsts-11.mit.edu>
+
+ * getsize.c (ext2fs_get_device_size): Add support for reading the
+ partition size from a BSD disk label.
+
+Thu Aug 10 09:33:26 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * getsize.c (ext2fs_get_device_size): New function that determins
+ the size of a device. Used by mke2fs and e2fsck.
+
+Sat Aug 12 03:09:54 1995 Remy Card <card@bbj>
+
+ * Makefile.in (install): Install static libraries in $(ulibdir)
+ (/usr/lib on Linux) instead of $(libdir) (/lib on Linux).
+
+Wed Aug 9 17:04:23 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * bitmaps.c (ext2fs_free_inode_bitmap, ext2fs_free_block_bitmap):
+ Move these functions to freefs.c.
+
+ * closefs.c (ext2fs_flush): If swapping blocks, clear the group
+ descriptors shadow memory to keep purify quiet. (This
+ also has the nice benefit that the unused portion of the
+ shadow descriptors are zeroed out.)
+
+ * dirblock.c (ext2fs_write_dir_block): We need to use
+ dirent->rec_len *before* it's byteswapped to find the
+ location of the next directory structure!
+
+ * alloc.c (ext2fs_new_inode): Fix bug which could potentially
+ cause ext2fs_new_inode to loop infinitely if we're trying
+ to allocate an inode in group #0 and there are no free
+ inodes at all in the system.
+
+ * closefs.c: #include <errno.h> if it exists.
+
+Sun Aug 6 13:27:50 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * ext2fs.h (BLOCK_FLAG_HOLE): Added new definition for
+ BLOCK_FLAG_APPEND. Added documentation for the block
+ interator flags.
+
+Sat Aug 5 11:44:05 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * Makefile.in (DLL_INSTALL_DIR, ELF_INSTALL_DIR): Set the
+ installation directories correctly.
+
+Tue Jul 18 09:27:38 1995 <tytso@rsx-11.mit.edu>
+
+ * namei.c (process_dir_block):
+ * mkdir.c (ext2fs_mkdir):
+ * expanddir.c (expand_dir_proc): Use ext2fs_{read,write}_dir_block
+ to read/write the directory block.
+
+ * dirblock.c (ext2fs_read_dir_block), ext2fs_write_dir_block): New
+ file containing functions for reading and writing
+ directory blocks (byte swapping if necesssary)
+
+ * block.c (block_iterate_ind, block_iterate_dind,
+ block_iterate_tind): Byte swap the block addresses if
+ EXT2_SWAP_BYTES is set (and swap them back before writing
+ them out.)
+
+ * inode.c (inocpy_with_swap): New function.
+ (ext2fs_get_next_inode, ext2fs_read_inode, ext2fs_write_inode):
+ Call inocpy_with_swap if EXT2_SWAP_BYTES if set.
+
+ * closefs.c (ext2fs_flush): If EXT2_SWAP_BYTES is set, then swap
+ the superblock and group descriptors before writing it out.
+
+ * openfs.c (ext2fs_open): If the magic number is byte-swapped,
+ then set the EXT2_SWAP_BYTES and byte-swap the superblock
+ and group descriptors.
+
+ * swapfs.c (ext2fs_swap_super, ext2fs_swap_group_desc): New functions
+ to desp ext2 filesystem structures.
+
+ * bitops.c (set_bit, clear_bit, test_bit): Use modifications
+ supplied by Pete A. Zaitcev so that the C language
+ versions of these functions are more portable. They will
+ now work on both little and big endian systems, and the
+ assumption that 32-bit integers are used is gone.
+
+ * bitops.h (ext2_swab16, ext2_swab32): Added new functions for
+ doing byte swapping.
+
+ * ext2fs.h (EXT2_SWAP_BYTES): Add new flag which indicates that
+ byte swapping should take place.
+
+Sun Jul 16 06:21:43 1995 <tytso@rsx-11.mit.edu>
+
+ * Makefile.in, cmp_bitmaps.c (ext2fs_compare_block_bitmap_end,
+ ext2fs_compare_inode_bitmap_end): Added new file
+ containing routines to compare bitmaps.
+
+ * ext2_err.et (EXT2_ET_NEQ_BLOCK_BITMAP, EXT2_ET_NEQ_INODE_BITMAP):
+ Added new error codes.
+
+Sat Jul 15 04:23:37 1995 <tytso@rsx-11.mit.edu>
+
+ * inode.c (ext2fs_get_next_inode): Don't check scan->inode_buffer;
+ if the magic number is correct, it will be allocated.
+
+Fri Jul 14 19:02:59 1995 <tytso@rsx-11.mit.edu>
+
+ * block.c (block_iterate_ind, block_iterate_dind,
+ block_iterate_tind): Don't recompute block_nr each loop;
+ just increment it! Factor check of BLOCK_FLAG_APPEND out
+ of the loop. Factor mask of BLOCK_CHANGED into changed
+ variable out of the loop. (block_iterate_ind, in
+ particular, gets called a lot, so every little
+ optimization helps.)
+
+Thu Jul 13 08:02:45 1995 <tytso@rsx-11.mit.edu>
+
+ * block.c (block_iterate_ind, block_iterate_dind,
+ block_iterate_tind): Precompute limit of loop to speed up
+ block_iterate_ind and company.
+
+ * bitops.h (ext2fs_fast_mark_block_bitmap,
+ ext2fs_fast_unmark_block_bitmap, ext2fs_fast_test_block_bitmap,
+ ext2fs_fast_mark_inode_bitmap, ext2fs_fast_unmark_inode_bitmap,
+ ext2fs_fast_test_inode_bitmap): Add fast version of these
+ functions, which don't do range checking.
+
+ * bitops.h (ext2fs_get_block_bitmap_start,
+ ext2fs_get_inode_bitmap_start, ext2fs_get_block_bitmap_end,
+ ext2fs_get_inode_bitmap_end): Add new accessor functions
+ which return the start and end points of the bitmaps.
+
+Tue Jul 11 18:59:41 1995 <tytso@rsx-11.mit.edu>
+
+ * llseek.c (ext2_llseek): If the offset is small enough, use lseek
+ instead of llseek. The errno if the offset is too large
+ and lseek is not supported should be EINVAL, not -EINVAL.
+
+Thu Jun 15 23:43:02 1995 Remy Card <card@bbj>
+
+ * Makefile.in: Added support for ELF shared libraries.
+ Fixed typos in the compilation rules.
+ (distclean): Added Makefile.
+
+ * llseek.c (llseek): New function, if llseek() does not exist in the
+ C library.
+ (ext2_llseek): Changed to call llseek().
+
+Mon Jun 12 08:29:07 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * ext2fs.h: Use __u32 to define blk_t, instead of unsigned long.
+
+Sun Jun 11 15:02:54 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * mkdir.c (ext2fs_mkdir): Use LINUX_S_IFDIR instead of S_IFDIR.
+
+ * ext2fs.h (LINUX_S_IFDIR): Define a linux specific versions of
+ the S_*, which are normally defined in <sys/stat.h>. This
+ allows us to compile e2fsprogs on a non-Linux system,
+ which may have a different value for S_IFDIR.
+
+Sat Jun 10 23:47:05 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * bitops.c (clear_bit, set_bit): Remove calls to cli() and sti();
+ this is a user-mode application!
+
+Thu Jun 8 13:13:22 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * llseek.c: Put the include of <linux/unistd.h> inside the #ifdef
+ __linux__ so that non-linux systems won't see it.
+
+ * alloc.c: Include <errno.h> if possible.
+ * badblocks.c: Ditto.
+ * bb_inode.c: Ditto.
+ * bitmaps.c: Ditto.
+ * block.c: Ditto.
+ * expanddir.c: Ditto.
+ * get_pathname.c: Ditto.
+ * initialize.c: Ditto.
+ * inode.c: Ditto.
+ * llseek.c: Ditto.
+ * mkdir.c: Ditto.
+ * namei.c: Ditto.
+ * newdir.c: Ditto.
+ * openfs.c: Ditto.
+ * rw_bitmaps.c: Ditto.
+ * unix_io.c: Ditto.
+
+ * Makefile.in: Rewritten to conform to GNU coding standards and
+ support separate compilation directories.
+
+Thu May 11 04:13:12 1995 <tytso@rsx-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Don't allow more than one
+ bitmaps's worth of inodes in a group.
+
+Sat Mar 11 14:07:11 1995 Theodore Y. Ts'o <tytso@localhost>
+
+ * llseek.c (ext2_llseek): Added error checking to the llseek()
+ compat code to protect against overflow. This only
+ applies to 1.0 and early 1.1 kernels, which don't support
+ the llseek() system call.
+
+Thu Nov 24 16:29:00 1994 Theodore Y. Ts'o (tytso@rt-11)
+
+ * unix_io.c (unix_open): Initialize the read_error and write_error
+ io_channel pointers to be null.
+
+ * bb_inode.c (clear_bad_block_proc): If an illegal block number is
+ found, clear it but don't try to update the filesystem
+ accounting information, since that's hopeless anyway.
+
+ * block.c (bloblock_iterate_ind, bloblock_iterate_dind,
+ bloblock_iterate_tind): Check to see if the indirect blocks are
+ valid before trying to read them.
+
+ * ext2_err.et (EXT2_ET_BAD_IND_BLOCK, EX2_ET_BAD_DIND_BLOCK,
+ EXT2_ET_BAD_TIND_BLOCK): Add new error codes.
+
+ * bitops.h (ext2fs_mark_block_bitmap, ext2fs_unmark_block_bitmap,
+ ext2fs_test_block_bitmap, ext2fs_mark_inode_bitmap,
+ ext2fs_unmark_inode_bitmap, ext2fs_test_inode_bitmap): If an
+ illegal block or inode number is passed in, return instead
+ of trying to test, set, or clear the bit.
+
+Mon Nov 7 21:32:33 1994 Remy Card <card@bbj>
+
+ * Makefile: Added a dummy install target in case shared libraries
+ are not built.
+
+Mon Oct 24 14:11:44 1994 (tytso@rsx-11)
+
+ * bitmaps.c (ext2fs_allocate_block_bitmap): Fix calculation of how
+ the real last block of the bitmap should be calculated.
+
+Wed Sep 7 10:05:36 1994 (tytso@rsx-11)
+
+ * bitmaps.c (ext2fs_fudge_inode_bitmap_end,
+ ext2fs_fudge_block_bitmap_end, ext2fs_clear_inode_bitmap,
+ ext2fs_clear_block_bitmap, ext2fs_free_inode_bitmap,
+ ext2fs_free_block_bitmap): Add magic number checking for
+ the inode and block bitmaps.
+
+ * bitmaps.c (ext2fs_allocate_block_bitmap): Fix to set the correct
+ magic number for a block bitmap instead of an inode bitmap.
+
+ * inode.c (ext2fs_close_inode_scan, ext2fs_get_next_inode): Add
+ magic number checking for the inode_scan structure.
+
+ * badblocks.c (badblocks_list_free, badblocks_list_add,
+ badblocks_list_test, badblocks_list_iterate_begin,
+ badblocks_list_iterate, badblocks_list_iterate_end): Add
+ magic number checking for the badblocks_list and
+ badblocks_iterate structures.
+
+ * ext2_err.et (EXT2_ET_MAGIC_UNIX_IO_CHANNEL):
+ * unix_io.c (unix_open, unix_close, unix_set_blksize, unix_read_blk,
+ unix_write_blk, unix_flush): Add magic number checking
+ both for io_channel structure and unix_private_data
+ structure.
+
+ * openfs.c (ext2fs_open): Add check for io_manager structure's
+ magic number.
+
+ * rw_bitmaps.c (ext2fs_write_inode_bitmap, ext2fs_write_block_bitmap,
+ ext2fs_read_inode_bitmap, ext2fs_read_block_bitmap,
+ ext2fs_read_bitmaps, ext2fs_write_bitmaps):
+ * read_bb.c (ext2fs_read_bb_inode):
+ * read_bb_file.c (ext2fs_read_bb_FILE):
+ * newdir.c (ext2fs_new_dir_block):
+ * namei.c (ext2fs_dir_iterate, ext2fs_lookup, ext2fs_namei):
+ * link.c (ext2fs_link, ext2fs_unlink):
+ * inode.c (ext2fs_open_inode_scan, ext2fs_read_inode,
+ ext2fs_write_inode, ext2fs_get_blocks,
+ ext2fs_check_directory):
+ * get_pathname.c (ext2fs_get_pathname):
+ * expanddir.c (ext2fs_expand_dir):
+ * block.c (ext2fs_block_iterate):
+ * bitmaps.c (ext2fs_allocate_inode_bitmap,
+ ext2fs_allocate_block_bitmap):
+ * bb_inode.c (ext2fs_update_bb_inode):
+ * alloc.c (ext2fs_new_inode,ext2fs_new_block,ext2fs_get_free_blocks):
+ * check_desc.c (ext2fs_check_desc):
+ * closefs.c (ext2fs_close, ext2fs_flush):
+ * freefs.c (ext2fs_free): Add check for ext2_filsys magic number.
+
+ * Makefile:
+ * ext2fs.h:
+ * openfs.c:
+ * check_desc.c (ext2fs_check_desc): Move ext2fs_check_desc from
+ openfs.c into its own file.
+
+ * ext2fs.h (EXT2_CHECK_MAGIC): Added macro for checking for
+ structure magic numbers.
+
+ * closefs.c (ext2fs_flush): Folded in Remy Card's changes to clear
+ the EXT2_VALID_FS flag in the backup superblock blocks, so that if
+ someone uses the -b option to specify the use of the backup
+ superblock --- this usually means that the main superblock is
+ toast. :-)
+
+ * ext2fs.h:
+ * ext2_err.et (EXT2_ET_REV_TOO_HIGH):
+ * openfs.c (ext2fs_open): Folded in Remy Card's changes to add a
+ revision level to the superblock.
+
+Sun Aug 21 00:50:08 1994 Theodore Y. Ts'o (tytso@rt-11)
+
+ * ext2fs.h:
+ * bitmaps.c:
+ * bitops.c
+ * bitops.h:
+ * openfs.c:
+ * initialize.c: Completely revamped the inode and block bitmap
+ structures, so that they can be better chance of being extensible
+ in a shared library. They are now their own type, instead of
+ being a char *. Also, the function signatures of
+ ext2fs_test_block_bitmap, ext2fs_mark_block_bitmap,
+ ext2fs_unmark_block_bitmap, ext2fs_test_inode_bitmap,
+ ext2fs_mark_inode_bitmap, and ext2fs_unmark_inode_bitmap were
+ changed to eliminate the ext2_filsys argument, since it is no
+ longer necessary.
+
+Wed Aug 17 21:46:44 1994 Remy Card (card@bbj)
+
+ * unix_io.c (unix_read_blk and unix_write_blk): use the llseek
+ system call if available.
+
+ * llseek.c: new file. This is the stub calling the llseek system
+ call which allows supports for 2GB+ file systems.
+
+ * initialize.c (ext2fs_initialize): Ext2fs_initialize now stores
+ the creator operating system.
+
+Wed Aug 17 10:03:24 1994 Theodore Y. Ts'o (tytso@rt-11)
+
+ * initialize.c (ext2fs_initialize): Ext2fs_initialize now sets up
+ the group descriptor statistics in addition to everything else.
+ This relieves mke2fs of the responsibility of doing it.
+
+ * bitops.c, bitops.h: Add assembly inline functions for the 68000.
+ Added a new #define, _EXT2_HAVE_ASM_BITOPS_ to control whether or
+ not the generic C function equivalents should be included or not.
+
+ * openfs.c (ext2fs_open): If a superblock is specified, then use
+ the backup group descriptors that go along with this superblock,
+ instead of using the primary group descriptors. This allows
+ e2fsck to recover filesystems where the primary group descriptors
+ have been trashed.
+
+
diff --git a/e2fslib/MCONFIG b/e2fslib/MCONFIG
new file mode 100644
index 0000000..5fde38f
--- /dev/null
+++ b/e2fslib/MCONFIG
@@ -0,0 +1,199 @@
+# Beginning of file MCONFIG
+
+all::
+
+check::
+
+SHELL = /bin/sh
+
+prefix = /usr
+root_prefix =
+exec_prefix = ${prefix}
+root_bindir = $(root_prefix)/bin
+root_sbindir = $(root_prefix)/sbin
+root_libdir = $(root_prefix)/lib
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+mandir = ${prefix}/man
+man1dir = $(mandir)/man1
+man3dir = $(mandir)/man3
+man8dir = $(mandir)/man8
+infodir = ${prefix}/info
+datadir = ${prefix}/share
+
+
+
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+CC = cc
+BUILD_CC = cc
+DEFS = -DENABLE_SWAPFS=1 -DPACKAGE=\"e2fsprogs\" -DVERSION=\"1.25\" -DSTDC_HEADERS=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_ARGZ_H=1 -DHAVE_LIMITS_H=1 -DHAVE_LOCALE_H=1 -DHAVE_NL_TYPES_H=1 -DHAVE_MALLOC_H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_GETCWD=1 -DHAVE_MUNMAP=1 -DHAVE_PUTENV=1 -DHAVE_SETENV=1 -DHAVE_SETLOCALE=1 -DHAVE_STRCHR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRDUP=1 -DHAVE___ARGZ_COUNT=1 -DHAVE___ARGZ_STRINGIFY=1 -DHAVE___ARGZ_NEXT=1 -DHAVE_STPCPY=1 -DHAVE_STPCPY=1 -DHAVE_LC_MESSAGES=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1 -DHAVE_ERRNO_H=1 -DHAVE_MALLOC_H=1 -DHAVE_MNTENT_H=1 -DHAVE_PATHS_H=1 -DHAVE_DIRENT_H=1 -DHAVE_GETOPT_H=1 -DHAVE_SETJMP_H=1 -DHAVE_SIGNAL_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_LINUX_FD_H=1 -DHAVE_LINUX_MAJOR_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_MOUNT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_NET_IF_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_VPRINTF=1 -DHAVE_LSEEK64_PROTOTYPE=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DWORDS_BIGENDIAN=1 -DHAVE_GETRUSAGE=1 -DHAVE_LLSEEK=1 -DHAVE_LSEEK64=1 -DHAVE_OPEN64=1 -DHAVE_STRCASECMP=1 -DHAVE_SRANDOM=1 -DHAVE_FCHOWN=1 -DHAVE_MALLINFO=1 -DHAVE_FDATASYNC=1 -DHAVE_STRNLEN=1 -DHAVE_EXT2_IOCTLS=1
+CFLAGS = -g -O2
+CPPFLAGS =
+ALL_CFLAGS = $(CPPFLAGS) $(DEFS) $(USE_WFLAGS) $(CFLAGS) $(XTRA_CFLAGS) \
+ -I$(top_builddir)/lib -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/include $(LINUX_INCLUDE)
+LDFLAGS =
+ALL_LDFLAGS = $(LDFLAGS)
+RM = /bin/rm
+LN = /bin/ln
+LN_S = ln -s
+MV = /bin/mv
+CP = /bin/cp
+CHMOD = /bin/chmod
+AR = ar
+AWK = /usr/bin/awk
+SED = /bin/sed
+PERL = /usr/bin/perl
+RANLIB = ranlib
+STRIP = strip
+LD = $(PURE) cc
+ARUPD = $(AR) r
+LDCONFIG = :
+
+#
+# Library definitions
+#
+LIB = $(top_builddir)/lib
+LIBSS = $(LIB)/libss.a
+LIBCOM_ERR = $(LIB)/libcom_err.a
+LIBE2P = $(LIB)/libe2p.a
+LIBEXT2FS = $(LIB)/libext2fs.a
+LIBUUID = $(LIB)/libuuid.a
+DEPLIBUUID = $(LIB)/libuuid.a
+
+STATIC_LIBSS = $(LIB)/libss.a
+STATIC_LIBCOM_ERR = $(LIB)/libcom_err.a
+STATIC_LIBE2P = $(LIB)/libe2p.a
+STATIC_LIBEXT2FS = $(LIB)/libext2fs.a
+STATIC_LIBUUID = $(LIB)/libuuid.a
+DEPSTATIC_LIBUUID = $(LIB)/libuuid.a
+
+PROFILED_LIBSS = $(LIB)/libss
+PROFILED_LIBCOM_ERR = $(LIB)/libcom_err
+PROFILED_LIBE2P = $(LIB)/libe2p
+PROFILED_LIBEXT2FS = $(LIB)/libext2fs
+PROFILED_LIBUUID = $(LIB)/libuuid
+DEPPROFILED_LIBUUID = $(LIB)/libuuid
+
+#
+# Use these definitions is you use tools 2.x, x < 16
+#
+#DLL_BIN=/usr/dll/bin
+#JUMP_PREFIX=/usr/dll/jump/
+
+#
+# Use these definitions if you use tools 2.16 or above
+#
+DLL_BIN=/usr/bin
+JUMP_PREFIX=/usr/bin/jump
+
+# An include directive pointing to a directory holding enough linux-like
+# include files to satisfy some programs here
+LINUX_INCLUDE=
+
+#
+# A fast substitution command for fixing up man pages, shell scripts, etc.
+#
+SUBST_CONF=$(top_builddir)/util/subst.conf
+SUBSTITUTE= $(top_builddir)/util/subst -f $(SUBST_CONF)
+DEP_SUBSTITUTE= $(top_builddir)/util/subst $(SUBST_CONF)
+
+$(top_builddir)/util/subst:
+ cd $(top_builddir)/util ; $(MAKE) subst
+
+#
+# Warning flags
+#
+# Run make gcc-wall to do a build with warning messages.
+#
+#
+WFLAGS= -ansi -D_POSIX_SOURCE -pedantic \
+ -Wall -Wwrite-strings -Wpointer-arith \
+ -Wcast-qual -Wcast-align -Wtraditional \
+ -Wstrict-prototypes -Wmissing-prototypes \
+ -Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow
+
+gcc-wall-new:
+ (make USE_WFLAGS="$(WFLAGS)" > /dev/null) 2>&1 | sed -f $(top_srcdir)/util/gcc-wall-cleanup
+
+gcc-wall:
+ make clean > /dev/null
+ make gcc-wall-new
+
+#
+# Installation user and groups
+#
+BINGRP= bin
+BINOWN= bin
+BINMODE= 555
+INCGRP= bin
+INCOWN= bin
+INCMODE= 444
+LIBOWN= bin
+LIBGRP= bin
+LIBMODE= 444
+MANGRP= bin
+MANOWN= bin
+MANMODE= 444
+
+#
+# Autoconf magic...
+#
+
+DEP_LIB_MAKEFILES = $(top_srcdir)/lib/Makefile.elf-lib \
+ $(top_srcdir)/lib/Makefile.dll-lib $(top_srcdir)/lib/Makefile.bsd-lib \
+ $(top_srcdir)/lib/Makefile.checker $(top_srcdir)/lib/Makefile.profile
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir); ./config.status --recheck
+
+$(top_builddir)/MCONFIG: $(top_srcdir)/MCONFIG.in $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=MCONFIG ./config.status
+
+$(top_builddir)/lib/substitute_sh: $(top_srcdir)/lib/substitute_sh.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=lib/substitute_sh ./config.status
+
+$(top_builddir)/util/subst.conf: $(top_srcdir)/util/subst.conf.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=util/subst.conf ./config.status
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/MCONFIG \
+ $(DEP_MAKEFILE) $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=$(my_dir)/Makefile ./config.status
+
+$(top_srcdir)/configure: $(top_srcdir)/configure.in
+ cd $(top_srcdir) && autoconf
+
+#
+# Make depend magic...
+#
+
+.depend: Makefile $(SRCS) $(top_srcdir)/depfix.sed $(top_srcdir)/wordwrap.pl
+ if test -n "$(SRCS)" ; then \
+ $(CC) -M $(ALL_CFLAGS) $(SRCS) | \
+ $(SED) -f $(top_srcdir)/depfix.sed \
+ -e 's; $(srcdir)/; $$(srcdir)/;g' \
+ -e 's; $(top_srcdir)/; $$(top_srcdir)/;g' \
+ -e 's; $(top_builddir)/; $$(top_builddir)/;g' \
+ -e 's; \./; ;g' \
+ -e '/^ *\\$$/d' | \
+ $(PERL) $(top_srcdir)/wordwrap.pl > .depend; \
+ else :; fi
+
+depend:: .depend
+ if test -n "$(SRCS)" ; then \
+ sed -e '/^# +++ Dependency line eater +++/,$$d' \
+ < $(srcdir)/Makefile.in | cat - .depend \
+ > $(srcdir)/Makefile.in.new; \
+ if cmp -s $(srcdir)/Makefile.in $(srcdir)/Makefile.in.new ; then \
+ $(RM) $(srcdir)/Makefile.in.new ; \
+ else \
+ $(MV) $(srcdir)/Makefile.in $(srcdir)/Makefile.in.old; \
+ $(MV) $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in; \
+ fi ; else :; fi
+
+# End of file MCONFIG
diff --git a/e2fslib/Makefile b/e2fslib/Makefile
new file mode 100644
index 0000000..dd3f6cf
--- /dev/null
+++ b/e2fslib/Makefile
@@ -0,0 +1,642 @@
+# Generated automatically from Makefile.in by configure.
+srcdir = .
+top_srcdir = ../..
+top_builddir = ../..
+my_dir = lib/ext2fs
+INSTALL = /usr/bin/install -c
+
+
+# Beginning of file MCONFIG
+
+all::
+
+check::
+
+SHELL = /bin/sh
+
+prefix = /usr
+root_prefix =
+exec_prefix = ${prefix}
+root_bindir = $(root_prefix)/bin
+root_sbindir = $(root_prefix)/sbin
+root_libdir = $(root_prefix)/lib
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+mandir = ${prefix}/man
+man1dir = $(mandir)/man1
+man3dir = $(mandir)/man3
+man8dir = $(mandir)/man8
+infodir = ${prefix}/info
+datadir = ${prefix}/share
+
+
+
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+CC = cc
+BUILD_CC = cc
+DEFS = -DENABLE_SWAPFS=1 -DPACKAGE=\"e2fsprogs\" -DVERSION=\"1.25\" -DSTDC_HEADERS=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_ARGZ_H=1 -DHAVE_LIMITS_H=1 -DHAVE_LOCALE_H=1 -DHAVE_NL_TYPES_H=1 -DHAVE_MALLOC_H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_GETCWD=1 -DHAVE_MUNMAP=1 -DHAVE_PUTENV=1 -DHAVE_SETENV=1 -DHAVE_SETLOCALE=1 -DHAVE_STRCHR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRDUP=1 -DHAVE___ARGZ_COUNT=1 -DHAVE___ARGZ_STRINGIFY=1 -DHAVE___ARGZ_NEXT=1 -DHAVE_STPCPY=1 -DHAVE_STPCPY=1 -DHAVE_LC_MESSAGES=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1 -DHAVE_ERRNO_H=1 -DHAVE_MALLOC_H=1 -DHAVE_MNTENT_H=1 -DHAVE_PATHS_H=1 -DHAVE_DIRENT_H=1 -DHAVE_GETOPT_H=1 -DHAVE_SETJMP_H=1 -DHAVE_SIGNAL_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_LINUX_FD_H=1 -DHAVE_LINUX_MAJOR_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_MOUNT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_NET_IF_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_VPRINTF=1 -DHAVE_LSEEK64_PROTOTYPE=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DWORDS_BIGENDIAN=1 -DHAVE_GETRUSAGE=1 -DHAVE_LLSEEK=1 -DHAVE_LSEEK64=1 -DHAVE_OPEN64=1 -DHAVE_STRCASECMP=1 -DHAVE_SRANDOM=1 -DHAVE_FCHOWN=1 -DHAVE_MALLINFO=1 -DHAVE_FDATASYNC=1 -DHAVE_STRNLEN=1 -DHAVE_EXT2_IOCTLS=1
+CFLAGS = -g -O -G 0 -fno-pic -mno-abicalls
+CPPFLAGS =
+ALL_CFLAGS = $(CPPFLAGS) $(DEFS) $(USE_WFLAGS) $(CFLAGS) $(XTRA_CFLAGS) \
+ -I. $(LINUX_INCLUDE)
+LDFLAGS =
+ALL_LDFLAGS = $(LDFLAGS)
+RM = /bin/rm
+LN = /bin/ln
+LN_S = ln -s
+MV = /bin/mv
+CP = /bin/cp
+CHMOD = /bin/chmod
+AR = ar
+AWK = /usr/bin/awk
+SED = /bin/sed
+PERL = /usr/bin/perl
+RANLIB = ranlib
+STRIP = strip
+LD = $(PURE) cc
+ARUPD = $(AR) r
+LDCONFIG = :
+
+#
+# Library definitions
+#
+LIB = $(top_builddir)/lib
+LIBSS = $(LIB)/libss.a
+LIBCOM_ERR = $(LIB)/libcom_err.a
+LIBE2P = $(LIB)/libe2p.a
+LIBEXT2FS = $(LIB)/libext2fs.a
+LIBUUID = $(LIB)/libuuid.a
+DEPLIBUUID = $(LIB)/libuuid.a
+
+STATIC_LIBSS = $(LIB)/libss.a
+STATIC_LIBCOM_ERR = $(LIB)/libcom_err.a
+STATIC_LIBE2P = $(LIB)/libe2p.a
+STATIC_LIBEXT2FS = $(LIB)/libext2fs.a
+STATIC_LIBUUID = $(LIB)/libuuid.a
+DEPSTATIC_LIBUUID = $(LIB)/libuuid.a
+
+PROFILED_LIBSS = $(LIB)/libss
+PROFILED_LIBCOM_ERR = $(LIB)/libcom_err
+PROFILED_LIBE2P = $(LIB)/libe2p
+PROFILED_LIBEXT2FS = $(LIB)/libext2fs
+PROFILED_LIBUUID = $(LIB)/libuuid
+DEPPROFILED_LIBUUID = $(LIB)/libuuid
+
+#
+# Use these definitions if you use tools 2.16 or above
+#
+DLL_BIN=/usr/bin
+JUMP_PREFIX=/usr/bin/jump
+
+# An include directive pointing to a directory holding enough linux-like
+# include files to satisfy some programs here
+LINUX_INCLUDE=
+
+#
+# A fast substitution command for fixing up man pages, shell scripts, etc.
+#
+SUBST_CONF=util/subst.conf
+SUBSTITUTE=util/subst -f $(SUBST_CONF)
+DEP_SUBSTITUTE=util/subst $(SUBST_CONF)
+
+$(top_builddir)/util/subst:
+ cd $(top_builddir)/util ; $(MAKE) subst
+
+#
+# Warning flags
+#
+# Run make gcc-wall to do a build with warning messages.
+#
+#
+WFLAGS= -ansi -D_POSIX_SOURCE -pedantic \
+ -Wall -Wwrite-strings -Wpointer-arith \
+ -Wcast-qual -Wcast-align -Wtraditional \
+ -Wstrict-prototypes -Wmissing-prototypes \
+ -Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow
+
+gcc-wall-new:
+ (make USE_WFLAGS="$(WFLAGS)" > /dev/null) 2>&1 | sed -f $(top_srcdir)/util/gcc-wall-cleanup
+
+gcc-wall:
+ make clean > /dev/null
+ make gcc-wall-new
+
+#
+# Installation user and groups
+#
+BINGRP= bin
+BINOWN= bin
+BINMODE= 555
+INCGRP= bin
+INCOWN= bin
+INCMODE= 444
+LIBOWN= bin
+LIBGRP= bin
+LIBMODE= 444
+MANGRP= bin
+MANOWN= bin
+MANMODE= 444
+
+#
+# Autoconf magic...
+#
+
+DEP_LIB_MAKEFILES = $(top_srcdir)/lib/Makefile.elf-lib \
+ $(top_srcdir)/lib/Makefile.dll-lib $(top_srcdir)/lib/Makefile.bsd-lib \
+ $(top_srcdir)/lib/Makefile.checker $(top_srcdir)/lib/Makefile.profile
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir); ./config.status --recheck
+
+$(top_builddir)/lib/substitute_sh: $(top_srcdir)/lib/substitute_sh.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=lib/substitute_sh ./config.status
+
+$(top_builddir)/util/subst.conf: $(top_srcdir)/util/subst.conf.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=util/subst.conf ./config.status
+
+$(top_srcdir)/configure: $(top_srcdir)/configure.in
+ cd $(top_srcdir) && autoconf
+
+#
+# Make depend magic...
+#
+
+.depend: Makefile $(SRCS) $(top_srcdir)/depfix.sed $(top_srcdir)/wordwrap.pl
+ if test -n "$(SRCS)" ; then \
+ $(CC) -M $(ALL_CFLAGS) $(SRCS) | \
+ $(SED) -f $(top_srcdir)/depfix.sed \
+ -e 's; $(srcdir)/; $$(srcdir)/;g' \
+ -e 's; $(top_srcdir)/; $$(top_srcdir)/;g' \
+ -e 's; $(top_builddir)/; $$(top_builddir)/;g' \
+ -e 's; \./; ;g' \
+ -e '/^ *\\$$/d' | \
+ $(PERL) $(top_srcdir)/wordwrap.pl > .depend; \
+ else :; fi
+
+depend:: .depend
+ if test -n "$(SRCS)" ; then \
+ sed -e '/^# +++ Dependency line eater +++/,$$d' \
+ < $(srcdir)/Makefile.in | cat - .depend \
+ > $(srcdir)/Makefile.in.new; \
+ if cmp -s $(srcdir)/Makefile.in $(srcdir)/Makefile.in.new ; then \
+ $(RM) $(srcdir)/Makefile.in.new ; \
+ else \
+ $(MV) $(srcdir)/Makefile.in $(srcdir)/Makefile.in.old; \
+ $(MV) $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in; \
+ fi ; else :; fi
+
+# End of file MCONFIG
+
+DEBUGFS_LIB_OBJS = bb_compat.o cmp_bitmaps.o dupfs.o fileio.o \
+ namei.o test_io.o write_bb_file.o
+
+RESIZE_LIB_OBJS = rs_bitmap.o
+
+E2IMAGE_LIB_OBJS = imager.o
+
+OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
+ ext2_err.o \
+ alloc.o \
+ alloc_tables.o \
+ badblocks.o \
+ bb_inode.o \
+ bitmaps.o \
+ bitops.o \
+ block.o \
+ bmap.o \
+ check_desc.o \
+ closefs.o \
+ dblist.o \
+ dblist_dir.o \
+ dirblock.o \
+ dir_iterate.o \
+ expanddir.o \
+ ext_attr.o \
+ finddev.o \
+ flushb.o \
+ freefs.o \
+ gen_bitmap.o \
+ get_pathname.o \
+ getsize.o \
+ icount.o \
+ initialize.o \
+ inline.o \
+ inode.o \
+ ismounted.o \
+ link.o \
+ llseek.o \
+ lookup.o \
+ mkdir.o \
+ mkjournal.o \
+ native.o \
+ newdir.o \
+ openfs.o \
+ read_bb.o \
+ read_bb_file.o \
+ rw_bitmaps.o \
+ swapfs.o \
+ unix_io.o \
+ unlink.o \
+ valid_blk.o \
+ version.o
+
+SRCS= ext2_err.c \
+ $(srcdir)/alloc.c \
+ $(srcdir)/alloc_tables.c \
+ $(srcdir)/badblocks.c \
+ $(srcdir)/bb_compat.c \
+ $(srcdir)/bb_inode.c \
+ $(srcdir)/bitmaps.c \
+ $(srcdir)/bitops.c \
+ $(srcdir)/block.c \
+ $(srcdir)/bmap.c \
+ $(srcdir)/check_desc.c \
+ $(srcdir)/closefs.c \
+ $(srcdir)/cmp_bitmaps.c \
+ $(srcdir)/dblist.c \
+ $(srcdir)/dblist_dir.c \
+ $(srcdir)/dirblock.c \
+ $(srcdir)/dir_iterate.c \
+ $(srcdir)/dupfs.c \
+ $(srcdir)/expanddir.c \
+ $(srcdir)/ext_attr.c \
+ $(srcdir)/fileio.c \
+ $(srcdir)/finddev.c \
+ $(srcdir)/flushb.c \
+ $(srcdir)/freefs.c \
+ $(srcdir)/gen_bitmap.c \
+ $(srcdir)/get_pathname.c \
+ $(srcdir)/getsize.c \
+ $(srcdir)/icount.c \
+ $(srcdir)/imager.c \
+ $(srcdir)/initialize.c \
+ $(srcdir)/inline.c \
+ $(srcdir)/inode.c \
+ $(srcdir)/ismounted.c \
+ $(srcdir)/link.c \
+ $(srcdir)/llseek.c \
+ $(srcdir)/lookup.c \
+ $(srcdir)/mkdir.c \
+ $(srcdir)/mkjournal.c \
+ $(srcdir)/namei.c \
+ $(srcdir)/native.c \
+ $(srcdir)/newdir.c \
+ $(srcdir)/openfs.c \
+ $(srcdir)/read_bb.c \
+ $(srcdir)/read_bb_file.c \
+ $(srcdir)/rs_bitmap.c \
+ $(srcdir)/rw_bitmaps.c \
+ $(srcdir)/swapfs.c \
+ $(srcdir)/test_io.c \
+ $(srcdir)/unix_io.c \
+ $(srcdir)/unlink.c \
+ $(srcdir)/valid_blk.c \
+ $(srcdir)/version.c \
+ $(srcdir)/write_bb_file.c \
+ $(srcdir)/tst_badblocks.c \
+ $(srcdir)/tst_bitops.c \
+ $(srcdir)/tst_byteswap.c \
+ $(srcdir)/tst_getsize.c \
+ $(srcdir)/tst_iscan.c
+
+HFILES= bitops.h ext2fs.h ext2_io.h ext2_fs.h ext2_ext_attr.h
+HFILES_IN= ext2_err.h ext2_types.h
+
+LIBRARY= libext2fs
+LIBDIR= ext2fs
+
+DLL_ADDRESS = 0x66900000
+DLL_JUMPSIZE = 0x1000
+DLL_GOTSIZE = 0x1000
+DLL_VERSION = 1.2
+DLL_IMAGE = libe2fs
+DLL_STUB = libext2fs
+DLL_LIBS = -L../.. -lcom_err
+DLL_MYDIR = ext2fs
+DLL_INSTALL_DIR = $(root_libdir)
+
+ELF_VERSION = 2.4
+ELF_SO_VERSION = 2
+ELF_IMAGE = libext2fs
+ELF_MYDIR = ext2fs
+ELF_INSTALL_DIR = $(root_libdir)
+ELF_OTHER_LIBS = -L../.. -lcom_err
+
+BSDLIB_VERSION = 2.1
+BSDLIB_IMAGE = libext2fs
+BSDLIB_MYDIR = ext2fs
+BSDLIB_INSTALL_DIR = $(root_libdir)
+
+
+all:: subdirs $(LIBRARY).a
+
+install-shlibs::
+
+subdirs::
+
+$(LIBRARY).a: $(OBJS)
+ (if test -r $@; then $(RM) -f $@.bak && $(MV) $@ $@.bak; fi)
+ $(ARUPD) $@ $(OBJS)
+ -$(RANLIB) $@
+
+.c.o:
+ $(CC) $(ALL_CFLAGS) -c $< -o $@
+# $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
+# $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
+# (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
+# -o jump/$*.o -c $<)
+# $(CC) $(ALL_CFLAGS) -fPIC -o elfshared/$*.o -c $<
+# $(CC) $(ALL_CFLAGS) -fpic -o pic/$*.o -c $<
+
+COMPILE_ET=et/compile_et
+
+DISTFILES= Makefile *.c *.h image
+
+ext2_err.et: $(DEP_SUBSTITUTE) $(srcdir)/ext2_err.et.in
+ $(SUBSTITUTE) $(srcdir)/ext2_err.et.in ext2_err.et
+
+ext2_err.c ext2_err.h: ext2_err.et
+ $(COMPILE_ET) ext2_err.et
+
+tst_badblocks: tst_badblocks.o freefs.o \
+ read_bb_file.o write_bb_file.o badblocks.o
+ $(CC) -o tst_badblocks tst_badblocks.o freefs.o \
+ read_bb_file.o write_bb_file.o badblocks.o $(LIBCOM_ERR)
+
+tst_iscan: tst_iscan.o inode.o badblocks.o test_io.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_iscan tst_iscan.o inode.o badblocks.o test_io.o \
+ $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
+
+tst_getsize: tst_getsize.o getsize.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_getsize tst_getsize.o getsize.o $(STATIC_LIBEXT2FS) \
+ $(LIBCOM_ERR)
+
+tst_ismounted: $(srcdir)/ismounted.c $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_ismounted $(srcdir)/ismounted.c -DDEBUG $(ALL_CFLAGS) $(LIBCOM_ERR)
+
+tst_byteswap: tst_byteswap.o bitops.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_byteswap tst_byteswap.o bitops.o $(STATIC_LIBEXT2FS) \
+ $(LIBCOM_ERR)
+
+tst_bitops: tst_bitops.o inline.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_bitops tst_bitops.o inline.o \
+ $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
+
+mkjournal: mkjournal.c $(STATIC_LIBEXT2FS)
+ $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS)
+
+check:: tst_badblocks tst_iscan tst_byteswap
+ ./tst_badblocks
+ ./tst_iscan
+ ./tst_byteswap
+
+clean::
+ $(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/* \
+ tst_badblocks tst_iscan ext2_err.et ext2_err.c ext2_err.h \
+ tst_byteswap tst_ismounted mkjournal \
+ ../libext2fs.a ../libext2fs_p.a ../libext2fs_chk.a
+#
+# Hack to parallel makes recognize dependencies correctly.
+#
+$(top_builddir)/lib/ext2fs/ext2_err.h: ext2_err.h
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+ext2_err.o: ext2_err.c
+alloc.o: $(srcdir)/alloc.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+alloc_tables.o: $(srcdir)/alloc_tables.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+badblocks.o: $(srcdir)/badblocks.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+bb_compat.o: $(srcdir)/bb_compat.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+bb_inode.o: $(srcdir)/bb_inode.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+bitmaps.o: $(srcdir)/bitmaps.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+bitops.o: $(srcdir)/bitops.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+block.o: $(srcdir)/block.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+bmap.o: $(srcdir)/bmap.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+check_desc.o: $(srcdir)/check_desc.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+closefs.o: $(srcdir)/closefs.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+dblist.o: $(srcdir)/dblist.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+dblist_dir.o: $(srcdir)/dblist_dir.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+dirblock.o: $(srcdir)/dirblock.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+dir_iterate.o: $(srcdir)/dir_iterate.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+dupfs.o: $(srcdir)/dupfs.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+expanddir.o: $(srcdir)/expanddir.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+ext_attr.o: $(srcdir)/ext_attr.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+fileio.o: $(srcdir)/fileio.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+finddev.o: $(srcdir)/finddev.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+flushb.o: $(srcdir)/flushb.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+freefs.o: $(srcdir)/freefs.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+gen_bitmap.o: $(srcdir)/gen_bitmap.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+get_pathname.o: $(srcdir)/get_pathname.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+getsize.o: $(srcdir)/getsize.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+icount.o: $(srcdir)/icount.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+imager.o: $(srcdir)/imager.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+initialize.o: $(srcdir)/initialize.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+inline.o: $(srcdir)/inline.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+inode.o: $(srcdir)/inode.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+link.o: $(srcdir)/link.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+llseek.o: $(srcdir)/llseek.c com_err.h \
+ $(srcdir)/ext2_io.h
+lookup.o: $(srcdir)/lookup.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+mkdir.o: $(srcdir)/mkdir.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+mkjournal.o: $(srcdir)/mkjournal.c $(srcdir)/ext2_fs.h \
+ ext2_types.h e2p/e2p.h \
+ $(srcdir)/ext2fs.h com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h \
+ $(srcdir)/jfs_user.h linux/jfs.h \
+ linux/jfs_compat.h linux/list.h
+namei.o: $(srcdir)/namei.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+native.o: $(srcdir)/native.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+newdir.o: $(srcdir)/newdir.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+openfs.o: $(srcdir)/openfs.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+read_bb.o: $(srcdir)/read_bb.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+read_bb_file.o: $(srcdir)/read_bb_file.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+rs_bitmap.o: $(srcdir)/rs_bitmap.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+rw_bitmaps.o: $(srcdir)/rw_bitmaps.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+swapfs.o: $(srcdir)/swapfs.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+test_io.o: $(srcdir)/test_io.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+unix_io.o: $(srcdir)/unix_io.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+unlink.o: $(srcdir)/unlink.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+valid_blk.o: $(srcdir)/valid_blk.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+version.o: $(srcdir)/version.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h \
+ version.h
+write_bb_file.o: $(srcdir)/write_bb_file.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+tst_badblocks.o: $(srcdir)/tst_badblocks.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+tst_bitops.o: $(srcdir)/tst_bitops.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+tst_byteswap.o: $(srcdir)/tst_byteswap.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+tst_getsize.o: $(srcdir)/tst_getsize.c $(srcdir)/ext2_fs.h \
+ ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ ext2_err.h $(srcdir)/bitops.h
+tst_iscan.o: $(srcdir)/tst_iscan.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
diff --git a/e2fslib/Makefile.in b/e2fslib/Makefile.in
new file mode 100644
index 0000000..d301d98
--- /dev/null
+++ b/e2fslib/Makefile.in
@@ -0,0 +1,477 @@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ../..
+my_dir = lib/ext2fs
+INSTALL = @INSTALL@
+
+@MCONFIG@
+
+@DEBUGFS_CMT@DEBUGFS_LIB_OBJS = bb_compat.o cmp_bitmaps.o dupfs.o fileio.o \
+@DEBUGFS_CMT@ namei.o test_io.o write_bb_file.o
+
+@RESIZER_CMT@RESIZE_LIB_OBJS = rs_bitmap.o
+
+@IMAGER_CMT@E2IMAGE_LIB_OBJS = imager.o
+
+OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
+ ext2_err.o \
+ alloc.o \
+ alloc_tables.o \
+ badblocks.o \
+ bb_inode.o \
+ bitmaps.o \
+ bitops.o \
+ block.o \
+ bmap.o \
+ check_desc.o \
+ closefs.o \
+ dblist.o \
+ dblist_dir.o \
+ dirblock.o \
+ dir_iterate.o \
+ expanddir.o \
+ ext_attr.o \
+ finddev.o \
+ flushb.o \
+ freefs.o \
+ gen_bitmap.o \
+ get_pathname.o \
+ getsize.o \
+ icount.o \
+ initialize.o \
+ inline.o \
+ inode.o \
+ ismounted.o \
+ link.o \
+ llseek.o \
+ lookup.o \
+ mkdir.o \
+ mkjournal.o \
+ native.o \
+ newdir.o \
+ openfs.o \
+ read_bb.o \
+ read_bb_file.o \
+ rw_bitmaps.o \
+ swapfs.o \
+ unix_io.o \
+ unlink.o \
+ valid_blk.o \
+ version.o
+
+SRCS= ext2_err.c \
+ $(srcdir)/alloc.c \
+ $(srcdir)/alloc_tables.c \
+ $(srcdir)/badblocks.c \
+ $(srcdir)/bb_compat.c \
+ $(srcdir)/bb_inode.c \
+ $(srcdir)/bitmaps.c \
+ $(srcdir)/bitops.c \
+ $(srcdir)/block.c \
+ $(srcdir)/bmap.c \
+ $(srcdir)/check_desc.c \
+ $(srcdir)/closefs.c \
+ $(srcdir)/cmp_bitmaps.c \
+ $(srcdir)/dblist.c \
+ $(srcdir)/dblist_dir.c \
+ $(srcdir)/dirblock.c \
+ $(srcdir)/dir_iterate.c \
+ $(srcdir)/dupfs.c \
+ $(srcdir)/expanddir.c \
+ $(srcdir)/ext_attr.c \
+ $(srcdir)/fileio.c \
+ $(srcdir)/finddev.c \
+ $(srcdir)/flushb.c \
+ $(srcdir)/freefs.c \
+ $(srcdir)/gen_bitmap.c \
+ $(srcdir)/get_pathname.c \
+ $(srcdir)/getsize.c \
+ $(srcdir)/icount.c \
+ $(srcdir)/imager.c \
+ $(srcdir)/initialize.c \
+ $(srcdir)/inline.c \
+ $(srcdir)/inode.c \
+ $(srcdir)/ismounted.c \
+ $(srcdir)/link.c \
+ $(srcdir)/llseek.c \
+ $(srcdir)/lookup.c \
+ $(srcdir)/mkdir.c \
+ $(srcdir)/mkjournal.c \
+ $(srcdir)/namei.c \
+ $(srcdir)/native.c \
+ $(srcdir)/newdir.c \
+ $(srcdir)/openfs.c \
+ $(srcdir)/read_bb.c \
+ $(srcdir)/read_bb_file.c \
+ $(srcdir)/rs_bitmap.c \
+ $(srcdir)/rw_bitmaps.c \
+ $(srcdir)/swapfs.c \
+ $(srcdir)/test_io.c \
+ $(srcdir)/unix_io.c \
+ $(srcdir)/unlink.c \
+ $(srcdir)/valid_blk.c \
+ $(srcdir)/version.c \
+ $(srcdir)/write_bb_file.c \
+ $(srcdir)/tst_badblocks.c \
+ $(srcdir)/tst_bitops.c \
+ $(srcdir)/tst_byteswap.c \
+ $(srcdir)/tst_getsize.c \
+ $(srcdir)/tst_iscan.c
+
+HFILES= bitops.h ext2fs.h ext2_io.h ext2_fs.h ext2_ext_attr.h
+HFILES_IN= ext2_err.h ext2_types.h
+
+LIBRARY= libext2fs
+LIBDIR= ext2fs
+
+DLL_ADDRESS = 0x66900000
+DLL_JUMPSIZE = 0x1000
+DLL_GOTSIZE = 0x1000
+DLL_VERSION = 1.2
+DLL_IMAGE = libe2fs
+DLL_STUB = libext2fs
+DLL_LIBS = -L../.. -lcom_err
+DLL_MYDIR = ext2fs
+DLL_INSTALL_DIR = $(root_libdir)
+
+ELF_VERSION = 2.4
+ELF_SO_VERSION = 2
+ELF_IMAGE = libext2fs
+ELF_MYDIR = ext2fs
+ELF_INSTALL_DIR = $(root_libdir)
+ELF_OTHER_LIBS = -L../.. -lcom_err
+
+BSDLIB_VERSION = 2.1
+BSDLIB_IMAGE = libext2fs
+BSDLIB_MYDIR = ext2fs
+BSDLIB_INSTALL_DIR = $(root_libdir)
+
+@MAKEFILE_LIBRARY@
+@MAKEFILE_DLL@
+@MAKEFILE_ELF@
+@MAKEFILE_BSDLIB@
+@MAKEFILE_PROFILE@
+@MAKEFILE_CHECKER@
+
+.c.o:
+ $(CC) $(ALL_CFLAGS) -c $< -o $@
+@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
+@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
+@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
+@DLL_CMT@ -o jump/$*.o -c $<)
+@ELF_CMT@ $(CC) $(ALL_CFLAGS) -fPIC -o elfshared/$*.o -c $<
+@BSDLIB_CMT@ $(CC) $(ALL_CFLAGS) -fpic -o pic/$*.o -c $<
+
+COMPILE_ET=../et/compile_et
+
+DISTFILES= Makefile *.c *.h image
+
+ext2_err.et: $(DEP_SUBSTITUTE) $(srcdir)/ext2_err.et.in
+ $(SUBSTITUTE) $(srcdir)/ext2_err.et.in ext2_err.et
+
+ext2_err.c ext2_err.h: ext2_err.et
+ $(COMPILE_ET) ext2_err.et
+
+tst_badblocks: tst_badblocks.o freefs.o \
+ read_bb_file.o write_bb_file.o badblocks.o
+ $(CC) -o tst_badblocks tst_badblocks.o freefs.o \
+ read_bb_file.o write_bb_file.o badblocks.o $(LIBCOM_ERR)
+
+tst_iscan: tst_iscan.o inode.o badblocks.o test_io.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_iscan tst_iscan.o inode.o badblocks.o test_io.o \
+ $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
+
+tst_getsize: tst_getsize.o getsize.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_getsize tst_getsize.o getsize.o $(STATIC_LIBEXT2FS) \
+ $(LIBCOM_ERR)
+
+tst_ismounted: $(srcdir)/ismounted.c $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_ismounted $(srcdir)/ismounted.c -DDEBUG $(ALL_CFLAGS) $(LIBCOM_ERR)
+
+tst_byteswap: tst_byteswap.o bitops.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_byteswap tst_byteswap.o bitops.o $(STATIC_LIBEXT2FS) \
+ $(LIBCOM_ERR)
+
+tst_bitops: tst_bitops.o inline.o $(STATIC_LIBEXT2FS)
+ $(CC) -o tst_bitops tst_bitops.o inline.o \
+ $(STATIC_LIBEXT2FS) $(LIBCOM_ERR)
+
+mkjournal: mkjournal.c $(STATIC_LIBEXT2FS)
+ $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS)
+
+check:: tst_badblocks tst_iscan tst_byteswap
+ ./tst_badblocks
+ ./tst_iscan
+ ./tst_byteswap
+
+installdirs::
+ $(top_srcdir)/mkinstalldirs $(DESTDIR)$(libdir) \
+ $(DESTDIR)$(includedir)/ext2fs
+
+install:: all $(HFILES) $(HFILES_IN) installdirs
+ $(INSTALL_DATA) libext2fs.a $(DESTDIR)$(libdir)/libext2fs.a
+ $(CHMOD) 644 $(DESTDIR)$(libdir)/libext2fs.a
+ -$(RANLIB) $(DESTDIR)$(libdir)/libext2fs.a
+ $(CHMOD) $(LIBMODE) $(DESTDIR)$(libdir)/libext2fs.a
+ for i in $(HFILES); do \
+ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir)/ext2fs/$$i; \
+ done
+ for i in $(HFILES_IN); do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(includedir)/ext2fs/$$i; \
+ done
+
+uninstall::
+ $(RM) -f $(DESTDIR)$(libdir)/libext2fs.a
+ $(RM) -rf $(DESTDIR)$(includedir)/ext2fs
+
+clean::
+ $(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/* \
+ tst_badblocks tst_iscan ext2_err.et ext2_err.c ext2_err.h \
+ tst_byteswap tst_ismounted mkjournal \
+ ../libext2fs.a ../libext2fs_p.a ../libext2fs_chk.a
+
+mostlyclean:: clean
+distclean:: clean
+ $(RM) -f .depend ext2_err.c ext2_err.h Makefile \
+ $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+#
+# Hack to parallel makes recognize dependencies correctly.
+#
+$(top_builddir)/lib/ext2fs/ext2_err.h: ext2_err.h
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+ext2_err.o: ext2_err.c
+alloc.o: $(srcdir)/alloc.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+alloc_tables.o: $(srcdir)/alloc_tables.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+badblocks.o: $(srcdir)/badblocks.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+bb_compat.o: $(srcdir)/bb_compat.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+bb_inode.o: $(srcdir)/bb_inode.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+bitmaps.o: $(srcdir)/bitmaps.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+bitops.o: $(srcdir)/bitops.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+block.o: $(srcdir)/block.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+bmap.o: $(srcdir)/bmap.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+check_desc.o: $(srcdir)/check_desc.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+closefs.o: $(srcdir)/closefs.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+dblist.o: $(srcdir)/dblist.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+dblist_dir.o: $(srcdir)/dblist_dir.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+dirblock.o: $(srcdir)/dirblock.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+dir_iterate.o: $(srcdir)/dir_iterate.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+dupfs.o: $(srcdir)/dupfs.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+expanddir.o: $(srcdir)/expanddir.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+ext_attr.o: $(srcdir)/ext_attr.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2_ext_attr.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+fileio.o: $(srcdir)/fileio.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+finddev.o: $(srcdir)/finddev.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+flushb.o: $(srcdir)/flushb.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+freefs.o: $(srcdir)/freefs.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+gen_bitmap.o: $(srcdir)/gen_bitmap.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+get_pathname.o: $(srcdir)/get_pathname.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+getsize.o: $(srcdir)/getsize.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+icount.o: $(srcdir)/icount.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+imager.o: $(srcdir)/imager.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+initialize.o: $(srcdir)/initialize.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+inline.o: $(srcdir)/inline.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+inode.o: $(srcdir)/inode.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+link.o: $(srcdir)/link.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+llseek.o: $(srcdir)/llseek.c $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h
+lookup.o: $(srcdir)/lookup.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+mkdir.o: $(srcdir)/mkdir.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+mkjournal.o: $(srcdir)/mkjournal.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/e2p/e2p.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
+ $(srcdir)/jfs_user.h $(top_srcdir)/include/linux/jfs.h \
+ $(top_srcdir)/include/linux/jfs_compat.h $(top_srcdir)/include/linux/list.h
+namei.o: $(srcdir)/namei.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+native.o: $(srcdir)/native.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+newdir.o: $(srcdir)/newdir.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+openfs.o: $(srcdir)/openfs.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+read_bb.o: $(srcdir)/read_bb.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+read_bb_file.o: $(srcdir)/read_bb_file.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+rs_bitmap.o: $(srcdir)/rs_bitmap.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+rw_bitmaps.o: $(srcdir)/rw_bitmaps.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h
+swapfs.o: $(srcdir)/swapfs.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+test_io.o: $(srcdir)/test_io.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+unix_io.o: $(srcdir)/unix_io.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+unlink.o: $(srcdir)/unlink.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+valid_blk.o: $(srcdir)/valid_blk.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+version.o: $(srcdir)/version.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h \
+ $(top_srcdir)/version.h
+write_bb_file.o: $(srcdir)/write_bb_file.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+tst_badblocks.o: $(srcdir)/tst_badblocks.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+tst_bitops.o: $(srcdir)/tst_bitops.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+tst_byteswap.o: $(srcdir)/tst_byteswap.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+tst_getsize.o: $(srcdir)/tst_getsize.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+tst_iscan.o: $(srcdir)/tst_iscan.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
diff --git a/e2fslib/alloc.c b/e2fslib/alloc.c
new file mode 100644
index 0000000..2de05bc
--- /dev/null
+++ b/e2fslib/alloc.c
@@ -0,0 +1,178 @@
+/*
+ * alloc.c --- allocate new inodes, blocks for ext2fs
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <string.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Right now, just search forward from the parent directory's block
+ * group to find the next free inode.
+ *
+ * Should have a special policy for directories.
+ */
+errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
+ ext2fs_inode_bitmap map, ext2_ino_t *ret)
+{
+ ext2_ino_t dir_group = 0;
+ ext2_ino_t i;
+ ext2_ino_t start_inode;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!map)
+ map = fs->inode_map;
+ if (!map)
+ return EXT2_ET_NO_INODE_BITMAP;
+
+ if (dir > 0)
+ dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
+
+ start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
+ if (start_inode < EXT2_FIRST_INODE(fs->super))
+ start_inode = EXT2_FIRST_INODE(fs->super);
+ i = start_inode;
+
+ do {
+ if (!ext2fs_fast_test_inode_bitmap(map, i))
+ break;
+ i++;
+ if (i > fs->super->s_inodes_count)
+ i = EXT2_FIRST_INODE(fs->super);
+ } while (i != start_inode);
+
+ if (ext2fs_test_inode_bitmap(map, i))
+ return EXT2_ET_INODE_ALLOC_FAIL;
+ *ret = i;
+ return 0;
+}
+
+/*
+ * Stupid algorithm --- we now just search forward starting from the
+ * goal. Should put in a smarter one someday....
+ */
+errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
+ ext2fs_block_bitmap map, blk_t *ret)
+{
+ blk_t i;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!map)
+ map = fs->block_map;
+ if (!map)
+ return EXT2_ET_NO_BLOCK_BITMAP;
+ if (!goal || (goal >= fs->super->s_blocks_count))
+ goal = fs->super->s_first_data_block;
+ i = goal;
+ do {
+ if (!ext2fs_fast_test_block_bitmap(map, i)) {
+ *ret = i;
+ return 0;
+ }
+ i++;
+ if (i >= fs->super->s_blocks_count)
+ i = fs->super->s_first_data_block;
+ } while (i != goal);
+ return EXT2_ET_BLOCK_ALLOC_FAIL;
+}
+
+/*
+ * This function zeros out the allocated block, and updates all of the
+ * appropriate filesystem records.
+ */
+errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
+ char *block_buf, blk_t *ret)
+{
+ errcode_t retval;
+ blk_t block;
+ int group;
+ char *buf = 0;
+
+ if (!block_buf) {
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+ block_buf = buf;
+ }
+ memset(block_buf, 0, fs->blocksize);
+
+ if (!fs->block_map) {
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval)
+ goto fail;
+ }
+
+ retval = ext2fs_new_block(fs, goal, 0, &block);
+ if (retval)
+ goto fail;
+
+ retval = io_channel_write_blk(fs->io, block, 1, block_buf);
+ if (retval)
+ goto fail;
+
+ fs->super->s_free_blocks_count--;
+ group = ext2fs_group_of_blk(fs, block);
+ fs->group_desc[group].bg_free_blocks_count--;
+ ext2fs_mark_block_bitmap(fs->block_map, block);
+ ext2fs_mark_super_dirty(fs);
+ ext2fs_mark_bb_dirty(fs);
+ *ret = block;
+ return 0;
+
+fail:
+ if (buf)
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
+ int num, ext2fs_block_bitmap map, blk_t *ret)
+{
+ blk_t b = start;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!map)
+ map = fs->block_map;
+ if (!map)
+ return EXT2_ET_NO_BLOCK_BITMAP;
+ if (!b)
+ b = fs->super->s_first_data_block;
+ if (!finish)
+ finish = start;
+ if (!num)
+ num = 1;
+ do {
+ if (b+num-1 > fs->super->s_blocks_count)
+ b = fs->super->s_first_data_block;
+ if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
+ *ret = b;
+ return 0;
+ }
+ b++;
+ } while (b != finish);
+ return EXT2_ET_BLOCK_ALLOC_FAIL;
+}
+
diff --git a/e2fslib/alloc.o b/e2fslib/alloc.o
new file mode 100644
index 0000000..93c31d6
--- /dev/null
+++ b/e2fslib/alloc.o
Binary files differ
diff --git a/e2fslib/alloc_tables.c b/e2fslib/alloc_tables.c
new file mode 100644
index 0000000..ca274cc
--- /dev/null
+++ b/e2fslib/alloc_tables.c
@@ -0,0 +1,120 @@
+/*
+ * alloc_tables.c --- Allocate tables for a newly initialized
+ * filesystem. Used by mke2fs when initializing a filesystem
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
+ ext2fs_block_bitmap bmap)
+{
+ errcode_t retval;
+ blk_t group_blk, start_blk, last_blk, new_blk, blk;
+ int j;
+
+ group_blk = fs->super->s_first_data_block +
+ (group * fs->super->s_blocks_per_group);
+
+ last_blk = group_blk + fs->super->s_blocks_per_group;
+ if (last_blk >= fs->super->s_blocks_count)
+ last_blk = fs->super->s_blocks_count - 1;
+
+ start_blk = group_blk + 3 + fs->desc_blocks;
+ if (start_blk > last_blk)
+ start_blk = group_blk;
+
+ if (!bmap)
+ bmap = fs->block_map;
+
+ /*
+ * Allocate the inode table
+ */
+ if (!fs->group_desc[group].bg_inode_table) {
+ retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+ fs->inode_blocks_per_group,
+ bmap, &new_blk);
+ if (retval)
+ return retval;
+ for (j=0, blk = new_blk;
+ j < fs->inode_blocks_per_group;
+ j++, blk++)
+ ext2fs_mark_block_bitmap(bmap, blk);
+ fs->group_desc[group].bg_inode_table = new_blk;
+ }
+
+ /*
+ * Allocate the block and inode bitmaps, if necessary
+ */
+ if (fs->stride) {
+ start_blk += fs->inode_blocks_per_group;
+ start_blk += ((fs->stride * group) %
+ (last_blk - start_blk));
+ if (start_blk > last_blk)
+ /* should never happen */
+ start_blk = group_blk;
+ } else
+ start_blk = group_blk;
+
+ if (!fs->group_desc[group].bg_block_bitmap) {
+ retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
+ if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
+ retval = ext2fs_get_free_blocks(fs, group_blk,
+ last_blk, 1, bmap, &new_blk);
+ if (retval)
+ return retval;
+ ext2fs_mark_block_bitmap(bmap, new_blk);
+ fs->group_desc[group].bg_block_bitmap = new_blk;
+ }
+
+ if (!fs->group_desc[group].bg_inode_bitmap) {
+ retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
+ if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
+ retval = ext2fs_get_free_blocks(fs, group_blk,
+ last_blk, 1, bmap, &new_blk);
+ if (retval)
+ return retval;
+ ext2fs_mark_block_bitmap(bmap, new_blk);
+ fs->group_desc[group].bg_inode_bitmap = new_blk;
+ }
+ return 0;
+}
+
+
+
+errcode_t ext2fs_allocate_tables(ext2_filsys fs)
+{
+ errcode_t retval;
+ dgrp_t i;
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
+ if (retval)
+ return retval;
+ }
+ return 0;
+}
+
diff --git a/e2fslib/alloc_tables.o b/e2fslib/alloc_tables.o
new file mode 100644
index 0000000..ef79962
--- /dev/null
+++ b/e2fslib/alloc_tables.o
Binary files differ
diff --git a/e2fslib/badblocks.c b/e2fslib/badblocks.c
new file mode 100644
index 0000000..4e94e8c
--- /dev/null
+++ b/e2fslib/badblocks.c
@@ -0,0 +1,236 @@
+/*
+ * badblocks.c --- routines to manipulate the bad block structure
+ *
+ * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+/*
+ * Helper function for making a badblocks list
+ */
+static errcode_t make_badblocks_list(int size, int num, blk_t *list,
+ ext2_badblocks_list *ret)
+{
+ ext2_badblocks_list bb;
+ errcode_t retval;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_list),
+ (void **) &bb);
+ if (retval)
+ return retval;
+ memset(bb, 0, sizeof(struct ext2_struct_badblocks_list));
+ bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
+ bb->size = size ? size : 10;
+ bb->num = num;
+ retval = ext2fs_get_mem(bb->size * sizeof(blk_t), (void **) &bb->list);
+ if (!bb->list) {
+ ext2fs_free_mem((void **) &bb);
+ return retval;
+ }
+ if (list)
+ memcpy(bb->list, list, bb->size * sizeof(blk_t));
+ else
+ memset(bb->list, 0, bb->size * sizeof(blk_t));
+ *ret = bb;
+ return 0;
+}
+
+
+/*
+ * This procedure creates an empty badblocks list.
+ */
+errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
+{
+ return make_badblocks_list(size, 0, 0, ret);
+}
+
+/*
+ * This procedure copies a badblocks list
+ */
+errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
+ ext2_badblocks_list *dest)
+{
+ errcode_t retval;
+
+ retval = make_badblocks_list(src->size, src->num, src->list,
+ dest);
+ if (retval)
+ return retval;
+ (*dest)->badblocks_flags = src->badblocks_flags;
+ return 0;
+}
+
+
+/*
+ * This procedure frees a badblocks list.
+ *
+ * (note: moved to closefs.c)
+ */
+
+
+/*
+ * This procedure adds a block to a badblocks list.
+ */
+errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
+{
+ errcode_t retval;
+ int i, j;
+ unsigned long old_size;
+
+ EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+
+ if (bb->num >= bb->size) {
+ old_size = bb->size * sizeof(blk_t);
+ bb->size += 100;
+ retval = ext2fs_resize_mem(old_size, bb->size * sizeof(blk_t),
+ (void **) &bb->list);
+ if (retval) {
+ bb->size -= 100;
+ return retval;
+ }
+ }
+
+ /*
+ * Add special case code for appending to the end of the list
+ */
+ i = bb->num-1;
+ if ((bb->num != 0) && (bb->list[i] == blk))
+ return 0;
+ if ((bb->num == 0) || (bb->list[i] < blk)) {
+ bb->list[bb->num++] = blk;
+ return 0;
+ }
+
+ j = bb->num;
+ for (i=0; i < bb->num; i++) {
+ if (bb->list[i] == blk)
+ return 0;
+ if (bb->list[i] > blk) {
+ j = i;
+ break;
+ }
+ }
+ for (i=bb->num; i > j; i--)
+ bb->list[i] = bb->list[i-1];
+ bb->list[j] = blk;
+ bb->num++;
+ return 0;
+}
+
+/*
+ * This procedure tests to see if a particular block is on a badblocks
+ * list.
+ */
+int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
+{
+ int low, high, mid;
+
+ if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+ return 0;
+
+ if (bb->num == 0)
+ return 0;
+
+ low = 0;
+ high = bb->num-1;
+ if (blk == bb->list[low])
+ return 1;
+ if (blk == bb->list[high])
+ return 1;
+
+ while (low < high) {
+ mid = (low+high)/2;
+ if (mid == low || mid == high)
+ break;
+ if (blk == bb->list[mid])
+ return 1;
+ if (blk < bb->list[mid])
+ high = mid;
+ else
+ low = mid;
+ }
+ return 0;
+}
+
+errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
+ ext2_badblocks_iterate *ret)
+{
+ ext2_badblocks_iterate iter;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_struct_badblocks_iterate),
+ (void **) &iter);
+ if (retval)
+ return retval;
+
+ iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
+ iter->bb = bb;
+ iter->ptr = 0;
+ *ret = iter;
+ return 0;
+}
+
+int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
+{
+ ext2_badblocks_list bb;
+
+ if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
+ return 0;
+
+ bb = iter->bb;
+
+ if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+ return 0;
+
+ if (iter->ptr < bb->num) {
+ *blk = bb->list[iter->ptr++];
+ return 1;
+ }
+ *blk = 0;
+ return 0;
+}
+
+void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
+{
+ if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
+ return;
+
+ iter->bb = 0;
+ ext2fs_free_mem((void **) &iter);
+}
+
+int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
+{
+ EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+ EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+
+ if (bb1->num != bb2->num)
+ return 0;
+
+ if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
+ return 0;
+ return 1;
+}
diff --git a/e2fslib/badblocks.o b/e2fslib/badblocks.o
new file mode 100644
index 0000000..6da4c25
--- /dev/null
+++ b/e2fslib/badblocks.o
Binary files differ
diff --git a/e2fslib/bb_compat.c b/e2fslib/bb_compat.c
new file mode 100644
index 0000000..40f7343
--- /dev/null
+++ b/e2fslib/bb_compat.c
@@ -0,0 +1,63 @@
+/*
+ * bb_compat.c --- compatibility badblocks routines
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+errcode_t badblocks_list_create(badblocks_list *ret, int size)
+{
+ return ext2fs_badblocks_list_create(ret, size);
+}
+
+void badblocks_list_free(badblocks_list bb)
+{
+ ext2fs_badblocks_list_free(bb);
+}
+
+errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
+{
+ return ext2fs_badblocks_list_add(bb, blk);
+}
+
+int badblocks_list_test(badblocks_list bb, blk_t blk)
+{
+ return ext2fs_badblocks_list_test(bb, blk);
+}
+
+errcode_t badblocks_list_iterate_begin(badblocks_list bb,
+ badblocks_iterate *ret)
+{
+ return ext2fs_badblocks_list_iterate_begin(bb, ret);
+}
+
+int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
+{
+ return ext2fs_badblocks_list_iterate(iter, blk);
+}
+
+void badblocks_list_iterate_end(badblocks_iterate iter)
+{
+ ext2fs_badblocks_list_iterate_end(iter);
+}
diff --git a/e2fslib/bb_compat.o b/e2fslib/bb_compat.o
new file mode 100644
index 0000000..579ca8c
--- /dev/null
+++ b/e2fslib/bb_compat.o
Binary files differ
diff --git a/e2fslib/bb_inode.c b/e2fslib/bb_inode.c
new file mode 100644
index 0000000..34c4955
--- /dev/null
+++ b/e2fslib/bb_inode.c
@@ -0,0 +1,287 @@
+/*
+ * bb_inode.c --- routines to update the bad block inode.
+ *
+ * WARNING: This routine modifies a lot of state in the filesystem; if
+ * this routine returns an error, the bad block inode may be in an
+ * inconsistent state.
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct set_badblock_record {
+ ext2_badblocks_iterate bb_iter;
+ int bad_block_count;
+ blk_t *ind_blocks;
+ int max_ind_blocks;
+ int ind_blocks_size;
+ int ind_blocks_ptr;
+ char *block_buf;
+ errcode_t err;
+};
+
+static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block, int ref_offset,
+ void *priv_data);
+static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block, int ref_offset,
+ void *priv_data);
+
+/*
+ * Given a bad blocks bitmap, update the bad blocks inode to reflect
+ * the map.
+ */
+errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
+{
+ errcode_t retval;
+ struct set_badblock_record rec;
+ struct ext2_inode inode;
+ blk_t blk;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!fs->block_map)
+ return EXT2_ET_NO_BLOCK_BITMAP;
+
+ rec.bad_block_count = 0;
+ rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
+ rec.max_ind_blocks = 10;
+ retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
+ (void **) &rec.ind_blocks);
+ if (retval)
+ return retval;
+ memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &rec.block_buf);
+ if (retval)
+ goto cleanup;
+ memset(rec.block_buf, 0, fs->blocksize);
+ rec.err = 0;
+
+ /*
+ * First clear the old bad blocks (while saving the indirect blocks)
+ */
+ retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
+ BLOCK_FLAG_DEPTH_TRAVERSE, 0,
+ clear_bad_block_proc, &rec);
+ if (retval)
+ goto cleanup;
+ if (rec.err) {
+ retval = rec.err;
+ goto cleanup;
+ }
+
+ /*
+ * Now set the bad blocks!
+ *
+ * First, mark the bad blocks as used. This prevents a bad
+ * block from being used as an indirecto block for the bad
+ * block inode (!).
+ */
+ if (bb_list) {
+ retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+ &rec.bb_iter);
+ if (retval)
+ goto cleanup;
+ while (ext2fs_badblocks_list_iterate(rec.bb_iter, &blk)) {
+ ext2fs_mark_block_bitmap(fs->block_map, blk);
+ }
+ ext2fs_badblocks_list_iterate_end(rec.bb_iter);
+ ext2fs_mark_bb_dirty(fs);
+
+ retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+ &rec.bb_iter);
+ if (retval)
+ goto cleanup;
+ retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
+ BLOCK_FLAG_APPEND, 0,
+ set_bad_block_proc, &rec);
+ ext2fs_badblocks_list_iterate_end(rec.bb_iter);
+ if (retval)
+ goto cleanup;
+ if (rec.err) {
+ retval = rec.err;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Update the bad block inode's mod time and block count
+ * field.
+ */
+ retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
+ if (retval)
+ goto cleanup;
+
+ inode.i_atime = inode.i_mtime = time(0);
+ if (!inode.i_ctime)
+ inode.i_ctime = time(0);
+ inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
+ inode.i_size = rec.bad_block_count * fs->blocksize;
+
+ retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
+ if (retval)
+ goto cleanup;
+
+cleanup:
+ ext2fs_free_mem((void **) &rec.ind_blocks);
+ ext2fs_free_mem((void **) &rec.block_buf);
+ return retval;
+}
+
+/*
+ * Helper function for update_bb_inode()
+ *
+ * Clear the bad blocks in the bad block inode, while saving the
+ * indirect blocks.
+ */
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block, int ref_offset,
+ void *priv_data)
+{
+ struct set_badblock_record *rec = (struct set_badblock_record *)
+ priv_data;
+ errcode_t retval;
+ int group;
+ unsigned long old_size;
+
+ if (!*block_nr)
+ return 0;
+
+ /*
+ * If the block number is outrageous, clear it and ignore it.
+ */
+ if (*block_nr >= fs->super->s_blocks_count ||
+ *block_nr < fs->super->s_first_data_block) {
+ *block_nr = 0;
+ return BLOCK_CHANGED;
+ }
+
+ if (blockcnt < 0) {
+ if (rec->ind_blocks_size >= rec->max_ind_blocks) {
+ old_size = rec->max_ind_blocks * sizeof(blk_t);
+ rec->max_ind_blocks += 10;
+ retval = ext2fs_resize_mem(old_size,
+ rec->max_ind_blocks * sizeof(blk_t),
+ (void **) &rec->ind_blocks);
+ if (retval) {
+ rec->max_ind_blocks -= 10;
+ rec->err = retval;
+ return BLOCK_ABORT;
+ }
+ }
+ rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
+ }
+
+ /*
+ * Mark the block as unused, and update accounting information
+ */
+ ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
+ ext2fs_mark_bb_dirty(fs);
+ group = ext2fs_group_of_blk(fs, *block_nr);
+ fs->group_desc[group].bg_free_blocks_count++;
+ fs->super->s_free_blocks_count++;
+ ext2fs_mark_super_dirty(fs);
+
+ *block_nr = 0;
+ return BLOCK_CHANGED;
+}
+
+
+/*
+ * Helper function for update_bb_inode()
+ *
+ * Set the block list in the bad block inode, using the supplied bitmap.
+ */
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+ e2_blkcnt_t blockcnt, blk_t ref_block,
+ int ref_offset, void *priv_data)
+{
+ struct set_badblock_record *rec = (struct set_badblock_record *)
+ priv_data;
+ errcode_t retval;
+ blk_t blk;
+ int group;
+
+ if (blockcnt >= 0) {
+ /*
+ * Get the next bad block.
+ */
+ if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
+ return BLOCK_ABORT;
+ rec->bad_block_count++;
+ } else {
+ /*
+ * An indirect block; fetch a block from the
+ * previously used indirect block list. The block
+ * most be not marked as used; if so, get another one.
+ * If we run out of reserved indirect blocks, allocate
+ * a new one.
+ */
+ retry:
+ if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
+ blk = rec->ind_blocks[rec->ind_blocks_ptr++];
+ if (ext2fs_test_block_bitmap(fs->block_map, blk))
+ goto retry;
+ } else {
+ retval = ext2fs_new_block(fs, 0, 0, &blk);
+ if (retval) {
+ rec->err = retval;
+ return BLOCK_ABORT;
+ }
+ }
+ retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
+ if (retval) {
+ rec->err = retval;
+ return BLOCK_ABORT;
+ }
+ ext2fs_mark_block_bitmap(fs->block_map, blk);
+ ext2fs_mark_bb_dirty(fs);
+ }
+
+ /*
+ * Update block counts
+ */
+ group = ext2fs_group_of_blk(fs, blk);
+ fs->group_desc[group].bg_free_blocks_count--;
+ fs->super->s_free_blocks_count--;
+ ext2fs_mark_super_dirty(fs);
+
+ *block_nr = blk;
+ return BLOCK_CHANGED;
+}
+
+
+
+
+
+
diff --git a/e2fslib/bb_inode.o b/e2fslib/bb_inode.o
new file mode 100644
index 0000000..f053cfa
--- /dev/null
+++ b/e2fslib/bb_inode.o
Binary files differ
diff --git a/e2fslib/bitmaps.c b/e2fslib/bitmaps.c
new file mode 100644
index 0000000..44f16a9
--- /dev/null
+++ b/e2fslib/bitmaps.c
@@ -0,0 +1,213 @@
+/*
+ * bitmaps.c --- routines to read, write, and manipulate the inode and
+ * block bitmaps.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
+ const char *descr, char *init_map,
+ ext2fs_generic_bitmap *ret)
+{
+ ext2fs_generic_bitmap bitmap;
+ errcode_t retval;
+ size_t size;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
+ (void **) &bitmap);
+ if (retval)
+ return retval;
+
+ bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ bitmap->fs = NULL;
+ bitmap->start = start;
+ bitmap->end = end;
+ bitmap->real_end = real_end;
+ bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
+ if (descr) {
+ retval = ext2fs_get_mem(strlen(descr)+1,
+ (void **) &bitmap->description);
+ if (retval) {
+ ext2fs_free_mem((void **) &bitmap);
+ return retval;
+ }
+ strcpy(bitmap->description, descr);
+ } else
+ bitmap->description = 0;
+
+ size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
+ retval = ext2fs_get_mem(size, (void **) &bitmap->bitmap);
+ if (retval) {
+ ext2fs_free_mem((void **) &bitmap->description);
+ ext2fs_free_mem((void **) &bitmap);
+ return retval;
+ }
+
+ if (init_map)
+ memcpy(bitmap->bitmap, init_map, size);
+ else
+ memset(bitmap->bitmap, 0, size);
+ *ret = bitmap;
+ return 0;
+}
+
+errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
+ __u32 end,
+ __u32 real_end,
+ const char *descr,
+ ext2fs_generic_bitmap *ret)
+{
+ return make_bitmap(start, end, real_end, descr, 0, ret);
+}
+
+errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
+ ext2fs_generic_bitmap *dest)
+{
+ errcode_t retval;
+ ext2fs_generic_bitmap new_map;
+
+ retval = make_bitmap(src->start, src->end, src->real_end,
+ src->description, src->bitmap, &new_map);
+ if (retval)
+ return retval;
+ new_map->magic = src->magic;
+ new_map->fs = src->fs;
+ new_map->base_error_code = src->base_error_code;
+ *dest = new_map;
+ return 0;
+}
+
+void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
+{
+ __u32 i, j;
+
+ for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
+ ext2fs_set_bit(j, map->bitmap);
+
+ return;
+}
+
+errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
+ const char *descr,
+ ext2fs_inode_bitmap *ret)
+{
+ ext2fs_inode_bitmap bitmap;
+ errcode_t retval;
+ __u32 start, end, real_end;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ fs->write_bitmaps = ext2fs_write_bitmaps;
+
+ start = 1;
+ end = fs->super->s_inodes_count;
+ real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
+
+ retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
+ descr, &bitmap);
+ if (retval)
+ return retval;
+
+ bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
+ bitmap->fs = fs;
+ bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
+
+ *ret = bitmap;
+ return 0;
+}
+
+errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
+ const char *descr,
+ ext2fs_block_bitmap *ret)
+{
+ ext2fs_block_bitmap bitmap;
+ errcode_t retval;
+ __u32 start, end, real_end;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ fs->write_bitmaps = ext2fs_write_bitmaps;
+
+ start = fs->super->s_first_data_block;
+ end = fs->super->s_blocks_count-1;
+ real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
+ * fs->group_desc_count)-1 + start;
+
+ retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
+ descr, &bitmap);
+ if (retval)
+ return retval;
+
+ bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ bitmap->fs = fs;
+ bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
+
+ *ret = bitmap;
+ return 0;
+}
+
+errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t end, ext2_ino_t *oend)
+{
+ EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
+
+ if (end > bitmap->real_end)
+ return EXT2_ET_FUDGE_INODE_BITMAP_END;
+ if (oend)
+ *oend = bitmap->end;
+ bitmap->end = end;
+ return 0;
+}
+
+errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
+ blk_t end, blk_t *oend)
+{
+ EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+ if (end > bitmap->real_end)
+ return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
+ if (oend)
+ *oend = bitmap->end;
+ bitmap->end = end;
+ return 0;
+}
+
+void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
+{
+ if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
+ return;
+
+ memset(bitmap->bitmap, 0,
+ (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+}
+
+void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
+{
+ if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
+ return;
+
+ memset(bitmap->bitmap, 0,
+ (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+}
diff --git a/e2fslib/bitmaps.o b/e2fslib/bitmaps.o
new file mode 100644
index 0000000..7d03127
--- /dev/null
+++ b/e2fslib/bitmaps.o
Binary files differ
diff --git a/e2fslib/bitops.c b/e2fslib/bitops.c
new file mode 100644
index 0000000..e27c5a0
--- /dev/null
+++ b/e2fslib/bitops.c
@@ -0,0 +1,91 @@
+/*
+ * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
+ * routines.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef _EXT2_HAVE_ASM_BITOPS_
+
+/*
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents. You should
+ * recode these in the native assmebly language, if at all possible.
+ *
+ * C language equivalents written by Theodore Ts'o, 9/26/92.
+ * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
+ * systems, as well as non-32 bit systems.
+ */
+
+int ext2fs_set_bit(int nr,void * addr)
+{
+ int mask, retval;
+ unsigned char *ADDR = (unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ retval = (mask & *ADDR) != 0;
+ *ADDR |= mask;
+ return retval;
+}
+
+int ext2fs_clear_bit(int nr, void * addr)
+{
+ int mask, retval;
+ unsigned char *ADDR = (unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ retval = (mask & *ADDR) != 0;
+ *ADDR &= ~mask;
+ return retval;
+}
+
+int ext2fs_test_bit(int nr, const void * addr)
+{
+ int mask;
+ const unsigned char *ADDR = (const unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ return ((mask & *ADDR) != 0);
+}
+
+#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
+
+void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
+ const char *description)
+{
+#ifndef OMIT_COM_ERR
+ if (description)
+ com_err(0, errcode, "#%u for %s", arg, description);
+ else
+ com_err(0, errcode, "#%u", arg);
+#endif
+}
+
+void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
+ int code, unsigned long arg)
+{
+#ifndef OMIT_COM_ERR
+ if (bitmap->description)
+ com_err(0, bitmap->base_error_code+code,
+ "#%u for %s", arg, bitmap->description);
+ else
+ com_err(0, bitmap->base_error_code + code, "#%u", arg);
+#endif
+}
+
diff --git a/e2fslib/bitops.h b/e2fslib/bitops.h
new file mode 100644
index 0000000..58a64d1
--- /dev/null
+++ b/e2fslib/bitops.h
@@ -0,0 +1,718 @@
+/*
+ * bitops.h --- Bitmap frobbing code. The byte swapping routines are
+ * also included here.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
+ * Linus Torvalds.
+ */
+
+
+extern int ext2fs_set_bit(int nr,void * addr);
+extern int ext2fs_clear_bit(int nr, void * addr);
+extern int ext2fs_test_bit(int nr, const void * addr);
+extern __u16 ext2fs_swab16(__u16 val);
+extern __u32 ext2fs_swab32(__u32 val);
+
+/*
+ * EXT2FS bitmap manipulation routines.
+ */
+
+/* Support for sending warning messages from the inline subroutines */
+extern const char *ext2fs_block_string;
+extern const char *ext2fs_inode_string;
+extern const char *ext2fs_mark_string;
+extern const char *ext2fs_unmark_string;
+extern const char *ext2fs_test_string;
+extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
+ const char *description);
+extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
+ int code, unsigned long arg);
+
+extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block);
+extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+
+extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
+extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode);
+extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
+
+extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block);
+extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block);
+extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block);
+
+extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode);
+extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode);
+extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode);
+extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
+extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
+extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
+extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
+
+extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num);
+extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
+
+/*
+ * The inline routines themselves...
+ *
+ * If NO_INLINE_FUNCS is defined, then we won't try to do inline
+ * functions at all; they will be included as normal functions in
+ * inline.c
+ */
+#ifdef NO_INLINE_FUNCS
+#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__mc68000__) || \
+ defined(__sparc__)))
+ /* This prevents bitops.c from trying to include the C */
+ /* function version of these functions */
+#define _EXT2_HAVE_ASM_BITOPS_
+#endif
+#endif /* NO_INLINE_FUNCS */
+
+#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
+#ifdef INCLUDE_INLINE_FUNCS
+#define _INLINE_ extern
+#else
+#ifdef __GNUC__
+#define _INLINE_ extern __inline__
+#else /* For Watcom C */
+#define _INLINE_ extern inline
+#endif
+#endif
+
+#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
+ (defined(__i386__) || defined(__i486__) || defined(__i586__)))
+
+#define _EXT2_HAVE_ASM_BITOPS_
+#define _EXT2_HAVE_ASM_SWAB_
+#define _EXT2_HAVE_ASM_FINDBIT_
+
+/*
+ * These are done by inline assembly for speed reasons.....
+ *
+ * All bitoperations return 0 if the bit was cleared before the
+ * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
+ * is the LSB of (addr+1).
+ */
+
+/*
+ * Some hacks to defeat gcc over-optimizations..
+ */
+struct __dummy_h { unsigned long a[100]; };
+#define EXT2FS_ADDR (*(struct __dummy_h *) addr)
+#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
+
+_INLINE_ int ext2fs_set_bit(int nr, void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (EXT2FS_ADDR)
+ :"r" (nr));
+ return oldbit;
+}
+
+_INLINE_ int ext2fs_clear_bit(int nr, void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (EXT2FS_ADDR)
+ :"r" (nr));
+ return oldbit;
+}
+
+_INLINE_ int ext2fs_test_bit(int nr, const void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit)
+ :"m" (EXT2FS_CONST_ADDR),"r" (nr));
+ return oldbit;
+}
+
+#if 0
+_INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size)
+{
+ int d0, d1, d2;
+ int res;
+
+ if (!size)
+ return 0;
+ /* This looks at memory. Mark it volatile to tell gcc not to move it around */
+ __asm__ __volatile__(
+ "cld\n\t"
+ "xorl %%eax,%%eax\n\t"
+ "xorl %%edx,%%edx\n\t"
+ "repe; scasl\n\t"
+ "je 1f\n\t"
+ "movl -4(%%edi),%%eax\n\t"
+ "subl $4,%%edi\n\t"
+ "bsfl %%eax,%%edx\n"
+ "1:\tsubl %%esi,%%edi\n\t"
+ "shll $3,%%edi\n\t"
+ "addl %%edi,%%edx"
+ :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+ :"1" ((size + 31) >> 5), "2" (addr), "S" (addr));
+ return res;
+}
+
+_INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+ int set = 0, bit = offset & 31, res;
+
+ if (bit) {
+ /*
+ * Look for zero in first byte
+ */
+ __asm__("bsfl %1,%0\n\t"
+ "jne 1f\n\t"
+ "movl $32, %0\n"
+ "1:"
+ : "=r" (set)
+ : "r" (*p >> bit));
+ if (set < (32 - bit))
+ return set + offset;
+ set = 32 - bit;
+ p++;
+ }
+ /*
+ * No bit found yet, search remaining full bytes for a bit
+ */
+ res = ext2fs_find_first_bit_set(p, size - 32 * (p - (unsigned long *) addr));
+ return (offset + set + res);
+}
+#endif
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+_INLINE_ __u32 ext2fs_swab32(__u32 val)
+{
+#ifdef EXT2FS_REQUIRE_486
+ __asm__("bswap %0" : "=r" (val) : "0" (val));
+#else
+ __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
+ "rorl $16,%0\n\t" /* swap words */
+ "xchgb %b0,%h0" /* swap higher bytes */
+ :"=q" (val)
+ : "0" (val));
+#endif
+ return val;
+}
+
+_INLINE_ __u16 ext2fs_swab16(__u16 val)
+{
+ __asm__("xchgb %b0,%h0" /* swap bytes */ \
+ : "=q" (val) \
+ : "0" (val)); \
+ return val;
+}
+#endif
+
+#undef EXT2FS_ADDR
+
+#endif /* i386 */
+
+#ifdef __mc68000__
+
+#define _EXT2_HAVE_ASM_BITOPS_
+
+_INLINE_ int ext2fs_set_bit(int nr,void * addr)
+{
+ char retval;
+
+ __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
+ : "=d" (retval) : "d" (nr^7), "a" (addr));
+
+ return retval;
+}
+
+_INLINE_ int ext2fs_clear_bit(int nr, void * addr)
+{
+ char retval;
+
+ __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
+ : "=d" (retval) : "d" (nr^7), "a" (addr));
+
+ return retval;
+}
+
+_INLINE_ int ext2fs_test_bit(int nr, const void * addr)
+{
+ char retval;
+
+ __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
+ : "=d" (retval) : "d" (nr^7), "a" (addr));
+
+ return retval;
+}
+
+#endif /* __mc68000__ */
+
+#ifdef __sparc__
+
+#define _EXT2_HAVE_ASM_BITOPS_
+
+#ifndef EXT2_OLD_BITOPS
+
+/*
+ * Do the bitops so that we are compatible with the standard i386
+ * convention.
+ */
+
+_INLINE_ int ext2fs_set_bit(int nr,void * addr)
+{
+#if 1
+ int mask;
+ unsigned char *ADDR = (unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ __asm__ __volatile__("ldub [%0], %%g6\n\t"
+ "or %%g6, %2, %%g5\n\t"
+ "stb %%g5, [%0]\n\t"
+ "and %%g6, %2, %0\n"
+ : "=&r" (ADDR)
+ : "0" (ADDR), "r" (mask)
+ : "g5", "g6");
+ return (int) ADDR;
+#else
+ int mask, retval;
+ unsigned char *ADDR = (unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ retval = (mask & *ADDR) != 0;
+ *ADDR |= mask;
+ return retval;
+#endif
+}
+
+_INLINE_ int ext2fs_clear_bit(int nr, void * addr)
+{
+#if 1
+ int mask;
+ unsigned char *ADDR = (unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ __asm__ __volatile__("ldub [%0], %%g6\n\t"
+ "andn %%g6, %2, %%g5\n\t"
+ "stb %%g5, [%0]\n\t"
+ "and %%g6, %2, %0\n"
+ : "=&r" (ADDR)
+ : "0" (ADDR), "r" (mask)
+ : "g5", "g6");
+ return (int) ADDR;
+
+#else
+ int mask, retval;
+ unsigned char *ADDR = (unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ retval = (mask & *ADDR) != 0;
+ *ADDR &= ~mask;
+ return retval;
+#endif
+}
+
+_INLINE_ int ext2fs_test_bit(int nr, const void * addr)
+{
+ int mask;
+ const unsigned char *ADDR = (const unsigned char *) addr;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ return ((mask & *ADDR) != 0);
+}
+
+#else
+
+/* Do things the old, unplesant way. */
+
+_INLINE_ int ext2fs_set_bit(int nr, void *addr)
+{
+ int mask, retval;
+ unsigned long *ADDR = (unsigned long *) addr;
+
+ ADDR += nr >> 5;
+ mask = 1 << (nr & 31);
+ retval = ((mask & *ADDR) != 0);
+ *ADDR |= mask;
+ return retval;
+}
+
+_INLINE_ int ext2fs_clear_bit(int nr, void *addr)
+{
+ int mask, retval;
+ unsigned long *ADDR = (unsigned long *) addr;
+
+ ADDR += nr >> 5;
+ mask = 1 << (nr & 31);
+ retval = ((mask & *ADDR) != 0);
+ *ADDR &= ~mask;
+ return retval;
+}
+
+_INLINE_ int ext2fs_test_bit(int nr, const void *addr)
+{
+ int mask;
+ const unsigned long *ADDR = (const unsigned long *) addr;
+
+ ADDR += nr >> 5;
+ mask = 1 << (nr & 31);
+ return ((mask & *ADDR) != 0);
+}
+#endif
+
+#endif /* __sparc__ */
+
+#if !defined(_EXT2_HAVE_ASM_SWAB_) && defined(EXT2FS_ENABLE_SWAPFS)
+
+_INLINE_ __u16 ext2fs_swab16(__u16 val)
+{
+ return (val >> 8) | (val << 8);
+}
+
+_INLINE_ __u32 ext2fs_swab32(__u32 val)
+{
+ return ((val>>24) | ((val>>8)&0xFF00) |
+ ((val<<8)&0xFF0000) | (val<<24));
+}
+
+#endif /* !_EXT2_HAVE_ASM_SWAB */
+
+#if !defined(_EXT2_HAVE_ASM_FINDBIT_)
+
+extern int ffs(int);
+
+_INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size)
+{
+ char *cp = (unsigned char *) addr;
+ int res = 0, d0;
+
+ if (!size)
+ return 0;
+
+ while ((size > res) && (*cp == 0)) {
+ cp++;
+ res += 8;
+ }
+ d0 = ffs(*cp);
+ if (d0 == 0)
+ return size;
+
+ return res + d0 - 1;
+}
+
+_INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset)
+{
+ unsigned char * p;
+ int set = 0, bit = offset & 7, res = 0, d0;
+
+ res = offset >> 3;
+ p = ((unsigned char *) addr) + res;
+
+ if (bit) {
+ set = ffs(*p & ~((1 << bit) - 1));
+ if (set)
+ return (offset & ~7) + set - 1;
+ p++;
+ res += 8;
+ }
+ while ((size > res) && (*p == 0)) {
+ p++;
+ res += 8;
+ }
+ d0 = ffs(*p);
+ if (d0 == 0)
+ return size;
+
+ return (res + d0 - 1);
+}
+#endif
+
+/* These two routines moved to gen_bitmap.c */
+extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ __u32 bitno);
+extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ blk_t bitno);
+_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ blk_t bitno);
+
+_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ blk_t bitno)
+{
+ if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
+ return 0;
+ }
+ return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block)
+{
+ return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
+ bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block)
+{
+ return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block)
+{
+ return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode)
+{
+ return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ inode);
+}
+
+_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode)
+{
+ return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ inode);
+}
+
+_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode)
+{
+ return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ inode);
+}
+
+_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block)
+{
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((block < bitmap->start) || (block > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+ bitmap->description);
+ return;
+ }
+#endif
+ ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block)
+{
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((block < bitmap->start) || (block > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
+ block, bitmap->description);
+ return;
+ }
+#endif
+ ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
+ blk_t block)
+{
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((block < bitmap->start) || (block > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+ block, bitmap->description);
+ return 0;
+ }
+#endif
+ return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode)
+{
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((inode < bitmap->start) || (inode > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
+ inode, bitmap->description);
+ return;
+ }
+#endif
+ ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode)
+{
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((inode < bitmap->start) || (inode > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
+ inode, bitmap->description);
+ return;
+ }
+#endif
+ ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t inode)
+{
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((inode < bitmap->start) || (inode > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
+ inode, bitmap->description);
+ return 0;
+ }
+#endif
+ return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
+{
+ return bitmap->start;
+}
+
+_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
+{
+ return bitmap->start;
+}
+
+_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
+{
+ return bitmap->end;
+}
+
+_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
+{
+ return bitmap->end;
+}
+
+_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+ block, bitmap->description);
+ return 0;
+ }
+ for (i=0; i < num; i++) {
+ if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+ return 0;
+ }
+ return 1;
+}
+
+_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+ block, bitmap->description);
+ return 0;
+ }
+#endif
+ for (i=0; i < num; i++) {
+ if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+ return 0;
+ }
+ return 1;
+}
+
+_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+ bitmap->description);
+ return;
+ }
+ for (i=0; i < num; i++)
+ ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+ bitmap->description);
+ return;
+ }
+#endif
+ for (i=0; i < num; i++)
+ ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
+ bitmap->description);
+ return;
+ }
+ for (i=0; i < num; i++)
+ ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+#ifdef EXT2FS_DEBUG_FAST_OPS
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
+ bitmap->description);
+ return;
+ }
+#endif
+ for (i=0; i < num; i++)
+ ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+#undef _INLINE_
+#endif
+
diff --git a/e2fslib/bitops.o b/e2fslib/bitops.o
new file mode 100644
index 0000000..42f78cb
--- /dev/null
+++ b/e2fslib/bitops.o
Binary files differ
diff --git a/e2fslib/block.c b/e2fslib/block.c
new file mode 100644
index 0000000..a0bf738
--- /dev/null
+++ b/e2fslib/block.c
@@ -0,0 +1,496 @@
+/*
+ * block.c --- iterate over all blocks in an inode
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct block_context {
+ ext2_filsys fs;
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t bcount,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data);
+ e2_blkcnt_t bcount;
+ int bsize;
+ int flags;
+ errcode_t errcode;
+ char *ind_buf;
+ char *dind_buf;
+ char *tind_buf;
+ void *priv_data;
+};
+
+static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
+ int ref_offset, struct block_context *ctx)
+{
+ int ret = 0, changed = 0;
+ int i, flags, limit, offset;
+ blk_t *block_nr;
+
+ limit = ctx->fs->blocksize >> 2;
+ if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
+ ret = (*ctx->func)(ctx->fs, ind_block,
+ BLOCK_COUNT_IND, ref_block,
+ ref_offset, ctx->priv_data);
+ if (!*ind_block || (ret & BLOCK_ABORT)) {
+ ctx->bcount += limit;
+ return ret;
+ }
+ if (*ind_block >= ctx->fs->super->s_blocks_count ||
+ *ind_block < ctx->fs->super->s_first_data_block) {
+ ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
+ ret |= BLOCK_ERROR;
+ return ret;
+ }
+ if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ ctx->errcode = 0;
+ memset(ctx->ind_buf, 0, ctx->fs->blocksize);
+ } else
+ ctx->errcode = io_channel_read_blk(ctx->fs->io, *ind_block,
+ 1, ctx->ind_buf);
+ if (ctx->errcode) {
+ ret |= BLOCK_ERROR;
+ return ret;
+ }
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES |
+ EXT2_FLAG_SWAP_BYTES_READ)) {
+ block_nr = (blk_t *) ctx->ind_buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
+ }
+#endif
+ block_nr = (blk_t *) ctx->ind_buf;
+ offset = 0;
+ if (ctx->flags & BLOCK_FLAG_APPEND) {
+ for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
+ flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+ *ind_block, offset,
+ ctx->priv_data);
+ changed |= flags;
+ if (flags & BLOCK_ABORT) {
+ ret |= BLOCK_ABORT;
+ break;
+ }
+ offset += sizeof(blk_t);
+ }
+ } else {
+ for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
+ if (*block_nr == 0)
+ continue;
+ flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+ *ind_block, offset,
+ ctx->priv_data);
+ changed |= flags;
+ if (flags & BLOCK_ABORT) {
+ ret |= BLOCK_ABORT;
+ break;
+ }
+ offset += sizeof(blk_t);
+ }
+ }
+ if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (changed & BLOCK_CHANGED)) {
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES |
+ EXT2_FLAG_SWAP_BYTES_WRITE)) {
+ block_nr = (blk_t *) ctx->ind_buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
+ }
+#endif
+ ctx->errcode = io_channel_write_blk(ctx->fs->io, *ind_block,
+ 1, ctx->ind_buf);
+ if (ctx->errcode)
+ ret |= BLOCK_ERROR | BLOCK_ABORT;
+ }
+ if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
+ !(ret & BLOCK_ABORT))
+ ret |= (*ctx->func)(ctx->fs, ind_block,
+ BLOCK_COUNT_IND, ref_block,
+ ref_offset, ctx->priv_data);
+ return ret;
+}
+
+static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
+ int ref_offset, struct block_context *ctx)
+{
+ int ret = 0, changed = 0;
+ int i, flags, limit, offset;
+ blk_t *block_nr;
+
+ limit = ctx->fs->blocksize >> 2;
+ if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
+ BLOCK_FLAG_DATA_ONLY)))
+ ret = (*ctx->func)(ctx->fs, dind_block,
+ BLOCK_COUNT_DIND, ref_block,
+ ref_offset, ctx->priv_data);
+ if (!*dind_block || (ret & BLOCK_ABORT)) {
+ ctx->bcount += limit*limit;
+ return ret;
+ }
+ if (*dind_block >= ctx->fs->super->s_blocks_count ||
+ *dind_block < ctx->fs->super->s_first_data_block) {
+ ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
+ ret |= BLOCK_ERROR;
+ return ret;
+ }
+ if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ ctx->errcode = 0;
+ memset(ctx->dind_buf, 0, ctx->fs->blocksize);
+ } else
+ ctx->errcode = io_channel_read_blk(ctx->fs->io, *dind_block,
+ 1, ctx->dind_buf);
+ if (ctx->errcode) {
+ ret |= BLOCK_ERROR;
+ return ret;
+ }
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES |
+ EXT2_FLAG_SWAP_BYTES_READ)) {
+ block_nr = (blk_t *) ctx->dind_buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
+ }
+#endif
+ block_nr = (blk_t *) ctx->dind_buf;
+ offset = 0;
+ if (ctx->flags & BLOCK_FLAG_APPEND) {
+ for (i = 0; i < limit; i++, block_nr++) {
+ flags = block_iterate_ind(block_nr,
+ *dind_block, offset,
+ ctx);
+ changed |= flags;
+ if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+ ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+ break;
+ }
+ offset += sizeof(blk_t);
+ }
+ } else {
+ for (i = 0; i < limit; i++, block_nr++) {
+ if (*block_nr == 0) {
+ ctx->bcount += limit;
+ continue;
+ }
+ flags = block_iterate_ind(block_nr,
+ *dind_block, offset,
+ ctx);
+ changed |= flags;
+ if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+ ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+ break;
+ }
+ offset += sizeof(blk_t);
+ }
+ }
+ if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (changed & BLOCK_CHANGED)) {
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES |
+ EXT2_FLAG_SWAP_BYTES_WRITE)) {
+ block_nr = (blk_t *) ctx->dind_buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
+ }
+#endif
+ ctx->errcode = io_channel_write_blk(ctx->fs->io, *dind_block,
+ 1, ctx->dind_buf);
+ if (ctx->errcode)
+ ret |= BLOCK_ERROR | BLOCK_ABORT;
+ }
+ if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
+ !(ret & BLOCK_ABORT))
+ ret |= (*ctx->func)(ctx->fs, dind_block,
+ BLOCK_COUNT_DIND, ref_block,
+ ref_offset, ctx->priv_data);
+ return ret;
+}
+
+static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
+ int ref_offset, struct block_context *ctx)
+{
+ int ret = 0, changed = 0;
+ int i, flags, limit, offset;
+ blk_t *block_nr;
+
+ limit = ctx->fs->blocksize >> 2;
+ if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
+ BLOCK_FLAG_DATA_ONLY)))
+ ret = (*ctx->func)(ctx->fs, tind_block,
+ BLOCK_COUNT_TIND, ref_block,
+ ref_offset, ctx->priv_data);
+ if (!*tind_block || (ret & BLOCK_ABORT)) {
+ ctx->bcount += limit*limit*limit;
+ return ret;
+ }
+ if (*tind_block >= ctx->fs->super->s_blocks_count ||
+ *tind_block < ctx->fs->super->s_first_data_block) {
+ ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
+ ret |= BLOCK_ERROR;
+ return ret;
+ }
+ if (ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ ctx->errcode = 0;
+ memset(ctx->tind_buf, 0, ctx->fs->blocksize);
+ } else
+ ctx->errcode = io_channel_read_blk(ctx->fs->io, *tind_block,
+ 1, ctx->tind_buf);
+ if (ctx->errcode) {
+ ret |= BLOCK_ERROR;
+ return ret;
+ }
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES |
+ EXT2_FLAG_SWAP_BYTES_READ)) {
+ block_nr = (blk_t *) ctx->tind_buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
+ }
+#endif
+ block_nr = (blk_t *) ctx->tind_buf;
+ offset = 0;
+ if (ctx->flags & BLOCK_FLAG_APPEND) {
+ for (i = 0; i < limit; i++, block_nr++) {
+ flags = block_iterate_dind(block_nr,
+ *tind_block,
+ offset, ctx);
+ changed |= flags;
+ if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+ ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+ break;
+ }
+ offset += sizeof(blk_t);
+ }
+ } else {
+ for (i = 0; i < limit; i++, block_nr++) {
+ if (*block_nr == 0) {
+ ctx->bcount += limit*limit;
+ continue;
+ }
+ flags = block_iterate_dind(block_nr,
+ *tind_block,
+ offset, ctx);
+ changed |= flags;
+ if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+ ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+ break;
+ }
+ offset += sizeof(blk_t);
+ }
+ }
+ if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (changed & BLOCK_CHANGED)) {
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES |
+ EXT2_FLAG_SWAP_BYTES_WRITE)) {
+ block_nr = (blk_t *) ctx->tind_buf;
+ for (i = 0; i < limit; i++, block_nr++)
+ *block_nr = ext2fs_swab32(*block_nr);
+ }
+#endif
+ ctx->errcode = io_channel_write_blk(ctx->fs->io, *tind_block,
+ 1, ctx->tind_buf);
+ if (ctx->errcode)
+ ret |= BLOCK_ERROR | BLOCK_ABORT;
+ }
+ if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
+ !(ret & BLOCK_ABORT))
+ ret |= (*ctx->func)(ctx->fs, tind_block,
+ BLOCK_COUNT_TIND, ref_block,
+ ref_offset, ctx->priv_data);
+
+ return ret;
+}
+
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+ ext2_ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data),
+ void *priv_data)
+{
+ int i;
+ int got_inode = 0;
+ int ret = 0;
+ blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
+ struct ext2_inode inode;
+ errcode_t retval;
+ struct block_context ctx;
+ int limit;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ /*
+ * Check to see if we need to limit large files
+ */
+ if (flags & BLOCK_FLAG_NO_LARGE) {
+ ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+ if (ctx.errcode)
+ return ctx.errcode;
+ got_inode = 1;
+ if (!LINUX_S_ISDIR(inode.i_mode) &&
+ (inode.i_size_high != 0))
+ return EXT2_ET_FILE_TOO_BIG;
+ }
+
+ retval = ext2fs_get_blocks(fs, ino, blocks);
+ if (retval)
+ return retval;
+
+ limit = fs->blocksize >> 2;
+
+ ctx.fs = fs;
+ ctx.func = func;
+ ctx.priv_data = priv_data;
+ ctx.flags = flags;
+ ctx.bcount = 0;
+ if (block_buf) {
+ ctx.ind_buf = block_buf;
+ } else {
+ retval = ext2fs_get_mem(fs->blocksize * 3,
+ (void **) &ctx.ind_buf);
+ if (retval)
+ return retval;
+ }
+ ctx.dind_buf = ctx.ind_buf + fs->blocksize;
+ ctx.tind_buf = ctx.dind_buf + fs->blocksize;
+
+ /*
+ * Iterate over the HURD translator block (if present)
+ */
+ if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
+ !(flags & BLOCK_FLAG_DATA_ONLY)) {
+ ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+ if (ctx.errcode)
+ goto abort_exit;
+ got_inode = 1;
+ if (inode.osd1.hurd1.h_i_translator) {
+ ret |= (*ctx.func)(fs,
+ &inode.osd1.hurd1.h_i_translator,
+ BLOCK_COUNT_TRANSLATOR,
+ 0, 0, priv_data);
+ if (ret & BLOCK_ABORT)
+ goto abort_exit;
+ }
+ }
+
+ /*
+ * Iterate over normal data blocks
+ */
+ for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
+ if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= (*ctx.func)(fs, &blocks[i],
+ ctx.bcount, 0, i, priv_data);
+ if (ret & BLOCK_ABORT)
+ goto abort_exit;
+ }
+ }
+ if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
+ 0, EXT2_IND_BLOCK, &ctx);
+ if (ret & BLOCK_ABORT)
+ goto abort_exit;
+ } else
+ ctx.bcount += limit;
+ if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
+ 0, EXT2_DIND_BLOCK, &ctx);
+ if (ret & BLOCK_ABORT)
+ goto abort_exit;
+ } else
+ ctx.bcount += limit * limit;
+ if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
+ ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
+ 0, EXT2_TIND_BLOCK, &ctx);
+ if (ret & BLOCK_ABORT)
+ goto abort_exit;
+ }
+
+abort_exit:
+ if (ret & BLOCK_CHANGED) {
+ if (!got_inode) {
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval)
+ return retval;
+ }
+ for (i=0; i < EXT2_N_BLOCKS; i++)
+ inode.i_block[i] = blocks[i];
+ retval = ext2fs_write_inode(fs, ino, &inode);
+ if (retval)
+ return retval;
+ }
+
+ if (!block_buf)
+ ext2fs_free_mem((void **) &ctx.ind_buf);
+
+ return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
+}
+
+/*
+ * Emulate the old ext2fs_block_iterate function!
+ */
+
+struct xlate {
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ int bcount,
+ void *priv_data);
+ void *real_private;
+};
+
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
+ blk_t ref_block, int ref_offset, void *priv_data)
+{
+ struct xlate *xl = (struct xlate *) priv_data;
+
+ return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
+}
+
+errcode_t ext2fs_block_iterate(ext2_filsys fs,
+ ext2_ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ void *priv_data),
+ void *priv_data)
+{
+ struct xlate xl;
+
+ xl.real_private = priv_data;
+ xl.func = func;
+
+ return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
+ block_buf, xlate_func, &xl);
+}
+
diff --git a/e2fslib/block.o b/e2fslib/block.o
new file mode 100644
index 0000000..3ec71ce
--- /dev/null
+++ b/e2fslib/block.o
Binary files differ
diff --git a/e2fslib/bmap.c b/e2fslib/bmap.c
new file mode 100644
index 0000000..25ba695
--- /dev/null
+++ b/e2fslib/bmap.c
@@ -0,0 +1,237 @@
+/*
+ * bmap.c --- logical to physical block mapping
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
+#define _BMAP_INLINE_ __inline__
+#else
+#define _BMAP_INLINE_
+#endif
+
+extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ char *block_buf, int bmap_flags,
+ blk_t block, blk_t *phys_blk);
+
+#define BMAP_ALLOC 1
+
+#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
+
+static errcode_t _BMAP_INLINE_ block_ind_bmap(ext2_filsys fs, int flags,
+ blk_t ind, char *block_buf,
+ int *blocks_alloc,
+ blk_t nr, blk_t *ret_blk)
+{
+ errcode_t retval;
+ blk_t b;
+
+ if (!ind) {
+ *ret_blk = 0;
+ return 0;
+ }
+ retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
+ if (retval)
+ return retval;
+
+ b = ((blk_t *) block_buf)[nr];
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+ b = ext2fs_swab32(b);
+#endif
+
+ if (!b && (flags & BMAP_ALLOC)) {
+ b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
+ retval = ext2fs_alloc_block(fs, b,
+ block_buf + fs->blocksize, &b);
+ if (retval)
+ return retval;
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
+ ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
+ else
+#endif
+ ((blk_t *) block_buf)[nr] = b;
+
+ retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
+ if (retval)
+ return retval;
+
+ (*blocks_alloc)++;
+ }
+
+ *ret_blk = b;
+ return 0;
+}
+
+static errcode_t _BMAP_INLINE_ block_dind_bmap(ext2_filsys fs, int flags,
+ blk_t dind, char *block_buf,
+ int *blocks_alloc,
+ blk_t nr, blk_t *ret_blk)
+{
+ blk_t b;
+ errcode_t retval;
+ blk_t addr_per_block;
+
+ addr_per_block = (blk_t) fs->blocksize >> 2;
+
+ retval = block_ind_bmap(fs, flags, dind, block_buf, blocks_alloc,
+ nr / addr_per_block, &b);
+ if (retval)
+ return retval;
+ retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
+ nr % addr_per_block, ret_blk);
+ return retval;
+}
+
+static errcode_t _BMAP_INLINE_ block_tind_bmap(ext2_filsys fs, int flags,
+ blk_t tind, char *block_buf,
+ int *blocks_alloc,
+ blk_t nr, blk_t *ret_blk)
+{
+ blk_t b;
+ errcode_t retval;
+ blk_t addr_per_block;
+
+ addr_per_block = (blk_t) fs->blocksize >> 2;
+
+ retval = block_dind_bmap(fs, flags, tind, block_buf, blocks_alloc,
+ nr / addr_per_block, &b);
+ if (retval)
+ return retval;
+ retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
+ nr % addr_per_block, ret_blk);
+ return retval;
+}
+
+errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
+ char *block_buf, int bmap_flags, blk_t block,
+ blk_t *phys_blk)
+{
+ struct ext2_inode inode_buf;
+ blk_t addr_per_block;
+ blk_t b;
+ char *buf = 0;
+ errcode_t retval = 0;
+ int blocks_alloc = 0;
+
+ *phys_blk = 0;
+
+ /* Read inode structure if necessary */
+ if (!inode) {
+ retval = ext2fs_read_inode(fs, ino, &inode_buf);
+ if (!retval)
+ return retval;
+ inode = &inode_buf;
+ }
+ addr_per_block = (blk_t) fs->blocksize >> 2;
+
+ if (!block_buf) {
+ retval = ext2fs_get_mem(fs->blocksize * 2, (void **) &buf);
+ if (retval)
+ return retval;
+ block_buf = buf;
+ }
+
+ if (block < EXT2_NDIR_BLOCKS) {
+ *phys_blk = inode_bmap(inode, block);
+ b = block ? inode_bmap(inode, block-1) : 0;
+
+ if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
+ retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ if (retval)
+ goto done;
+ inode_bmap(inode, block) = b;
+ blocks_alloc++;
+ *phys_blk = b;
+ }
+ goto done;
+ }
+
+ /* Indirect block */
+ block -= EXT2_NDIR_BLOCKS;
+ if (block < addr_per_block) {
+ b = inode_bmap(inode, EXT2_IND_BLOCK);
+ if (!b) {
+ if (!(bmap_flags & BMAP_ALLOC))
+ goto done;
+
+ b = inode_bmap(inode, EXT2_IND_BLOCK-1);
+ retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ if (retval)
+ goto done;
+ inode_bmap(inode, EXT2_IND_BLOCK) = b;
+ blocks_alloc++;
+ }
+ retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
+ &blocks_alloc, block, phys_blk);
+ goto done;
+ }
+
+ /* Doubly indirect block */
+ block -= addr_per_block;
+ if (block < addr_per_block * addr_per_block) {
+ b = inode_bmap(inode, EXT2_DIND_BLOCK);
+ if (!b) {
+ if (!(bmap_flags & BMAP_ALLOC))
+ goto done;
+
+ b = inode_bmap(inode, EXT2_IND_BLOCK);
+ retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ if (retval)
+ goto done;
+ inode_bmap(inode, EXT2_DIND_BLOCK) = b;
+ blocks_alloc++;
+ }
+ retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
+ &blocks_alloc, block, phys_blk);
+ goto done;
+ }
+
+ /* Triply indirect block */
+ block -= addr_per_block * addr_per_block;
+ b = inode_bmap(inode, EXT2_TIND_BLOCK);
+ if (!b) {
+ if (!(bmap_flags & BMAP_ALLOC))
+ goto done;
+
+ b = inode_bmap(inode, EXT2_DIND_BLOCK);
+ retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ if (retval)
+ goto done;
+ inode_bmap(inode, EXT2_TIND_BLOCK) = b;
+ blocks_alloc++;
+ }
+ retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
+ &blocks_alloc, block, phys_blk);
+done:
+ if (buf)
+ ext2fs_free_mem((void **) &buf);
+ if ((retval == 0) && blocks_alloc) {
+ inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
+ retval = ext2fs_write_inode(fs, ino, inode);
+ }
+ return retval;
+}
+
+
+
diff --git a/e2fslib/bmap.o b/e2fslib/bmap.o
new file mode 100644
index 0000000..288700c
--- /dev/null
+++ b/e2fslib/bmap.o
Binary files differ
diff --git a/e2fslib/bmove.c b/e2fslib/bmove.c
new file mode 100644
index 0000000..c0205ca
--- /dev/null
+++ b/e2fslib/bmove.c
@@ -0,0 +1,160 @@
+/*
+ * bmove.c --- Move blocks around to make way for a particular
+ * filesystem structure.
+ *
+ * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
+ * under the terms of the GNU Public License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+struct process_block_struct {
+ ext2_ino_t ino;
+ struct ext2_inode * inode;
+ ext2fs_block_bitmap reserve;
+ ext2fs_block_bitmap alloc_map;
+ errcode_t error;
+ char *buf;
+ int add_dir;
+ int flags;
+};
+
+static int process_block(ext2_filsys fs, blk_t *block_nr,
+ e2_blkcnt_t blockcnt, blk_t ref_block,
+ int ref_offset, void *priv_data)
+{
+ struct process_block_struct *pb;
+ errcode_t retval;
+ int ret;
+ blk_t block, orig;
+
+ pb = (struct process_block_struct *) priv_data;
+ block = orig = *block_nr;
+ ret = 0;
+
+ /*
+ * Let's see if this is one which we need to relocate
+ */
+ if (ext2fs_test_block_bitmap(pb->reserve, block)) {
+ do {
+ if (++block >= fs->super->s_blocks_count)
+ block = fs->super->s_first_data_block;
+ if (block == orig) {
+ pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
+ return BLOCK_ABORT;
+ }
+ } while (ext2fs_test_block_bitmap(pb->reserve, block) ||
+ ext2fs_test_block_bitmap(pb->alloc_map, block));
+
+ retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
+ if (retval) {
+ pb->error = retval;
+ return BLOCK_ABORT;
+ }
+ retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
+ if (retval) {
+ pb->error = retval;
+ return BLOCK_ABORT;
+ }
+ *block_nr = block;
+ ext2fs_mark_block_bitmap(pb->alloc_map, block);
+ ret = BLOCK_CHANGED;
+ if (pb->flags & EXT2_BMOVE_DEBUG)
+ printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
+ blockcnt, orig, block);
+ }
+ if (pb->add_dir) {
+ retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
+ block, (int) blockcnt);
+ if (retval) {
+ pb->error = retval;
+ ret |= BLOCK_ABORT;
+ }
+ }
+ return ret;
+}
+
+errcode_t ext2fs_move_blocks(ext2_filsys fs,
+ ext2fs_block_bitmap reserve,
+ ext2fs_block_bitmap alloc_map,
+ int flags)
+{
+ ext2_ino_t ino;
+ struct ext2_inode inode;
+ errcode_t retval;
+ struct process_block_struct pb;
+ ext2_inode_scan scan;
+ char *block_buf;
+
+ retval = ext2fs_open_inode_scan(fs, 0, &scan);
+ if (retval)
+ return retval;
+
+ pb.reserve = reserve;
+ pb.error = 0;
+ pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
+ pb.flags = flags;
+
+ retval = ext2fs_get_mem(fs->blocksize * 4, (void **) &block_buf);
+ if (retval)
+ return retval;
+ pb.buf = block_buf + fs->blocksize * 3;
+
+ /*
+ * If GET_DBLIST is set in the flags field, then we should
+ * gather directory block information while we're doing the
+ * block move.
+ */
+ if (flags & EXT2_BMOVE_GET_DBLIST) {
+ if (fs->dblist) {
+ ext2fs_free_dblist(fs->dblist);
+ fs->dblist = NULL;
+ }
+ retval = ext2fs_init_dblist(fs, 0);
+ if (retval)
+ return retval;
+ }
+
+ retval = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (retval)
+ return retval;
+
+ while (ino) {
+ if ((inode.i_links_count == 0) ||
+ !ext2fs_inode_has_valid_blocks(&inode))
+ goto next;
+
+ pb.ino = ino;
+ pb.inode = &inode;
+
+ pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
+ flags & EXT2_BMOVE_GET_DBLIST);
+
+ retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
+ process_block, &pb);
+ if (retval)
+ return retval;
+ if (pb.error)
+ return pb.error;
+
+ next:
+ retval = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
+ goto next;
+ }
+ return 0;
+}
+
diff --git a/e2fslib/brel.h b/e2fslib/brel.h
new file mode 100644
index 0000000..be97243
--- /dev/null
+++ b/e2fslib/brel.h
@@ -0,0 +1,86 @@
+/*
+ * brel.h
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+struct ext2_block_relocate_entry {
+ blk_t new;
+ __s16 offset;
+ __u16 flags;
+ union {
+ blk_t block_ref;
+ ext2_ino_t inode_ref;
+ } owner;
+};
+
+#define RELOCATE_TYPE_REF 0x0007
+#define RELOCATE_BLOCK_REF 0x0001
+#define RELOCATE_INODE_REF 0x0002
+
+typedef struct ext2_block_relocation_table *ext2_brel;
+
+struct ext2_block_relocation_table {
+ __u32 magic;
+ char *name;
+ blk_t current;
+ void *priv_data;
+
+ /*
+ * Add a block relocation entry.
+ */
+ errcode_t (*put)(ext2_brel brel, blk_t old,
+ struct ext2_block_relocate_entry *ent);
+
+ /*
+ * Get a block relocation entry.
+ */
+ errcode_t (*get)(ext2_brel brel, blk_t old,
+ struct ext2_block_relocate_entry *ent);
+
+ /*
+ * Initialize for iterating over the block relocation entries.
+ */
+ errcode_t (*start_iter)(ext2_brel brel);
+
+ /*
+ * The iterator function for the inode relocation entries.
+ * Returns an inode number of 0 when out of entries.
+ */
+ errcode_t (*next)(ext2_brel brel, blk_t *old,
+ struct ext2_block_relocate_entry *ent);
+
+ /*
+ * Move the inode relocation table from one block number to
+ * another.
+ */
+ errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
+
+ /*
+ * Remove a block relocation entry.
+ */
+ errcode_t (*delete)(ext2_brel brel, blk_t old);
+
+
+ /*
+ * Free the block relocation table.
+ */
+ errcode_t (*free)(ext2_brel brel);
+};
+
+errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
+ ext2_brel *brel);
+
+#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
+#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
+#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
+#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
+#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
+#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
+#define ext2fs_brel_free(brel) ((brel)->free((brel)))
+
diff --git a/e2fslib/brel_ma.c b/e2fslib/brel_ma.c
new file mode 100644
index 0000000..8ad8e9f
--- /dev/null
+++ b/e2fslib/brel_ma.c
@@ -0,0 +1,197 @@
+/*
+ * brel_ma.c
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * TODO: rewrite to not use a direct array!!! (Fortunately this
+ * module isn't really used yet.)
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "brel.h"
+
+static errcode_t bma_put(ext2_brel brel, blk_t old,
+ struct ext2_block_relocate_entry *ent);
+static errcode_t bma_get(ext2_brel brel, blk_t old,
+ struct ext2_block_relocate_entry *ent);
+static errcode_t bma_start_iter(ext2_brel brel);
+static errcode_t bma_next(ext2_brel brel, blk_t *old,
+ struct ext2_block_relocate_entry *ent);
+static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
+static errcode_t bma_delete(ext2_brel brel, blk_t old);
+static errcode_t bma_free(ext2_brel brel);
+
+struct brel_ma {
+ __u32 magic;
+ blk_t max_block;
+ struct ext2_block_relocate_entry *entries;
+};
+
+errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
+ ext2_brel *new_brel)
+{
+ ext2_brel brel = 0;
+ errcode_t retval;
+ struct brel_ma *ma = 0;
+ size_t size;
+
+ *new_brel = 0;
+
+ /*
+ * Allocate memory structures
+ */
+ retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
+ (void **) &brel);
+ if (retval)
+ goto errout;
+ memset(brel, 0, sizeof(struct ext2_block_relocation_table));
+
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &brel->name);
+ if (retval)
+ goto errout;
+ strcpy(brel->name, name);
+
+ retval = ext2fs_get_mem(sizeof(struct brel_ma), (void **) &ma);
+ if (retval)
+ goto errout;
+ memset(ma, 0, sizeof(struct brel_ma));
+ brel->priv_data = ma;
+
+ size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
+ (max_block+1));
+ retval = ext2fs_get_mem(size, (void **) &ma->entries);
+ if (retval)
+ goto errout;
+ memset(ma->entries, 0, size);
+ ma->max_block = max_block;
+
+ /*
+ * Fill in the brel data structure
+ */
+ brel->put = bma_put;
+ brel->get = bma_get;
+ brel->start_iter = bma_start_iter;
+ brel->next = bma_next;
+ brel->move = bma_move;
+ brel->delete = bma_delete;
+ brel->free = bma_free;
+
+ *new_brel = brel;
+ return 0;
+
+errout:
+ bma_free(brel);
+ return retval;
+}
+
+static errcode_t bma_put(ext2_brel brel, blk_t old,
+ struct ext2_block_relocate_entry *ent)
+{
+ struct brel_ma *ma;
+
+ ma = brel->priv_data;
+ if (old > ma->max_block)
+ return EXT2_ET_INVALID_ARGUMENT;
+ ma->entries[(unsigned)old] = *ent;
+ return 0;
+}
+
+static errcode_t bma_get(ext2_brel brel, blk_t old,
+ struct ext2_block_relocate_entry *ent)
+{
+ struct brel_ma *ma;
+
+ ma = brel->priv_data;
+ if (old > ma->max_block)
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned)old].new == 0)
+ return ENOENT;
+ *ent = ma->entries[old];
+ return 0;
+}
+
+static errcode_t bma_start_iter(ext2_brel brel)
+{
+ brel->current = 0;
+ return 0;
+}
+
+static errcode_t bma_next(ext2_brel brel, blk_t *old,
+ struct ext2_block_relocate_entry *ent)
+{
+ struct brel_ma *ma;
+
+ ma = brel->priv_data;
+ while (++brel->current < ma->max_block) {
+ if (ma->entries[(unsigned)brel->current].new == 0)
+ continue;
+ *old = brel->current;
+ *ent = ma->entries[(unsigned)brel->current];
+ return 0;
+ }
+ *old = 0;
+ return 0;
+}
+
+static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
+{
+ struct brel_ma *ma;
+
+ ma = brel->priv_data;
+ if ((old > ma->max_block) || (new > ma->max_block))
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned)old].new == 0)
+ return ENOENT;
+ ma->entries[(unsigned)new] = ma->entries[old];
+ ma->entries[(unsigned)old].new = 0;
+ return 0;
+}
+
+static errcode_t bma_delete(ext2_brel brel, blk_t old)
+{
+ struct brel_ma *ma;
+
+ ma = brel->priv_data;
+ if (old > ma->max_block)
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned)old].new == 0)
+ return ENOENT;
+ ma->entries[(unsigned)old].new = 0;
+ return 0;
+}
+
+static errcode_t bma_free(ext2_brel brel)
+{
+ struct brel_ma *ma;
+
+ if (!brel)
+ return 0;
+
+ ma = brel->priv_data;
+
+ if (ma) {
+ if (ma->entries)
+ ext2fs_free_mem((void **) &ma->entries);
+ ext2fs_free_mem((void **) &ma);
+ }
+ if (brel->name)
+ ext2fs_free_mem((void **) &brel->name);
+ ext2fs_free_mem((void **) &brel);
+ return 0;
+}
diff --git a/e2fslib/check_desc.c b/e2fslib/check_desc.c
new file mode 100644
index 0000000..902c4b6
--- /dev/null
+++ b/e2fslib/check_desc.c
@@ -0,0 +1,68 @@
+/*
+ * check_desc.c --- Check the group descriptors of an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * This routine sanity checks the group descriptors
+ */
+errcode_t ext2fs_check_desc(ext2_filsys fs)
+{
+ int i;
+ blk_t block = fs->super->s_first_data_block;
+ blk_t next;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ next = block + fs->super->s_blocks_per_group;
+ /*
+ * Check to make sure block bitmap for group is
+ * located within the group.
+ */
+ if (fs->group_desc[i].bg_block_bitmap < block ||
+ fs->group_desc[i].bg_block_bitmap >= next)
+ return EXT2_ET_GDESC_BAD_BLOCK_MAP;
+ /*
+ * Check to make sure inode bitmap for group is
+ * located within the group
+ */
+ if (fs->group_desc[i].bg_inode_bitmap < block ||
+ fs->group_desc[i].bg_inode_bitmap >= next)
+ return EXT2_ET_GDESC_BAD_INODE_MAP;
+ /*
+ * Check to make sure inode table for group is located
+ * within the group
+ */
+ if (fs->group_desc[i].bg_inode_table < block ||
+ ((fs->group_desc[i].bg_inode_table +
+ fs->inode_blocks_per_group) >= next))
+ return EXT2_ET_GDESC_BAD_INODE_TABLE;
+
+ block = next;
+ }
+ return 0;
+}
diff --git a/e2fslib/check_desc.o b/e2fslib/check_desc.o
new file mode 100644
index 0000000..86571de
--- /dev/null
+++ b/e2fslib/check_desc.o
Binary files differ
diff --git a/e2fslib/closefs.c b/e2fslib/closefs.c
new file mode 100644
index 0000000..f52c343
--- /dev/null
+++ b/e2fslib/closefs.c
@@ -0,0 +1,291 @@
+/*
+ * closefs.c --- close an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <string.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static int test_root(int a, int b)
+{
+ if (a == 0)
+ return 1;
+ while (1) {
+ if (a == 1)
+ return 1;
+ if (a % b)
+ return 0;
+ a = a / b;
+ }
+}
+
+int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
+{
+ if (!(fs->super->s_feature_ro_compat &
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+ return 1;
+
+ if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
+ test_root(group_block, 7))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * This function forces out the primary superblock. We need to only
+ * write out those fields which we have changed, since if the
+ * filesystem is mounted, it may have changed some of the other
+ * fields.
+ *
+ * It takes as input a superblock which has already been byte swapped
+ * (if necessary).
+ *
+ */
+static errcode_t write_primary_superblock(ext2_filsys fs,
+ struct ext2_super_block *super)
+{
+ __u16 *old_super, *new_super;
+ int check_idx, write_idx, size;
+ errcode_t retval;
+
+ if (!fs->io->manager->write_byte || !fs->orig_super) {
+ io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
+ retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
+ super);
+ io_channel_set_blksize(fs->io, fs->blocksize);
+ return retval;
+ }
+
+ old_super = (__u16 *) fs->orig_super;
+ new_super = (__u16 *) super;
+
+ for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
+ if (old_super[check_idx] == new_super[check_idx])
+ continue;
+ write_idx = check_idx;
+ for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
+ if (old_super[check_idx] == new_super[check_idx])
+ break;
+ size = 2 * (check_idx - write_idx);
+#if 0
+ printf("Writing %d bytes starting at %d\n",
+ size, write_idx*2);
+#endif
+ retval = io_channel_write_byte(fs->io,
+ SUPERBLOCK_OFFSET + (2 * write_idx), size,
+ new_super + write_idx);
+ if (retval)
+ return retval;
+ }
+ memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
+ return 0;
+}
+
+
+/*
+ * Updates the revision to EXT2_DYNAMIC_REV
+ */
+void ext2fs_update_dynamic_rev(ext2_filsys fs)
+{
+ struct ext2_super_block *sb = fs->super;
+
+ if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
+ return;
+
+ sb->s_rev_level = EXT2_DYNAMIC_REV;
+ sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
+ sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+ /* s_uuid is handled by e2fsck already */
+ /* other fields should be left alone */
+}
+
+errcode_t ext2fs_flush(ext2_filsys fs)
+{
+ dgrp_t i,j,maxgroup,sgrp;
+ blk_t group_block;
+ errcode_t retval;
+ char *group_ptr;
+ unsigned long fs_state;
+ struct ext2_super_block *super_shadow = 0;
+ struct ext2_group_desc *group_shadow = 0;
+ struct ext2_group_desc *s, *t;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ fs_state = fs->super->s_state;
+
+ fs->super->s_wtime = time(NULL);
+ fs->super->s_block_group_nr = 0;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+ retval = EXT2_ET_NO_MEMORY;
+ retval = ext2fs_get_mem(SUPERBLOCK_SIZE,
+ (void **) &super_shadow);
+ if (retval)
+ goto errout;
+ retval = ext2fs_get_mem((size_t)(fs->blocksize *
+ fs->desc_blocks),
+ (void **) &group_shadow);
+ if (retval)
+ goto errout;
+ memset(group_shadow, 0, (size_t) fs->blocksize *
+ fs->desc_blocks);
+
+ /* swap the superblock */
+ *super_shadow = *fs->super;
+ ext2fs_swap_super(super_shadow);
+
+ /* swap the group descriptors */
+ for (j=0, s=fs->group_desc, t=group_shadow;
+ j < fs->group_desc_count; j++, t++, s++) {
+ *t = *s;
+ ext2fs_swap_group_desc(t);
+ }
+ } else {
+ super_shadow = fs->super;
+ group_shadow = fs->group_desc;
+ }
+#else
+ super_shadow = fs->super;
+ group_shadow = fs->group_desc;
+#endif
+
+ /*
+ * Write out master superblock. This has to be done
+ * separately, since it is located at a fixed location
+ * (SUPERBLOCK_OFFSET).
+ */
+ retval = write_primary_superblock(fs, super_shadow);
+ if (retval)
+ goto errout;
+
+ /*
+ * If this is an external journal device, don't write out the
+ * block group descriptors or any of the backup superblocks
+ */
+ if (fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+ retval = 0;
+ goto errout;
+ }
+
+ /*
+ * Set the state of the FS to be non-valid. (The state has
+ * already been backed up earlier, and will be restored when
+ * we exit.)
+ */
+ fs->super->s_state &= ~EXT2_VALID_FS;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+ *super_shadow = *fs->super;
+ ext2fs_swap_super(super_shadow);
+ }
+#endif
+
+ /*
+ * Write out the master group descriptors, and the backup
+ * superblocks and group descriptors.
+ */
+ group_block = fs->super->s_first_data_block;
+ maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 :
+ fs->group_desc_count;
+ for (i = 0; i < maxgroup; i++) {
+ if (!ext2fs_bg_has_super(fs, i))
+ goto next_group;
+
+ sgrp = i;
+ if (sgrp > ((1 << 16) - 1))
+ sgrp = (1 << 16) - 1;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+ super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
+ else
+#endif
+ fs->super->s_block_group_nr = sgrp;
+
+ if (i !=0 ) {
+ retval = io_channel_write_blk(fs->io, group_block,
+ -SUPERBLOCK_SIZE,
+ super_shadow);
+ if (retval)
+ goto errout;
+ }
+ if (fs->flags & EXT2_FLAG_SUPER_ONLY)
+ goto next_group;
+ group_ptr = (char *) group_shadow;
+ for (j=0; j < fs->desc_blocks; j++) {
+ retval = io_channel_write_blk(fs->io,
+ group_block+1+j, 1,
+ group_ptr);
+ if (retval)
+ goto errout;
+ group_ptr += fs->blocksize;
+ }
+ next_group:
+ group_block += EXT2_BLOCKS_PER_GROUP(fs->super);
+ }
+ fs->super->s_block_group_nr = 0;
+
+ /*
+ * If the write_bitmaps() function is present, call it to
+ * flush the bitmaps. This is done this way so that a simple
+ * program that doesn't mess with the bitmaps doesn't need to
+ * drag in the bitmaps.c code.
+ */
+ if (fs->write_bitmaps) {
+ retval = fs->write_bitmaps(fs);
+ if (retval)
+ goto errout;
+ }
+
+ fs->flags &= ~EXT2_FLAG_DIRTY;
+
+ /*
+ * Flush the blocks out to disk
+ */
+ retval = io_channel_flush(fs->io);
+errout:
+ fs->super->s_state = fs_state;
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+ if (super_shadow)
+ ext2fs_free_mem((void **) &super_shadow);
+ if (group_shadow)
+ ext2fs_free_mem((void **) &group_shadow);
+ }
+ return retval;
+}
+
+errcode_t ext2fs_close(ext2_filsys fs)
+{
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (fs->flags & EXT2_FLAG_DIRTY) {
+ retval = ext2fs_flush(fs);
+ if (retval)
+ return retval;
+ }
+ if (fs->write_bitmaps) {
+ retval = fs->write_bitmaps(fs);
+ if (retval)
+ return retval;
+ }
+ ext2fs_free(fs);
+ return 0;
+}
+
diff --git a/e2fslib/closefs.o b/e2fslib/closefs.o
new file mode 100644
index 0000000..b62baf1
--- /dev/null
+++ b/e2fslib/closefs.o
Binary files differ
diff --git a/e2fslib/cmp_bitmaps.c b/e2fslib/cmp_bitmaps.c
new file mode 100644
index 0000000..51cc3d0
--- /dev/null
+++ b/e2fslib/cmp_bitmaps.c
@@ -0,0 +1,72 @@
+/*
+ * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
+ *
+ * Copyright (C) 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
+ ext2fs_block_bitmap bm2)
+{
+ blk_t i;
+
+ EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
+ EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+ if ((bm1->start != bm2->start) ||
+ (bm1->end != bm2->end) ||
+ (memcmp(bm1->bitmap, bm2->bitmap,
+ (size_t) (bm1->end - bm1->start)/8)))
+ return EXT2_ET_NEQ_BLOCK_BITMAP;
+
+ for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
+ if (ext2fs_fast_test_block_bitmap(bm1, i) !=
+ ext2fs_fast_test_block_bitmap(bm2, i))
+ return EXT2_ET_NEQ_BLOCK_BITMAP;
+
+ return 0;
+}
+
+errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
+ ext2fs_inode_bitmap bm2)
+{
+ ext2_ino_t i;
+
+ EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
+ EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
+
+ if ((bm1->start != bm2->start) ||
+ (bm1->end != bm2->end) ||
+ (memcmp(bm1->bitmap, bm2->bitmap,
+ (size_t) (bm1->end - bm1->start)/8)))
+ return EXT2_ET_NEQ_INODE_BITMAP;
+
+ for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
+ if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
+ ext2fs_fast_test_inode_bitmap(bm2, i))
+ return EXT2_ET_NEQ_INODE_BITMAP;
+
+ return 0;
+}
+
diff --git a/e2fslib/cmp_bitmaps.o b/e2fslib/cmp_bitmaps.o
new file mode 100644
index 0000000..21c8386
--- /dev/null
+++ b/e2fslib/cmp_bitmaps.o
Binary files differ
diff --git a/e2fslib/com_err.h b/e2fslib/com_err.h
new file mode 100644
index 0000000..f28dce8
--- /dev/null
+++ b/e2fslib/com_err.h
@@ -0,0 +1,40 @@
+/*
+ * Header file for common error description library.
+ *
+ * Copyright 1988, Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * For copyright and distribution info, see the documentation supplied
+ * with this package.
+ */
+
+#ifndef __COM_ERR_H
+
+typedef long errcode_t;
+
+#ifdef __STDC__
+#include <stdarg.h>
+
+/* ANSI C -- use prototypes etc */
+void com_err (const char *, long, const char *, ...);
+void com_err_va (const char *whoami, errcode_t code, const char *fmt,
+ va_list args);
+char const *error_message (long);
+extern void (*com_err_hook) (const char *, long, const char *, va_list);
+void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
+ (const char *, long, const char *, va_list);
+void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
+int init_error_table(const char * const *msgs, int base, int count);
+#else
+/* no prototypes */
+void com_err ();
+void com_err_va ();
+char *error_message ();
+extern void (*com_err_hook) ();
+void (*set_com_err_hook ()) ();
+void (*reset_com_err_hook ()) ();
+int init_error_table();
+#endif
+
+#define __COM_ERR_H
+#endif /* ! defined(__COM_ERR_H) */
diff --git a/e2fslib/dblist.c b/e2fslib/dblist.c
new file mode 100644
index 0000000..a195b5b
--- /dev/null
+++ b/e2fslib/dblist.c
@@ -0,0 +1,254 @@
+/*
+ * dblist.c -- directory block list functions
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b);
+
+/*
+ * Returns the number of directories in the filesystem as reported by
+ * the group descriptors. Of course, the group descriptors could be
+ * wrong!
+ */
+errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
+{
+ dgrp_t i;
+ ext2_ino_t num_dirs, max_dirs;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ num_dirs = 0;
+ max_dirs = fs->super->s_inodes_per_group;
+ for (i = 0; i < fs->group_desc_count; i++) {
+ if (fs->group_desc[i].bg_used_dirs_count > max_dirs)
+ num_dirs += max_dirs / 8;
+ else
+ num_dirs += fs->group_desc[i].bg_used_dirs_count;
+ }
+ if (num_dirs > fs->super->s_inodes_count)
+ num_dirs = fs->super->s_inodes_count;
+
+ *ret_num_dirs = num_dirs;
+
+ return 0;
+}
+
+/*
+ * helper function for making a new directory block list (for
+ * initialize and copy).
+ */
+static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
+ struct ext2_db_entry *list,
+ ext2_dblist *ret_dblist)
+{
+ ext2_dblist dblist;
+ errcode_t retval;
+ size_t len;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if ((ret_dblist == 0) && fs->dblist &&
+ (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
+ return 0;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist),
+ (void **) &dblist);
+ if (retval)
+ return retval;
+ memset(dblist, 0, sizeof(struct ext2_struct_dblist));
+
+ dblist->magic = EXT2_ET_MAGIC_DBLIST;
+ dblist->fs = fs;
+ if (size)
+ dblist->size = size;
+ else {
+ retval = ext2fs_get_num_dirs(fs, &dblist->size);
+ if (retval)
+ goto cleanup;
+ dblist->size = (dblist->size * 2) + 12;
+ }
+ len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
+ dblist->count = count;
+ retval = ext2fs_get_mem(len, (void **) &dblist->list);
+ if (retval)
+ goto cleanup;
+
+ if (list)
+ memcpy(dblist->list, list, len);
+ else
+ memset(dblist->list, 0, len);
+ if (ret_dblist)
+ *ret_dblist = dblist;
+ else
+ fs->dblist = dblist;
+ return 0;
+cleanup:
+ if (dblist)
+ ext2fs_free_mem((void **) &dblist);
+ return retval;
+}
+
+/*
+ * Initialize a directory block list
+ */
+errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
+{
+ ext2_dblist dblist;
+ errcode_t retval;
+
+ retval = make_dblist(fs, 0, 0, 0, &dblist);
+ if (retval)
+ return retval;
+
+ dblist->sorted = 1;
+ if (ret_dblist)
+ *ret_dblist = dblist;
+ else
+ fs->dblist = dblist;
+
+ return 0;
+}
+
+/*
+ * Copy a directory block list
+ */
+errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
+{
+ ext2_dblist dblist;
+ errcode_t retval;
+
+ retval = make_dblist(src->fs, src->size, src->count, src->list,
+ &dblist);
+ if (retval)
+ return retval;
+ dblist->sorted = src->sorted;
+ *dest = dblist;
+ return 0;
+}
+
+/*
+ * Close a directory block list
+ *
+ * (moved to closefs.c)
+ */
+
+
+/*
+ * Add a directory block to the directory block list
+ */
+errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
+ int blockcnt)
+{
+ struct ext2_db_entry *new_entry;
+ errcode_t retval;
+ unsigned long old_size;
+
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ if (dblist->count >= dblist->size) {
+ old_size = dblist->size * sizeof(struct ext2_db_entry);
+ dblist->size += 100;
+ retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
+ sizeof(struct ext2_db_entry),
+ (void **) &dblist->list);
+ if (retval) {
+ dblist->size -= 100;
+ return retval;
+ }
+ }
+ new_entry = dblist->list + ( (int) dblist->count++);
+ new_entry->blk = blk;
+ new_entry->ino = ino;
+ new_entry->blockcnt = blockcnt;
+
+ dblist->sorted = 0;
+
+ return 0;
+}
+
+/*
+ * Change the directory block to the directory block list
+ */
+errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
+ int blockcnt)
+{
+ dgrp_t i;
+
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ for (i=0; i < dblist->count; i++) {
+ if ((dblist->list[i].ino != ino) ||
+ (dblist->list[i].blockcnt != blockcnt))
+ continue;
+ dblist->list[i].blk = blk;
+ dblist->sorted = 0;
+ return 0;
+ }
+ return EXT2_ET_DB_NOT_FOUND;
+}
+
+/*
+ * This function iterates over the directory block list
+ */
+errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
+ int (*func)(ext2_filsys fs,
+ struct ext2_db_entry *db_info,
+ void *priv_data),
+ void *priv_data)
+{
+ ext2_ino_t i;
+ int ret;
+
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ if (!dblist->sorted) {
+ qsort(dblist->list, (size_t) dblist->count,
+ sizeof(struct ext2_db_entry), dir_block_cmp);
+ dblist->sorted = 1;
+ }
+ for (i=0; i < dblist->count; i++) {
+ ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data);
+ if (ret & DBLIST_ABORT)
+ return 0;
+ }
+ return 0;
+}
+
+
+static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b)
+{
+ const struct ext2_db_entry *db_a =
+ (const struct ext2_db_entry *) a;
+ const struct ext2_db_entry *db_b =
+ (const struct ext2_db_entry *) b;
+
+ if (db_a->blk != db_b->blk)
+ return (int) (db_a->blk - db_b->blk);
+
+ if (db_a->ino != db_b->ino)
+ return (int) (db_a->ino - db_b->ino);
+
+ return (int) (db_a->blockcnt - db_b->blockcnt);
+}
+
+int ext2fs_dblist_count(ext2_dblist dblist)
+{
+ return (int) dblist->count;
+}
diff --git a/e2fslib/dblist.o b/e2fslib/dblist.o
new file mode 100644
index 0000000..6ca5fc4
--- /dev/null
+++ b/e2fslib/dblist.o
Binary files differ
diff --git a/e2fslib/dblist_dir.c b/e2fslib/dblist_dir.c
new file mode 100644
index 0000000..c4ea584
--- /dev/null
+++ b/e2fslib/dblist_dir.c
@@ -0,0 +1,77 @@
+/*
+ * dblist_dir.c --- iterate by directory entry
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
+ void *priv_data);
+
+errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_ino_t dir,
+ int entry,
+ struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data),
+ void *priv_data)
+{
+ errcode_t retval;
+ struct dir_context ctx;
+
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ ctx.dir = 0;
+ ctx.flags = flags;
+ if (block_buf)
+ ctx.buf = block_buf;
+ else {
+ retval = ext2fs_get_mem(dblist->fs->blocksize,
+ (void **) &ctx.buf);
+ if (retval)
+ return retval;
+ }
+ ctx.func = 0;
+ ctx.func2 = func;
+ ctx.priv_data = priv_data;
+ ctx.errcode = 0;
+
+ retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
+
+ if (!block_buf)
+ ext2fs_free_mem((void **) &ctx.buf);
+ if (retval)
+ return retval;
+ return ctx.errcode;
+}
+
+static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
+ void *priv_data)
+{
+ struct dir_context *ctx;
+
+ ctx = (struct dir_context *) priv_data;
+ ctx->dir = db_info->ino;
+
+ return ext2fs_process_dir_block(fs, &db_info->blk,
+ db_info->blockcnt, 0, 0, priv_data);
+}
diff --git a/e2fslib/dblist_dir.o b/e2fslib/dblist_dir.o
new file mode 100644
index 0000000..40f1c71
--- /dev/null
+++ b/e2fslib/dblist_dir.o
Binary files differ
diff --git a/e2fslib/dir_iterate.c b/e2fslib/dir_iterate.c
new file mode 100644
index 0000000..ae97d82
--- /dev/null
+++ b/e2fslib/dir_iterate.c
@@ -0,0 +1,137 @@
+/*
+ * dir_iterate.c --- ext2fs directory iteration operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+errcode_t ext2fs_dir_iterate(ext2_filsys fs,
+ ext2_ino_t dir,
+ int flags,
+ char *block_buf,
+ int (*func)(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data),
+ void *priv_data)
+{
+ struct dir_context ctx;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_check_directory(fs, dir);
+ if (retval)
+ return retval;
+
+ ctx.dir = dir;
+ ctx.flags = flags;
+ if (block_buf)
+ ctx.buf = block_buf;
+ else {
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &ctx.buf);
+ if (retval)
+ return retval;
+ }
+ ctx.func = func;
+ ctx.func2 = 0;
+ ctx.priv_data = priv_data;
+ ctx.errcode = 0;
+ retval = ext2fs_block_iterate2(fs, dir, 0, 0,
+ ext2fs_process_dir_block, &ctx);
+ if (!block_buf)
+ ext2fs_free_mem((void **) &ctx.buf);
+ if (retval)
+ return retval;
+ return ctx.errcode;
+}
+
+/*
+ * Helper function which is private to this module. Used by
+ * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
+ */
+int ext2fs_process_dir_block(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block,
+ int ref_offset,
+ void *priv_data)
+{
+ struct dir_context *ctx = (struct dir_context *) priv_data;
+ int offset = 0;
+ int ret = 0;
+ int changed = 0;
+ int do_abort = 0;
+ int entry;
+ struct ext2_dir_entry *dirent;
+
+ if (blockcnt < 0)
+ return 0;
+
+ entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
+
+ ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
+ if (ctx->errcode)
+ return BLOCK_ABORT;
+
+ while (offset < fs->blocksize) {
+ dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
+ if (((offset + dirent->rec_len) > fs->blocksize) ||
+ (dirent->rec_len < 8) ||
+ ((dirent->rec_len % 4) != 0) ||
+ (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+ ctx->errcode = EXT2_ET_DIR_CORRUPTED;
+ return BLOCK_ABORT;
+ }
+ if (!dirent->inode &&
+ !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
+ goto next;
+
+ if (ctx->func)
+ ret = (ctx->func)(dirent, offset, fs->blocksize,
+ ctx->buf, ctx->priv_data);
+ else if (ctx->func2) {
+ ret = (ctx->func2)(ctx->dir, entry, dirent, offset,
+ fs->blocksize, ctx->buf,
+ ctx->priv_data);
+ if (entry < DIRENT_OTHER_FILE)
+ entry++;
+ }
+
+ if (ret & DIRENT_CHANGED)
+ changed++;
+ if (ret & DIRENT_ABORT) {
+ do_abort++;
+ break;
+ }
+next:
+ offset += dirent->rec_len;
+ }
+
+ if (changed) {
+ ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
+ if (ctx->errcode)
+ return BLOCK_ABORT;
+ }
+ if (do_abort)
+ return BLOCK_ABORT;
+ return 0;
+}
+
diff --git a/e2fslib/dir_iterate.o b/e2fslib/dir_iterate.o
new file mode 100644
index 0000000..36f8330
--- /dev/null
+++ b/e2fslib/dir_iterate.o
Binary files differ
diff --git a/e2fslib/dirblock.c b/e2fslib/dirblock.c
new file mode 100644
index 0000000..9efbceb
--- /dev/null
+++ b/e2fslib/dirblock.c
@@ -0,0 +1,100 @@
+/*
+ * dirblock.c --- directory block routines.
+ *
+ * Copyright (C) 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
+ void *buf)
+{
+ errcode_t retval;
+ char *p, *end;
+ struct ext2_dir_entry *dirent;
+ unsigned int rec_len, do_swap;
+
+ retval = io_channel_read_blk(fs->io, block, 1, buf);
+ if (retval)
+ return retval;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
+ EXT2_FLAG_SWAP_BYTES_READ)) != 0;
+#endif
+ p = (char *) buf;
+ end = (char *) buf + fs->blocksize;
+ while (p < end-8) {
+ dirent = (struct ext2_dir_entry *) p;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (do_swap) {
+ dirent->inode = ext2fs_swab32(dirent->inode);
+ dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+ dirent->name_len = ext2fs_swab16(dirent->name_len);
+ }
+#endif
+ rec_len = dirent->rec_len;
+ if ((rec_len < 8) || (rec_len % 4)) {
+ rec_len = 8;
+ retval = EXT2_ET_DIR_CORRUPTED;
+ }
+ if (((dirent->name_len & 0xFF) + 8) > dirent->rec_len)
+ retval = EXT2_ET_DIR_CORRUPTED;
+ p += rec_len;
+ }
+ return retval;
+}
+
+errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
+ void *inbuf)
+{
+ errcode_t retval;
+ char *p, *end, *write_buf;
+ char *buf = 0;
+ struct ext2_dir_entry *dirent;
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) {
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+ write_buf = buf;
+ memcpy(buf, inbuf, fs->blocksize);
+ p = buf;
+ end = buf + fs->blocksize;
+ while (p < end) {
+ dirent = (struct ext2_dir_entry *) p;
+ if ((dirent->rec_len < 8) ||
+ (dirent->rec_len % 4)) {
+ retval = EXT2_ET_DIR_CORRUPTED;
+ goto errout;
+ }
+ p += dirent->rec_len;
+ dirent->inode = ext2fs_swab32(dirent->inode);
+ dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+ dirent->name_len = ext2fs_swab16(dirent->name_len);
+ }
+ } else
+#endif
+ write_buf = (char *) inbuf;
+ retval = io_channel_write_blk(fs->io, block, 1, write_buf);
+errout:
+ if (buf)
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+
diff --git a/e2fslib/dirblock.o b/e2fslib/dirblock.o
new file mode 100644
index 0000000..e79011f
--- /dev/null
+++ b/e2fslib/dirblock.o
Binary files differ
diff --git a/e2fslib/dll/jump.funcs b/e2fslib/dll/jump.funcs
new file mode 100644
index 0000000..7498b03
--- /dev/null
+++ b/e2fslib/dll/jump.funcs
@@ -0,0 +1,178 @@
+00000000 T _ext2fs_open libext2fs openfs
+00000000 T _ext2fs_check_desc libext2fs openfs
+00000000 T _ext2fs_free libext2fs freefs
+00000000 T _ext2fs_flush libext2fs closefs
+00000000 T _ext2fs_close libext2fs closefs
+00000000 T _ext2fs_allocate_inode_bitmap libext2fs bitmaps
+00000000 T _ext2fs_allocate_block_bitmap libext2fs bitmaps
+00000000 T _ext2fs_free_inode_bitmap libext2fs bitmaps
+00000000 T _ext2fs_free_block_bitmap libext2fs bitmaps
+00000000 T _ext2fs_fudge_inode_bitmap_end libext2fs bitmaps
+00000000 T _ext2fs_fudge_block_bitmap_end libext2fs bitmaps
+00000000 T _ext2fs_clear_inode_bitmap libext2fs bitmaps
+00000000 T _ext2fs_clear_block_bitmap libext2fs bitmaps
+00000000 T _ext2fs_write_inode_bitmap libext2fs rw_bitmaps
+00000000 T _ext2fs_write_block_bitmap libext2fs rw_bitmaps
+00000000 T _ext2fs_read_inode_bitmap libext2fs rw_bitmaps
+00000000 T _ext2fs_read_block_bitmap libext2fs rw_bitmaps
+00000000 T _ext2fs_read_bitmaps libext2fs rw_bitmaps
+00000000 T _ext2fs_write_bitmaps libext2fs rw_bitmaps
+00000000 T _ext2fs_open_inode_scan libext2fs inode
+00000000 T _ext2fs_close_inode_scan libext2fs inode
+00000000 T _ext2fs_get_next_inode libext2fs inode
+00000000 T _ext2fs_read_inode libext2fs inode
+00000000 T _ext2fs_write_inode libext2fs inode
+00000000 T _ext2fs_get_blocks libext2fs inode
+00000000 T _ext2fs_check_directory libext2fs inode
+00000000 T _ext2fs_block_iterate libext2fs block
+00000000 T _ext2fs_dir_iterate libext2fs namei
+00000000 T _ext2fs_lookup libext2fs namei
+00000000 T _ext2fs_namei libext2fs namei
+00000000 T _ext2fs_new_dir_block libext2fs newdir
+00000000 T _ext2fs_mkdir libext2fs mkdir
+00000000 T _ext2fs_get_pathname libext2fs get_pathname
+00000000 T _ext2fs_warn_bitmap libext2fs bitops
+00000000 T _ext2fs_link libext2fs link
+00000000 T _ext2fs_unlink libext2fs link
+00000000 T _ext2fs_new_inode libext2fs alloc
+00000000 T _ext2fs_new_block libext2fs alloc
+00000000 T _ext2fs_get_free_blocks libext2fs alloc
+00000000 T _ext2fs_expand_dir libext2fs expanddir
+00000000 T _ext2fs_set_bit libext2fs inline
+00000000 T _ext2fs_clear_bit libext2fs inline
+00000000 T _ext2fs_test_bit libext2fs inline
+00000000 T _ext2fs_mark_block_bitmap libext2fs inline
+00000000 T _ext2fs_unmark_block_bitmap libext2fs inline
+00000000 T _ext2fs_test_block_bitmap libext2fs inline
+00000000 T _ext2fs_mark_inode_bitmap libext2fs inline
+00000000 T _ext2fs_unmark_inode_bitmap libext2fs inline
+00000000 T _ext2fs_test_inode_bitmap libext2fs inline
+00000000 T _ext2fs_mark_super_dirty libext2fs inline
+00000000 T _ext2fs_mark_changed libext2fs inline
+00000000 T _ext2fs_test_changed libext2fs inline
+00000000 T _ext2fs_mark_valid libext2fs inline
+00000000 T _ext2fs_unmark_valid libext2fs inline
+00000000 T _ext2fs_test_valid libext2fs inline
+00000000 T _ext2fs_mark_ib_dirty libext2fs inline
+00000000 T _ext2fs_mark_bb_dirty libext2fs inline
+00000000 T _ext2fs_test_ib_dirty libext2fs inline
+00000000 T _ext2fs_test_bb_dirty libext2fs inline
+00000000 T _ext2fs_group_of_blk libext2fs inline
+00000000 T _ext2fs_group_of_ino libext2fs inline
+00000000 T _ext2fs_initialize libext2fs initialize
+00000000 T _badblocks_list_create libext2fs badblocks
+00000000 T _badblocks_list_free libext2fs badblocks
+00000000 T _badblocks_list_add libext2fs badblocks
+00000000 T _badblocks_list_test libext2fs badblocks
+00000000 T _badblocks_list_iterate_begin libext2fs badblocks
+00000000 T _badblocks_list_iterate libext2fs badblocks
+00000000 T _badblocks_list_iterate_end libext2fs badblocks
+00000000 T _ext2fs_read_bb_inode libext2fs read_bb
+00000000 T _ext2fs_update_bb_inode libext2fs bb_inode
+00000000 T _ext2fs_read_bb_FILE libext2fs read_bb_file
+00000000 T _initialize_ext2_error_table libext2fs ext2_err
+00000000 T _ext2fs_llseek libext2fs llseek
+00000000 T _ext2fs_set_inode_callback libext2fs inode
+00000000 T _ext2fs_compare_block_bitmap libext2fs cmp_bitmaps
+00000000 T _ext2fs_compare_inode_bitmap libext2fs cmp_bitmaps
+00000000 T _ext2fs_read_dir_block libext2fs dirblock
+00000000 T _ext2fs_write_dir_block libext2fs dirblock
+00000000 T _ext2fs_swab16 libext2fs inline
+00000000 T _ext2fs_swab32 libext2fs inline
+00000000 T _ext2fs_fast_mark_block_bitmap libext2fs inline
+00000000 T _ext2fs_fast_unmark_block_bitmap libext2fs inline
+00000000 T _ext2fs_fast_test_block_bitmap libext2fs inline
+00000000 T _ext2fs_fast_mark_inode_bitmap libext2fs inline
+00000000 T _ext2fs_fast_unmark_inode_bitmap libext2fs inline
+00000000 T _ext2fs_fast_test_inode_bitmap libext2fs inline
+00000000 T _ext2fs_get_block_bitmap_start libext2fs inline
+00000000 T _ext2fs_get_inode_bitmap_start libext2fs inline
+00000000 T _ext2fs_get_block_bitmap_end libext2fs inline
+00000000 T _ext2fs_get_inode_bitmap_end libext2fs inline
+00000000 T _ext2fs_swap_super libext2fs swapfs
+00000000 T _ext2fs_swap_group_desc libext2fs swapfs
+00000000 T _ext2fs_get_device_size libext2fs getsize
+00000000 T _ext2fs_check_if_mounted libext2fs ismounted
+00000000 T _ext2fs_allocate_tables libext2fs alloc_tables
+00000000 T _ext2fs_allocate_generic_bitmap libext2fs bitmaps
+00000000 T _ext2fs_warn_bitmap2 libext2fs bitops
+00000000 T _ext2fs_free_generic_bitmap libext2fs freefs
+00000000 T _ext2fs_mark_generic_bitmap libext2fs inline
+00000000 T _ext2fs_unmark_generic_bitmap libext2fs inline
+00000000 T _ext2fs_test_generic_bitmap libext2fs inline
+00000000 T _ext2fs_namei_follow libext2fs namei
+00000000 T _ext2fs_follow_link libext2fs namei
+00000000 T _ext2fs_native_flag libext2fs native
+00000000 T _ext2fs_swap_inode libext2fs swapfs
+00000000 T _ext2fs_block_iterate2 libext2fs block
+00000000 T _ext2fs_inode_scan_goto_blockgroup libext2fs inode
+00000000 T _ext2fs_badblocks_list_create libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_add libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_test libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_iterate_begin libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_iterate libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_iterate_end libext2fs badblocks
+#00000000 U _ext2fs_brel_memarray_create libext2fs brel_ma
+00000000 T __DUMMY__ libext2fs brel_ma
+00000000 T _ext2fs_badblocks_list_free libext2fs closefs
+00000000 T _ext2fs_free_dblist libext2fs closefs
+00000000 T _ext2fs_get_num_dirs libext2fs dblist
+00000000 T _ext2fs_init_dblist libext2fs dblist
+00000000 T _ext2fs_add_dir_block libext2fs dblist
+00000000 T _ext2fs_dblist_iterate libext2fs dblist
+00000000 T _ext2fs_dblist_dir_iterate libext2fs dblist_dir
+00000000 T _ext2fs_process_dir_block libext2fs dir_iterate
+00000000 T _ext2fs_test_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_fast_test_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_mark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_fast_mark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_unmark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_fast_unmark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_inode_scan_flags libext2fs inode
+#00000000 U _ext2fs_irel_memarray_create libext2fs irel_ma
+00000000 U __DUMMY__ libext2fs irel_ma
+00000000 T _ext2fs_resize_generic_bitmap libext2fs rs_bitmap
+00000000 T _ext2fs_inode_has_valid_blocks libext2fs valid_blk
+00000000 T _ext2fs_free_icount libext2fs icount
+00000000 T _ext2fs_create_icount libext2fs icount
+00000000 T _ext2fs_icount_fetch libext2fs icount
+00000000 T _ext2fs_icount_increment libext2fs icount
+00000000 T _ext2fs_icount_decrement libext2fs icount
+00000000 T _ext2fs_icount_store libext2fs icount
+00000000 T _ext2fs_get_icount_size libext2fs icount
+00000000 T _ext2fs_create_icount2 libext2fs icount
+00000000 T _ext2fs_get_library_version libext2fs version
+00000000 T _ext2fs_parse_version_string libext2fs version
+00000000 T _ext2fs_set_dir_block libext2fs dblist
+00000000 T _ext2fs_badblocks_copy libext2fs badblocks
+00000000 T _ext2fs_copy_bitmap libext2fs bitmaps
+00000000 T _ext2fs_bg_has_super libext2fs closefs
+00000000 T _ext2fs_copy_dblist libext2fs dblist
+00000000 T _ext2fs_dup_handle libext2fs dupfs
+00000000 T _ext2fs_icount_validate libext2fs icount
+00000000 T _ext2fs_resize_inode_bitmap libext2fs rs_bitmap
+00000000 T _ext2fs_resize_block_bitmap libext2fs rs_bitmap
+00000000 T _ext2fs_dblist_count libext2fs dblist
+00000000 T _ext2fs_alloc_block libext2fs alloc
+00000000 T _ext2fs_allocate_group_table libext2fs alloc_tables
+00000000 T _ext2fs_set_bitmap_padding libext2fs bitmaps
+00000000 T _ext2fs_bmap libext2fs bmap
+#00000000 T _ext2fs_move_blocks libext2fs bmove
+00000000 T __DUMMY__ libext2fs bmove
+00000000 T _ext2fs_file_open libext2fs fileio
+00000000 T _ext2fs_file_get_fs libext2fs fileio
+00000000 T _ext2fs_file_close libext2fs fileio
+00000000 T _ext2fs_file_read libext2fs fileio
+00000000 T _ext2fs_file_write libext2fs fileio
+00000000 T _ext2fs_file_lseek libext2fs fileio
+00000000 T _ext2fs_file_get_size libext2fs fileio
+00000000 T _ext2fs_file_set_size libext2fs fileio
+00000000 T _ext2fs_get_mem libext2fs inline
+00000000 T _ext2fs_free_mem libext2fs inline
+00000000 T _ext2fs_resize_mem libext2fs inline
+00000000 T _ext2fs_read_bb_FILE2 libext2fs read_bb_file
+00000000 T _ext2fs_write_bb_FILE libext2fs write_bb_file
+00000000 T _ext2fs_badblocks_equal libext2fs badblocks
+00000000 T _ext2fs_update_dynamic_rev libext2fs closefs
+00000000 T _ext2fs_sync_device libext2fs flushb
+
diff --git a/e2fslib/dll/jump.import b/e2fslib/dll/jump.import
new file mode 100644
index 0000000..53208d5
--- /dev/null
+++ b/e2fslib/dll/jump.import
@@ -0,0 +1,166 @@
+00000004 D __et_list libcom_err jump/error_message
+00000004 D _com_err_hook libcom_err jump/com_err
+/usr/lib/libc.sa(__libc.o):00001000 a __GOT_SIZE
+/usr/lib/libc.sa(__libc.o):6008f0b0 A _AL
+/usr/lib/libc.sa(__libc.o):6008f198 A _AL_PARM
+/usr/lib/libc.sa(__libc.o):6008f060 A _AM
+/usr/lib/libc.sa(__libc.o):6008f0b4 A _BC
+/usr/lib/libc.sa(__libc.o):6008f064 A _BS
+/usr/lib/libc.sa(__libc.o):6008f0bc A _BT
+/usr/lib/libc.sa(__libc.o):6008f068 A _CA
+/usr/lib/libc.sa(__libc.o):6008f0c0 A _CD
+/usr/lib/libc.sa(__libc.o):6008f0c4 A _CE
+/usr/lib/libc.sa(__libc.o):6008f0c8 A _CL
+/usr/lib/libc.sa(__libc.o):6008f0cc A _CM
+/usr/lib/libc.sa(__libc.o):6008f048 A _COLS
+/usr/lib/libc.sa(__libc.o):6008f0d0 A _CR
+/usr/lib/libc.sa(__libc.o):6008f0d4 A _CS
+/usr/lib/libc.sa(__libc.o):6008f06c A _DA
+/usr/lib/libc.sa(__libc.o):6008f070 A _DB
+/usr/lib/libc.sa(__libc.o):6008f0d8 A _DC
+/usr/lib/libc.sa(__libc.o):6008f0dc A _DL
+/usr/lib/libc.sa(__libc.o):6008f19c A _DL_PARM
+/usr/lib/libc.sa(__libc.o):6008f0e0 A _DM
+/usr/lib/libc.sa(__libc.o):6008f0e4 A _DO
+/usr/lib/libc.sa(__libc.o):6008f1a4 A _DOWN_PARM
+/usr/lib/libc.sa(__libc.o):6008f03c A _Def_term
+/usr/lib/libc.sa(__libc.o):6008f0e8 A _ED
+/usr/lib/libc.sa(__libc.o):6008f0ec A _EI
+/usr/lib/libc.sa(__libc.o):6008f074 A _EO
+/usr/lib/libc.sa(__libc.o):6008f1b8 A _GT
+/usr/lib/libc.sa(__libc.o):6008f078 A _HC
+/usr/lib/libc.sa(__libc.o):6008f118 A _HO
+/usr/lib/libc.sa(__libc.o):6008f07c A _HZ
+/usr/lib/libc.sa(__libc.o):6008f11c A _IC
+/usr/lib/libc.sa(__libc.o):6008f120 A _IM
+/usr/lib/libc.sa(__libc.o):6008f080 A _IN
+/usr/lib/libc.sa(__libc.o):6008f124 A _IP
+/usr/lib/libc.sa(__libc.o):6008f0f0 A _K0
+/usr/lib/libc.sa(__libc.o):6008f0f4 A _K1
+/usr/lib/libc.sa(__libc.o):6008f0f8 A _K2
+/usr/lib/libc.sa(__libc.o):6008f0fc A _K3
+/usr/lib/libc.sa(__libc.o):6008f100 A _K4
+/usr/lib/libc.sa(__libc.o):6008f104 A _K5
+/usr/lib/libc.sa(__libc.o):6008f108 A _K6
+/usr/lib/libc.sa(__libc.o):6008f10c A _K7
+/usr/lib/libc.sa(__libc.o):6008f110 A _K8
+/usr/lib/libc.sa(__libc.o):6008f114 A _K9
+/usr/lib/libc.sa(__libc.o):6008f128 A _KD
+/usr/lib/libc.sa(__libc.o):6008f12c A _KE
+/usr/lib/libc.sa(__libc.o):6008f130 A _KH
+/usr/lib/libc.sa(__libc.o):6008f134 A _KL
+/usr/lib/libc.sa(__libc.o):6008f138 A _KR
+/usr/lib/libc.sa(__libc.o):6008f13c A _KS
+/usr/lib/libc.sa(__libc.o):6008f140 A _KU
+/usr/lib/libc.sa(__libc.o):6008f1a8 A _LEFT_PARM
+/usr/lib/libc.sa(__libc.o):6008f044 A _LINES
+/usr/lib/libc.sa(__libc.o):6008f144 A _LL
+/usr/lib/libc.sa(__libc.o):6008f148 A _MA
+/usr/lib/libc.sa(__libc.o):6008f300 A _MCAppPath
+/usr/lib/libc.sa(__libc.o):6008f084 A _MI
+/usr/lib/libc.sa(__libc.o):6008f088 A _MS
+/usr/lib/libc.sa(__libc.o):6008f030 A _My_term
+/usr/lib/libc.sa(__libc.o):6008f08c A _NC
+/usr/lib/libc.sa(__libc.o):6008f14c A _ND
+/usr/lib/libc.sa(__libc.o):6008f150 A _NL
+/usr/lib/libc.sa(__libc.o):6008f1bc A _NONL
+/usr/lib/libc.sa(__libc.o):6008f090 A _NS
+/usr/lib/libc.sa(__libc.o):6008f094 A _OS
+/usr/lib/libc.sa(__libc.o):6008f1b0 A _PC
+/usr/lib/libc.sa(__libc.o):6008f154 A _RC
+/usr/lib/libc.sa(__libc.o):6008f1ac A _RIGHT_PARM
+/usr/lib/libc.sa(__libc.o):6008f158 A _SC
+/usr/lib/libc.sa(__libc.o):6008f15c A _SE
+/usr/lib/libc.sa(__libc.o):6008f160 A _SF
+/usr/lib/libc.sa(__libc.o):6008f164 A _SO
+/usr/lib/libc.sa(__libc.o):6008f168 A _SR
+/usr/lib/libc.sa(__libc.o):6008f16c A _TA
+/usr/lib/libc.sa(__libc.o):6008f170 A _TE
+/usr/lib/libc.sa(__libc.o):6008f174 A _TI
+/usr/lib/libc.sa(__libc.o):6008f178 A _UC
+/usr/lib/libc.sa(__libc.o):6008f17c A _UE
+/usr/lib/libc.sa(__libc.o):6008f098 A _UL
+/usr/lib/libc.sa(__libc.o):6008f180 A _UP
+/usr/lib/libc.sa(__libc.o):6008f1c0 A _UPPERCASE
+/usr/lib/libc.sa(__libc.o):6008f1a0 A _UP_PARM
+/usr/lib/libc.sa(__libc.o):6008f188 A _US
+/usr/lib/libc.sa(__libc.o):6008f18c A _VB
+/usr/lib/libc.sa(__libc.o):6008f194 A _VE
+/usr/lib/libc.sa(__libc.o):6008f190 A _VS
+/usr/lib/libc.sa(__libc.o):6008f09c A _XB
+/usr/lib/libc.sa(__libc.o):6008f0a0 A _XN
+/usr/lib/libc.sa(__libc.o):6008f0a8 A _XS
+/usr/lib/libc.sa(__libc.o):6008f0a4 A _XT
+/usr/lib/libc.sa(__libc.o):6008f0ac A _XX
+/usr/lib/libc.sa(__libc.o):6008f2a4 A __IO_file_jumps
+/usr/lib/libc.sa(__libc.o):6008f1f4 A __IO_list_all
+/usr/lib/libc.sa(__libc.o):6008f2a8 A __IO_proc_jumps
+/usr/lib/libc.sa(__libc.o):6008f1ec A __IO_stderr_
+/usr/lib/libc.sa(__libc.o):6008f1e4 A __IO_stdin_
+/usr/lib/libc.sa(__libc.o):6008f1e8 A __IO_stdout_
+/usr/lib/libc.sa(__libc.o):6008f2ac A __IO_str_jumps
+/usr/lib/libc.sa(__libc.o):6008f214 A ____brk_addr
+/usr/lib/libc.sa(__libc.o):6008f01c A ___ctype_b
+/usr/lib/libc.sa(__libc.o):6008f020 A ___ctype_tolower
+/usr/lib/libc.sa(__libc.o):6008f024 A ___ctype_toupper
+/usr/lib/libc.sa(__libc.o):6008f1fc A ___environ
+/usr/lib/libc.sa(__libc.o):6008f250 A ___exit_funcs
+/usr/lib/libc.sa(__libc.o):6008f2f0 A ___glob_closedir_hook
+/usr/lib/libc.sa(__libc.o):6008f2f4 A ___glob_opendir_hook
+/usr/lib/libc.sa(__libc.o):6008f2f8 A ___glob_readdir_hook
+/usr/lib/libc.sa(__libc.o):6008f278 A ___ttyname
+/usr/lib/libc.sa(__libc.o):6008f238 A __collate_info
+/usr/lib/libc.sa(__libc.o):6008f23c A __ctype_info
+/usr/lib/libc.sa(__libc.o):6008f028 A __echoit
+/usr/lib/libc.sa(__libc.o):6008f034 A __endwin
+/usr/lib/libc.sa(__libc.o):6008f288 A __gdbm_fetch_val
+/usr/lib/libc.sa(__libc.o):6008f280 A __gdbm_file
+/usr/lib/libc.sa(__libc.o):6008f284 A __gdbm_memory
+/usr/lib/libc.sa(__libc.o):6008f240 A __monetary_info
+/usr/lib/libc.sa(__libc.o):6008f234 A __null_auth
+/usr/lib/libc.sa(__libc.o):6008f244 A __numeric_info
+/usr/lib/libc.sa(__libc.o):6008f2ec A __obstack
+/usr/lib/libc.sa(__libc.o):6008f1c8 A __pfast
+/usr/lib/libc.sa(__libc.o):6008f02c A __rawmode
+/usr/lib/libc.sa(__libc.o):6008f1dc A __res
+/usr/lib/libc.sa(__libc.o):6008f04c A __res_iflg
+/usr/lib/libc.sa(__libc.o):6008f050 A __res_lflg
+/usr/lib/libc.sa(__libc.o):6008f270 A __res_opcodes
+/usr/lib/libc.sa(__libc.o):6008f274 A __res_resultcodes
+/usr/lib/libc.sa(__libc.o):6008f248 A __response_info
+/usr/lib/libc.sa(__libc.o):6008f2fc A __sigintr
+/usr/lib/libc.sa(__libc.o):6008f00c A __sys_errlist
+/usr/lib/libc.sa(__libc.o):6008f010 A __sys_nerr
+/usr/lib/libc.sa(__libc.o):6008f014 A __sys_siglist
+/usr/lib/libc.sa(__libc.o):6008f24c A __time_info
+/usr/lib/libc.sa(__libc.o):6008f05c A __tty
+/usr/lib/libc.sa(__libc.o):6008f040 A __tty_ch
+/usr/lib/libc.sa(__libc.o):6008f1cc A __unctrl
+/usr/lib/libc.sa(__libc.o):6008f27c A __win
+/usr/lib/libc.sa(__libc.o):6008f058 A _curscr
+/usr/lib/libc.sa(__libc.o):6008f228 A _daylight
+/usr/lib/libc.sa(__libc.o):6008f200 A _errno
+/usr/lib/libc.sa(__libc.o):6008f1d0 A _gdbm_errno
+/usr/lib/libc.sa(__libc.o):6008f28c A _gdbm_version
+/usr/lib/libc.sa(__libc.o):6008f008 A _h_errlist
+/usr/lib/libc.sa(__libc.o):6008f1d8 A _h_errno
+/usr/lib/libc.sa(__libc.o):6008f2a0 A _h_nerr
+/usr/lib/libc.sa(__libc.o):6008f1c4 A _normtty
+/usr/lib/libc.sa(__libc.o):6008f204 A _optarg
+/usr/lib/libc.sa(__libc.o):6008f20c A _opterr
+/usr/lib/libc.sa(__libc.o):6008f208 A _optind
+/usr/lib/libc.sa(__libc.o):6008f2e4 A _optopt
+/usr/lib/libc.sa(__libc.o):6008f218 A _ospeed
+/usr/lib/libc.sa(__libc.o):6008f26c A _re_max_failures
+/usr/lib/libc.sa(__libc.o):6008f210 A _re_syntax_options
+/usr/lib/libc.sa(__libc.o):6008f1e0 A _rexecoptions
+/usr/lib/libc.sa(__libc.o):6008f230 A _rpc_createerr
+/usr/lib/libc.sa(__libc.o):6008f25c A _stderr
+/usr/lib/libc.sa(__libc.o):6008f254 A _stdin
+/usr/lib/libc.sa(__libc.o):6008f258 A _stdout
+/usr/lib/libc.sa(__libc.o):6008f054 A _stdscr
+/usr/lib/libc.sa(__libc.o):6008f2e8 A _svc_fdset
+/usr/lib/libc.sa(__libc.o):6008f224 A _timezone
+/usr/lib/libc.sa(__libc.o):6008f21c A _tputs_baud_rate
+/usr/lib/libc.sa(__libc.o):6008f038 A _ttytype
+/usr/lib/libc.sa(__libc.o):6008f220 A _tzname
diff --git a/e2fslib/dll/jump.params b/e2fslib/dll/jump.params
new file mode 100644
index 0000000..d4d1b33
--- /dev/null
+++ b/e2fslib/dll/jump.params
@@ -0,0 +1,6 @@
+Name=libe2fs
+Text=0x66900000
+Data=0x00000000
+Jump=0x00001000
+GOT=0x00001000
+Version=1.2.0
diff --git a/e2fslib/dll/jump.undefs b/e2fslib/dll/jump.undefs
new file mode 100644
index 0000000..294a0b7
--- /dev/null
+++ b/e2fslib/dll/jump.undefs
@@ -0,0 +1,2 @@
+6690b080 D __NEEDS_SHRLIB_libc_4
+6690b098 D __NEEDS_SHRLIB_libet_1
diff --git a/e2fslib/dll/jump.vars b/e2fslib/dll/jump.vars
new file mode 100644
index 0000000..5f219d3
--- /dev/null
+++ b/e2fslib/dll/jump.vars
@@ -0,0 +1,6 @@
+00000004 D _unix_io_manager libext2fs unix_io
+00000004 D _test_io_manager libext2fs test_io
+00000004 D _test_io_backing_manager libext2fs test_io
+00000004 D _test_io_cb_read_blk libext2fs test_io
+00000004 D _test_io_cb_write_blk libext2fs test_io
+00000004 D _test_io_cb_set_blksize libext2fs test_io
diff --git a/e2fslib/dosio.c b/e2fslib/dosio.c
new file mode 100644
index 0000000..d695b18
--- /dev/null
+++ b/e2fslib/dosio.c
@@ -0,0 +1,456 @@
+/*
+ * dosio.c -- Disk I/O module for the ext2fs/DOS library.
+ *
+ * Copyright (c) 1997 by Theodore Ts'o.
+ *
+ * Copyright (c) 1997 Mark Habersack
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ */
+
+#include <stdio.h>
+#include <bios.h>
+#include <string.h>
+#include <ctype.h>
+#include <io.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <ext2fs/ext2_types.h>
+#include "utils.h"
+#include "dosio.h"
+#include "et/com_err.h"
+#include "ext2_err.h"
+#include "ext2fs/io.h"
+
+/*
+ * Some helper macros
+ */
+#define LINUX_EXT2FS 0x83
+#define LINUX_SWAP 0x82
+#define WRITE_ERR(_msg_) write(2, _msg_, strlen(_msg_))
+#define WRITE_ERR_S(_msg_) write(2, _msg_, sizeof(_msg_))
+
+/*
+ * Exported variables
+ */
+unsigned long _dio_error;
+unsigned long _dio_hw_error;
+
+/*
+ * Array of all opened partitions
+ */
+static PARTITION **partitions = NULL;
+static unsigned short npart = 0; /* Number of mapped partitions */
+static PARTITION *active = NULL;
+
+/*
+ * I/O Manager routine prototypes
+ */
+static errcode_t dos_open(const char *dev, int flags, io_channel *channel);
+static errcode_t dos_close(io_channel channel);
+static errcode_t dos_set_blksize(io_channel channel, int blksize);
+static errcode_t dos_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf);
+static errcode_t dos_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf);
+static errcode_t dos_flush(io_channel channel);
+
+static struct struct_io_manager struct_dos_manager = {
+ EXT2_ET_MAGIC_IO_MANAGER,
+ "DOS I/O Manager",
+ dos_open,
+ dos_close,
+ dos_set_blksize,
+ dos_read_blk,
+ dos_write_blk,
+ dos_flush
+};
+io_manager dos_io_manager = &struct_dos_manager;
+
+/*
+ * Macro taken from unix_io.c
+ */
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+ if ((struct)->magic != (code)) return (code)
+
+/*
+ * Calculates a CHS address of a sector from its LBA
+ * offset for the given partition.
+ */
+static void lba2chs(unsigned long lba_addr, CHS *chs, PARTITION *part)
+{
+ unsigned long abss;
+
+ chs->offset = lba_addr & 0x000001FF;
+ abss = (lba_addr >> 9) + part->start;
+ chs->cyl = abss / (part->sects * part->heads);
+ chs->head = (abss / part->sects) % part->heads;
+ chs->sector = (abss % part->sects) + 1;
+}
+
+#ifdef __TURBOC__
+#pragma argsused
+#endif
+/*
+ * Scans the passed partition table looking for *pno partition
+ * that has LINUX_EXT2FS type.
+ *
+ * TODO:
+ * For partition numbers >5 Linux uses DOS extended partitions -
+ * dive into them an return an appropriate entry. Also dive into
+ * extended partitions when scanning for a first Linux/ext2fs.
+ */
+static PTABLE_ENTRY *scan_partition_table(PTABLE_ENTRY *pentry,
+ unsigned short phys,
+ unsigned char *pno)
+{
+ unsigned i;
+
+ if(*pno != 0xFF && *pno >= 5)
+ return NULL; /* We don't support extended partitions for now */
+
+ if(*pno != 0xFF)
+ {
+ if(pentry[*pno].type == LINUX_EXT2FS)
+ return &pentry[*pno];
+ else
+ {
+ if(!pentry[*pno].type)
+ *pno = 0xFE;
+ else if(pentry[*pno].type == LINUX_SWAP)
+ *pno = 0xFD;
+ return NULL;
+ }
+ }
+
+ for(i = 0; i < 4; i++)
+ if(pentry[i].type == LINUX_EXT2FS)
+ {
+ *pno = i;
+ return &pentry[i];
+ }
+
+ return NULL;
+}
+
+/*
+ * Allocate libext2fs structures associated with I/O manager
+ */
+static io_channel alloc_io_channel(PARTITION *part)
+{
+ io_channel ioch;
+
+ ioch = (io_channel)malloc(sizeof(struct struct_io_channel));
+ if (!ioch)
+ return NULL;
+ memset(ioch, 0, sizeof(struct struct_io_channel));
+ ioch->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ ioch->manager = dos_io_manager;
+ ioch->name = (char *)malloc(strlen(part->dev)+1);
+ if (!ioch->name) {
+ free(ioch);
+ return NULL;
+ }
+ strcpy(ioch->name, part->dev);
+ ioch->private_data = part;
+ ioch->block_size = 1024; /* The smallest ext2fs block size */
+ ioch->read_error = 0;
+ ioch->write_error = 0;
+
+ return ioch;
+}
+
+#ifdef __TURBOC__
+#pragma argsused
+#endif
+/*
+ * Open the 'name' partition, initialize all information structures
+ * we need to keep and create libext2fs I/O manager.
+ */
+static errcode_t dos_open(const char *dev, int flags, io_channel *channel)
+{
+ unsigned char *tmp, sec[512];
+ PARTITION *part;
+ PTABLE_ENTRY *pent;
+ PARTITION **newparts;
+
+ if(!dev)
+ {
+ _dio_error = ERR_BADDEV;
+ return EXT2_ET_BAD_DEVICE_NAME;
+ }
+
+ /*
+ * First check whether the dev name is OK
+ */
+ tmp = (unsigned char*)strrchr(dev, '/');
+ if(!tmp)
+ {
+ _dio_error = ERR_BADDEV;
+ return EXT2_ET_BAD_DEVICE_NAME;
+ }
+ *tmp = 0;
+ if(strcmp(dev, "/dev"))
+ {
+ _dio_error = ERR_BADDEV;
+ return EXT2_ET_BAD_DEVICE_NAME;
+ }
+ *tmp++ = '/';
+
+ /*
+ * Check whether the partition data is already in cache
+ */
+
+ part = (PARTITION*)malloc(sizeof(PARTITION));
+ if (!part)
+ return ENOMEM;
+ {
+ int i = 0;
+
+ for(;i < npart; i++)
+ if(!strcmp(partitions[i]->dev, dev))
+ {
+ /* Found it! Make it the active one */
+ active = partitions[i];
+ *channel = alloc_io_channel(active);
+ if (!*channel)
+ return ENOMEM;
+ return 0;
+ }
+ }
+
+ /*
+ * Drive number & optionally partn number
+ */
+ switch(tmp[0])
+ {
+ case 'h':
+ case 's':
+ part->phys = 0x80;
+ part->phys += toupper(tmp[2]) - 'A';
+ /*
+ * Do we have the partition number?
+ */
+ if(tmp[3])
+ part->pno = isdigit((int)tmp[3]) ? tmp[3] - '0' - 1: 0;
+ else
+ part->pno = 0xFF;
+ break;
+
+ case 'f':
+ if(tmp[2])
+ part->phys = isdigit((int)tmp[2]) ? tmp[2] - '0' : 0;
+ else
+ part->phys = 0x00; /* We'll assume /dev/fd0 */
+ break;
+
+ default:
+ _dio_error = ERR_BADDEV;
+ return ENODEV;
+ }
+
+ if(part->phys < 0x80)
+ {
+ /* We don't support floppies for now */
+ _dio_error = ERR_NOTSUPP;
+ return EINVAL;
+ }
+
+ part->dev = strdup(dev);
+
+ /*
+ * Get drive's geometry
+ */
+ _dio_hw_error = biosdisk(DISK_GET_GEOMETRY,
+ part->phys,
+ 0, /* head */
+ 0, /* cylinder */
+ 1, /* sector */
+ 1, /* just one sector */
+ sec);
+
+ if(!HW_OK())
+ {
+ _dio_error = ERR_HARDWARE;
+ if (part)
+ free(part);
+ return EFAULT;
+ }
+
+ /*
+ * Calculate the geometry
+ */
+ part->cyls = (unsigned short)(((sec[0] >> 6) << 8) + sec[1] + 1);
+ part->heads = sec[3] + 1;
+ part->sects = sec[0] & 0x3F;
+
+ /*
+ * Now that we know all we need, let's look for the partition
+ */
+ _dio_hw_error = biosdisk(DISK_READ, part->phys, 0, 0, 1, 1, sec);
+
+ if(!HW_OK())
+ {
+ _dio_error = ERR_HARDWARE;
+ if (part)
+ free(part);
+ return EFAULT;
+ }
+
+ pent = (PTABLE_ENTRY*)&sec[0x1BE];
+ pent = scan_partition_table(pent, part->phys, &part->pno);
+
+ if(!pent)
+ {
+ _dio_error = part->pno == 0xFE ? ERR_EMPTYPART :
+ part->pno == 0xFD ? ERR_LINUXSWAP : ERR_NOTEXT2FS;
+ if (part)
+ free(part);
+ return ENODEV;
+ }
+
+ /*
+ * Calculate the remaining figures
+ */
+ {
+ unsigned long fsec, fhead, fcyl;
+
+ fsec = (unsigned long)(pent->start_sec & 0x3F);
+ fhead = (unsigned long)pent->start_head;
+ fcyl = ((pent->start_sec >> 6) << 8) + pent->start_cyl;
+ part->start = fsec + fhead * part->sects + fcyl *
+ (part->heads * part->sects) - 1;
+ part->len = pent->size;
+ }
+
+ /*
+ * Add the partition to the table
+ */
+ newparts = (PARTITION**)realloc(partitions, sizeof(PARTITION) * npart);
+ if (!newparts) {
+ free(part);
+ return ENOMEM;
+ }
+ partitions = newparts;
+ partitions[npart++] = active = part;
+
+ /*
+ * Now alloc all libe2fs structures
+ */
+ *channel = alloc_io_channel(active);
+ if (!*channel)
+ return ENOMEM;
+
+ return 0;
+}
+
+static errcode_t dos_close(io_channel channel)
+{
+ if (channel->name)
+ free(channel->name);
+ if (channel)
+ free(channel);
+
+ return 0;
+}
+
+static errcode_t dos_set_blksize(io_channel channel, int blksize)
+{
+ channel->block_size = blksize;
+
+ return 0;
+}
+
+static errcode_t dos_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ PARTITION *part;
+ size_t size;
+ ext2_loff_t loc;
+ CHS chs;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ part = (PARTITION*)channel->private_data;
+
+ size = (size_t)((count < 0) ? -count : count * channel->block_size);
+ loc = (ext2_loff_t) block * channel->block_size;
+
+ lba2chs(loc, &chs, part);
+ /*
+ * Potential bug here:
+ * If DJGPP is used then reads of >18 sectors will fail!
+ * Have to rewrite biosdisk.
+ */
+ _dio_hw_error = biosdisk(DISK_READ,
+ part->phys,
+ chs.head,
+ chs.cyl,
+ chs.sector,
+ size < 512 ? 1 : size/512,
+ buf);
+
+ if(!HW_OK())
+ {
+ _dio_error = ERR_HARDWARE;
+ return EFAULT;
+ }
+
+ return 0;
+}
+
+static errcode_t dos_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ PARTITION *part;
+ size_t size;
+ ext2_loff_t loc;
+ CHS chs;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ part = (PARTITION*)channel->private_data;
+
+ if(count == 1)
+ size = (size_t)channel->block_size;
+ else
+ {
+ if (count < 0)
+ size = (size_t)-count;
+ else
+ size = (size_t)(count * channel->block_size);
+ }
+
+ loc = (ext2_loff_t)block * channel->block_size;
+ lba2chs(loc, &chs, part);
+ _dio_hw_error = biosdisk(DISK_WRITE,
+ part->phys,
+ chs.head,
+ chs.cyl,
+ chs.sector,
+ size < 512 ? 1 : size/512,
+ (void*)buf);
+
+ if(!HW_OK())
+ {
+ _dio_error = ERR_HARDWARE;
+ return EFAULT;
+ }
+
+ return 0;
+}
+
+#ifdef __TURBOC__
+#pragma argsused
+#endif
+static errcode_t dos_flush(io_channel channel)
+{
+ /*
+ * No buffers, no flush...
+ */
+ return 0;
+}
diff --git a/e2fslib/dosio.h b/e2fslib/dosio.h
new file mode 100644
index 0000000..a0d652d
--- /dev/null
+++ b/e2fslib/dosio.h
@@ -0,0 +1,153 @@
+/*
+ * v1.0
+ *
+ * Disk I/O include file for the ext2fs/DOS library.
+ *
+ * Copyright (c) 1997 Mark Habersack
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ */
+#ifndef __diskio_h
+#define __diskio_h
+#ifdef __TURBOC__
+#ifndef __LARGE__
+# error "ext2fs/DOS library requires LARGE model!"
+#endif
+#endif
+
+#ifdef __TURBOC__
+#include "msdos.h"
+#endif
+
+/*
+ * A helper structure used in LBA => CHS conversion
+ */
+typedef struct
+{
+ unsigned short cyl; /* Cylinder (or track) */
+ unsigned short head;
+ unsigned short sector;
+ unsigned short offset; /* Offset of byte within the sector */
+} CHS;
+
+/*
+ * All partition data we need is here
+ */
+typedef struct
+{
+ char *dev; /* _Linux_ device name (like "/dev/hda1") */
+ unsigned char phys; /* Physical DOS drive number */
+ unsigned long start; /* LBA address of partition start */
+ unsigned long len; /* length of partition in sectors */
+ unsigned char pno; /* Partition number (read from *dev) */
+
+ /* This partition's drive geometry */
+ unsigned short cyls;
+ unsigned short heads;
+ unsigned short sects;
+} PARTITION;
+
+/*
+ * PC partition table entry format
+ */
+#ifdef __DJGPP__
+#pragma pack(1)
+#endif
+typedef struct
+{
+ unsigned char active;
+ unsigned char start_head;
+ unsigned char start_sec;
+ unsigned char start_cyl;
+ unsigned char type;
+ unsigned char end_head;
+ unsigned char end_sec;
+ unsigned char end_cyl;
+ unsigned long first_sec_rel;
+ unsigned long size;
+} PTABLE_ENTRY;
+#ifdef __DJGPP__
+#pragma pack()
+#endif
+
+/*
+ * INT 0x13 operation codes
+ */
+#define DISK_READ 0x02
+#define DISK_WRITE 0x03
+#define DISK_GET_GEOMETRY 0x08
+#define DISK_READY 0x10
+
+/*
+ * Errors to put in _dio_error
+ */
+#define ERR_BADDEV 0x00000001L
+#define ERR_HARDWARE 0x00000002L
+#define ERR_NOTSUPP 0x00000003L
+#define ERR_NOTEXT2FS 0x00000004L
+#define ERR_EMPTYPART 0x00000005L
+#define ERR_LINUXSWAP 0x00000006L
+
+/*
+ * Functions in diskio.c
+ */
+
+/*
+ * Variable contains last module's error
+ */
+extern unsigned long _dio_error;
+
+/*
+ * This one contains last hardware error (if _dio_error == ERR_HARDWARE)
+ */
+extern unsigned long _dio_hw_error;
+
+/*
+ * Macros to check for disk hardware errors
+ */
+#define HW_OK() ((unsigned char)_dio_hw_error == 0x00)
+#define HW_BAD_CMD() ((unsigned char)_dio_hw_error == 0x01)
+#define HW_NO_ADDR_MARK() ((unsigned char)_dio_hw_error == 0x02)
+#define HW_WRITE_PROT() ((unsigned char)_dio_hw_error == 0x03)
+#define HW_NO_SECTOR() ((unsigned char)_dio_hw_error == 0x04)
+#define HW_RESET_FAIL() ((unsigned char)_dio_hw_error == 0x05)
+#define HW_DISK_CHANGED() ((unsigned char)_dio_hw_error == 0x06)
+#define HW_DRIVE_FAIL() ((unsigned char)_dio_hw_error == 0x07)
+#define HW_DMA_OVERRUN() ((unsigned char)_dio_hw_error == 0x08)
+#define HW_DMA_BOUNDARY() ((unsigned char)_dio_hw_error == 0x09)
+#define HW_BAD_SECTOR() ((unsigned char)_dio_hw_error == 0x0A)
+#define HW_BAD_TRACK() ((unsigned char)_dio_hw_error == 0x0B)
+#define HW_UNSUPP_TRACK() ((unsigned char)_dio_hw_error == 0x0C)
+#define HW_BAD_CRC_ECC() ((unsigned char)_dio_hw_error == 0x10)
+#define HW_CRC_ECC_CORR() ((unsigned char)_dio_hw_error == 0x11)
+#define HW_CONTR_FAIL() ((unsigned char)_dio_hw_error == 0x20)
+#define HW_SEEK_FAIL() ((unsigned char)_dio_hw_error == 0x40)
+#define HW_ATTACH_FAIL() ((unsigned char)_dio_hw_error == 0x80)
+#define HW_DRIVE_NREADY() ((unsigned char)_dio_hw_error == 0xAA)
+#define HW_UNDEF_ERROR() ((unsigned char)_dio_hw_error == 0xBB)
+#define HW_WRITE_FAULT() ((unsigned char)_dio_hw_error == 0xCC)
+#define HW_STATUS_ERROR() ((unsigned char)_dio_hw_error == 0xE0)
+#define HW_SENSE_FAIL() ((unsigned char)_dio_hw_error == 0xFF)
+
+
+/*
+ * Open the specified partition.
+ * String 'dev' must have a format:
+ *
+ * /dev/{sd|hd|fd}[X]
+ *
+ * where,
+ *
+ * only one of the option in curly braces can be used and X is an optional
+ * partition number for the given device. If X is not specified, function
+ * scans the drive's partition table in search for the first Linux ext2fs
+ * partition (signature 0x83). Along the way it dives into every extended
+ * partition encountered.
+ * Scan ends if either (a) there are no more used partition entries, or
+ * (b) there is no Xth partition.
+ *
+ * Routine returns 0 on success and !=0 otherwise.
+ */
+int open_partition(char *dev);
+
+#endif /* __diskio_h */
diff --git a/e2fslib/dupfs.c b/e2fslib/dupfs.c
new file mode 100644
index 0000000..31579a4
--- /dev/null
+++ b/e2fslib/dupfs.c
@@ -0,0 +1,92 @@
+/*
+ * dupfs.c --- duplicate a ext2 filesystem handle
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <string.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
+{
+ ext2_filsys fs;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys),
+ (void **) &fs);
+ if (retval)
+ return retval;
+
+ *fs = *src;
+ fs->device_name = 0;
+ fs->super = 0;
+ fs->group_desc = 0;
+ fs->inode_map = 0;
+ fs->block_map = 0;
+ fs->badblocks = 0;
+ fs->dblist = 0;
+
+ io_channel_bumpcount(fs->io);
+ if (fs->icache)
+ fs->icache->refcount++;
+
+ retval = ext2fs_get_mem(strlen(src->device_name)+1,
+ (void **) &fs->device_name);
+ if (retval)
+ goto errout;
+ strcpy(fs->device_name, src->device_name);
+
+ retval = ext2fs_get_mem(SUPERBLOCK_SIZE, (void **) &fs->super);
+ if (retval)
+ goto errout;
+ memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
+
+ retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
+ (void **) &fs->group_desc);
+ if (retval)
+ goto errout;
+ memcpy(fs->group_desc, src->group_desc,
+ (size_t) fs->desc_blocks * fs->blocksize);
+
+ if (src->inode_map) {
+ retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
+ if (retval)
+ goto errout;
+ }
+ if (src->block_map) {
+ retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
+ if (retval)
+ goto errout;
+ }
+ if (src->badblocks) {
+ retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
+ if (retval)
+ goto errout;
+ }
+ if (src->dblist) {
+ retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
+ if (retval)
+ goto errout;
+ }
+ *dest = fs;
+ return 0;
+errout:
+ ext2fs_free(fs);
+ return retval;
+
+}
+
diff --git a/e2fslib/dupfs.o b/e2fslib/dupfs.o
new file mode 100644
index 0000000..e0e2738
--- /dev/null
+++ b/e2fslib/dupfs.o
Binary files differ
diff --git a/e2fslib/e2image.h b/e2fslib/e2image.h
new file mode 100644
index 0000000..e12b7d6
--- /dev/null
+++ b/e2fslib/e2image.h
@@ -0,0 +1,51 @@
+/*
+ * e2image.h --- header file describing the ext2 image format
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * Note: this uses the POSIX IO interfaces, unlike most of the other
+ * functions in this library. So sue me.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+struct ext2_image_hdr {
+ __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
+ char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
+ char fs_hostname[64];/* Hostname of machine of image */
+ char fs_netaddr[32]; /* Network address */
+ __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
+ __u32 fs_device; /* Device number of image */
+ char fs_device_name[64]; /* Device name */
+ char fs_uuid[16]; /* UUID of filesystem */
+ __u32 fs_blocksize; /* Block size of the filesystem */
+ __u32 fs_reserved[8];
+
+ __u32 image_device; /* Device number of image file */
+ __u32 image_inode; /* Inode number of image file */
+ __u32 image_time; /* Time of image creation */
+ __u32 image_reserved[8];
+
+ __u32 offset_super; /* Byte offset of the sb and descriptors */
+ __u32 offset_inode; /* Byte offset of the inode table */
+ __u32 offset_inodemap; /* Byte offset of the inode bitmaps */
+ __u32 offset_blockmap; /* Byte offset of the inode bitmaps */
+ __u32 offset_reserved[8];
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2fslib/e2p/e2p.h b/e2fslib/e2p/e2p.h
new file mode 100644
index 0000000..61d05f7
--- /dev/null
+++ b/e2fslib/e2p/e2p.h
@@ -0,0 +1,39 @@
+#include <sys/types.h> /* Needed by dirent.h on netbsd */
+#include <stdio.h>
+#include <dirent.h>
+
+#include <ext2_fs.h>
+
+#define E2P_FEATURE_COMPAT 0
+#define E2P_FEATURE_INCOMPAT 1
+#define E2P_FEATURE_RO_INCOMPAT 2
+
+
+/* `options' for print_flags() */
+
+#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
+
+
+int fgetflags (const char * name, unsigned long * flags);
+int fgetversion (const char * name, unsigned long * version);
+int fsetflags (const char * name, unsigned long flags);
+int fsetversion (const char * name, unsigned long version);
+int getflags (int fd, unsigned long * flags);
+int getversion (int fd, unsigned long * version);
+int iterate_on_dir (const char * dir_name,
+ int (*func) (const char *, struct dirent *, void *),
+ void * private);
+void list_super(struct ext2_super_block * s);
+void list_super2(struct ext2_super_block * s, FILE *f);
+void print_fs_errors (FILE * f, unsigned short errors);
+void print_flags (FILE * f, unsigned long flags, unsigned options);
+void print_fs_state (FILE * f, unsigned short state);
+int setflags (int fd, unsigned long flags);
+int setversion (int fd, unsigned long version);
+
+const char *e2p_feature2string(int compat, unsigned int mask);
+int e2p_string2feature(char *string, int *compat, unsigned int *mask);
+int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
+
+int e2p_is_null_uuid(void *uu);
+void e2p_uuid_to_str(void *uu, char *out);
diff --git a/e2fslib/et/.cvsignore b/e2fslib/et/.cvsignore
new file mode 100644
index 0000000..8526e03
--- /dev/null
+++ b/e2fslib/et/.cvsignore
@@ -0,0 +1 @@
+compile_et
diff --git a/e2fslib/et/ChangeLog b/e2fslib/et/ChangeLog
new file mode 100644
index 0000000..a8fec3c
--- /dev/null
+++ b/e2fslib/et/ChangeLog
@@ -0,0 +1,210 @@
+2001-09-20 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.25
+
+2001-09-16 Theodore Tso <tytso@valinux.com>
+
+ * compile_et.sh.in: Make the shell script safe from directory
+ pathnames with spaces.
+
+2001-09-10 Theodore Tso <tytso@valinux.com>
+
+ * com_err.texinfo: Add appropriate @node and @menu lines so that
+ the a valid .info file can be made. Use @deftypefun to
+ define functions. Change the e-mail address where bug
+ reports to be sent to be is the e2fsprogs maintainer.
+
+2001-09-02 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.24a
+
+2001-08-30 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.24
+
+2001-08-15 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.23
+
+2001-06-23 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.22
+
+2001-06-15 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.21
+
+2001-05-25 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.20
+
+2000-12-04 <tytso@snap.thunk.org>
+
+ * compile_et.1: Fix simple typo in the man page.
+
+2000-07-13 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.19
+
+2000-07-04 Theodore Ts'o <tytso@valinux.com>
+
+ * Makefile.in: Remove explicit link of -lc in the shared library.
+ (It shouldn't be necessary, and is harmful in some cases).
+
+1999-11-19 <tytso@valinux.com>
+
+ * Makefile.in (distclean): Remove TAGS and Makefile.in.old from
+ the source directory.
+
+1999-11-10 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.18
+
+1999-10-26 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.17
+
+1999-10-22 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.16
+
+1999-10-22 <tytso@valinux.com>
+
+ * com_err.3: Fix to have correct #include path for com_err.h
+
+1999-09-07 <tytso@rsts-11.mit.edu>
+
+ * Updated copyright statements with permission of the original
+ authors.
+
+1999-07-18 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.15
+
+1999-01-09 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.14
+
+1998-12-15 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.13
+
+1998-07-09 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.12
+
+1998-06-27 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * et_h.awk, et_c.awk: Work around libm bug on the ARM.
+
+1998-03-30 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in: Fix bug where my_dir was set incorrectly. Install
+ the et_c.awk and et_h.awk files in $(datadir)/et (i.e.,
+ /usr/share/et) directory. Change to use new
+ installation directory variables convention. Fix
+ uninstall rules to take $(DESTDIR) into account.
+
+ * compile_et.1: Change man page to reflect the fact that
+ compile_et is now a awk/sed script, not a yacc script.
+
+ * compile_et.sh.in: Look in $(datadir)/et for et_c.awk and
+ et_h.awk; if not found, look in the build directory. Add
+ error checking for non-existent input file.
+
+Fri Oct 31 01:14:41 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * et_c.awk, et_h.awk: Remove support for non STDC compilers, since
+ the workarounds caused problems with the header file.
+
+Sun Aug 10 09:40:54 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * error_table.h:
+ * et_name.c (error_table_name):
+ * error_message.c (error_message.c): Make code be 16-bit safe.
+
+Tue Jun 17 01:33:20 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.11
+
+Thu Apr 24 12:16:42 1997 Theodre Ts'o <tytso@localhost.mit.edu>
+
+ * Release of E2fsprogs version 1.10
+
+Thu Apr 17 12:23:38 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.09
+
+Fri Apr 11 18:56:26 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.08
+
+Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * Release of E2fsprogs version 1.07
+
+Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.06
+
+Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.05
+
+Thu May 16 11:12:30 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.04
+
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
+Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.02
+
+Mon Sep 4 21:44:47 1995 Remy Card <card@bbj>
+
+ * Makefile.in: Added support for BSD shared libraries.
+
+Sat Aug 12 03:11:28 1995 Remy Card <card@bbj>
+
+ * Makefile.in (install): Install static libraries in $(ulibdir)
+ (/usr/lib on Linux) instead of $(libdir) (/lib on Linux).
+
+Sat Aug 5 11:44:17 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * Makefile.in (DLL_INSTALL_DIR, ELF_INSTALL_DIR): Set the
+ installation directories correctly.
+
+Thu Jun 15 23:39:51 1995 Remy Card <card@bbj>
+
+ * Makefile.in: Added support for ELF shared libraries.
+ Fixed typos in the compilation rules.
+ (distclean): Added compile_et.sh.
+
+Sat Jun 10 19:56:13 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
+
+ * compile_et.sh.in: Use ET_DIR instead of srcdir to determine the
+ location of the et directory.
+
+Thu Jun 8 12:45:41 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * vfprintf.c (vfprintf): Only compile this function if vfprintf
+ doesn't already exist and _doprnt does.
+
+ * compile_et.sh: Moved to compile_et.sh.in.
+
+ * Makefile.in: Rewritten to conform to GNU coding standards and
+ support separate compilation directories.
+ Don't preprocess compile_et.sh, as this is now done by configure.
+
+Mon Nov 7 21:17:48 1994 Remy Card <card@bbj>
+
+ * Makefile: Added a dummy install target in case shared libraries
+ are not built.
+
+Thu Sep 8 22:33:33 1994 (tytso@rsx-11)
+
+ * com_err.c (default_com_err_proc): Reversed order of \n\r to make
+ jik happy.
diff --git a/e2fslib/et/Makefile b/e2fslib/et/Makefile
new file mode 100644
index 0000000..79b6ca7
--- /dev/null
+++ b/e2fslib/et/Makefile
@@ -0,0 +1,334 @@
+# Generated automatically from Makefile.in by configure.
+#
+# Makefile for lib/et
+#
+
+srcdir = .
+top_srcdir = ../..
+top_builddir = ../..
+my_dir = lib/et
+INSTALL = /usr/bin/install -c
+
+DEP_MAKEFILE = $(DEP_LIB_MAKEFILES)
+
+
+# Beginning of file MCONFIG
+
+all::
+
+check::
+
+SHELL = /bin/sh
+
+prefix = /usr
+root_prefix =
+exec_prefix = ${prefix}
+root_bindir = $(root_prefix)/bin
+root_sbindir = $(root_prefix)/sbin
+root_libdir = $(root_prefix)/lib
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+mandir = ${prefix}/man
+man1dir = $(mandir)/man1
+man3dir = $(mandir)/man3
+man8dir = $(mandir)/man8
+infodir = ${prefix}/info
+datadir = ${prefix}/share
+
+
+
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+CC = cc
+BUILD_CC = cc
+DEFS = -DENABLE_SWAPFS=1 -DPACKAGE=\"e2fsprogs\" -DVERSION=\"1.25\" -DSTDC_HEADERS=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_ARGZ_H=1 -DHAVE_LIMITS_H=1 -DHAVE_LOCALE_H=1 -DHAVE_NL_TYPES_H=1 -DHAVE_MALLOC_H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_GETCWD=1 -DHAVE_MUNMAP=1 -DHAVE_PUTENV=1 -DHAVE_SETENV=1 -DHAVE_SETLOCALE=1 -DHAVE_STRCHR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRDUP=1 -DHAVE___ARGZ_COUNT=1 -DHAVE___ARGZ_STRINGIFY=1 -DHAVE___ARGZ_NEXT=1 -DHAVE_STPCPY=1 -DHAVE_STPCPY=1 -DHAVE_LC_MESSAGES=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1 -DHAVE_ERRNO_H=1 -DHAVE_MALLOC_H=1 -DHAVE_MNTENT_H=1 -DHAVE_PATHS_H=1 -DHAVE_DIRENT_H=1 -DHAVE_GETOPT_H=1 -DHAVE_SETJMP_H=1 -DHAVE_SIGNAL_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_LINUX_FD_H=1 -DHAVE_LINUX_MAJOR_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_MOUNT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_NET_IF_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_VPRINTF=1 -DHAVE_LSEEK64_PROTOTYPE=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DWORDS_BIGENDIAN=1 -DHAVE_GETRUSAGE=1 -DHAVE_LLSEEK=1 -DHAVE_LSEEK64=1 -DHAVE_OPEN64=1 -DHAVE_STRCASECMP=1 -DHAVE_SRANDOM=1 -DHAVE_FCHOWN=1 -DHAVE_MALLINFO=1 -DHAVE_FDATASYNC=1 -DHAVE_STRNLEN=1 -DHAVE_EXT2_IOCTLS=1
+CFLAGS = -g -O2
+CPPFLAGS =
+ALL_CFLAGS = $(CPPFLAGS) $(DEFS) $(USE_WFLAGS) $(CFLAGS) $(XTRA_CFLAGS) \
+ -I$(top_builddir)/lib -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/include $(LINUX_INCLUDE)
+LDFLAGS =
+ALL_LDFLAGS = $(LDFLAGS)
+RM = /bin/rm
+LN = /bin/ln
+LN_S = ln -s
+MV = /bin/mv
+CP = /bin/cp
+CHMOD = /bin/chmod
+AR = ar
+AWK = /usr/bin/awk
+SED = /bin/sed
+PERL = /usr/bin/perl
+RANLIB = ranlib
+STRIP = strip
+LD = $(PURE) cc
+ARUPD = $(AR) r
+LDCONFIG = :
+
+#
+# Library definitions
+#
+LIB = $(top_builddir)/lib
+LIBSS = $(LIB)/libss.a
+LIBCOM_ERR = $(LIB)/libcom_err.a
+LIBE2P = $(LIB)/libe2p.a
+LIBEXT2FS = $(LIB)/libext2fs.a
+LIBUUID = $(LIB)/libuuid.a
+DEPLIBUUID = $(LIB)/libuuid.a
+
+STATIC_LIBSS = $(LIB)/libss.a
+STATIC_LIBCOM_ERR = $(LIB)/libcom_err.a
+STATIC_LIBE2P = $(LIB)/libe2p.a
+STATIC_LIBEXT2FS = $(LIB)/libext2fs.a
+STATIC_LIBUUID = $(LIB)/libuuid.a
+DEPSTATIC_LIBUUID = $(LIB)/libuuid.a
+
+PROFILED_LIBSS = $(LIB)/libss
+PROFILED_LIBCOM_ERR = $(LIB)/libcom_err
+PROFILED_LIBE2P = $(LIB)/libe2p
+PROFILED_LIBEXT2FS = $(LIB)/libext2fs
+PROFILED_LIBUUID = $(LIB)/libuuid
+DEPPROFILED_LIBUUID = $(LIB)/libuuid
+
+#
+# Use these definitions is you use tools 2.x, x < 16
+#
+#DLL_BIN=/usr/dll/bin
+#JUMP_PREFIX=/usr/dll/jump/
+
+#
+# Use these definitions if you use tools 2.16 or above
+#
+DLL_BIN=/usr/bin
+JUMP_PREFIX=/usr/bin/jump
+
+# An include directive pointing to a directory holding enough linux-like
+# include files to satisfy some programs here
+LINUX_INCLUDE=
+
+#
+# A fast substitution command for fixing up man pages, shell scripts, etc.
+#
+SUBST_CONF=../util/subst.conf
+SUBSTITUTE= ../util/subst -f $(SUBST_CONF)
+DEP_SUBSTITUTE= ../util/subst $(SUBST_CONF)
+
+$(top_builddir)/util/subst:
+ cd $(top_builddir)/util ; $(MAKE) subst
+
+#
+# Warning flags
+#
+# Run make gcc-wall to do a build with warning messages.
+#
+#
+WFLAGS= -ansi -D_POSIX_SOURCE -pedantic \
+ -Wall -Wwrite-strings -Wpointer-arith \
+ -Wcast-qual -Wcast-align -Wtraditional \
+ -Wstrict-prototypes -Wmissing-prototypes \
+ -Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow
+
+gcc-wall-new:
+ (make USE_WFLAGS="$(WFLAGS)" > /dev/null) 2>&1 | sed -f $(top_srcdir)/util/gcc-wall-cleanup
+
+gcc-wall:
+ make clean > /dev/null
+ make gcc-wall-new
+
+#
+# Installation user and groups
+#
+BINGRP= bin
+BINOWN= bin
+BINMODE= 555
+INCGRP= bin
+INCOWN= bin
+INCMODE= 444
+LIBOWN= bin
+LIBGRP= bin
+LIBMODE= 444
+MANGRP= bin
+MANOWN= bin
+MANMODE= 444
+
+#
+# Autoconf magic...
+#
+
+DEP_LIB_MAKEFILES = $(top_srcdir)/lib/Makefile.elf-lib \
+ $(top_srcdir)/lib/Makefile.dll-lib $(top_srcdir)/lib/Makefile.bsd-lib \
+ $(top_srcdir)/lib/Makefile.checker $(top_srcdir)/lib/Makefile.profile
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir); ./config.status --recheck
+
+$(top_builddir)/lib/substitute_sh: $(top_srcdir)/lib/substitute_sh.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=lib/substitute_sh ./config.status
+
+$(top_builddir)/util/subst.conf: $(top_srcdir)/util/subst.conf.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=util/subst.conf ./config.status
+
+$(top_srcdir)/configure: $(top_srcdir)/configure.in
+ cd $(top_srcdir) && autoconf
+
+#
+# Make depend magic...
+#
+
+.depend: Makefile $(SRCS) $(top_srcdir)/depfix.sed $(top_srcdir)/wordwrap.pl
+ if test -n "$(SRCS)" ; then \
+ $(CC) -M $(ALL_CFLAGS) $(SRCS) | \
+ $(SED) -f $(top_srcdir)/depfix.sed \
+ -e 's; $(srcdir)/; $$(srcdir)/;g' \
+ -e 's; $(top_srcdir)/; $$(top_srcdir)/;g' \
+ -e 's; $(top_builddir)/; $$(top_builddir)/;g' \
+ -e 's; \./; ;g' \
+ -e '/^ *\\$$/d' | \
+ $(PERL) $(top_srcdir)/wordwrap.pl > .depend; \
+ else :; fi
+
+depend:: .depend
+ if test -n "$(SRCS)" ; then \
+ sed -e '/^# +++ Dependency line eater +++/,$$d' \
+ < $(srcdir)/Makefile.in | cat - .depend \
+ > $(srcdir)/Makefile.in.new; \
+ if cmp -s $(srcdir)/Makefile.in $(srcdir)/Makefile.in.new ; then \
+ $(RM) $(srcdir)/Makefile.in.new ; \
+ else \
+ $(MV) $(srcdir)/Makefile.in $(srcdir)/Makefile.in.old; \
+ $(MV) $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in; \
+ fi ; else :; fi
+
+# End of file MCONFIG
+
+all:: compile_et
+
+OBJS= error_message.o et_name.o init_et.o com_err.o
+SRCS = $(srcdir)/error_message.c $(srcdir)/et_name.c $(srcdir)/init_et.c \
+ $(srcdir)/com_err.c
+
+HFILES= com_err.h
+SHARE_FILES= et_c.awk et_h.awk
+
+LIBRARY= libcom_err
+LIBDIR= et
+
+DLL_ADDRESS = 0x66800000
+DLL_JUMPSIZE = 0x1000
+DLL_GOTSIZE = 0x1000
+DLL_VERSION = 1.0
+DLL_IMAGE = libet
+DLL_STUB = libcom_err
+DLL_MYDIR = et
+DLL_INSTALL_DIR = $(root_libdir)
+
+ELF_VERSION = 2.0
+ELF_SO_VERSION = 2
+ELF_IMAGE = libcom_err
+ELF_MYDIR = et
+ELF_INSTALL_DIR = $(root_libdir)
+ELF_OTHER_LIBS =
+
+BSDLIB_VERSION = 1.0
+BSDLIB_IMAGE = libcom_err
+BSDLIB_MYDIR = et
+BSDLIB_INSTALL_DIR = $(root_libdir)
+
+#
+# what to build...
+#
+.c.o:
+ $(CC) $(ALL_CFLAGS) -c $< -o $@
+# $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
+# $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
+# (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
+# -o jump/$*.o -c $<)
+# $(CC) $(ALL_CFLAGS) -fPIC -o elfshared/$*.o -c $<
+# $(CC) $(ALL_CFLAGS) -fpic -o pic/$*.o -c $<
+
+
+all:: subdirs $(LIBRARY).a
+
+install-shlibs::
+
+subdirs::
+
+$(LIBRARY).a: $(OBJS)
+ (if test -r $@; then $(RM) -f $@.bak && $(MV) $@ $@.bak; fi)
+ $(ARUPD) $@ $(OBJS)
+ -$(RANLIB) $@
+ $(RM) -f ../$@
+ $(LN) $@ ../$@
+
+
+
+
+
+
+
+compile_et: $(DEP_SUBSTITUTE) $(srcdir)/compile_et.sh.in
+ $(SUBSTITUTE) $(srcdir)/compile_et.sh.in compile_et
+ $(CHMOD) +x compile_et
+
+com_err.ps : com_err.dvi
+com_err.dvi: com_err.texinfo
+
+#libcom_err.o: $(LIBOBJS)
+# $(LD) -r -s -o libcom_err.o $(LIBOBJS)
+# chmod -x libcom_err.o
+
+TAGS: $(SRCS)
+ $(TAGS) $(SRCS)
+
+installdirs::
+ $(top_srcdir)/mkinstalldirs $(DESTDIR)$(libdir) \
+ $(DESTDIR)$(includedir)/et $(DESTDIR)$(datadir)/et \
+ $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) \
+ $(DESTDIR)$(man3dir)
+
+install:: compile_et libcom_err.a $(HFILES) installdirs
+ $(INSTALL_DATA) libcom_err.a $(DESTDIR)$(libdir)/libcom_err.a
+ $(CHMOD) 644 $(DESTDIR)$(libdir)/libcom_err.a
+ -$(RANLIB) $(DESTDIR)$(libdir)/libcom_err.a
+ $(CHMOD) $(LIBMODE) $(DESTDIR)$(libdir)/libcom_err.a
+ for i in $(HFILES); do \
+ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir)/et/$$i; \
+ done
+ for i in $(SHARE_FILES); do \
+ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(datadir)/et/$$i; \
+ done
+ $(INSTALL) compile_et $(DESTDIR)$(bindir)/compile_et
+ $(INSTALL_DATA) $(srcdir)/com_err.3 $(DESTDIR)$(man3dir)/com_err.3
+ $(INSTALL_DATA) $(srcdir)/compile_et.1 \
+ $(DESTDIR)$(man1dir)/compile_et.1
+
+uninstall::
+ $(RM) -f $(DESTDIR)$(libdir)/libcom_err.a \
+ $(DESTDIR)$(bindir)/compile_et
+ $(RM) -rf $(DESTDIR)$(includedir)/et $(DESTDIR)$(datadir)/et
+
+clean::
+ $(RM) -f compile_et libcom_err.a libcom_err_p.a
+ $(RM) -f $(OBJS) profiled/*
+ $(RM) -f *~ \#* *.bak *.otl *.aux *.toc *.PS *.dvi *.ps TAGS *.ln
+ $(RM) -f ../libcom_err.a ../libcom_err_p.a
+mostlyclean:: clean
+distclean:: clean
+ $(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+error_message.o: $(srcdir)/error_message.c $(srcdir)/com_err.h \
+ $(srcdir)/error_table.h $(srcdir)/internal.h
+et_name.o: $(srcdir)/et_name.c $(srcdir)/com_err.h $(srcdir)/error_table.h \
+ $(srcdir)/internal.h
+init_et.o: $(srcdir)/init_et.c $(srcdir)/com_err.h $(srcdir)/error_table.h
+com_err.o: $(srcdir)/com_err.c $(srcdir)/com_err.h $(srcdir)/error_table.h \
+ $(srcdir)/internal.h
diff --git a/e2fslib/et/Makefile.in b/e2fslib/et/Makefile.in
new file mode 100644
index 0000000..4a9e538
--- /dev/null
+++ b/e2fslib/et/Makefile.in
@@ -0,0 +1,129 @@
+#
+# Makefile for lib/et
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ../..
+my_dir = lib/et
+INSTALL = @INSTALL@
+
+DEP_MAKEFILE = $(DEP_LIB_MAKEFILES)
+
+@MCONFIG@
+
+all:: compile_et
+
+OBJS= error_message.o et_name.o init_et.o com_err.o
+SRCS = $(srcdir)/error_message.c $(srcdir)/et_name.c $(srcdir)/init_et.c \
+ $(srcdir)/com_err.c
+
+HFILES= com_err.h
+SHARE_FILES= et_c.awk et_h.awk
+
+LIBRARY= libcom_err
+LIBDIR= et
+
+DLL_ADDRESS = 0x66800000
+DLL_JUMPSIZE = 0x1000
+DLL_GOTSIZE = 0x1000
+DLL_VERSION = 1.0
+DLL_IMAGE = libet
+DLL_STUB = libcom_err
+DLL_MYDIR = et
+DLL_INSTALL_DIR = $(root_libdir)
+
+ELF_VERSION = 2.0
+ELF_SO_VERSION = 2
+ELF_IMAGE = libcom_err
+ELF_MYDIR = et
+ELF_INSTALL_DIR = $(root_libdir)
+ELF_OTHER_LIBS =
+
+BSDLIB_VERSION = 1.0
+BSDLIB_IMAGE = libcom_err
+BSDLIB_MYDIR = et
+BSDLIB_INSTALL_DIR = $(root_libdir)
+
+#
+# what to build...
+#
+.c.o:
+ $(CC) $(ALL_CFLAGS) -c $< -o $@
+@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
+@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
+@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
+@DLL_CMT@ -o jump/$*.o -c $<)
+@ELF_CMT@ $(CC) $(ALL_CFLAGS) -fPIC -o elfshared/$*.o -c $<
+@BSDLIB_CMT@ $(CC) $(ALL_CFLAGS) -fpic -o pic/$*.o -c $<
+
+@MAKEFILE_LIBRARY@
+@MAKEFILE_DLL@
+@MAKEFILE_ELF@
+@MAKEFILE_BSDLIB@
+@MAKEFILE_PROFILE@
+@MAKEFILE_CHECKER@
+
+compile_et: $(DEP_SUBSTITUTE) $(srcdir)/compile_et.sh.in
+ $(SUBSTITUTE) $(srcdir)/compile_et.sh.in compile_et
+ $(CHMOD) +x compile_et
+
+com_err.ps : com_err.dvi
+com_err.dvi: com_err.texinfo
+
+#libcom_err.o: $(LIBOBJS)
+# $(LD) -r -s -o libcom_err.o $(LIBOBJS)
+# chmod -x libcom_err.o
+
+TAGS: $(SRCS)
+ $(TAGS) $(SRCS)
+
+installdirs::
+ $(top_srcdir)/mkinstalldirs $(DESTDIR)$(libdir) \
+ $(DESTDIR)$(includedir)/et $(DESTDIR)$(datadir)/et \
+ $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) \
+ $(DESTDIR)$(man3dir)
+
+install:: compile_et libcom_err.a $(HFILES) installdirs
+ $(INSTALL_DATA) libcom_err.a $(DESTDIR)$(libdir)/libcom_err.a
+ $(CHMOD) 644 $(DESTDIR)$(libdir)/libcom_err.a
+ -$(RANLIB) $(DESTDIR)$(libdir)/libcom_err.a
+ $(CHMOD) $(LIBMODE) $(DESTDIR)$(libdir)/libcom_err.a
+ for i in $(HFILES); do \
+ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir)/et/$$i; \
+ done
+ for i in $(SHARE_FILES); do \
+ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(datadir)/et/$$i; \
+ done
+ $(INSTALL) compile_et $(DESTDIR)$(bindir)/compile_et
+ $(INSTALL_DATA) $(srcdir)/com_err.3 $(DESTDIR)$(man3dir)/com_err.3
+ $(INSTALL_DATA) $(srcdir)/compile_et.1 \
+ $(DESTDIR)$(man1dir)/compile_et.1
+
+uninstall::
+ $(RM) -f $(DESTDIR)$(libdir)/libcom_err.a \
+ $(DESTDIR)$(bindir)/compile_et
+ $(RM) -rf $(DESTDIR)$(includedir)/et $(DESTDIR)$(datadir)/et
+
+clean::
+ $(RM) -f compile_et libcom_err.a libcom_err_p.a
+ $(RM) -f $(OBJS) profiled/*
+ $(RM) -f *~ \#* *.bak *.otl *.aux *.toc *.PS *.dvi *.ps TAGS *.ln
+ $(RM) -f ../libcom_err.a ../libcom_err_p.a
+mostlyclean:: clean
+distclean:: clean
+ $(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+error_message.o: $(srcdir)/error_message.c $(srcdir)/com_err.h \
+ $(srcdir)/error_table.h $(srcdir)/internal.h
+et_name.o: $(srcdir)/et_name.c $(srcdir)/com_err.h $(srcdir)/error_table.h \
+ $(srcdir)/internal.h
+init_et.o: $(srcdir)/init_et.c $(srcdir)/com_err.h $(srcdir)/error_table.h
+com_err.o: $(srcdir)/com_err.c $(srcdir)/com_err.h $(srcdir)/error_table.h \
+ $(srcdir)/internal.h
diff --git a/e2fslib/et/com_err.c b/e2fslib/et/com_err.c
new file mode 100644
index 0000000..81a70cf
--- /dev/null
+++ b/e2fslib/et/com_err.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 1987, 1988 by MIT Student Information Processing Board.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <stdio.h>
+#include "com_err.h"
+#include "error_table.h"
+#include "internal.h"
+
+#if !defined(__STDC__) && !defined(STDARG_PROTOTYPES)
+#include <varargs.h>
+#define VARARGS
+#endif
+
+static void
+#ifdef __STDC__
+ default_com_err_proc (const char *whoami, errcode_t code, const
+ char *fmt, va_list args)
+#else
+ default_com_err_proc (whoami, code, fmt, args)
+ const char *whoami;
+ errcode_t code;
+ const char *fmt;
+ va_list args;
+#endif
+{
+ if (whoami) {
+ fputs(whoami, stderr);
+ fputs(": ", stderr);
+ }
+ if (code) {
+ fputs(error_message(code), stderr);
+ fputs(" ", stderr);
+ }
+ if (fmt) {
+ vfprintf (stderr, fmt, args);
+ }
+ /* should do this only on a tty in raw mode */
+ putc('\r', stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+}
+
+#ifdef __STDC__
+typedef void (*errf) (const char *, errcode_t, const char *, va_list);
+#else
+typedef void (*errf) ();
+#endif
+
+errf com_err_hook = default_com_err_proc;
+
+#ifdef __STDC__
+void com_err_va (const char *whoami, errcode_t code, const char *fmt,
+ va_list args)
+#else
+void com_err_va (whoami, code, fmt, args)
+ const char *whoami;
+ errcode_t code;
+ const char *fmt;
+ va_list args;
+#endif
+{
+ (*com_err_hook) (whoami, code, fmt, args);
+}
+
+#ifndef VARARGS
+void com_err (const char *whoami,
+ errcode_t code,
+ const char *fmt, ...)
+{
+#else
+void com_err (va_alist)
+ va_dcl
+{
+ const char *whoami, *fmt;
+ errcode_t code;
+#endif
+ va_list pvar;
+
+ if (!com_err_hook)
+ com_err_hook = default_com_err_proc;
+#ifdef VARARGS
+ va_start (pvar);
+ whoami = va_arg (pvar, const char *);
+ code = va_arg (pvar, errcode_t);
+ fmt = va_arg (pvar, const char *);
+#else
+ va_start(pvar, fmt);
+#endif
+ com_err_va (whoami, code, fmt, pvar);
+ va_end(pvar);
+}
+
+errf set_com_err_hook (new_proc)
+ errf new_proc;
+{
+ errf x = com_err_hook;
+
+ if (new_proc)
+ com_err_hook = new_proc;
+ else
+ com_err_hook = default_com_err_proc;
+
+ return x;
+}
+
+errf reset_com_err_hook () {
+ errf x = com_err_hook;
+ com_err_hook = default_com_err_proc;
+ return x;
+}
diff --git a/e2fslib/et/com_err.h b/e2fslib/et/com_err.h
new file mode 100644
index 0000000..f28dce8
--- /dev/null
+++ b/e2fslib/et/com_err.h
@@ -0,0 +1,40 @@
+/*
+ * Header file for common error description library.
+ *
+ * Copyright 1988, Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * For copyright and distribution info, see the documentation supplied
+ * with this package.
+ */
+
+#ifndef __COM_ERR_H
+
+typedef long errcode_t;
+
+#ifdef __STDC__
+#include <stdarg.h>
+
+/* ANSI C -- use prototypes etc */
+void com_err (const char *, long, const char *, ...);
+void com_err_va (const char *whoami, errcode_t code, const char *fmt,
+ va_list args);
+char const *error_message (long);
+extern void (*com_err_hook) (const char *, long, const char *, va_list);
+void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
+ (const char *, long, const char *, va_list);
+void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
+int init_error_table(const char * const *msgs, int base, int count);
+#else
+/* no prototypes */
+void com_err ();
+void com_err_va ();
+char *error_message ();
+extern void (*com_err_hook) ();
+void (*set_com_err_hook ()) ();
+void (*reset_com_err_hook ()) ();
+int init_error_table();
+#endif
+
+#define __COM_ERR_H
+#endif /* ! defined(__COM_ERR_H) */
diff --git a/e2fslib/et/com_err.o b/e2fslib/et/com_err.o
new file mode 100644
index 0000000..f851d2d
--- /dev/null
+++ b/e2fslib/et/com_err.o
Binary files differ
diff --git a/e2fslib/et/com_err.texinfo b/e2fslib/et/com_err.texinfo
new file mode 100644
index 0000000..6ca745d
--- /dev/null
+++ b/e2fslib/et/com_err.texinfo
@@ -0,0 +1,579 @@
+\input texinfo @c -*-texinfo-*-
+
+@c $Header: /home/cvs/arcboot/e2fslib/et/com_err.texinfo,v 1.1 2004/11/29 10:39:38 ladis Exp $
+@c $Source: /home/cvs/arcboot/e2fslib/et/com_err.texinfo,v $
+@c $Locker: $
+
+@c Note that although this source file is in texinfo format (more
+@c or less), it is not yet suitable for turning into an ``info''
+@c file. Sorry, maybe next time.
+@c
+@c In order to produce hardcopy documentation from a texinfo file,
+@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
+@c provided in this distribution. (texinfo.tex is from the Free
+@c Software Foundation, and is under different copyright restrictions
+@c from the rest of this package.)
+
+@setfilename com_err
+@settitle A Common Error Description Library for UNIX
+
+@ifinfo
+@dircategory Development
+@format
+START-INFO-DIR-ENTRY
+* com_err: (com_err.info). A Common Error Description Library for UNIX.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@iftex
+@tolerance 10000
+
+@c Mutate section headers...
+@begingroup
+ @catcode#=6
+ @gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
+@endgroup
+@end iftex
+
+@ifinfo
+This file documents the use of the Common Error Description library.
+
+Copyright (C) 1987, 1988 Student Information Processing Board of the
+Massachusetts Institute of Technology.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+
+Note that the file texinfo.tex, provided with this distribution, is from
+the Free Software Foundation, and is under different copyright restrictions
+from the remainder of this package.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+
+@setchapternewpage odd
+
+@titlepage
+@center @titlefont{A Common Error Description}
+@center @titlefont{Library for UNIX}
+@sp 2
+@center Ken Raeburn
+@center Bill Sommerfeld
+@sp 1
+@center MIT Student Information Processing Board
+@sp 3
+@center last updated 1 January 1989
+@center for version 1.2
+@center ***DRAFT COPY ONLY***
+
+@vskip 2in
+
+@center @b{Abstract}
+
+UNIX has always had a clean and simple system call interface, with a
+standard set of error codes passed between the kernel and user
+programs. Unfortunately, the same cannot be said of many of the
+libraries layered on top of the primitives provided by the kernel.
+Typically, each one has used a different style of indicating errors to
+their callers, leading to a total hodgepodge of error handling, and
+considerable amounts of work for the programmer. This paper describes
+a library and associated utilities which allows a more uniform way for
+libraries to return errors to their callers, and for programs to
+describe errors and exceptional conditions to their users.
+
+@page
+@vskip 0pt plus 1filll
+
+Copyright @copyright{} 1987, 1988 by the Student Information Processing
+Board of the Massachusetts Institute of Technology.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+
+Note that the file texinfo.tex, provided with this distribution, is from
+the Free Software Foundation, and is under different copyright restrictions
+from the remainder of this package.
+
+@end titlepage
+
+
+@node Top, Why com_err?, (dir), (dir)
+
+@top A Common Error Description Library for UNIX
+
+This manual documents the com_err library.
+
+@menu
+* Why com_err?::
+* Error codes::
+* Error table source file::
+* The error-table compiler::
+* Run-time support routines::
+* Coding Conventions::
+* Building and Installation::
+* Bug Reports::
+* Acknowledgements::
+@end menu
+
+@end ifinfo
+
+@page
+
+@node Why com_err?, Error codes, Top, Top
+@section Why com_err?
+
+In building application software packages, a programmer often has to
+deal with a number of libraries, each of which can use a different
+error-reporting mechanism. Sometimes one of two values is returned,
+indicating simply SUCCESS or FAILURE, with no description of errors
+encountered. Sometimes it is an index into a table of text strings,
+where the name of the table used is dependent on the library being
+used when the error is generated; since each table starts numbering at
+0 or 1, additional information as to the source of the error code is
+needed to determine which table to look at. Sometimes no text messages are
+supplied at all, and the programmer must supply them at any point at which
+he may wish to report error conditions.
+Often, a global variable is assigned some value describing the error, but
+the programmer has to know in each case whether to look at @code{errno},
+@code{h_errno}, the return value from @code{hes_err()}, or whatever other
+variables or routines are specified.
+And what happens if something
+in the procedure of
+examining or reporting the error changes the same variable?
+
+The package we have developed is an attempt to present a common
+error-handling mechanism to manipulate the most common form of error code
+in a fashion that does not have the problems listed above.
+
+A list of up to 256 text messages is supplied to a translator we have
+written, along with the three- to four-character ``name'' of the error
+table. The library using this error table need only call a routine
+generated from this error-table source to make the table ``known'' to the
+com_err library, and any error code the library generates can be converted
+to the corresponding error message. There is also a default format for
+error codes accidentally returned before making the table known, which is
+of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
+of the table.
+
+@node Error codes, Error table source file, Why com_err?, Top
+@section Error codes
+
+Error codes themselves are 32 bit (signed) integers, of which the high
+order 24 bits are an identifier of which error table the error code is
+from, and the low order 8 bits are a sequential error number within
+the table. An error code may thus be easily decomposed into its component
+parts. Only the lowest 32 bits of an error code are considered significant
+on systems which support wider values.
+
+Error table 0 is defined to match the UNIX system call error table
+(@code{sys_errlist}); this allows @code{errno} values to be used directly
+in the library (assuming that @code{errno} is of a type with the same width
+as @t{long}). Other error table numbers are formed by compacting together
+the first four characters of the error table name. The mapping between
+characters in the name and numeric values in the error code are defined in
+a system-independent fashion, so that two systems that can pass integral
+values between them can reliably pass error codes without loss of meaning;
+this should work even if the character sets used are not the same.
+(However, if this is to be done, error table 0 should be avoided, since the
+local system call error tables may differ.)
+
+Any variable which is to contain an error code should be declared @t{long}.
+The draft proposed American National Standard for C (as of May, 1988)
+requires that @t{long} variables be at least 32 bits; any system which does
+not support 32-bit @t{long} values cannot make use of this package (nor
+much other software that assumes an ANSI-C environment base) without
+significant effort.
+
+@node Error table source file, The error-table compiler, Error codes, Top
+@section Error table source file
+
+The error table source file begins with the declaration of the table name,
+as
+
+@example
+error_table @var{tablename}
+@end example
+
+Individual error codes are
+specified with
+
+@example
+error_code @var{ERROR_NAME}, @var{"text message"}
+@end example
+
+where @samp{ec} can also be used as a short form of @samp{error_code}. To
+indicate the end of the table, use @samp{end}. Thus, a (short) sample
+error table might be:
+
+@example
+
+ error_table dsc
+
+ error_code DSC_DUP_MTG_NAME,
+ "Meeting already exists"
+
+ ec DSC_BAD_PATH,
+ "A bad meeting pathname was given"
+
+ ec DSC_BAD_MODES,
+ "Invalid mode for this access control list"
+
+ end
+
+@end example
+
+@node The error-table compiler, Run-time support routines, Error table source file, Top
+@section The error-table compiler
+
+The error table compiler is named @code{compile_et}. It takes one
+argument, the pathname of a file (ending in @samp{.et}, e.g.,
+@samp{dsc_err.et}) containing an error table source file. It parses the
+error table, and generates two output files -- a C header file
+(@samp{discuss_err.h}) which contains definitions of the numerical values
+of the error codes defined in the error table, and a C source file which
+should be compiled and linked with the executable. The header file must be
+included in the source of a module which wishes to reference the error
+codes defined; the object module generated from the C code may be linked in
+to a program which wishes to use the printed forms of the error codes.
+
+This translator accepts a @kbd{-language @var{lang}} argument, which
+determines for which language (or language variant) the output should be
+written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
+and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will
+be extended to include some support for C++. The default is currently
+@kbd{K&R-C}, though the generated sources will have ANSI-C code
+conditionalized on the symbol @t{__STDC__}.
+
+@node Run-time support routines, Coding Conventions, The error-table compiler, Top
+@section Run-time support routines
+
+Any source file which uses the routines supplied with or produced by the
+com_err package should include the header file @file{<com_err.h>}. It
+contains declarations and definitions which may be needed on some systems.
+(Some functions cannot be referenced properly without the return type
+declarations in this file. Some functions may work properly on most
+architectures even without the header file, but relying on this is not
+recommended.)
+
+The run-time support routines and variables provided via this package
+include the following:
+
+@example
+void initialize_@var{xxxx}_error_table (void);
+@end example
+
+One of these routines is built by the error compiler for each error table.
+It makes the @var{xxxx} error table ``known'' to the error reporting
+system. By convention, this routine should be called in the initialization
+routine of the @var{xxxx} library. If the library has no initialization
+routine, some combination of routines which form the core of the library
+should ensure that this routine is called. It is not advised to leave it
+the caller to make this call.
+
+There is no harm in calling this routine more than once.
+
+@example
+#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
+@end example
+
+This symbol contains the value of the first error code entry in the
+specified table.
+This rarely needs be used by the
+programmer.
+
+@deftypefun const char *error_message (long @var{code});
+
+This routine returns the character string error message associated
+with @code{code}; if this is associated with an unknown error table, or
+if the code is associated with a known error table but the code is not
+in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
+returned, where @var{xxxx} is the error table name produced by
+reversing the compaction performed on the error table number implied
+by that error code, and @var{nn} is the offset from that base value.
+
+Although this routine is available for use when needed, its use should be
+left to circumstances which render @code{com_err} (below) unusable.
+
+@end deftypefun
+
+@deftypefun
+void com_err (const char *@var{whoami}, long @var{error_code},
+ const char *@var{format}, ...);
+
+This routine provides an alternate way to print error messages to
+standard error; it allows the error message to be passed in as a
+parameter, rather than in an external variable. @emph{Provide grammatical
+context for ``message.''}
+
+The module reporting the error should be passed in via @var{whoami}.
+If @var{format} is @code{(char *)NULL}, the formatted message will not be
+printed. @var{format} may not be omitted.
+
+@end deftypefun
+
+@deftypefun
+void com_err_va (const char *@var{whoami}, long @var{error_code}, const char *@var{format}, va_list @var{args});
+
+This routine provides an interface, equivalent to @code{com_err} above,
+which may be used by higher-level variadic functions (functions which
+accept variable numbers of arguments).
+
+@end deftypefun
+
+@deftypefun void (*set_com_err_hook (void (*@var{proc}) (const char *@var{whoami}, long @var{error_code}, va_list @var{args}))) (const char *@var{whoami}, long @var{error_code}, va_list @var{args});
+
+@deftypefunx void reset_com_err_hook ();
+
+These two routines allow a routine to be dynamically substituted for
+@samp{com_err}. After @samp{set_com_err_hook} has been called,
+calls to @samp{com_err} will turn into calls to the new hook routine.
+@samp{reset_com_err_hook} turns off this hook. This may intended to
+be used in daemons (to use a routine which calls @cite{syslog(3)}), or
+in a window system application (which could pop up a dialogue box).
+
+If a program is to be used in an environment in which simply printing
+messages to the @code{stderr} stream would be inappropriate (such as in a
+daemon program which runs without a terminal attached),
+@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
+The following is an example of an error handler which uses @cite{syslog(3)}
+as supplied in BSD 4.3:
+
+@example
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+/* extern openlog (const char * name, int logopt, int facility); */
+/* extern syslog (int priority, char * message, ...); */
+
+void hook (const char * whoami, long code,
+ const char * format, va_list args)
+@{
+ char buffer[BUFSIZ];
+ static int initialized = 0;
+ if (!initialized) @{
+ openlog (whoami,
+ LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
+ LOG_DAEMON);
+ initialized = 1;
+ @}
+ vsprintf (buffer, format, args);
+ syslog (LOG_ERR, "%s %s", error_message (code), buffer);
+@}
+@end example
+
+After making the call
+@code{set_com_err_hook (hook);},
+any calls to @code{com_err} will result in messages being sent to the
+@var{syslogd} daemon for logging.
+The name of the program, @samp{whoami}, is supplied to the
+@samp{openlog()} call, and the message is formatted into a buffer and
+passed to @code{syslog}.
+
+Note that since the extra arguments to @code{com_err} are passed by
+reference via the @code{va_list} value @code{args}, the hook routine may
+place any form of interpretation on them, including ignoring them. For
+consistency, @code{printf}-style interpretation is suggested, via
+@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
+the ANSI C library).
+
+@end deftypefun
+
+@node Coding Conventions, Building and Installation, Run-time support routines, Top
+@section Coding Conventions
+
+The following conventions are just some general stylistic conventions
+to follow when writing robust libraries and programs. Conventions
+similar to this are generally followed inside the UNIX kernel and most
+routines in the Multics operating system. In general, a routine
+either succeeds (returning a zero error code, and doing some side
+effects in the process), or it fails, doing minimal side effects; in
+any event, any invariant which the library assumes must be maintained.
+
+In general, it is not in the domain of non user-interface library
+routines to write error messages to the user's terminal, or halt the
+process. Such forms of ``error handling'' should be reserved for
+failures of internal invariants and consistancy checks only, as it
+provides the user of the library no way to clean up for himself in the
+event of total failure.
+
+Library routines which can fail should be set up to return an error
+code. This should usually be done as the return value of the
+function; if this is not acceptable, the routine should return a
+``null'' value, and put the error code into a parameter passed by
+reference.
+
+Routines which use the first style of interface can be used from
+user-interface levels of a program as follows:
+
+@example
+@{
+ if ((code = initialize_world(getuid(), random())) != 0) @{
+ com_err("demo", code,
+ "when trying to initialize world");
+ exit(1);
+ @}
+ if ((database = open_database("my_secrets", &code))==NULL) @{
+ com_err("demo", code,
+ "while opening my_secrets");
+ exit(1);
+ @}
+@}
+@end example
+
+A caller which fails to check the return status is in error. It is
+possible to look for code which ignores error returns by using lint;
+look for error messages of the form ``foobar returns value which is
+sometimes ignored'' or ``foobar returns value which is always
+ignored.''
+
+Since libraries may be built out of other libraries, it is often necessary
+for the success of one routine to depend on another. When a lower level
+routine returns an error code, the middle level routine has a few possible
+options. It can simply return the error code to its caller after doing
+some form of cleanup, it can substitute one of its own, or it can take
+corrective action of its own and continue normally. For instance, a
+library routine which makes a ``connect'' system call to make a network
+connection may reflect the system error code @code{ECONNREFUSED}
+(Connection refused) to its caller, or it may return a ``server not
+available, try again later,'' or it may try a different server.
+
+Cleanup which is typically necessary may include, but not be limited
+to, freeing allocated memory which will not be needed any more,
+unlocking concurrancy locks, dropping reference counts, closing file
+descriptors, or otherwise undoing anything which the procedure did up
+to this point. When there are a lot of things which can go wrong, it
+is generally good to write one block of error-handling code which is
+branched to, using a goto, in the event of failure. A common source
+of errors in UNIX programs is failing to close file descriptors on
+error returns; this leaves a number of ``zombied'' file descriptors
+open, which eventually causes the process to run out of file
+descriptors and fall over.
+
+@example
+@{
+ FILE *f1=NULL, *f2=NULL, *f3=NULL;
+ int status = 0;
+
+ if ( (f1 = fopen(FILE1, "r")) == NULL) @{
+ status = errno;
+ goto error;
+ @}
+
+ /*
+ * Crunch for a while
+ */
+
+ if ( (f2 = fopen(FILE2, "w")) == NULL) @{
+ status = errno;
+ goto error;
+ @}
+
+ if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
+ status = errno;
+ goto error;
+ @}
+
+ /*
+ * Do more processing.
+ */
+ fclose(f1);
+ fclose(f2);
+ fclose(f3);
+ return 0;
+
+error:
+ if (f1) fclose(f1);
+ if (f2) fclose(f2);
+ if (f3) fclose(f3);
+ return status;
+@}
+@end example
+
+@node Building and Installation, Bug Reports, Coding Conventions, Top
+@section Building and Installation
+
+The distribution of this package will probably be done as a compressed
+``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
+Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory
+@t{profiled} should be created to hold objects compiled for profiling.
+Running ``make all'' should then be sufficient to build the library and
+error-table compiler. The files @samp{libcom_err.a},
+@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
+installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
+installed as manual pages.
+
+Potential problems:
+
+@itemize @bullet
+
+@item Use of @code{strcasecmp}, a routine provided in BSD for
+case-insensitive string comparisons. If an equivalent routine is
+available, you can modify @code{CFLAGS} in the makefile to define
+@code{strcasecmp} to the name of that routine.
+
+@item Compilers that defined @code{__STDC__} without providing the header
+file @code{<stdarg.h>}. One such example is Metaware's High ``C''
+compiler, as provided at Project Athena on the IBM RT/PC workstation; if
+@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
+available, and therefore @code{<varargs.h>} must be used. If the symbol
+@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
+be used.
+
+@item If your linker rejects symbols that are simultaneously defined in two
+library files, edit @samp{Makefile} to remove @samp{perror.c} from the
+library. This file contains a version of @cite{perror(3)} which calls
+@code{com_err} instead of calling @code{write} directly.
+
+@end itemize
+
+As I do not have access to non-BSD systems, there are probably
+bugs present that may interfere with building or using this package on
+other systems. If they are reported to me, they can probably be fixed for
+the next version.
+
+@node Bug Reports, Acknowledgements, Building and Installation, Top
+@section Bug Reports
+
+The principal author of this library is: Ken
+Raeburn, @t{raeburn@@MIT.EDU}.
+
+This version of the com_err library is being maintained by Theodore
+Ts'o, and so bugs and comments should be sent to @t{tytso@@thunk.org}.
+
+
+@node Acknowledgements, , Bug Reports, Top
+@section Acknowledgements
+
+I would like to thank: Bill Sommerfeld, for his help with some of this
+documentation, and catching some of the bugs the first time around;
+Honeywell Information Systems, for not killing off the @emph{Multics}
+operating system before I had an opportunity to use it; Honeywell's
+customers, who persuaded them not to do so, for a while; Ted Anderson of
+CMU, for catching some problems before version 1.2 left the nest; Stan
+Zanarotti and several others of MIT's Student Information Processing Board,
+for getting us started with ``discuss,'' for which this package was
+originally written; and everyone I've talked into --- I mean, asked to read
+this document and the ``man'' pages.
+
+@bye
diff --git a/e2fslib/et/compile_et b/e2fslib/et/compile_et
new file mode 100755
index 0000000..ca19559
--- /dev/null
+++ b/e2fslib/et/compile_et
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+#
+AWK=/usr/bin/awk
+DIR="${DIR-/usr/share/et}"
+ET_DIR="et"
+
+if test "x$1" = x ; then
+ echo "Usage: compile_et file"
+ exit 1
+fi
+
+if test ! -f "$DIR/et_h.awk" -o ! -f "$DIR/et_c.awk" ; then
+ DIR="$ET_DIR"
+# echo "Falling back to $DIR..."
+ if test ! -f "$DIR/et_h.awk" -o ! -f "$DIR/et_c.awk" ; then
+ echo "compile_et: Couldn't find compile_et's template files."
+ exit 1
+ fi
+fi
+
+ROOT=`echo $1 | sed -e s/.et$//`
+BASE=`basename $ROOT`
+
+if test ! -f "$ROOT.et" ; then
+ echo "compile_et: $ROOT.et: File not found"
+ exit 1;
+fi
+
+$AWK -f "${DIR}/et_h.awk" "outfile=${BASE}.h" "$ROOT.et"
+$AWK -f "${DIR}/et_c.awk" "outfile=${BASE}.c" "$ROOT.et"
diff --git a/e2fslib/et/compile_et.sh.in b/e2fslib/et/compile_et.sh.in
new file mode 100644
index 0000000..ad445fa
--- /dev/null
+++ b/e2fslib/et/compile_et.sh.in
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+#
+AWK=@AWK@
+DIR="${DIR-@datadir@/et}"
+ET_DIR="@ET_DIR@"
+
+if test "x$1" = x ; then
+ echo "Usage: compile_et file"
+ exit 1
+fi
+
+if test ! -f "$DIR/et_h.awk" -o ! -f "$DIR/et_c.awk" ; then
+ DIR="$ET_DIR"
+# echo "Falling back to $DIR..."
+ if test ! -f "$DIR/et_h.awk" -o ! -f "$DIR/et_c.awk" ; then
+ echo "compile_et: Couldn't find compile_et's template files."
+ exit 1
+ fi
+fi
+
+ROOT=`echo $1 | sed -e s/.et$//`
+BASE=`basename $ROOT`
+
+if test ! -f "$ROOT.et" ; then
+ echo "compile_et: $ROOT.et: File not found"
+ exit 1;
+fi
+
+$AWK -f "${DIR}/et_h.awk" "outfile=${BASE}.h" "$ROOT.et"
+$AWK -f "${DIR}/et_c.awk" "outfile=${BASE}.c" "$ROOT.et"
diff --git a/e2fslib/et/error_message.c b/e2fslib/et/error_message.c
new file mode 100644
index 0000000..b9e3628
--- /dev/null
+++ b/e2fslib/et/error_message.c
@@ -0,0 +1,88 @@
+/*
+ * $ Header: lib/et/SCCS/s.error_message.c 1.16 99/10/23 01:16:05-00:00 tytso@mit.edu $
+ * $ Source: /usr/src/e2fsprogs/BK/e2fsprogs/lib/et/SCCS/s.error_message.c $
+ * $ Locker: <Not implemented> $
+ *
+ * Copyright 1987 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "com_err.h"
+#include "error_table.h"
+#include "internal.h"
+
+static char buffer[25];
+
+struct et_list * _et_list = (struct et_list *) NULL;
+
+
+#ifdef __STDC__
+const char * error_message (errcode_t code)
+#else
+const char * error_message (code)
+ errcode_t code;
+#endif
+{
+ int offset;
+ struct et_list *et;
+ errcode_t table_num;
+ int started = 0;
+ char *cp;
+
+ offset = (int) (code & ((1<<ERRCODE_RANGE)-1));
+ table_num = code - offset;
+ if (!table_num) {
+#ifdef HAS_SYS_ERRLIST
+ if (offset < sys_nerr)
+ return(sys_errlist[offset]);
+ else
+ goto oops;
+#else
+ cp = strerror(offset);
+ if (cp)
+ return(cp);
+ else
+ goto oops;
+#endif
+ }
+ for (et = _et_list; et; et = et->next) {
+ if (et->table->base == table_num) {
+ /* This is the right table */
+ if (et->table->n_msgs <= offset)
+ goto oops;
+ return(et->table->msgs[offset]);
+ }
+ }
+oops:
+ strcpy (buffer, "Unknown code ");
+ if (table_num) {
+ strcat (buffer, error_table_name (table_num));
+ strcat (buffer, " ");
+ }
+ for (cp = buffer; *cp; cp++)
+ ;
+ if (offset >= 100) {
+ *cp++ = '0' + offset / 100;
+ offset %= 100;
+ started++;
+ }
+ if (started || offset >= 10) {
+ *cp++ = '0' + offset / 10;
+ offset %= 10;
+ }
+ *cp++ = '0' + offset;
+ *cp = '\0';
+ return(buffer);
+}
diff --git a/e2fslib/et/error_message.o b/e2fslib/et/error_message.o
new file mode 100644
index 0000000..9223eb8
--- /dev/null
+++ b/e2fslib/et/error_message.o
Binary files differ
diff --git a/e2fslib/et/error_table.h b/e2fslib/et/error_table.h
new file mode 100644
index 0000000..d9a7b4b
--- /dev/null
+++ b/e2fslib/et/error_table.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1988 by the Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#ifndef _ET_H
+/* Are we using ANSI C? */
+#ifndef __STDC__
+#define const
+#endif
+
+struct error_table {
+ char const * const * msgs;
+ long base;
+ int n_msgs;
+};
+struct et_list {
+ struct et_list *next;
+ const struct error_table *table;
+};
+extern struct et_list * _et_list;
+
+#define ERRCODE_RANGE 8 /* # of bits to shift table number */
+#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
+
+#ifdef __STDC__
+extern const char *error_table_name(errcode_t num);
+#else
+extern const char *error_table_name();
+#endif
+
+#define _ET_H
+#endif
diff --git a/e2fslib/et/et_c.awk b/e2fslib/et/et_c.awk
new file mode 100644
index 0000000..5f95b55
--- /dev/null
+++ b/e2fslib/et/et_c.awk
@@ -0,0 +1,187 @@
+BEGIN {
+char_shift=64
+## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+c2n["A"]=1
+c2n["B"]=2
+c2n["C"]=3
+c2n["D"]=4
+c2n["E"]=5
+c2n["F"]=6
+c2n["G"]=7
+c2n["H"]=8
+c2n["I"]=9
+c2n["J"]=10
+c2n["K"]=11
+c2n["L"]=12
+c2n["M"]=13
+c2n["N"]=14
+c2n["O"]=15
+c2n["P"]=16
+c2n["Q"]=17
+c2n["R"]=18
+c2n["S"]=19
+c2n["T"]=20
+c2n["U"]=21
+c2n["V"]=22
+c2n["W"]=23
+c2n["X"]=24
+c2n["Y"]=25
+c2n["Z"]=26
+c2n["a"]=27
+c2n["b"]=28
+c2n["c"]=29
+c2n["d"]=30
+c2n["e"]=31
+c2n["f"]=32
+c2n["g"]=33
+c2n["h"]=34
+c2n["i"]=35
+c2n["j"]=36
+c2n["k"]=37
+c2n["l"]=38
+c2n["m"]=39
+c2n["n"]=40
+c2n["o"]=41
+c2n["p"]=42
+c2n["q"]=43
+c2n["r"]=44
+c2n["s"]=45
+c2n["t"]=46
+c2n["u"]=47
+c2n["v"]=48
+c2n["w"]=49
+c2n["x"]=50
+c2n["y"]=51
+c2n["z"]=52
+c2n["0"]=53
+c2n["1"]=54
+c2n["2"]=55
+c2n["3"]=56
+c2n["4"]=57
+c2n["5"]=58
+c2n["6"]=59
+c2n["7"]=60
+c2n["8"]=61
+c2n["9"]=62
+c2n["_"]=63
+}
+/^#/ { next }
+/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
+ table_number = 0
+ table_name = $2
+ mod_base = 1000000
+ for(i=1; i<=length(table_name); i++) {
+ table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
+ }
+
+ # We start playing *_high, *low games here because the some
+ # awk programs do not have the necessary precision (sigh)
+ tab_base_low = table_number % mod_base
+ if (tab_base_low < 0) {
+ # Work around stupid bug in the ARM libm
+ tab_base_low = tab_base_low + mod_base
+ }
+ tab_base_high = int(table_number / mod_base)
+ tab_base_sign = 1;
+
+ # figure out: table_number_base=table_number*256
+ tab_base_low = tab_base_low * 256
+ tab_base_high = (tab_base_high * 256) + \
+ int(tab_base_low / mod_base)
+ tab_base_low = tab_base_low % mod_base
+ if (tab_base_low < 0) {
+ # Work around stupid bug in the ARM libm
+ tab_base_low = tab_base_low + mod_base
+ }
+
+ if (table_number > 128*256*256) {
+ # figure out: table_number_base -= 256*256*256*256
+ # sub_high, sub_low is 256*256*256*256
+ sub_low = 256*256*256 % mod_base
+ sub_high = int(256*256*256 / mod_base)
+
+ sub_low = sub_low * 256
+ sub_high = (sub_high * 256) + int(sub_low / mod_base)
+ sub_low = sub_low % mod_base
+
+ tab_base_low = sub_low - tab_base_low;
+ tab_base_high = sub_high - tab_base_high;
+ tab_base_sign = -1;
+ if (tab_base_low < 0) {
+ tab_base_low = tab_base_low + mod_base
+ tab_base_high--
+ }
+ }
+ print "/*" > outfile
+ print " * " outfile ":" > outfile
+ print " * This file is automatically generated; please do not edit it." > outfile
+ print " */" > outfile
+
+ print "" > outfile
+ print "static const char * const text[] = {" > outfile
+ table_item_count = 0
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
+ skipone=1
+ next
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
+ text=""
+ for (i=3; i<=NF; i++) {
+ text = text FS $i
+ }
+ text=substr(text,2,length(text)-1);
+ printf "\t%s,\n", text > outfile
+ table_item_count++
+}
+
+{
+ if (skipone) {
+ printf "\t%s,\n", $0 > outfile
+ table_item_count++
+ }
+ skipone=0
+}
+END {
+
+
+ print " 0" > outfile
+ print "};" > outfile
+ print "" > outfile
+ print "struct error_table {" > outfile
+ print " char const * const * msgs;" > outfile
+ print " long base;" > outfile
+ print " int n_msgs;" > outfile
+ print "};" > outfile
+ print "struct et_list {" > outfile
+ print " struct et_list *next;" > outfile
+ print " const struct error_table * table;" > outfile
+ print "};" > outfile
+ print "extern struct et_list *_et_list;" > outfile
+ print "" > outfile
+ if (tab_base_high == 0) {
+ print "static const struct error_table et = { text, " \
+ sprintf("%dL, %d };", tab_base_sign*tab_base_low, \
+ table_item_count) > outfile
+ } else {
+ print "static const struct error_table et = { text, " \
+ sprintf("%d%06dL, %d };", tab_base_sign*tab_base_high, \
+ tab_base_low, table_item_count) > outfile
+ }
+ print "" > outfile
+ print "static struct et_list link = { 0, 0 };" > outfile
+ print "" > outfile
+ print "void initialize_" table_name "_error_table(void);" > outfile
+ print "" > outfile
+ print "void initialize_" table_name "_error_table(void) {" > outfile
+ print " if (!link.table) {" > outfile
+ print " link.next = _et_list;" > outfile
+ print " link.table = &et;" > outfile
+ print " _et_list = &link;" > outfile
+ print " }" > outfile
+ print "}" > outfile
+
+
+}
diff --git a/e2fslib/et/et_h.awk b/e2fslib/et/et_h.awk
new file mode 100644
index 0000000..8b83a21
--- /dev/null
+++ b/e2fslib/et/et_h.awk
@@ -0,0 +1,159 @@
+BEGIN {
+char_shift=64
+## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+c2n["A"]=1
+c2n["B"]=2
+c2n["C"]=3
+c2n["D"]=4
+c2n["E"]=5
+c2n["F"]=6
+c2n["G"]=7
+c2n["H"]=8
+c2n["I"]=9
+c2n["J"]=10
+c2n["K"]=11
+c2n["L"]=12
+c2n["M"]=13
+c2n["N"]=14
+c2n["O"]=15
+c2n["P"]=16
+c2n["Q"]=17
+c2n["R"]=18
+c2n["S"]=19
+c2n["T"]=20
+c2n["U"]=21
+c2n["V"]=22
+c2n["W"]=23
+c2n["X"]=24
+c2n["Y"]=25
+c2n["Z"]=26
+c2n["a"]=27
+c2n["b"]=28
+c2n["c"]=29
+c2n["d"]=30
+c2n["e"]=31
+c2n["f"]=32
+c2n["g"]=33
+c2n["h"]=34
+c2n["i"]=35
+c2n["j"]=36
+c2n["k"]=37
+c2n["l"]=38
+c2n["m"]=39
+c2n["n"]=40
+c2n["o"]=41
+c2n["p"]=42
+c2n["q"]=43
+c2n["r"]=44
+c2n["s"]=45
+c2n["t"]=46
+c2n["u"]=47
+c2n["v"]=48
+c2n["w"]=49
+c2n["x"]=50
+c2n["y"]=51
+c2n["z"]=52
+c2n["0"]=53
+c2n["1"]=54
+c2n["2"]=55
+c2n["3"]=56
+c2n["4"]=57
+c2n["5"]=58
+c2n["6"]=59
+c2n["7"]=60
+c2n["8"]=61
+c2n["9"]=62
+c2n["_"]=63
+}
+/^#/ { next }
+/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
+ table_number = 0
+ table_name = $2
+ mod_base = 1000000
+ for(i=1; i<=length(table_name); i++) {
+ table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
+ }
+ # We start playing *_high, *low games here because the some
+ # awk programs do not have the necessary precision (sigh)
+ tab_base_low = table_number % mod_base
+ if (tab_base_low < 0) {
+ # Work around stupid bug in the ARM libm
+ tab_base_low = tab_base_low + mod_base
+ }
+ tab_base_high = int(table_number / mod_base)
+ tab_base_sign = 1;
+
+ # figure out: table_number_base=table_number*256
+ tab_base_low = tab_base_low * 256
+ tab_base_high = (tab_base_high * 256) + \
+ int(tab_base_low / mod_base)
+ tab_base_low = tab_base_low % mod_base
+ if (tab_base_low < 0) {
+ # Work around stupid bug in the ARM libm
+ tab_base_low = tab_base_low + mod_base
+ }
+
+ if (table_number > 128*256*256) {
+ # figure out: table_number_base -= 256*256*256*256
+ # sub_high, sub_low is 256*256*256*256
+ sub_low = 256*256*256 % mod_base
+ sub_high = int(256*256*256 / mod_base)
+
+ sub_low = sub_low * 256
+ sub_high = (sub_high * 256) + int(sub_low / mod_base)
+ sub_low = sub_low % mod_base
+
+ tab_base_low = sub_low - tab_base_low;
+ tab_base_high = sub_high - tab_base_high;
+ tab_base_sign = -1;
+ if (tab_base_low < 0) {
+ tab_base_low = tab_base_low + mod_base
+ tab_base_high--
+ }
+ }
+ curr_low = tab_base_low
+ curr_high = tab_base_high
+ curr_sign = tab_base_sign
+ print "/*" > outfile
+ print " * " outfile ":" > outfile
+ print " * This file is automatically generated; please do not edit it." > outfile
+ print " */" > outfile
+ print "" > outfile
+}
+
+/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/ {
+ tag=substr($2,1,length($2)-1)
+ if (curr_high == 0) {
+ printf "#define %-40s (%dL)\n", tag, \
+ curr_sign*curr_low > outfile
+ } else {
+ printf "#define %-40s (%d%06dL)\n", tag, curr_high*curr_sign, \
+ curr_low > outfile
+ }
+ curr_low += curr_sign;
+ if (curr_low >= mod_base) {
+ curr_low -= mod_base;
+ curr_high++
+ }
+ if (curr_low < 0) {
+ cur_low += mod_base
+ cur_high--
+ }
+}
+
+END {
+ print "extern void initialize_" table_name "_error_table(void);" > outfile
+ if (tab_base_high == 0) {
+ print "#define ERROR_TABLE_BASE_" table_name " (" \
+ sprintf("%d", tab_base_sign*tab_base_low) \
+ "L)" > outfile
+ } else {
+ print "#define ERROR_TABLE_BASE_" table_name " (" \
+ sprintf("%d%06d", tab_base_sign*tab_base_high, \
+ tab_base_low) "L)" > outfile
+ }
+ print "" > outfile
+ print "/* for compatibility with older versions... */" > outfile
+ print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
+ print "#define " table_name "_err_base ERROR_TABLE_BASE_" table_name > outfile
+}
diff --git a/e2fslib/et/et_name.c b/e2fslib/et/et_name.c
new file mode 100644
index 0000000..1888326
--- /dev/null
+++ b/e2fslib/et/et_name.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1987 by MIT Student Information Processing Board
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include "com_err.h"
+#include "error_table.h"
+#include "internal.h"
+
+static const char char_set[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+static char buf[6];
+
+const char * error_table_name(num)
+ errcode_t num;
+{
+ int ch;
+ int i;
+ char *p;
+
+ /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
+ p = buf;
+ num >>= ERRCODE_RANGE;
+ /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
+ num &= 077777777L;
+ /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
+ for (i = 4; i >= 0; i--) {
+ ch = (int)((num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1));
+ if (ch != 0)
+ *p++ = char_set[ch-1];
+ }
+ *p = '\0';
+ return(buf);
+}
diff --git a/e2fslib/et/et_name.o b/e2fslib/et/et_name.o
new file mode 100644
index 0000000..c2510b2
--- /dev/null
+++ b/e2fslib/et/et_name.o
Binary files differ
diff --git a/e2fslib/et/init_et.c b/e2fslib/et/init_et.c
new file mode 100644
index 0000000..bfdb73d
--- /dev/null
+++ b/e2fslib/et/init_et.c
@@ -0,0 +1,63 @@
+/*
+ * $ Header: lib/et/SCCS/s.init_et.c 1.15 99/10/23 01:16:06-00:00 tytso@mit.edu $
+ * $ Source: /usr/src/e2fsprogs/BK/e2fsprogs/lib/et/SCCS/s.init_et.c $
+ * $ Locker: <Not implemented> $
+ *
+ * Copyright 1986, 1987, 1988 by MIT Information Systems and
+ * the MIT Student Information Processing Board.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include "com_err.h"
+#include "error_table.h"
+
+#ifndef __STDC__
+#define const
+#endif
+
+struct foobar {
+ struct et_list etl;
+ struct error_table et;
+};
+
+extern struct et_list * _et_list;
+
+#ifdef __STDC__
+int init_error_table(const char * const *msgs, int base, int count)
+#else
+int init_error_table(msgs, base, count)
+ const char * const * msgs;
+ int base;
+ int count;
+#endif
+{
+ struct foobar * new_et;
+
+ if (!base || !count || !msgs)
+ return 0;
+
+ new_et = (struct foobar *) malloc(sizeof(struct foobar));
+ if (!new_et)
+ return ENOMEM; /* oops */
+ new_et->etl.table = &new_et->et;
+ new_et->et.msgs = msgs;
+ new_et->et.base = base;
+ new_et->et.n_msgs= count;
+
+ new_et->etl.next = _et_list;
+ _et_list = &new_et->etl;
+ return 0;
+}
diff --git a/e2fslib/et/init_et.o b/e2fslib/et/init_et.o
new file mode 100644
index 0000000..9a7698a
--- /dev/null
+++ b/e2fslib/et/init_et.o
Binary files differ
diff --git a/e2fslib/et/internal.h b/e2fslib/et/internal.h
new file mode 100644
index 0000000..30b1921
--- /dev/null
+++ b/e2fslib/et/internal.h
@@ -0,0 +1,30 @@
+/*
+ * internal include file for com_err package
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+#ifndef __STDC__
+#undef const
+#define const
+#endif
+
+#include <errno.h>
+
+#ifdef NEED_SYS_ERRLIST
+extern char const * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+/* AIX and Ultrix have standard conforming header files. */
+#if !defined(ultrix) && !defined(_AIX)
+#ifdef __STDC__
+void perror (const char *);
+#endif
+#endif
diff --git a/e2fslib/et/libcom_err.a b/e2fslib/et/libcom_err.a
new file mode 100644
index 0000000..4c848dc
--- /dev/null
+++ b/e2fslib/et/libcom_err.a
Binary files differ
diff --git a/e2fslib/et/vfprintf.c b/e2fslib/et/vfprintf.c
new file mode 100644
index 0000000..a1dc1e8
--- /dev/null
+++ b/e2fslib/et/vfprintf.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 5.2 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#if !HAVE_VPRINTF && HAVE_DOPRNT
+#include <stdio.h>
+#include <varargs.h>
+
+int
+vfprintf(iop, fmt, ap)
+ FILE *iop;
+ char *fmt;
+ va_list ap;
+{
+ int len;
+ char localbuf[BUFSIZ];
+
+ if (iop->_flag & _IONBF) {
+ iop->_flag &= ~_IONBF;
+ iop->_ptr = iop->_base = localbuf;
+ len = _doprnt(fmt, ap, iop);
+ (void) fflush(iop);
+ iop->_flag |= _IONBF;
+ iop->_base = NULL;
+ iop->_bufsiz = 0;
+ iop->_cnt = 0;
+ } else
+ len = _doprnt(fmt, ap, iop);
+
+ return (ferror(iop) ? EOF : len);
+}
+#endif /* !HAVE_VPRINTF */
diff --git a/e2fslib/expanddir.c b/e2fslib/expanddir.c
new file mode 100644
index 0000000..112dedc
--- /dev/null
+++ b/e2fslib/expanddir.c
@@ -0,0 +1,132 @@
+/*
+ * expand.c --- expand an ext2fs directory
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct expand_dir_struct {
+ int done;
+ int newblocks;
+ errcode_t err;
+};
+
+static int expand_dir_proc(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block,
+ int ref_offset,
+ void *priv_data)
+{
+ struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
+ blk_t new_blk;
+ static blk_t last_blk = 0;
+ char *block;
+ errcode_t retval;
+ int group;
+
+ if (*blocknr) {
+ last_blk = *blocknr;
+ return 0;
+ }
+ retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
+ if (retval) {
+ es->err = retval;
+ return BLOCK_ABORT;
+ }
+ if (blockcnt > 0) {
+ retval = ext2fs_new_dir_block(fs, 0, 0, &block);
+ if (retval) {
+ es->err = retval;
+ return BLOCK_ABORT;
+ }
+ es->done = 1;
+ retval = ext2fs_write_dir_block(fs, new_blk, block);
+ } else {
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &block);
+ if (retval) {
+ es->err = retval;
+ return BLOCK_ABORT;
+ }
+ memset(block, 0, fs->blocksize);
+ retval = io_channel_write_blk(fs->io, new_blk, 1, block);
+ }
+ if (retval) {
+ es->err = retval;
+ return BLOCK_ABORT;
+ }
+ ext2fs_free_mem((void **) &block);
+ *blocknr = new_blk;
+ ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+ ext2fs_mark_bb_dirty(fs);
+ group = ext2fs_group_of_blk(fs, new_blk);
+ fs->group_desc[group].bg_free_blocks_count--;
+ fs->super->s_free_blocks_count--;
+ ext2fs_mark_super_dirty(fs);
+ es->newblocks++;
+
+ if (es->done)
+ return (BLOCK_CHANGED | BLOCK_ABORT);
+ else
+ return BLOCK_CHANGED;
+}
+
+errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
+{
+ errcode_t retval;
+ struct expand_dir_struct es;
+ struct ext2_inode inode;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ if (!fs->block_map)
+ return EXT2_ET_NO_BLOCK_BITMAP;
+
+ retval = ext2fs_check_directory(fs, dir);
+ if (retval)
+ return retval;
+
+ es.done = 0;
+ es.err = 0;
+ es.newblocks = 0;
+
+ retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
+ 0, expand_dir_proc, &es);
+
+ if (es.err)
+ return es.err;
+ if (!es.done)
+ return EXT2_ET_EXPAND_DIR_ERR;
+
+ /*
+ * Update the size and block count fields in the inode.
+ */
+ retval = ext2fs_read_inode(fs, dir, &inode);
+ if (retval)
+ return retval;
+
+ inode.i_size += fs->blocksize;
+ inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
+
+ retval = ext2fs_write_inode(fs, dir, &inode);
+ if (retval)
+ return retval;
+
+ return 0;
+}
diff --git a/e2fslib/expanddir.o b/e2fslib/expanddir.o
new file mode 100644
index 0000000..5c02110
--- /dev/null
+++ b/e2fslib/expanddir.o
Binary files differ
diff --git a/e2fslib/ext2_err.c b/e2fslib/ext2_err.c
new file mode 100644
index 0000000..a8b5097
--- /dev/null
+++ b/e2fslib/ext2_err.c
@@ -0,0 +1,140 @@
+/*
+ * :
+ * This file is automatically generated; please do not edit it.
+ */
+
+#include <stdlib.h>
+
+static const char * const text[] = {
+ "EXT2FS Library version 1.25",
+ "Wrong magic number for ext2_filsys structure",
+ "Wrong magic number for badblocks_list structure",
+ "Wrong magic number for badblocks_iterate structure",
+ "Wrong magic number for inode_scan structure",
+ "Wrong magic number for io_channel structure",
+ "Wrong magic number for unix io_channel structure",
+ "Wrong magic number for io_manager structure",
+ "Wrong magic number for block_bitmap structure",
+ "Wrong magic number for inode_bitmap structure",
+ "Wrong magic number for generic_bitmap structure",
+ "Wrong magic number for test io_channel structure",
+ "Wrong magic number for directory block list structure",
+ "Wrong magic number for icount structure",
+ "Wrong magic number for Powerquest io_channel structure",
+ "Wrong magic number for ext2 file structure",
+ "Wrong magic number for Ext2 Image Header",
+ "Wrong magic number --- RESERVED_8",
+ "Wrong magic number --- RESERVED_9",
+ "Bad magic number in super-block",
+ "Filesystem revision too high",
+ "Attempt to write to filesystem opened read-only",
+ "Can't read group descriptors",
+ "Can't write group descriptors",
+ "Corrupt group descriptor: bad block for block bitmap",
+ "Corrupt group descriptor: bad block for inode bitmap",
+ "Corrupt group descriptor: bad block for inode table",
+ "Can't write an inode bitmap",
+ "Can't read an inode bitmap",
+ "Can't write an block bitmap",
+ "Can't read an block bitmap",
+ "Can't write an inode table",
+ "Can't read an inode table",
+ "Can't read next inode",
+ "Filesystem has unexpected block size",
+ "EXT2 directory corrupted",
+ "Attempt to read block from filesystem resulted in short read",
+ "Attempt to write block from filesystem resulted in short write",
+ "No free space in the directory",
+ "Inode bitmap not loaded",
+ "Block bitmap not loaded",
+ "Illegal inode number",
+ "Illegal block number",
+ "Internal error in ext2fs_expand_dir",
+ "Not enough space to build proposed filesystem",
+ "Illegal block number passed to ext2fs_mark_block_bitmap",
+ "Illegal block number passed to ext2fs_unmark_block_bitmap",
+ "Illegal block number passed to ext2fs_test_block_bitmap",
+ "Illegal inode number passed to ext2fs_mark_inode_bitmap",
+ "Illegal inode number passed to ext2fs_unmark_inode_bitmap",
+ "Illegal inode number passed to ext2fs_test_inode_bitmap",
+ "Attempt to fudge end of block bitmap past the real end",
+ "Attempt to fudge end of inode bitmap past the real end",
+ "Illegal indirect block found" ,
+ "Illegal doubly indirect block found" ,
+ "Illegal triply indirect block found" ,
+ "Block bitmaps are not the same",
+ "Inode bitmaps are not the same",
+ "Illegal or malformed device name",
+ "A block group is missing an inode table",
+ "The ext2 superblock is corrupt",
+ "Illegal generic bit number passed to ext2fs_mark_generic_bitmap",
+ "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap",
+ "Illegal generic bit number passed to ext2fs_test_generic_bitmap",
+ "Too many symbolic links encountered.",
+ "The callback function will not handle this case",
+ "The inode is from a bad block in the inode table",
+ "Filesystem has unsupported feature(s)",
+ "Filesystem has unsupported read-only feature(s)",
+ "IO Channel failed to seek on read or write",
+ "Memory allocation failed",
+ "Invalid argument passed to ext2 library",
+ "Could not allocate block in ext2 filesystem",
+ "Could not allocate inode in ext2 filesystem",
+ "Ext2 inode is not a directory",
+ "Too many references in table",
+ "File not found by ext2_lookup",
+ "File open read-only",
+ "Ext2 directory block not found",
+ "Ext2 directory already exists",
+ "Unimplemented ext2 library function",
+ "User cancel requested",
+ "Ext2 file too big",
+ "Supplied journal device not a block device",
+ "Journal superblock not found",
+ "Journal must be at least 1024 blocks",
+ "Unsupported journal version",
+ "Error loading external journal",
+ 0
+};
+
+struct error_table {
+ char const * const * msgs;
+ long base;
+ int n_msgs;
+};
+struct et_list {
+ struct et_list *next;
+ const struct error_table * table;
+};
+extern struct et_list *_et_list;
+
+const struct error_table et_ext2_error_table = { text, 2133571328L, 88 };
+
+static struct et_list link = { 0, 0 };
+
+void initialize_ext2_error_table_r(struct et_list **list);
+void initialize_ext2_error_table(void);
+
+void initialize_ext2_error_table(void) {
+ initialize_ext2_error_table_r(&_et_list);
+}
+
+/* For Heimdal compatibility */
+void initialize_ext2_error_table_r(struct et_list **list)
+{
+ struct et_list *et, **end;
+
+ for (end = list, et = *list; et; end = &et->next, et = et->next)
+ if (et->table->msgs == text)
+ return;
+ et = malloc(sizeof(struct et_list));
+ if (et == 0) {
+ if (!link.table)
+ et = &link;
+ else
+ return;
+ }
+ et->table = &et_ext2_error_table;
+ et->next = 0;
+ *end = et;
+}
diff --git a/e2fslib/ext2_err.et b/e2fslib/ext2_err.et
new file mode 100644
index 0000000..d58ba4c
--- /dev/null
+++ b/e2fslib/ext2_err.et
@@ -0,0 +1,276 @@
+#
+# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+#
+# %Begin-Header%
+# This file may be redistributed under the terms of the GNU Public
+# License.
+# %End-Header%
+#
+ error_table ext2
+
+ec EXT2_ET_BASE,
+ "EXT2FS Library version 1.25"
+
+ec EXT2_ET_MAGIC_EXT2FS_FILSYS,
+ "Wrong magic number for ext2_filsys structure"
+
+ec EXT2_ET_MAGIC_BADBLOCKS_LIST,
+ "Wrong magic number for badblocks_list structure"
+
+ec EXT2_ET_MAGIC_BADBLOCKS_ITERATE,
+ "Wrong magic number for badblocks_iterate structure"
+
+ec EXT2_ET_MAGIC_INODE_SCAN,
+ "Wrong magic number for inode_scan structure"
+
+ec EXT2_ET_MAGIC_IO_CHANNEL,
+ "Wrong magic number for io_channel structure"
+
+ec EXT2_ET_MAGIC_UNIX_IO_CHANNEL,
+ "Wrong magic number for unix io_channel structure"
+
+ec EXT2_ET_MAGIC_IO_MANAGER,
+ "Wrong magic number for io_manager structure"
+
+ec EXT2_ET_MAGIC_BLOCK_BITMAP,
+ "Wrong magic number for block_bitmap structure"
+
+ec EXT2_ET_MAGIC_INODE_BITMAP,
+ "Wrong magic number for inode_bitmap structure"
+
+ec EXT2_ET_MAGIC_GENERIC_BITMAP,
+ "Wrong magic number for generic_bitmap structure"
+
+ec EXT2_ET_MAGIC_TEST_IO_CHANNEL,
+ "Wrong magic number for test io_channel structure"
+
+ec EXT2_ET_MAGIC_DBLIST,
+ "Wrong magic number for directory block list structure"
+
+ec EXT2_ET_MAGIC_ICOUNT,
+ "Wrong magic number for icount structure"
+
+ec EXT2_ET_MAGIC_PQ_IO_CHANNEL,
+ "Wrong magic number for Powerquest io_channel structure"
+
+ec EXT2_ET_MAGIC_EXT2_FILE,
+ "Wrong magic number for ext2 file structure"
+
+ec EXT2_ET_MAGIC_E2IMAGE,
+ "Wrong magic number for Ext2 Image Header"
+
+ec EXT2_ET_MAGIC_RESERVED_8,
+ "Wrong magic number --- RESERVED_8"
+
+ec EXT2_ET_MAGIC_RESERVED_9,
+ "Wrong magic number --- RESERVED_9"
+
+ec EXT2_ET_BAD_MAGIC,
+ "Bad magic number in super-block"
+
+ec EXT2_ET_REV_TOO_HIGH,
+ "Filesystem revision too high"
+
+ec EXT2_ET_RO_FILSYS,
+ "Attempt to write to filesystem opened read-only"
+
+ec EXT2_ET_GDESC_READ,
+ "Can't read group descriptors"
+
+ec EXT2_ET_GDESC_WRITE,
+ "Can't write group descriptors"
+
+ec EXT2_ET_GDESC_BAD_BLOCK_MAP,
+ "Corrupt group descriptor: bad block for block bitmap"
+
+ec EXT2_ET_GDESC_BAD_INODE_MAP,
+ "Corrupt group descriptor: bad block for inode bitmap"
+
+ec EXT2_ET_GDESC_BAD_INODE_TABLE,
+ "Corrupt group descriptor: bad block for inode table"
+
+ec EXT2_ET_INODE_BITMAP_WRITE,
+ "Can't write an inode bitmap"
+
+ec EXT2_ET_INODE_BITMAP_READ,
+ "Can't read an inode bitmap"
+
+ec EXT2_ET_BLOCK_BITMAP_WRITE,
+ "Can't write an block bitmap"
+
+ec EXT2_ET_BLOCK_BITMAP_READ,
+ "Can't read an block bitmap"
+
+ec EXT2_ET_INODE_TABLE_WRITE,
+ "Can't write an inode table"
+
+ec EXT2_ET_INODE_TABLE_READ,
+ "Can't read an inode table"
+
+ec EXT2_ET_NEXT_INODE_READ,
+ "Can't read next inode"
+
+ec EXT2_ET_UNEXPECTED_BLOCK_SIZE,
+ "Filesystem has unexpected block size"
+
+ec EXT2_ET_DIR_CORRUPTED,
+ "EXT2 directory corrupted"
+
+ec EXT2_ET_SHORT_READ,
+ "Attempt to read block from filesystem resulted in short read"
+
+ec EXT2_ET_SHORT_WRITE,
+ "Attempt to write block from filesystem resulted in short write"
+
+ec EXT2_ET_DIR_NO_SPACE,
+ "No free space in the directory"
+
+ec EXT2_ET_NO_INODE_BITMAP,
+ "Inode bitmap not loaded"
+
+ec EXT2_ET_NO_BLOCK_BITMAP,
+ "Block bitmap not loaded"
+
+ec EXT2_ET_BAD_INODE_NUM,
+ "Illegal inode number"
+
+ec EXT2_ET_BAD_BLOCK_NUM,
+ "Illegal block number"
+
+ec EXT2_ET_EXPAND_DIR_ERR,
+ "Internal error in ext2fs_expand_dir"
+
+ec EXT2_ET_TOOSMALL,
+ "Not enough space to build proposed filesystem"
+
+ec EXT2_ET_BAD_BLOCK_MARK,
+ "Illegal block number passed to ext2fs_mark_block_bitmap"
+
+ec EXT2_ET_BAD_BLOCK_UNMARK,
+ "Illegal block number passed to ext2fs_unmark_block_bitmap"
+
+ec EXT2_ET_BAD_BLOCK_TEST,
+ "Illegal block number passed to ext2fs_test_block_bitmap"
+
+ec EXT2_ET_BAD_INODE_MARK,
+ "Illegal inode number passed to ext2fs_mark_inode_bitmap"
+
+ec EXT2_ET_BAD_INODE_UNMARK,
+ "Illegal inode number passed to ext2fs_unmark_inode_bitmap"
+
+ec EXT2_ET_BAD_INODE_TEST,
+ "Illegal inode number passed to ext2fs_test_inode_bitmap"
+
+ec EXT2_ET_FUDGE_BLOCK_BITMAP_END,
+ "Attempt to fudge end of block bitmap past the real end"
+
+ec EXT2_ET_FUDGE_INODE_BITMAP_END,
+ "Attempt to fudge end of inode bitmap past the real end"
+
+ec EXT2_ET_BAD_IND_BLOCK,
+ "Illegal indirect block found"
+
+ec EXT2_ET_BAD_DIND_BLOCK,
+ "Illegal doubly indirect block found"
+
+ec EXT2_ET_BAD_TIND_BLOCK,
+ "Illegal triply indirect block found"
+
+ec EXT2_ET_NEQ_BLOCK_BITMAP,
+ "Block bitmaps are not the same"
+
+ec EXT2_ET_NEQ_INODE_BITMAP,
+ "Inode bitmaps are not the same"
+
+ec EXT2_ET_BAD_DEVICE_NAME,
+ "Illegal or malformed device name"
+
+ec EXT2_ET_MISSING_INODE_TABLE,
+ "A block group is missing an inode table"
+
+ec EXT2_ET_CORRUPT_SUPERBLOCK,
+ "The ext2 superblock is corrupt"
+
+ec EXT2_ET_BAD_GENERIC_MARK,
+ "Illegal generic bit number passed to ext2fs_mark_generic_bitmap"
+
+ec EXT2_ET_BAD_GENERIC_UNMARK,
+ "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap"
+
+ec EXT2_ET_BAD_GENERIC_TEST,
+ "Illegal generic bit number passed to ext2fs_test_generic_bitmap"
+
+ec EXT2_ET_SYMLINK_LOOP,
+ "Too many symbolic links encountered."
+
+ec EXT2_ET_CALLBACK_NOTHANDLED,
+ "The callback function will not handle this case"
+
+ec EXT2_ET_BAD_BLOCK_IN_INODE_TABLE,
+ "The inode is from a bad block in the inode table"
+
+ec EXT2_ET_UNSUPP_FEATURE,
+ "Filesystem has unsupported feature(s)"
+
+ec EXT2_ET_RO_UNSUPP_FEATURE,
+ "Filesystem has unsupported read-only feature(s)"
+
+ec EXT2_ET_LLSEEK_FAILED,
+ "IO Channel failed to seek on read or write"
+
+ec EXT2_ET_NO_MEMORY,
+ "Memory allocation failed"
+
+ec EXT2_ET_INVALID_ARGUMENT,
+ "Invalid argument passed to ext2 library"
+
+ec EXT2_ET_BLOCK_ALLOC_FAIL,
+ "Could not allocate block in ext2 filesystem"
+
+ec EXT2_ET_INODE_ALLOC_FAIL,
+ "Could not allocate inode in ext2 filesystem"
+
+ec EXT2_ET_NO_DIRECTORY,
+ "Ext2 inode is not a directory"
+
+ec EXT2_ET_TOO_MANY_REFS,
+ "Too many references in table"
+
+ec EXT2_ET_FILE_NOT_FOUND,
+ "File not found by ext2_lookup"
+
+ec EXT2_ET_FILE_RO,
+ "File open read-only"
+
+ec EXT2_ET_DB_NOT_FOUND,
+ "Ext2 directory block not found"
+
+ec EXT2_ET_DIR_EXISTS,
+ "Ext2 directory already exists"
+
+ec EXT2_ET_UNIMPLEMENTED,
+ "Unimplemented ext2 library function"
+
+ec EXT2_ET_CANCEL_REQUESTED,
+ "User cancel requested"
+
+ec EXT2_ET_FILE_TOO_BIG,
+ "Ext2 file too big"
+
+ec EXT2_ET_JOURNAL_NOT_BLOCK,
+ "Supplied journal device not a block device"
+
+ec EXT2_ET_NO_JOURNAL_SB,
+ "Journal superblock not found"
+
+ec EXT2_ET_JOURNAL_TOO_SMALL,
+ "Journal must be at least 1024 blocks"
+
+ec EXT2_ET_JOURNAL_UNSUPP_VERSION,
+ "Unsupported journal version"
+
+ec EXT2_ET_LOAD_EXT_JOURNAL,
+ "Error loading external journal"
+
+ end
+
diff --git a/e2fslib/ext2_err.et.in b/e2fslib/ext2_err.et.in
new file mode 100644
index 0000000..235f75d
--- /dev/null
+++ b/e2fslib/ext2_err.et.in
@@ -0,0 +1,276 @@
+#
+# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+#
+# %Begin-Header%
+# This file may be redistributed under the terms of the GNU Public
+# License.
+# %End-Header%
+#
+ error_table ext2
+
+ec EXT2_ET_BASE,
+ "EXT2FS Library version @E2FSPROGS_VERSION@"
+
+ec EXT2_ET_MAGIC_EXT2FS_FILSYS,
+ "Wrong magic number for ext2_filsys structure"
+
+ec EXT2_ET_MAGIC_BADBLOCKS_LIST,
+ "Wrong magic number for badblocks_list structure"
+
+ec EXT2_ET_MAGIC_BADBLOCKS_ITERATE,
+ "Wrong magic number for badblocks_iterate structure"
+
+ec EXT2_ET_MAGIC_INODE_SCAN,
+ "Wrong magic number for inode_scan structure"
+
+ec EXT2_ET_MAGIC_IO_CHANNEL,
+ "Wrong magic number for io_channel structure"
+
+ec EXT2_ET_MAGIC_UNIX_IO_CHANNEL,
+ "Wrong magic number for unix io_channel structure"
+
+ec EXT2_ET_MAGIC_IO_MANAGER,
+ "Wrong magic number for io_manager structure"
+
+ec EXT2_ET_MAGIC_BLOCK_BITMAP,
+ "Wrong magic number for block_bitmap structure"
+
+ec EXT2_ET_MAGIC_INODE_BITMAP,
+ "Wrong magic number for inode_bitmap structure"
+
+ec EXT2_ET_MAGIC_GENERIC_BITMAP,
+ "Wrong magic number for generic_bitmap structure"
+
+ec EXT2_ET_MAGIC_TEST_IO_CHANNEL,
+ "Wrong magic number for test io_channel structure"
+
+ec EXT2_ET_MAGIC_DBLIST,
+ "Wrong magic number for directory block list structure"
+
+ec EXT2_ET_MAGIC_ICOUNT,
+ "Wrong magic number for icount structure"
+
+ec EXT2_ET_MAGIC_PQ_IO_CHANNEL,
+ "Wrong magic number for Powerquest io_channel structure"
+
+ec EXT2_ET_MAGIC_EXT2_FILE,
+ "Wrong magic number for ext2 file structure"
+
+ec EXT2_ET_MAGIC_E2IMAGE,
+ "Wrong magic number for Ext2 Image Header"
+
+ec EXT2_ET_MAGIC_RESERVED_8,
+ "Wrong magic number --- RESERVED_8"
+
+ec EXT2_ET_MAGIC_RESERVED_9,
+ "Wrong magic number --- RESERVED_9"
+
+ec EXT2_ET_BAD_MAGIC,
+ "Bad magic number in super-block"
+
+ec EXT2_ET_REV_TOO_HIGH,
+ "Filesystem revision too high"
+
+ec EXT2_ET_RO_FILSYS,
+ "Attempt to write to filesystem opened read-only"
+
+ec EXT2_ET_GDESC_READ,
+ "Can't read group descriptors"
+
+ec EXT2_ET_GDESC_WRITE,
+ "Can't write group descriptors"
+
+ec EXT2_ET_GDESC_BAD_BLOCK_MAP,
+ "Corrupt group descriptor: bad block for block bitmap"
+
+ec EXT2_ET_GDESC_BAD_INODE_MAP,
+ "Corrupt group descriptor: bad block for inode bitmap"
+
+ec EXT2_ET_GDESC_BAD_INODE_TABLE,
+ "Corrupt group descriptor: bad block for inode table"
+
+ec EXT2_ET_INODE_BITMAP_WRITE,
+ "Can't write an inode bitmap"
+
+ec EXT2_ET_INODE_BITMAP_READ,
+ "Can't read an inode bitmap"
+
+ec EXT2_ET_BLOCK_BITMAP_WRITE,
+ "Can't write an block bitmap"
+
+ec EXT2_ET_BLOCK_BITMAP_READ,
+ "Can't read an block bitmap"
+
+ec EXT2_ET_INODE_TABLE_WRITE,
+ "Can't write an inode table"
+
+ec EXT2_ET_INODE_TABLE_READ,
+ "Can't read an inode table"
+
+ec EXT2_ET_NEXT_INODE_READ,
+ "Can't read next inode"
+
+ec EXT2_ET_UNEXPECTED_BLOCK_SIZE,
+ "Filesystem has unexpected block size"
+
+ec EXT2_ET_DIR_CORRUPTED,
+ "EXT2 directory corrupted"
+
+ec EXT2_ET_SHORT_READ,
+ "Attempt to read block from filesystem resulted in short read"
+
+ec EXT2_ET_SHORT_WRITE,
+ "Attempt to write block from filesystem resulted in short write"
+
+ec EXT2_ET_DIR_NO_SPACE,
+ "No free space in the directory"
+
+ec EXT2_ET_NO_INODE_BITMAP,
+ "Inode bitmap not loaded"
+
+ec EXT2_ET_NO_BLOCK_BITMAP,
+ "Block bitmap not loaded"
+
+ec EXT2_ET_BAD_INODE_NUM,
+ "Illegal inode number"
+
+ec EXT2_ET_BAD_BLOCK_NUM,
+ "Illegal block number"
+
+ec EXT2_ET_EXPAND_DIR_ERR,
+ "Internal error in ext2fs_expand_dir"
+
+ec EXT2_ET_TOOSMALL,
+ "Not enough space to build proposed filesystem"
+
+ec EXT2_ET_BAD_BLOCK_MARK,
+ "Illegal block number passed to ext2fs_mark_block_bitmap"
+
+ec EXT2_ET_BAD_BLOCK_UNMARK,
+ "Illegal block number passed to ext2fs_unmark_block_bitmap"
+
+ec EXT2_ET_BAD_BLOCK_TEST,
+ "Illegal block number passed to ext2fs_test_block_bitmap"
+
+ec EXT2_ET_BAD_INODE_MARK,
+ "Illegal inode number passed to ext2fs_mark_inode_bitmap"
+
+ec EXT2_ET_BAD_INODE_UNMARK,
+ "Illegal inode number passed to ext2fs_unmark_inode_bitmap"
+
+ec EXT2_ET_BAD_INODE_TEST,
+ "Illegal inode number passed to ext2fs_test_inode_bitmap"
+
+ec EXT2_ET_FUDGE_BLOCK_BITMAP_END,
+ "Attempt to fudge end of block bitmap past the real end"
+
+ec EXT2_ET_FUDGE_INODE_BITMAP_END,
+ "Attempt to fudge end of inode bitmap past the real end"
+
+ec EXT2_ET_BAD_IND_BLOCK,
+ "Illegal indirect block found"
+
+ec EXT2_ET_BAD_DIND_BLOCK,
+ "Illegal doubly indirect block found"
+
+ec EXT2_ET_BAD_TIND_BLOCK,
+ "Illegal triply indirect block found"
+
+ec EXT2_ET_NEQ_BLOCK_BITMAP,
+ "Block bitmaps are not the same"
+
+ec EXT2_ET_NEQ_INODE_BITMAP,
+ "Inode bitmaps are not the same"
+
+ec EXT2_ET_BAD_DEVICE_NAME,
+ "Illegal or malformed device name"
+
+ec EXT2_ET_MISSING_INODE_TABLE,
+ "A block group is missing an inode table"
+
+ec EXT2_ET_CORRUPT_SUPERBLOCK,
+ "The ext2 superblock is corrupt"
+
+ec EXT2_ET_BAD_GENERIC_MARK,
+ "Illegal generic bit number passed to ext2fs_mark_generic_bitmap"
+
+ec EXT2_ET_BAD_GENERIC_UNMARK,
+ "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap"
+
+ec EXT2_ET_BAD_GENERIC_TEST,
+ "Illegal generic bit number passed to ext2fs_test_generic_bitmap"
+
+ec EXT2_ET_SYMLINK_LOOP,
+ "Too many symbolic links encountered."
+
+ec EXT2_ET_CALLBACK_NOTHANDLED,
+ "The callback function will not handle this case"
+
+ec EXT2_ET_BAD_BLOCK_IN_INODE_TABLE,
+ "The inode is from a bad block in the inode table"
+
+ec EXT2_ET_UNSUPP_FEATURE,
+ "Filesystem has unsupported feature(s)"
+
+ec EXT2_ET_RO_UNSUPP_FEATURE,
+ "Filesystem has unsupported read-only feature(s)"
+
+ec EXT2_ET_LLSEEK_FAILED,
+ "IO Channel failed to seek on read or write"
+
+ec EXT2_ET_NO_MEMORY,
+ "Memory allocation failed"
+
+ec EXT2_ET_INVALID_ARGUMENT,
+ "Invalid argument passed to ext2 library"
+
+ec EXT2_ET_BLOCK_ALLOC_FAIL,
+ "Could not allocate block in ext2 filesystem"
+
+ec EXT2_ET_INODE_ALLOC_FAIL,
+ "Could not allocate inode in ext2 filesystem"
+
+ec EXT2_ET_NO_DIRECTORY,
+ "Ext2 inode is not a directory"
+
+ec EXT2_ET_TOO_MANY_REFS,
+ "Too many references in table"
+
+ec EXT2_ET_FILE_NOT_FOUND,
+ "File not found by ext2_lookup"
+
+ec EXT2_ET_FILE_RO,
+ "File open read-only"
+
+ec EXT2_ET_DB_NOT_FOUND,
+ "Ext2 directory block not found"
+
+ec EXT2_ET_DIR_EXISTS,
+ "Ext2 directory already exists"
+
+ec EXT2_ET_UNIMPLEMENTED,
+ "Unimplemented ext2 library function"
+
+ec EXT2_ET_CANCEL_REQUESTED,
+ "User cancel requested"
+
+ec EXT2_ET_FILE_TOO_BIG,
+ "Ext2 file too big"
+
+ec EXT2_ET_JOURNAL_NOT_BLOCK,
+ "Supplied journal device not a block device"
+
+ec EXT2_ET_NO_JOURNAL_SB,
+ "Journal superblock not found"
+
+ec EXT2_ET_JOURNAL_TOO_SMALL,
+ "Journal must be at least 1024 blocks"
+
+ec EXT2_ET_JOURNAL_UNSUPP_VERSION,
+ "Unsupported journal version"
+
+ec EXT2_ET_LOAD_EXT_JOURNAL,
+ "Error loading external journal"
+
+ end
+
diff --git a/e2fslib/ext2_err.h b/e2fslib/ext2_err.h
new file mode 100644
index 0000000..5ff5afc
--- /dev/null
+++ b/e2fslib/ext2_err.h
@@ -0,0 +1,106 @@
+/*
+ * :
+ * This file is automatically generated; please do not edit it.
+ */
+
+#include <et/com_err.h>
+
+#define EXT2_ET_BASE (2133571328L)
+#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
+#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
+#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
+#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
+#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
+#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
+#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
+#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
+#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
+#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
+#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
+#define EXT2_ET_MAGIC_DBLIST (2133571340L)
+#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
+#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
+#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
+#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
+#define EXT2_ET_MAGIC_RESERVED_8 (2133571345L)
+#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L)
+#define EXT2_ET_BAD_MAGIC (2133571347L)
+#define EXT2_ET_REV_TOO_HIGH (2133571348L)
+#define EXT2_ET_RO_FILSYS (2133571349L)
+#define EXT2_ET_GDESC_READ (2133571350L)
+#define EXT2_ET_GDESC_WRITE (2133571351L)
+#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
+#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
+#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
+#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
+#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
+#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
+#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
+#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
+#define EXT2_ET_INODE_TABLE_READ (2133571360L)
+#define EXT2_ET_NEXT_INODE_READ (2133571361L)
+#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
+#define EXT2_ET_DIR_CORRUPTED (2133571363L)
+#define EXT2_ET_SHORT_READ (2133571364L)
+#define EXT2_ET_SHORT_WRITE (2133571365L)
+#define EXT2_ET_DIR_NO_SPACE (2133571366L)
+#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
+#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
+#define EXT2_ET_BAD_INODE_NUM (2133571369L)
+#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
+#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
+#define EXT2_ET_TOOSMALL (2133571372L)
+#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
+#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
+#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
+#define EXT2_ET_BAD_INODE_MARK (2133571376L)
+#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
+#define EXT2_ET_BAD_INODE_TEST (2133571378L)
+#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
+#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
+#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
+#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
+#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
+#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
+#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
+#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
+#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
+#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
+#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
+#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
+#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
+#define EXT2_ET_SYMLINK_LOOP (2133571392L)
+#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
+#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
+#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
+#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
+#define EXT2_ET_LLSEEK_FAILED (2133571397L)
+#define EXT2_ET_NO_MEMORY (2133571398L)
+#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
+#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
+#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
+#define EXT2_ET_NO_DIRECTORY (2133571402L)
+#define EXT2_ET_TOO_MANY_REFS (2133571403L)
+#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
+#define EXT2_ET_FILE_RO (2133571405L)
+#define EXT2_ET_DB_NOT_FOUND (2133571406L)
+#define EXT2_ET_DIR_EXISTS (2133571407L)
+#define EXT2_ET_UNIMPLEMENTED (2133571408L)
+#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
+#define EXT2_ET_FILE_TOO_BIG (2133571410L)
+#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
+#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
+#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
+#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
+#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
+extern const struct error_table et_ext2_error_table;
+extern void initialize_ext2_error_table(void);
+
+/* For compatibility with Heimdal */
+extern void initialize_ext2_error_table_r(struct et_list **list);
+
+#define ERROR_TABLE_BASE_ext2 (2133571328L)
+
+/* for compatibility with older versions... */
+#define init_ext2_err_tbl initialize_ext2_error_table
+#define ext2_err_base ERROR_TABLE_BASE_ext2
diff --git a/e2fslib/ext2_err.o b/e2fslib/ext2_err.o
new file mode 100644
index 0000000..282d74a
--- /dev/null
+++ b/e2fslib/ext2_err.o
Binary files differ
diff --git a/e2fslib/ext2_ext_attr.h b/e2fslib/ext2_ext_attr.h
new file mode 100644
index 0000000..504f747
--- /dev/null
+++ b/e2fslib/ext2_ext_attr.h
@@ -0,0 +1,58 @@
+/*
+ File: linux/ext2_ext_attr.h
+
+ On-disk format of extended attributes for the ext2 filesystem.
+
+ (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
+*/
+
+/* Magic value in attribute blocks */
+#define EXT2_EXT_ATTR_MAGIC 0xEA010000
+
+/* Maximum number of references to one attribute block */
+#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
+
+struct ext2_ext_attr_header {
+ __u32 h_magic; /* magic number for identification */
+ __u32 h_refcount; /* reference count */
+ __u32 h_blocks; /* number of disk blocks used */
+ __u32 h_hash; /* hash value of all attributes */
+ __u32 h_reserved[4]; /* zero right now */
+};
+
+struct ext2_ext_attr_entry {
+ __u8 e_name_len; /* length of name */
+ __u8 e_name_index; /* index into table of names (n/i) */
+ __u16 e_value_offs; /* offset in disk block of value */
+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
+ __u32 e_value_size; /* size of attribute value */
+ __u32 e_hash; /* hash value of name and value */
+ char e_name[0]; /* attribute name */
+};
+
+#define EXT2_EXT_ATTR_PAD_BITS 2
+#define EXT2_EXT_ATTR_PAD (1<<EXT2_EXT_ATTR_PAD_BITS)
+#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
+#define EXT2_EXT_ATTR_LEN(name_len) \
+ (((name_len) + EXT2_EXT_ATTR_ROUND + \
+ sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_EXT_ATTR_NEXT(entry) \
+ ( (struct ext2_ext_attr_entry *)( \
+ (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
+#define EXT2_EXT_ATTR_SIZE(size) \
+ (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
+
+#ifdef __KERNEL__
+# ifdef CONFIG_EXT2_FS_EXT_ATTR
+extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int);
+extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int);
+extern void ext2_ext_attr_free_inode(struct inode *inode);
+extern void ext2_ext_attr_put_super(struct super_block *sb);
+extern int ext2_ext_attr_init(void);
+extern void ext2_ext_attr_done(void);
+# else
+# define ext2_get_ext_attr NULL
+# define ext2_set_ext_attr NULL
+# endif
+#endif /* __KERNEL__ */
+
diff --git a/e2fslib/ext2_fs.h b/e2fslib/ext2_fs.h
new file mode 100644
index 0000000..25a9492
--- /dev/null
+++ b/e2fslib/ext2_fs.h
@@ -0,0 +1,624 @@
+/*
+ * linux/include/linux/ext2_fs.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/include/linux/minix_fs.h
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT2_FS_H
+#define _LINUX_EXT2_FS_H
+
+#include <ext2_types.h> /* Changed from linux/types.h */
+
+/*
+ * The second extended filesystem constants/structures
+ */
+
+/*
+ * Define EXT2FS_DEBUG to produce debug messages
+ */
+#undef EXT2FS_DEBUG
+
+/*
+ * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
+ */
+#define EXT2_PREALLOCATE
+#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
+
+/*
+ * The second extended file system version
+ */
+#define EXT2FS_DATE "95/08/09"
+#define EXT2FS_VERSION "0.5b"
+
+/*
+ * Special inodes numbers
+ */
+#define EXT2_BAD_INO 1 /* Bad blocks inode */
+#define EXT2_ROOT_INO 2 /* Root inode */
+#define EXT2_ACL_IDX_INO 3 /* ACL inode */
+#define EXT2_ACL_DATA_INO 4 /* ACL inode */
+#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
+#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
+#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
+#define EXT2_JOURNAL_INO 8 /* Journal inode */
+
+/* First non-reserved inode for old ext2 filesystems */
+#define EXT2_GOOD_OLD_FIRST_INO 11
+
+/*
+ * The second extended file system magic number
+ */
+#define EXT2_SUPER_MAGIC 0xEF53
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX 32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT2_MIN_BLOCK_SIZE 1024
+#define EXT2_MAX_BLOCK_SIZE 4096
+#define EXT2_MIN_BLOCK_LOG_SIZE 10
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
+#else
+# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#endif
+#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
+#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
+#else
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+#endif
+#ifdef __KERNEL__
+#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
+#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
+#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
+#else
+#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+ EXT2_GOOD_OLD_INODE_SIZE : \
+ (s)->s_inode_size)
+#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+ EXT2_GOOD_OLD_FIRST_INO : \
+ (s)->s_first_ino)
+#endif
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT2_MIN_FRAG_SIZE 1024
+#define EXT2_MAX_FRAG_SIZE 4096
+#define EXT2_MIN_FRAG_LOG_SIZE 10
+#ifdef __KERNEL__
+# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
+#else
+# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+#endif
+
+/*
+ * ACL structures
+ */
+struct ext2_acl_header /* Header of Access Control Lists */
+{
+ __u32 aclh_size;
+ __u32 aclh_file_count;
+ __u32 aclh_acle_count;
+ __u32 aclh_first_acle;
+};
+
+struct ext2_acl_entry /* Access Control List Entry */
+{
+ __u32 acle_size;
+ __u16 acle_perms; /* Access permissions */
+ __u16 acle_type; /* Type of entry */
+ __u16 acle_tag; /* User or group identity */
+ __u16 acle_pad1;
+ __u32 acle_next; /* Pointer on next entry for the */
+ /* same inode or on next free entry */
+};
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext2_group_desc
+{
+ __u32 bg_block_bitmap; /* Blocks bitmap block */
+ __u32 bg_inode_bitmap; /* Inodes bitmap block */
+ __u32 bg_inode_table; /* Inodes table block */
+ __u16 bg_free_blocks_count; /* Free blocks count */
+ __u16 bg_free_inodes_count; /* Free inodes count */
+ __u16 bg_used_dirs_count; /* Directories count */
+ __u16 bg_pad;
+ __u32 bg_reserved[3];
+};
+
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+#ifdef __KERNEL__
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
+# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
+# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
+#else
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
+#endif
+
+/*
+ * Constants relative to the data blocks
+ */
+#define EXT2_NDIR_BLOCKS 12
+#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
+#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
+#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
+
+/*
+ * Inode flags
+ */
+#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
+#define EXT2_UNRM_FL 0x00000002 /* Undelete */
+#define EXT2_COMPR_FL 0x00000004 /* Compress file */
+#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
+#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
+#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
+#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
+#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL 0x00000100
+#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
+#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */
+#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */
+#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
+#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */
+#define EXT2_IMAGIC_FL 0x00002000
+#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
+#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
+
+#define EXT2_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
+
+/*
+ * ioctl commands
+ */
+#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
+#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
+#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
+#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+ __u16 i_mode; /* File mode */
+ __u16 i_uid; /* Low 16 bits of Owner Uid */
+ __u32 i_size; /* Size in bytes */
+ __u32 i_atime; /* Access time */
+ __u32 i_ctime; /* Creation time */
+ __u32 i_mtime; /* Modification time */
+ __u32 i_dtime; /* Deletion Time */
+ __u16 i_gid; /* Low 16 bits of Group Id */
+ __u16 i_links_count; /* Links count */
+ __u32 i_blocks; /* Blocks count */
+ __u32 i_flags; /* File flags */
+ union {
+ struct {
+ __u32 l_i_reserved1;
+ } linux1;
+ struct {
+ __u32 h_i_translator;
+ } hurd1;
+ struct {
+ __u32 m_i_reserved1;
+ } masix1;
+ } osd1; /* OS dependent 1 */
+ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+ __u32 i_generation; /* File version (for NFS) */
+ __u32 i_file_acl; /* File ACL */
+ __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_faddr; /* Fragment address */
+ union {
+ struct {
+ __u8 l_i_frag; /* Fragment number */
+ __u8 l_i_fsize; /* Fragment size */
+ __u16 i_pad1;
+ __u16 l_i_uid_high; /* these 2 fields */
+ __u16 l_i_gid_high; /* were reserved2[0] */
+ __u32 l_i_reserved2;
+ } linux2;
+ struct {
+ __u8 h_i_frag; /* Fragment number */
+ __u8 h_i_fsize; /* Fragment size */
+ __u16 h_i_mode_high;
+ __u16 h_i_uid_high;
+ __u16 h_i_gid_high;
+ __u32 h_i_author;
+ } hurd2;
+ struct {
+ __u8 m_i_frag; /* Fragment number */
+ __u8 m_i_fsize; /* Fragment size */
+ __u16 m_pad1;
+ __u32 m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
+};
+
+#define i_size_high i_dir_acl
+
+#if defined(__KERNEL__) || defined(__linux__)
+#define i_reserved1 osd1.linux1.l_i_reserved1
+#define i_frag osd2.linux2.l_i_frag
+#define i_fsize osd2.linux2.l_i_fsize
+#define i_uid_low i_uid
+#define i_gid_low i_gid
+#define i_uid_high osd2.linux2.l_i_uid_high
+#define i_gid_high osd2.linux2.l_i_gid_high
+#define i_reserved2 osd2.linux2.l_i_reserved2
+
+#elif defined(__GNU__)
+
+#define i_translator osd1.hurd1.h_i_translator
+#define i_frag osd2.hurd2.h_i_frag;
+#define i_fsize osd2.hurd2.h_i_fsize;
+#define i_uid_high osd2.hurd2.h_i_uid_high
+#define i_gid_high osd2.hurd2.h_i_gid_high
+#define i_author osd2.hurd2.h_i_author
+
+#elif defined(__masix__)
+
+#define i_reserved1 osd1.masix1.m_i_reserved1
+#define i_frag osd2.masix2.m_i_frag
+#define i_fsize osd2.masix2.m_i_fsize
+#define i_reserved2 osd2.masix2.m_i_reserved2
+
+#endif /* defined(__KERNEL) || defined(__linux__) */
+
+/*
+ * File system states
+ */
+#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
+#define EXT2_ERROR_FS 0x0002 /* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
+#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
+#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
+
+#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
+ EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
+#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
+#define EXT2_ERRORS_PANIC 3 /* Panic */
+#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext2_super_block {
+ __u32 s_inodes_count; /* Inodes count */
+ __u32 s_blocks_count; /* Blocks count */
+ __u32 s_r_blocks_count; /* Reserved blocks count */
+ __u32 s_free_blocks_count; /* Free blocks count */
+ __u32 s_free_inodes_count; /* Free inodes count */
+ __u32 s_first_data_block; /* First Data Block */
+ __u32 s_log_block_size; /* Block size */
+ __s32 s_log_frag_size; /* Fragment size */
+ __u32 s_blocks_per_group; /* # Blocks per group */
+ __u32 s_frags_per_group; /* # Fragments per group */
+ __u32 s_inodes_per_group; /* # Inodes per group */
+ __u32 s_mtime; /* Mount time */
+ __u32 s_wtime; /* Write time */
+ __u16 s_mnt_count; /* Mount count */
+ __s16 s_max_mnt_count; /* Maximal mount count */
+ __u16 s_magic; /* Magic signature */
+ __u16 s_state; /* File system state */
+ __u16 s_errors; /* Behaviour when detecting errors */
+ __u16 s_minor_rev_level; /* minor revision level */
+ __u32 s_lastcheck; /* time of last check */
+ __u32 s_checkinterval; /* max. time between checks */
+ __u32 s_creator_os; /* OS */
+ __u32 s_rev_level; /* Revision level */
+ __u16 s_def_resuid; /* Default uid for reserved blocks */
+ __u16 s_def_resgid; /* Default gid for reserved blocks */
+ /*
+ * These fields are for EXT2_DYNAMIC_REV superblocks only.
+ *
+ * Note: the difference between the compatible feature set and
+ * the incompatible feature set is that if there is a bit set
+ * in the incompatible feature set that the kernel doesn't
+ * know about, it should refuse to mount the filesystem.
+ *
+ * e2fsck's requirements are more strict; if it doesn't know
+ * about a feature in either the compatible or incompatible
+ * feature set, it must abort and not try to meddle with
+ * things it doesn't understand...
+ */
+ __u32 s_first_ino; /* First non-reserved inode */
+ __u16 s_inode_size; /* size of inode structure */
+ __u16 s_block_group_nr; /* block group # of this superblock */
+ __u32 s_feature_compat; /* compatible feature set */
+ __u32 s_feature_incompat; /* incompatible feature set */
+ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
+ __u8 s_uuid[16]; /* 128-bit uuid for volume */
+ char s_volume_name[16]; /* volume name */
+ char s_last_mounted[64]; /* directory where last mounted */
+ __u32 s_algorithm_usage_bitmap; /* For compression */
+ /*
+ * Performance hints. Directory preallocation should only
+ * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+ */
+ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+ __u16 s_padding1;
+ /*
+ * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
+ */
+ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
+ __u32 s_journal_inum; /* inode number of journal file */
+ __u32 s_journal_dev; /* device number of journal file */
+ __u32 s_last_orphan; /* start of list of inodes to delete */
+
+ __u32 s_reserved[197]; /* Padding to the end of the block */
+};
+
+#ifdef __KERNEL__
+#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
+#else
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block. This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb) (sb)
+#endif
+
+/*
+ * Codes for operating systems
+ */
+#define EXT2_OS_LINUX 0
+#define EXT2_OS_HURD 1
+#define EXT2_OS_MASIX 2
+#define EXT2_OS_FREEBSD 3
+#define EXT2_OS_LITES 4
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
+#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+
+#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
+#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
+/*
+ * Feature set definitions
+ */
+
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_feature_compat & (mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_feature_incompat & (mask) )
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
+#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
+
+#define EXT2_FEATURE_COMPAT_SUPP 0
+#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
+#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+
+/*
+ * Default values for user and/or group using reserved blocks
+ */
+#define EXT2_DEF_RESUID 0
+#define EXT2_DEF_RESGID 0
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT2_NAME_LEN 255
+
+struct ext2_dir_entry {
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u16 name_len; /* Name length */
+ char name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*
+ * The new version of the directory entry. Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u8 name_len; /* Name length */
+ __u8 file_type;
+ char name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*
+ * Ext2 directory file types. Only the low 3 bits are used. The
+ * other bits are reserved for now.
+ */
+#define EXT2_FT_UNKNOWN 0
+#define EXT2_FT_REG_FILE 1
+#define EXT2_FT_DIR 2
+#define EXT2_FT_CHRDEV 3
+#define EXT2_FT_BLKDEV 4
+#define EXT2_FT_FIFO 5
+#define EXT2_FT_SOCK 6
+#define EXT2_FT_SYMLINK 7
+
+#define EXT2_FT_MAX 8
+
+/*
+ * EXT2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT2_DIR_PAD 4
+#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+ ~EXT2_DIR_ROUND)
+
+#ifdef __KERNEL__
+/*
+ * Function prototypes
+ */
+
+/*
+ * Ok, these declarations are also in <linux/kernel.h> but none of the
+ * ext2 source programs needs to include it so they are duplicated here.
+ */
+# define NORET_TYPE /**/
+# define ATTRIB_NORET __attribute__((noreturn))
+# define NORET_AND noreturn,
+
+/* acl.c */
+extern int ext2_permission (struct inode *, int);
+
+/* balloc.c */
+extern int ext2_bg_has_super(struct super_block *sb, int group);
+extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
+extern int ext2_new_block (const struct inode *, unsigned long,
+ __u32 *, __u32 *, int *);
+extern void ext2_free_blocks (const struct inode *, unsigned long,
+ unsigned long);
+extern unsigned long ext2_count_free_blocks (struct super_block *);
+extern void ext2_check_blocks_bitmap (struct super_block *);
+extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+ unsigned int block_group,
+ struct buffer_head ** bh);
+
+/* bitmap.c */
+extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
+
+/* dir.c */
+extern int ext2_check_dir_entry (const char *, struct inode *,
+ struct ext2_dir_entry_2 *, struct buffer_head *,
+ unsigned long);
+
+/* file.c */
+extern int ext2_read (struct inode *, struct file *, char *, int);
+extern int ext2_write (struct inode *, struct file *, char *, int);
+
+/* fsync.c */
+extern int ext2_sync_file (struct file *, struct dentry *, int);
+extern int ext2_fsync_inode (struct inode *, int);
+
+/* ialloc.c */
+extern struct inode * ext2_new_inode (const struct inode *, int);
+extern void ext2_free_inode (struct inode *);
+extern unsigned long ext2_count_free_inodes (struct super_block *);
+extern void ext2_check_inodes_bitmap (struct super_block *);
+
+/* inode.c */
+
+extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
+extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
+
+extern void ext2_read_inode (struct inode *);
+extern void ext2_write_inode (struct inode *, int);
+extern void ext2_put_inode (struct inode *);
+extern void ext2_delete_inode (struct inode *);
+extern int ext2_sync_inode (struct inode *);
+extern void ext2_discard_prealloc (struct inode *);
+
+/* ioctl.c */
+extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+/* namei.c */
+extern struct inode_operations ext2_dir_inode_operations;
+
+/* super.c */
+extern void ext2_error (struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
+ const char *, ...)
+ __attribute__ ((NORET_AND format (printf, 3, 4)));
+extern void ext2_warning (struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern void ext2_update_dynamic_rev (struct super_block *sb);
+extern void ext2_put_super (struct super_block *);
+extern void ext2_write_super (struct super_block *);
+extern int ext2_remount (struct super_block *, int *, char *);
+extern struct super_block * ext2_read_super (struct super_block *,void *,int);
+extern int ext2_statfs (struct super_block *, struct statfs *);
+
+/* truncate.c */
+extern void ext2_truncate (struct inode *);
+
+/*
+ * Inodes and files operations
+ */
+
+/* dir.c */
+extern struct file_operations ext2_dir_operations;
+
+/* file.c */
+extern struct inode_operations ext2_file_inode_operations;
+extern struct file_operations ext2_file_operations;
+
+/* symlink.c */
+extern struct inode_operations ext2_fast_symlink_inode_operations;
+
+extern struct address_space_operations ext2_aops;
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_EXT2_FS_H */
diff --git a/e2fslib/ext2_io.h b/e2fslib/ext2_io.h
new file mode 100644
index 0000000..b9ba0b6
--- /dev/null
+++ b/e2fslib/ext2_io.h
@@ -0,0 +1,100 @@
+/*
+ * io.h --- the I/O manager abstraction
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#ifndef _EXT2FS_EXT2_IO_H
+#define _EXT2FS_EXT2_IO_H
+
+/*
+ * ext2_loff_t is defined here since unix_io.c needs it.
+ */
+#if defined(__GNUC__) || defined(HAS_LONG_LONG)
+typedef long long ext2_loff_t;
+#else
+typedef long ext2_loff_t;
+#endif
+
+/* llseek.c */
+ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int);
+
+typedef struct struct_io_manager *io_manager;
+typedef struct struct_io_channel *io_channel;
+
+#define CHANNEL_FLAGS_WRITETHROUGH 0x01
+
+struct struct_io_channel {
+ errcode_t magic;
+ io_manager manager;
+ char *name;
+ int block_size;
+ errcode_t (*read_error)(io_channel channel,
+ unsigned long block,
+ int count,
+ void *data,
+ size_t size,
+ int actual_bytes_read,
+ errcode_t error);
+ errcode_t (*write_error)(io_channel channel,
+ unsigned long block,
+ int count,
+ const void *data,
+ size_t size,
+ int actual_bytes_written,
+ errcode_t error);
+ int refcount;
+ int flags;
+ int reserved[14];
+ void *private_data;
+ void *app_data;
+};
+
+struct struct_io_manager {
+ errcode_t magic;
+ const char *name;
+ errcode_t (*open)(const char *name, int flags, io_channel *channel);
+ errcode_t (*close)(io_channel channel);
+ errcode_t (*set_blksize)(io_channel channel, int blksize);
+ errcode_t (*read_blk)(io_channel channel, unsigned long block,
+ int count, void *data);
+ errcode_t (*write_blk)(io_channel channel, unsigned long block,
+ int count, const void *data);
+ errcode_t (*flush)(io_channel channel);
+ errcode_t (*write_byte)(io_channel channel, unsigned long offset,
+ int count, const void *data);
+ int reserved[15];
+};
+
+#define IO_FLAG_RW 1
+
+/*
+ * Convenience functions....
+ */
+#define io_channel_close(c) ((c)->manager->close((c)))
+#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
+#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
+#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
+#define io_channel_flush(c) ((c)->manager->flush((c)))
+#define io_channel_write_byte(c,b,n,d) ((c)->manager->write_byte((c),b,n,d))
+#define io_channel_bumpcount(c) ((c)->refcount++)
+
+/* unix_io.c */
+extern io_manager unix_io_manager;
+
+/* test_io.c */
+extern io_manager test_io_manager, test_io_backing_manager;
+extern void (*test_io_cb_read_blk)
+ (unsigned long block, int count, errcode_t err);
+extern void (*test_io_cb_write_blk)
+ (unsigned long block, int count, errcode_t err);
+extern void (*test_io_cb_set_blksize)
+ (int blksize, errcode_t err);
+
+#endif /* _EXT2FS_EXT2_IO_H */
+
diff --git a/e2fslib/ext2_types.h b/e2fslib/ext2_types.h
new file mode 100644
index 0000000..eff4a6b
--- /dev/null
+++ b/e2fslib/ext2_types.h
@@ -0,0 +1,53 @@
+#ifndef _EXT2_TYPES_H
+#define _EXT2_TYPES_H
+
+/*
+ * If linux/types.h is already been included, assume it has defined
+ * everything we need. (cross fingers)
+ */
+#ifndef _LINUX_TYPES_H
+
+typedef unsigned char __u8;
+typedef signed char __s8;
+
+#if (4 == 8)
+typedef int __s64;
+typedef unsigned int __u64;
+#elif (4 == 8)
+typedef long __s64;
+typedef unsigned long __u64;
+#elif (8 == 8)
+#if defined(__GNUC__)
+typedef __signed__ long long __s64;
+#else
+typedef signed long long __s64;
+#endif
+typedef unsigned long long __u64;
+#endif
+
+#if (4 == 2)
+typedef int __s16;
+typedef unsigned int __u16;
+#elif (2 == 2)
+typedef short __s16;
+typedef unsigned short __u16;
+#else
+ ?==error: undefined 16 bit type
+#endif
+
+#if (4 == 4)
+typedef int __s32;
+typedef unsigned int __u32;
+#elif (4 == 4)
+typedef long __s32;
+typedef unsigned long __u32;
+#elif (2 == 4)
+typedef short __s32;
+typedef unsigned short __u32;
+#else
+ ?== error: undefined 32 bit type
+#endif
+
+#endif /* LINUX_TYPES_H */
+
+#endif /* EXT2_TYPES_H */
diff --git a/e2fslib/ext2_types.h.in b/e2fslib/ext2_types.h.in
new file mode 100644
index 0000000..38f588f
--- /dev/null
+++ b/e2fslib/ext2_types.h.in
@@ -0,0 +1,53 @@
+#ifndef _EXT2_TYPES_H
+#define _EXT2_TYPES_H
+
+/*
+ * If linux/types.h is already been included, assume it has defined
+ * everything we need. (cross fingers)
+ */
+#ifndef _LINUX_TYPES_H
+
+typedef unsigned char __u8;
+typedef signed char __s8;
+
+#if (@SIZEOF_INT@ == 8)
+typedef int __s64;
+typedef unsigned int __u64;
+#elif (@SIZEOF_LONG@ == 8)
+typedef long __s64;
+typedef unsigned long __u64;
+#elif (@SIZEOF_LONG_LONG@ == 8)
+#if defined(__GNUC__)
+typedef __signed__ long long __s64;
+#else
+typedef signed long long __s64;
+#endif
+typedef unsigned long long __u64;
+#endif
+
+#if (@SIZEOF_INT@ == 2)
+typedef int __s16;
+typedef unsigned int __u16;
+#elif (@SIZEOF_SHORT@ == 2)
+typedef short __s16;
+typedef unsigned short __u16;
+#else
+ ?==error: undefined 16 bit type
+#endif
+
+#if (@SIZEOF_INT@ == 4)
+typedef int __s32;
+typedef unsigned int __u32;
+#elif (@SIZEOF_LONG@ == 4)
+typedef long __s32;
+typedef unsigned long __u32;
+#elif (@SIZEOF_SHORT@ == 4)
+typedef short __s32;
+typedef unsigned short __u32;
+#else
+ ?== error: undefined 32 bit type
+#endif
+
+#endif /* LINUX_TYPES_H */
+
+#endif /* EXT2_TYPES_H */
diff --git a/e2fslib/ext2fs.h b/e2fslib/ext2fs.h
new file mode 100644
index 0000000..bb3ae26
--- /dev/null
+++ b/e2fslib/ext2fs.h
@@ -0,0 +1,976 @@
+/*
+ * ext2fs.h --- ext2fs
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#ifndef _EXT2FS_EXT2FS_H
+#define _EXT2FS_EXT2FS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Non-GNU C compilers won't necessarily understand inline
+ */
+#if (!defined(__GNUC__) && !defined(__WATCOMC__))
+#define NO_INLINE_FUNCS
+#endif
+
+/*
+ * Build in support for byte-swapping filesystems if we the feature
+ * has been configured or if we're being built on a CPU architecture
+ * with a non-native byte order.
+ */
+#if defined(ENABLE_SWAPFS) || defined(WORDS_BIGENDIAN)
+#define EXT2FS_ENABLE_SWAPFS
+#endif
+
+/*
+ * Where the master copy of the superblock is located, and how big
+ * superblocks are supposed to be. We define SUPERBLOCK_SIZE because
+ * the size of the superblock structure is not necessarily trustworthy
+ * (some versions have the padding set up so that the superblock is
+ * 1032 bytes long).
+ */
+#define SUPERBLOCK_OFFSET 1024
+#define SUPERBLOCK_SIZE 1024
+
+/*
+ * The last ext2fs revision level that this version of the library is
+ * able to support.
+ */
+#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+
+#if EXT2_FLAT_INCLUDES
+#include "e2_types.h"
+#else
+#include <ext2_types.h>
+#endif /* EXT2_FLAT_INCLUDES */
+
+typedef __u32 ext2_ino_t;
+typedef __u32 blk_t;
+typedef __u32 dgrp_t;
+typedef __u32 ext2_off_t;
+typedef __s64 e2_blkcnt_t;
+
+#if EXT2_FLAT_INCLUDES
+#include "com_err.h"
+#include "ext2_io.h"
+#include "ext2_err.h"
+#else
+#include <et/com_err.h>
+#include <ext2_io.h>
+#include <ext2_err.h>
+#endif
+
+/*
+ * Portability help for Microsoft Visual C++
+ */
+#ifdef _MSC_VER
+#define EXT2_QSORT_TYPE int __cdecl
+#else
+#define EXT2_QSORT_TYPE int
+#endif
+
+typedef struct struct_ext2_filsys *ext2_filsys;
+
+struct ext2fs_struct_generic_bitmap {
+ errcode_t magic;
+ ext2_filsys fs;
+ __u32 start, end;
+ __u32 real_end;
+ char * description;
+ char * bitmap;
+ errcode_t base_error_code;
+ __u32 reserved[7];
+};
+
+#define EXT2FS_MARK_ERROR 0
+#define EXT2FS_UNMARK_ERROR 1
+#define EXT2FS_TEST_ERROR 2
+
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
+
+#ifdef EXT2_DYNAMIC_REV
+#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
+#else
+#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO
+#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
+#endif
+
+/*
+ * badblocks list definitions
+ */
+
+typedef struct ext2_struct_badblocks_list *ext2_badblocks_list;
+typedef struct ext2_struct_badblocks_iterate *ext2_badblocks_iterate;
+
+/* old */
+typedef struct ext2_struct_badblocks_list *badblocks_list;
+typedef struct ext2_struct_badblocks_iterate *badblocks_iterate;
+
+#define BADBLOCKS_FLAG_DIRTY 1
+
+/*
+ * ext2_dblist structure and abstractions (see dblist.c)
+ */
+struct ext2_db_entry {
+ ext2_ino_t ino;
+ blk_t blk;
+ int blockcnt;
+};
+
+typedef struct ext2_struct_dblist *ext2_dblist;
+
+#define DBLIST_ABORT 1
+
+/*
+ * ext2_fileio definitions
+ */
+
+#define EXT2_FILE_WRITE 0x0001
+#define EXT2_FILE_CREATE 0x0002
+
+#define EXT2_FILE_MASK 0x00FF
+
+#define EXT2_FILE_BUF_DIRTY 0x4000
+#define EXT2_FILE_BUF_VALID 0x2000
+
+typedef struct ext2_file *ext2_file_t;
+
+#define EXT2_SEEK_SET 0
+#define EXT2_SEEK_CUR 1
+#define EXT2_SEEK_END 2
+
+/*
+ * Flags for the ext2_filsys structure and for ext2fs_open()
+ */
+#define EXT2_FLAG_RW 0x01
+#define EXT2_FLAG_CHANGED 0x02
+#define EXT2_FLAG_DIRTY 0x04
+#define EXT2_FLAG_VALID 0x08
+#define EXT2_FLAG_IB_DIRTY 0x10
+#define EXT2_FLAG_BB_DIRTY 0x20
+#define EXT2_FLAG_SWAP_BYTES 0x40
+#define EXT2_FLAG_SWAP_BYTES_READ 0x80
+#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
+#define EXT2_FLAG_MASTER_SB_ONLY 0x200
+#define EXT2_FLAG_FORCE 0x400
+#define EXT2_FLAG_SUPER_ONLY 0x800
+#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000
+#define EXT2_FLAG_IMAGE_FILE 0x2000
+
+/*
+ * Special flag in the ext2 inode i_flag field that means that this is
+ * a new inode. (So that ext2_write_inode() can clear extra fields.)
+ */
+#define EXT2_NEW_INODE_FL 0x80000000
+
+/*
+ * Flags for mkjournal
+ *
+ * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock
+ */
+#define EXT2_MKJOURNAL_V1_SUPER 0x0000001
+
+struct struct_ext2_filsys {
+ errcode_t magic;
+ io_channel io;
+ int flags;
+ char * device_name;
+ struct ext2_super_block * super;
+ int blocksize;
+ int fragsize;
+ dgrp_t group_desc_count;
+ unsigned long desc_blocks;
+ struct ext2_group_desc * group_desc;
+ int inode_blocks_per_group;
+ ext2fs_inode_bitmap inode_map;
+ ext2fs_block_bitmap block_map;
+ errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
+ errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
+ errcode_t (*write_bitmaps)(ext2_filsys fs);
+ errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode);
+ errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode);
+ badblocks_list badblocks;
+ ext2_dblist dblist;
+ __u32 stride; /* for mke2fs */
+ struct ext2_super_block * orig_super;
+ struct ext2_image_hdr * image_header;
+ /*
+ * Reserved for future expansion
+ */
+ __u32 reserved[9];
+
+ /*
+ * Reserved for the use of the calling application.
+ */
+ void * priv_data;
+
+ /*
+ * Inode cache
+ */
+ struct ext2_inode_cache *icache;
+};
+
+#if EXT2_FLAT_INCLUDES
+#include "e2_bitops.h"
+#else
+#include <bitops.h>
+#endif
+
+/*
+ * Return flags for the block iterator functions
+ */
+#define BLOCK_CHANGED 1
+#define BLOCK_ABORT 2
+#define BLOCK_ERROR 4
+
+/*
+ * Block interate flags
+ *
+ * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
+ * function should be called on blocks where the block number is zero.
+ * This is used by ext2fs_expand_dir() to be able to add a new block
+ * to an inode. It can also be used for programs that want to be able
+ * to deal with files that contain "holes".
+ *
+ * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the
+ * indirect, doubly indirect, etc. blocks should be called after all
+ * of the blocks containined in the indirect blocks are processed.
+ * This is useful if you are going to be deallocating blocks from an
+ * inode.
+ *
+ * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
+ * called for data blocks only.
+ *
+ * BLOCK_FLAG_NO_LARGE is for internal use only. It informs
+ * ext2fs_block_iterate2 that large files won't be accepted.
+ */
+#define BLOCK_FLAG_APPEND 1
+#define BLOCK_FLAG_HOLE 1
+#define BLOCK_FLAG_DEPTH_TRAVERSE 2
+#define BLOCK_FLAG_DATA_ONLY 4
+
+#define BLOCK_FLAG_NO_LARGE 0x1000
+
+/*
+ * Magic "block count" return values for the block iterator function.
+ */
+#define BLOCK_COUNT_IND (-1)
+#define BLOCK_COUNT_DIND (-2)
+#define BLOCK_COUNT_TIND (-3)
+#define BLOCK_COUNT_TRANSLATOR (-4)
+
+#if 0
+/*
+ * Flags for ext2fs_move_blocks
+ */
+#define EXT2_BMOVE_GET_DBLIST 0x0001
+#define EXT2_BMOVE_DEBUG 0x0002
+#endif
+
+/*
+ * Return flags for the directory iterator functions
+ */
+#define DIRENT_CHANGED 1
+#define DIRENT_ABORT 2
+#define DIRENT_ERROR 3
+
+/*
+ * Directory iterator flags
+ */
+
+#define DIRENT_FLAG_INCLUDE_EMPTY 1
+
+
+#define DIRENT_DOT_FILE 1
+#define DIRENT_DOT_DOT_FILE 2
+#define DIRENT_OTHER_FILE 3
+
+/*
+ * Inode scan definitions
+ */
+typedef struct ext2_struct_inode_scan *ext2_inode_scan;
+
+/*
+ * ext2fs_scan flags
+ */
+#define EXT2_SF_CHK_BADBLOCKS 0x0001
+#define EXT2_SF_BAD_INODE_BLK 0x0002
+#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
+#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
+
+/*
+ * ext2fs_check_if_mounted flags
+ */
+#define EXT2_MF_MOUNTED 1
+#define EXT2_MF_ISROOT 2
+#define EXT2_MF_READONLY 4
+
+/*
+ * Ext2/linux mode flags. We define them here so that we don't need
+ * to depend on the OS's sys/stat.h, since we may be compiling on a
+ * non-Linux system.
+ */
+#define LINUX_S_IFMT 00170000
+#define LINUX_S_IFSOCK 0140000
+#define LINUX_S_IFLNK 0120000
+#define LINUX_S_IFREG 0100000
+#define LINUX_S_IFBLK 0060000
+#define LINUX_S_IFDIR 0040000
+#define LINUX_S_IFCHR 0020000
+#define LINUX_S_IFIFO 0010000
+#define LINUX_S_ISUID 0004000
+#define LINUX_S_ISGID 0002000
+#define LINUX_S_ISVTX 0001000
+
+#define LINUX_S_IRWXU 00700
+#define LINUX_S_IRUSR 00400
+#define LINUX_S_IWUSR 00200
+#define LINUX_S_IXUSR 00100
+
+#define LINUX_S_IRWXG 00070
+#define LINUX_S_IRGRP 00040
+#define LINUX_S_IWGRP 00020
+#define LINUX_S_IXGRP 00010
+
+#define LINUX_S_IRWXO 00007
+#define LINUX_S_IROTH 00004
+#define LINUX_S_IWOTH 00002
+#define LINUX_S_IXOTH 00001
+
+#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
+#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
+#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
+#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
+#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
+#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
+#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
+
+/*
+ * ext2_icount_t abstraction
+ */
+#define EXT2_ICOUNT_OPT_INCREMENT 0x01
+
+typedef struct ext2_icount *ext2_icount_t;
+
+/*
+ * Flags for ext2fs_bmap
+ */
+#define BMAP_ALLOC 1
+
+/*
+ * Flags for imager.c functions
+ */
+#define IMAGER_FLAG_INODEMAP 1
+#define IMAGER_FLAG_SPARSEWRITE 2
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+ if ((struct)->magic != (code)) return (code)
+
+
+/*
+ * For ext2 compression support
+ */
+#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
+#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
+
+/*
+ * Features supported by this version of the library
+ */
+#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
+ EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
+ EXT2_FEATURE_COMPAT_EXT_ATTR)
+
+/* This #ifdef is temporary until compression is fully supported */
+#ifdef ENABLE_COMPRESSION
+#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL
+/* If the below warning bugs you, then have
+ `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your
+ environment at configure time. */
+ #warning "Compression support is experimental"
+#endif
+#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
+ EXT2_FEATURE_INCOMPAT_COMPRESSION|\
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
+ EXT3_FEATURE_INCOMPAT_RECOVER)
+#else
+#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
+ EXT3_FEATURE_INCOMPAT_RECOVER)
+#endif
+#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
+/*
+ * function prototypes
+ */
+
+/* alloc.c */
+extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
+ ext2fs_inode_bitmap map, ext2_ino_t *ret);
+extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
+ ext2fs_block_bitmap map, blk_t *ret);
+extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
+ blk_t finish, int num,
+ ext2fs_block_bitmap map,
+ blk_t *ret);
+extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
+ char *block_buf, blk_t *ret);
+
+/* alloc_tables.c */
+extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
+extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
+ ext2fs_block_bitmap bmap);
+
+/* badblocks.c */
+extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
+ int size);
+extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
+ blk_t blk);
+extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
+ blk_t blk);
+extern errcode_t
+ ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
+ ext2_badblocks_iterate *ret);
+extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
+ blk_t *blk);
+extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
+extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
+ ext2_badblocks_list *dest);
+extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
+ ext2_badblocks_list bb2);
+
+/* bb_compat */
+extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
+extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
+extern int badblocks_list_test(badblocks_list bb, blk_t blk);
+extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
+ badblocks_iterate *ret);
+extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
+extern void badblocks_list_iterate_end(badblocks_iterate iter);
+extern void badblocks_list_free(badblocks_list bb);
+
+/* bb_inode.c */
+extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
+ ext2_badblocks_list bb_list);
+
+/* bitmaps.c */
+extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
+extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
+extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
+ __u32 end,
+ __u32 real_end,
+ const char *descr,
+ ext2fs_generic_bitmap *ret);
+extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
+ const char *descr,
+ ext2fs_block_bitmap *ret);
+extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
+ const char *descr,
+ ext2fs_inode_bitmap *ret);
+extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
+ ext2_ino_t end, ext2_ino_t *oend);
+extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
+ blk_t end, blk_t *oend);
+extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
+extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
+extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
+
+/* block.c */
+extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
+ ext2_ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ void *priv_data),
+ void *priv_data);
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+ ext2_ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data),
+ void *priv_data);
+
+/* bmap.c */
+extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode *inode,
+ char *block_buf, int bmap_flags,
+ blk_t block, blk_t *phys_blk);
+
+
+#if 0
+/* bmove.c */
+extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
+ ext2fs_block_bitmap reserve,
+ ext2fs_block_bitmap alloc_map,
+ int flags);
+#endif
+
+/* check_desc.c */
+extern errcode_t ext2fs_check_desc(ext2_filsys fs);
+
+/* closefs.c */
+extern errcode_t ext2fs_close(ext2_filsys fs);
+extern errcode_t ext2fs_flush(ext2_filsys fs);
+extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
+extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
+
+/* cmp_bitmaps.c */
+extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
+ ext2fs_block_bitmap bm2);
+extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
+ ext2fs_inode_bitmap bm2);
+
+/* dblist.c */
+
+extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
+extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
+extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
+ blk_t blk, int blockcnt);
+extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
+ int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
+ void *priv_data),
+ void *priv_data);
+extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
+ blk_t blk, int blockcnt);
+extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
+ ext2_dblist *dest);
+extern int ext2fs_dblist_count(ext2_dblist dblist);
+
+/* dblist_dir.c */
+extern errcode_t
+ ext2fs_dblist_dir_iterate(ext2_dblist dblist,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_ino_t dir,
+ int entry,
+ struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data),
+ void *priv_data);
+
+/* dirblock.c */
+extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
+ void *buf);
+extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
+ void *buf);
+
+/* dir_iterate.c */
+extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
+ ext2_ino_t dir,
+ int flags,
+ char *block_buf,
+ int (*func)(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data),
+ void *priv_data);
+
+/* dupfs.c */
+extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
+
+/* expanddir.c */
+extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
+
+/* ext_attr.c */
+void ext2fs_swap_ext_attr(ext2_filsys fs, char *to, char *from);
+extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
+extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *buf);
+/* fileio.c */
+extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
+ int flags, ext2_file_t *ret);
+extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
+extern errcode_t ext2fs_file_close(ext2_file_t file);
+extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
+ unsigned int wanted, unsigned int *got);
+extern errcode_t ext2fs_file_write(ext2_file_t file, void *buf,
+ unsigned int nbytes, unsigned int *written);
+extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
+ int whence, ext2_off_t *ret_pos);
+extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
+extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
+
+/* finddev.c */
+extern char *ext2fs_find_block_device(dev_t device);
+
+/* flushb.c */
+extern errcode_t ext2fs_sync_device(int fd, int flushb);
+
+/* freefs.c */
+extern void ext2fs_free(ext2_filsys fs);
+extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
+extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_free_dblist(ext2_dblist dblist);
+extern void ext2fs_badblocks_list_free(badblocks_list bb);
+
+/* getsize.c */
+extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
+ blk_t *retblocks);
+
+/* imager.c */
+extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
+
+/* initialize.c */
+extern errcode_t ext2fs_initialize(const char *name, int flags,
+ struct ext2_super_block *param,
+ io_manager manager, ext2_filsys *ret_fs);
+
+/* inode.c */
+extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
+extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
+ ext2_inode_scan *ret_scan);
+extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
+extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
+ struct ext2_inode *inode);
+extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
+ int group);
+extern void ext2fs_set_inode_callback
+ (ext2_inode_scan scan,
+ errcode_t (*done_group)(ext2_filsys fs,
+ ext2_inode_scan scan,
+ dgrp_t group,
+ void * priv_data),
+ void *done_group_data);
+extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
+ int clear_flags);
+extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode);
+extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode);
+extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
+extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
+
+/* icount.c */
+extern void ext2fs_free_icount(ext2_icount_t icount);
+extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
+ ext2_icount_t hint, ext2_icount_t *ret);
+extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
+ ext2_icount_t *ret);
+extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 count);
+extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
+
+/* ismounted.c */
+extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
+extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
+ char *mtpt, int mtlen);
+
+/* namei.c */
+extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
+ int namelen, char *buf, ext2_ino_t *inode);
+extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ const char *name, ext2_ino_t *inode);
+errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ const char *name, ext2_ino_t *inode);
+extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ ext2_ino_t inode, ext2_ino_t *res_inode);
+
+/* native.c */
+int ext2fs_native_flag(void);
+
+/* newdir.c */
+extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
+ ext2_ino_t parent_ino, char **block);
+
+/* mkdir.c */
+extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
+ const char *name);
+
+/* mkjournal.c */
+extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
+ __u32 size, int flags,
+ char **ret_jsb);
+extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
+ ext2_filsys journal_dev);
+extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
+ int flags);
+
+/* openfs.c */
+extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
+ int block_size, io_manager manager,
+ ext2_filsys *ret_fs);
+
+/* get_pathname.c */
+extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
+ char **name);
+
+/* link.c */
+errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
+ ext2_ino_t ino, int flags);
+errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
+ ext2_ino_t ino, int flags);
+
+/* read_bb.c */
+extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
+ ext2_badblocks_list *bb_list);
+
+/* read_bb_file.c */
+extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
+ ext2_badblocks_list *bb_list,
+ void *private,
+ void (*invalid)(ext2_filsys fs,
+ blk_t blk,
+ char *badstr,
+ void *private));
+extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
+ ext2_badblocks_list *bb_list,
+ void (*invalid)(ext2_filsys fs,
+ blk_t blk));
+
+/* rs_bitmap.c */
+extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
+ __u32 new_real_end,
+ ext2fs_generic_bitmap bmap);
+extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_inode_bitmap bmap);
+extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_block_bitmap bmap);
+extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
+ ext2fs_generic_bitmap *dest);
+
+/* swapfs.c */
+extern void ext2fs_swap_super(struct ext2_super_block * super);
+extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
+extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
+ struct ext2_inode *f, int hostorder);
+
+/* valid_blk.c */
+extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
+
+/* version.c */
+extern int ext2fs_parse_version_string(const char *ver_string);
+extern int ext2fs_get_library_version(const char **ver_string,
+ const char **date_string);
+
+/* write_bb_file.c */
+extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
+ unsigned int flags,
+ FILE *f);
+
+
+/* inline functions */
+extern errcode_t ext2fs_get_mem(unsigned long size, void **ptr);
+extern errcode_t ext2fs_free_mem(void **ptr);
+extern errcode_t ext2fs_resize_mem(unsigned long old_size,
+ unsigned long size, void **ptr);
+extern void ext2fs_mark_super_dirty(ext2_filsys fs);
+extern void ext2fs_mark_changed(ext2_filsys fs);
+extern int ext2fs_test_changed(ext2_filsys fs);
+extern void ext2fs_mark_valid(ext2_filsys fs);
+extern void ext2fs_unmark_valid(ext2_filsys fs);
+extern int ext2fs_test_valid(ext2_filsys fs);
+extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
+extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
+extern int ext2fs_test_ib_dirty(ext2_filsys fs);
+extern int ext2fs_test_bb_dirty(ext2_filsys fs);
+extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
+extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
+
+/*
+ * The actual inlined functions definitions themselves...
+ *
+ * If NO_INLINE_FUNCS is defined, then we won't try to do inline
+ * functions at all!
+ */
+#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
+#ifdef INCLUDE_INLINE_FUNCS
+#define _INLINE_ extern
+#else
+#ifdef __GNUC__
+#define _INLINE_ extern __inline__
+#else /* For Watcom C */
+#define _INLINE_ extern inline
+#endif
+#endif
+
+#ifndef EXT2_CUSTOM_MEMORY_ROUTINES
+/*
+ * Allocate memory
+ */
+_INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void **ptr)
+{
+ *ptr = malloc(size);
+ if (!*ptr)
+ return EXT2_ET_NO_MEMORY;
+ return 0;
+}
+
+/*
+ * Free memory
+ */
+_INLINE_ errcode_t ext2fs_free_mem(void **ptr)
+{
+ free(*ptr);
+ *ptr = 0;
+ return 0;
+}
+
+/*
+ * Resize memory
+ */
+_INLINE_ errcode_t ext2fs_resize_mem(unsigned long old_size,
+ unsigned long size, void **ptr)
+{
+ void *p;
+
+ p = realloc(*ptr, size);
+ if (!p)
+ return EXT2_ET_NO_MEMORY;
+ *ptr = p;
+ return 0;
+}
+#endif /* Custom memory routines */
+
+/*
+ * Mark a filesystem superblock as dirty
+ */
+_INLINE_ void ext2fs_mark_super_dirty(ext2_filsys fs)
+{
+ fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Mark a filesystem as changed
+ */
+_INLINE_ void ext2fs_mark_changed(ext2_filsys fs)
+{
+ fs->flags |= EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Check to see if a filesystem has changed
+ */
+_INLINE_ int ext2fs_test_changed(ext2_filsys fs)
+{
+ return (fs->flags & EXT2_FLAG_CHANGED);
+}
+
+/*
+ * Mark a filesystem as valid
+ */
+_INLINE_ void ext2fs_mark_valid(ext2_filsys fs)
+{
+ fs->flags |= EXT2_FLAG_VALID;
+}
+
+/*
+ * Mark a filesystem as NOT valid
+ */
+_INLINE_ void ext2fs_unmark_valid(ext2_filsys fs)
+{
+ fs->flags &= ~EXT2_FLAG_VALID;
+}
+
+/*
+ * Check to see if a filesystem is valid
+ */
+_INLINE_ int ext2fs_test_valid(ext2_filsys fs)
+{
+ return (fs->flags & EXT2_FLAG_VALID);
+}
+
+/*
+ * Mark the inode bitmap as dirty
+ */
+_INLINE_ void ext2fs_mark_ib_dirty(ext2_filsys fs)
+{
+ fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Mark the block bitmap as dirty
+ */
+_INLINE_ void ext2fs_mark_bb_dirty(ext2_filsys fs)
+{
+ fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Check to see if a filesystem's inode bitmap is dirty
+ */
+_INLINE_ int ext2fs_test_ib_dirty(ext2_filsys fs)
+{
+ return (fs->flags & EXT2_FLAG_IB_DIRTY);
+}
+
+/*
+ * Check to see if a filesystem's block bitmap is dirty
+ */
+_INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs)
+{
+ return (fs->flags & EXT2_FLAG_BB_DIRTY);
+}
+
+/*
+ * Return the group # of a block
+ */
+_INLINE_ int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
+{
+ return (blk - fs->super->s_first_data_block) /
+ fs->super->s_blocks_per_group;
+}
+
+/*
+ * Return the group # of an inode number
+ */
+_INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
+{
+ return (ino - 1) / fs->super->s_inodes_per_group;
+}
+#undef _INLINE_
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXT2FS_EXT2FS_H */
diff --git a/e2fslib/ext2fsP.h b/e2fslib/ext2fsP.h
new file mode 100644
index 0000000..aedee15
--- /dev/null
+++ b/e2fslib/ext2fsP.h
@@ -0,0 +1,93 @@
+/*
+ * ext2fsP.h --- private header file for ext2 library
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "ext2fs.h"
+
+/*
+ * Badblocks list
+ */
+struct ext2_struct_badblocks_list {
+ int magic;
+ int num;
+ int size;
+ blk_t *list;
+ int badblocks_flags;
+};
+
+struct ext2_struct_badblocks_iterate {
+ int magic;
+ badblocks_list bb;
+ int ptr;
+};
+
+
+/*
+ * Directory block iterator definition
+ */
+struct ext2_struct_dblist {
+ int magic;
+ ext2_filsys fs;
+ ext2_ino_t size;
+ ext2_ino_t count;
+ int sorted;
+ struct ext2_db_entry * list;
+};
+
+/*
+ * For directory iterators
+ */
+struct dir_context {
+ ext2_ino_t dir;
+ int flags;
+ char *buf;
+ int (*func)(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data);
+ int (*func2)(ext2_ino_t dir,
+ int entry,
+ struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data);
+ void *priv_data;
+ errcode_t errcode;
+};
+
+/*
+ * Inode cache structure
+ */
+struct ext2_inode_cache {
+ void * buffer;
+ blk_t buffer_blk;
+ int cache_last;
+ int cache_size;
+ int refcount;
+ struct ext2_inode_cache_ent *cache;
+};
+
+struct ext2_inode_cache_ent {
+ ext2_ino_t ino;
+ struct ext2_inode inode;
+};
+
+/* Function prototypes */
+
+extern int ext2fs_process_dir_block(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block,
+ int ref_offset,
+ void *priv_data);
+
+
diff --git a/e2fslib/ext_attr.c b/e2fslib/ext_attr.c
new file mode 100644
index 0000000..3a281e8
--- /dev/null
+++ b/e2fslib/ext_attr.c
@@ -0,0 +1,100 @@
+/*
+ * ext_attr.c --- extended attribute blocks
+ *
+ * Copyright (C) Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2_ext_attr.h"
+
+#include "ext2fs.h"
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+void ext2fs_swap_ext_attr(ext2_filsys fs, char *to, char *from)
+{
+ struct ext2_ext_attr_header *from_header =
+ (struct ext2_ext_attr_header *)from;
+ struct ext2_ext_attr_header *to_header =
+ (struct ext2_ext_attr_header *)to;
+ struct ext2_ext_attr_entry *from_entry, *to_entry;
+ char *from_end = (char *)from_header + fs->blocksize;
+ int n;
+
+ if (to_header != from_header)
+ memcpy(to_header, from_header, fs->blocksize);
+
+ to_header->h_magic = ext2fs_swab32(from_header->h_magic);
+ to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
+ to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
+ for (n=0; n<4; n++)
+ to_header->h_reserved[n] =
+ ext2fs_swab32(from_header->h_reserved[n]);
+
+ from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
+ to_entry = (struct ext2_ext_attr_entry *)(to_header+1);
+ while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
+ to_entry->e_value_offs =
+ ext2fs_swab16(from_entry->e_value_offs);
+ to_entry->e_value_block =
+ ext2fs_swab32(from_entry->e_value_block);
+ to_entry->e_value_size =
+ ext2fs_swab32(from_entry->e_value_size);
+ from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
+ to_entry = EXT2_EXT_ATTR_NEXT(to_entry);
+ }
+}
+#endif
+
+errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
+{
+ errcode_t retval;
+ struct ext2_ext_attr_entry *entry;
+
+ retval = io_channel_read_blk(fs->io, block, 1, buf);
+ if (retval)
+ return retval;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
+ EXT2_FLAG_SWAP_BYTES_READ)) != 0)
+ ext2fs_swap_ext_attr(fs, buf, buf);
+#endif
+ return 0;
+}
+
+errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
+{
+ errcode_t retval;
+ char *p, *end, *write_buf;
+ char *buf = NULL;
+ struct ext2_dir_entry *dirent;
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) {
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+ write_buf = buf;
+ ext2fs_swap_ext_attr(fs, buf, inbuf);
+ } else
+#endif
+ write_buf = (char *) inbuf;
+ retval = io_channel_write_blk(fs->io, block, 1, write_buf);
+ if (buf)
+ ext2fs_free_mem((void **) &buf);
+ if (!retval)
+ ext2fs_mark_changed(fs);
+ return retval;
+}
diff --git a/e2fslib/ext_attr.o b/e2fslib/ext_attr.o
new file mode 100644
index 0000000..f1fa6e9
--- /dev/null
+++ b/e2fslib/ext_attr.o
Binary files differ
diff --git a/e2fslib/fileio.c b/e2fslib/fileio.c
new file mode 100644
index 0000000..80e5032
--- /dev/null
+++ b/e2fslib/fileio.c
@@ -0,0 +1,336 @@
+/*
+ * fileio.c --- Simple file I/O routines
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct ext2_file {
+ errcode_t magic;
+ ext2_filsys fs;
+ ext2_ino_t ino;
+ struct ext2_inode inode;
+ int flags;
+ ext2_off_t pos;
+ blk_t blockno;
+ blk_t physblock;
+ char *buf;
+};
+
+#define BMAP_BUFFER (file->buf + fs->blocksize)
+
+errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
+ int flags, ext2_file_t *ret)
+{
+ ext2_file_t file;
+ errcode_t retval;
+
+ /*
+ * Don't let caller create or open a file for writing if the
+ * filesystem is read-only.
+ */
+ if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
+ !(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_file), (void **) &file);
+ if (retval)
+ return retval;
+
+ memset(file, 0, sizeof(struct ext2_file));
+ file->magic = EXT2_ET_MAGIC_EXT2_FILE;
+ file->fs = fs;
+ file->ino = ino;
+ file->flags = flags & EXT2_FILE_MASK;
+
+ retval = ext2fs_read_inode(fs, ino, &file->inode);
+ if (retval)
+ goto fail;
+
+ retval = ext2fs_get_mem(fs->blocksize * 3, (void **) &file->buf);
+ if (retval)
+ goto fail;
+
+ *ret = file;
+ return 0;
+
+fail:
+ if (file->buf)
+ ext2fs_free_mem((void **) &file->buf);
+ ext2fs_free_mem((void **) &file);
+ return retval;
+}
+
+/*
+ * This function returns the filesystem handle of a file from the structure
+ */
+ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
+{
+ if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
+ return 0;
+ return file->fs;
+}
+
+/*
+ * This function flushes the dirty block buffer out to disk if
+ * necessary.
+ */
+static errcode_t ext2fs_file_flush(ext2_file_t file)
+{
+ errcode_t retval;
+ ext2_filsys fs;
+
+ EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+ fs = file->fs;
+
+ if (!(file->flags & EXT2_FILE_BUF_VALID) ||
+ !(file->flags & EXT2_FILE_BUF_DIRTY))
+ return 0;
+
+ /*
+ * OK, the physical block hasn't been allocated yet.
+ * Allocate it.
+ */
+ if (!file->physblock) {
+ retval = ext2fs_bmap(fs, file->ino, &file->inode,
+ BMAP_BUFFER, BMAP_ALLOC,
+ file->blockno, &file->physblock);
+ if (retval)
+ return retval;
+ }
+
+ retval = io_channel_write_blk(fs->io, file->physblock,
+ 1, file->buf);
+ if (retval)
+ return retval;
+
+ file->flags &= ~EXT2_FILE_BUF_DIRTY;
+
+ return retval;
+}
+
+/*
+ * This function synchronizes the file's block buffer and the current
+ * file position, possibly invalidating block buffer if necessary
+ */
+static errcode_t sync_buffer_position(ext2_file_t file)
+{
+ blk_t b;
+ errcode_t retval;
+
+ b = file->pos / file->fs->blocksize;
+ if (b != file->blockno) {
+ retval = ext2fs_file_flush(file);
+ if (retval)
+ return retval;
+ file->flags &= ~EXT2_FILE_BUF_VALID;
+ }
+ file->blockno = b;
+ return 0;
+}
+
+/*
+ * This function loads the file's block buffer with valid data from
+ * the disk as necessary.
+ *
+ * If dontfill is true, then skip initializing the buffer since we're
+ * going to be replacing its entire contents anyway. If set, then the
+ * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
+ */
+#define DONTFILL 1
+static errcode_t load_buffer(ext2_file_t file, int dontfill)
+{
+ ext2_filsys fs = file->fs;
+ errcode_t retval;
+
+ if (!(file->flags & EXT2_FILE_BUF_VALID)) {
+ retval = ext2fs_bmap(fs, file->ino, &file->inode,
+ BMAP_BUFFER, 0, file->blockno,
+ &file->physblock);
+ if (retval)
+ return retval;
+ if (!dontfill) {
+ if (file->physblock) {
+ retval = io_channel_read_blk(fs->io,
+ file->physblock,
+ 1, file->buf);
+ if (retval)
+ return retval;
+ } else
+ memset(file->buf, 0, fs->blocksize);
+ }
+ file->flags |= EXT2_FILE_BUF_VALID;
+ }
+ return 0;
+}
+
+
+errcode_t ext2fs_file_close(ext2_file_t file)
+{
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+
+ retval = ext2fs_file_flush(file);
+
+ if (file->buf)
+ ext2fs_free_mem((void **) &file->buf);
+ ext2fs_free_mem((void **) &file);
+
+ return retval;
+}
+
+
+errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
+ unsigned int wanted, unsigned int *got)
+{
+ ext2_filsys fs;
+ errcode_t retval = 0;
+ unsigned int start, left, c, count = 0;
+ char *ptr = (char *) buf;
+
+ EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+ fs = file->fs;
+
+ while ((file->pos < file->inode.i_size) && (wanted > 0)) {
+ retval = sync_buffer_position(file);
+ if (retval)
+ goto fail;
+ retval = load_buffer(file, 0);
+ if (retval)
+ goto fail;
+
+ start = file->pos % fs->blocksize;
+ c = fs->blocksize - start;
+ if (c > wanted)
+ c = wanted;
+ left = file->inode.i_size - file->pos ;
+ if (c > left)
+ c = left;
+
+ memcpy(ptr, file->buf+start, c);
+ file->pos += c;
+ ptr += c;
+ count += c;
+ wanted -= c;
+ }
+
+fail:
+ if (got)
+ *got = count;
+ return retval;
+}
+
+
+errcode_t ext2fs_file_write(ext2_file_t file, void *buf,
+ unsigned int nbytes, unsigned int *written)
+{
+ ext2_filsys fs;
+ blk_t pb;
+ errcode_t retval = 0;
+ unsigned int start, c, count = 0;
+ char *ptr = (char *) buf;
+ int dontfill;
+
+ EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+ fs = file->fs;
+
+ if (!(file->flags & EXT2_FILE_WRITE))
+ return EXT2_ET_FILE_RO;
+
+ while (nbytes > 0) {
+ retval = sync_buffer_position(file);
+ if (retval)
+ goto fail;
+
+ start = file->pos % fs->blocksize;
+ c = fs->blocksize - start;
+ if (c > nbytes)
+ c = nbytes;
+
+ /*
+ * We only need to do a read-modify-update cycle if
+ * we're doing a partial write.
+ */
+ retval = load_buffer(file, (c == fs->blocksize));
+ if (retval)
+ goto fail;
+
+ file->flags |= EXT2_FILE_BUF_DIRTY;
+ memcpy(file->buf+start, ptr, c);
+ file->pos += c;
+ ptr += c;
+ count += c;
+ nbytes -= c;
+ }
+
+fail:
+ if (written)
+ *written = count;
+ return retval;
+}
+
+errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
+ int whence, ext2_off_t *ret_pos)
+{
+ EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+
+ if (whence == EXT2_SEEK_SET)
+ file->pos = offset;
+ else if (whence == EXT2_SEEK_CUR)
+ file->pos += offset;
+ else if (whence == EXT2_SEEK_END)
+ file->pos = file->inode.i_size + offset;
+ else
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ if (ret_pos)
+ *ret_pos = file->pos;
+
+ return 0;
+}
+
+/*
+ * This function returns the size of the file, according to the inode
+ */
+ext2_off_t ext2fs_file_get_size(ext2_file_t file)
+{
+ if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
+ return 0;
+ return file->inode.i_size;
+}
+
+/*
+ * This function sets the size of the file, truncating it if necessary
+ *
+ * XXX still need to call truncate
+ */
+errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
+{
+ errcode_t retval;
+ EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+
+ file->inode.i_size = size;
+ retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
+ if (retval)
+ return retval;
+
+ /*
+ * XXX truncate inode if necessary
+ */
+
+ return 0;
+}
diff --git a/e2fslib/fileio.o b/e2fslib/fileio.o
new file mode 100644
index 0000000..c57d53f
--- /dev/null
+++ b/e2fslib/fileio.o
Binary files differ
diff --git a/e2fslib/finddev.c b/e2fslib/finddev.c
new file mode 100644
index 0000000..2e9d70a
--- /dev/null
+++ b/e2fslib/finddev.c
@@ -0,0 +1,208 @@
+/*
+ * finddev.c -- this routine attempts to find a particular device in
+ * /dev
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <dirent.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct dir_list {
+ char *name;
+ struct dir_list *next;
+};
+
+/*
+ * This function adds an entry to the directory list
+ */
+static void add_to_dirlist(const char *name, struct dir_list **list)
+{
+ struct dir_list *dp;
+
+ dp = malloc(sizeof(struct dir_list));
+ if (!dp)
+ return;
+ dp->name = malloc(strlen(name)+1);
+ if (!dp->name) {
+ free(dp);
+ return;
+ }
+ strcpy(dp->name, name);
+ dp->next = *list;
+ *list = dp;
+}
+
+/*
+ * This function frees a directory list
+ */
+static void free_dirlist(struct dir_list **list)
+{
+ struct dir_list *dp, *next;
+
+ for (dp = *list; dp; dp = next) {
+ next = dp->next;
+ free(dp->name);
+ free(dp);
+ }
+ *list = 0;
+}
+
+static int scan_dir(char *dirname, dev_t device, struct dir_list **list,
+ char **ret_path)
+{
+ DIR *dir;
+ struct dirent *dp;
+ char path[1024], *cp;
+ int dirlen;
+ struct stat st;
+
+ dirlen = strlen(dirname);
+ if ((dir = opendir(dirname)) == NULL)
+ return errno;
+ dp = readdir(dir);
+ while (dp) {
+ if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
+ goto skip_to_next;
+ if (dp->d_name[0] == '.' &&
+ ((dp->d_name[1] == 0) ||
+ ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
+ goto skip_to_next;
+ sprintf(path, "%s/%s", dirname, dp->d_name);
+ if (stat(path, &st) < 0)
+ goto skip_to_next;
+ if (S_ISDIR(st.st_mode))
+ add_to_dirlist(path, list);
+ if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
+ cp = malloc(strlen(path)+1);
+ if (!cp) {
+ closedir(dir);
+ return ENOMEM;
+ }
+ strcpy(cp, path);
+ *ret_path = cp;
+ goto success;
+ }
+ skip_to_next:
+ dp = readdir(dir);
+ }
+success:
+ closedir(dir);
+ return 0;
+}
+
+/*
+ * This function finds the pathname to a block device with a given
+ * device number. It returns a pointer to allocated memory to the
+ * pathname on success, and NULL on failure.
+ */
+char *ext2fs_find_block_device(dev_t device)
+{
+ struct dir_list *list = 0, *new_list = 0;
+ struct dir_list *current;
+ char *ret_path = 0;
+
+ /*
+ * Add the starting directories to search...
+ */
+ add_to_dirlist("/devices", &list);
+ add_to_dirlist("/devfs", &list);
+ add_to_dirlist("/dev", &list);
+
+ while (list) {
+ current = list;
+ list = list->next;
+#ifdef DEBUG
+ printf("Scanning directory %s\n", current->name);
+#endif
+ scan_dir(current->name, device, &new_list, &ret_path);
+ free(current->name);
+ free(current);
+ if (ret_path)
+ break;
+ /*
+ * If we're done checking at this level, descend to
+ * the next level of subdirectories. (breadth-first)
+ */
+ if (list == 0) {
+ list = new_list;
+ new_list = 0;
+ }
+ }
+ free_dirlist(&list);
+ free_dirlist(&new_list);
+ return ret_path;
+}
+
+
+#ifdef DEBUG
+int main(int argc, char** argv)
+{
+ char *devname, *tmp;
+ int major, minor;
+ dev_t device;
+ const char *errmsg = "Couldn't parse %s: %s\n";
+
+ if ((argc != 2) && (argc != 3)) {
+ fprintf(stderr, "Usage: %s device_number\n", argv[0]);
+ fprintf(stderr, "\t: %s major minor\n", argv[0]);
+ exit(1);
+ }
+ if (argc == 2) {
+ device = strtoul(argv[1], &tmp, 0);
+ if (*tmp) {
+ fprintf(stderr, errmsg, "device number", argv[1]);
+ exit(1);
+ }
+ } else {
+ major = strtoul(argv[1], &tmp, 0);
+ if (*tmp) {
+ fprintf(stderr, errmsg, "major number", argv[1]);
+ exit(1);
+ }
+ minor = strtoul(argv[2], &tmp, 0);
+ if (*tmp) {
+ fprintf(stderr, errmsg, "minor number", argv[2]);
+ exit(1);
+ }
+ device = makedev(major, minor);
+ printf("Looking for device 0x%04x (%d:%d)\n", device,
+ major, minor);
+ }
+ devname = ext2fs_find_block_device(device);
+ if (devname) {
+ printf("Found device! %s\n", devname);
+ free(devname);
+ } else {
+ printf("Couldn't find device.\n");
+ }
+ return 0;
+}
+
+#endif
diff --git a/e2fslib/finddev.o b/e2fslib/finddev.o
new file mode 100644
index 0000000..aec337f
--- /dev/null
+++ b/e2fslib/finddev.o
Binary files differ
diff --git a/e2fslib/flushb.c b/e2fslib/flushb.c
new file mode 100644
index 0000000..282dca3
--- /dev/null
+++ b/e2fslib/flushb.c
@@ -0,0 +1,76 @@
+/*
+ * flushb.c --- Hides system-dependent information for both syncing a
+ * device to disk and to flush any buffers from disk cache.
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_MOUNT_H
+#include <sys/mount.h> /* This may define BLKFLSBUF */
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
+ * not all portable header file does so for us. This really should be
+ * fixed in the glibc header files. (Recent glibcs appear to define
+ * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
+ * defined anywhere portable.) Until then....
+ */
+#ifdef __linux__
+#ifndef BLKFLSBUF
+#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
+#endif
+#ifndef FDFLUSH
+#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */
+#endif
+#endif
+
+/*
+ * This function will sync a device/file, and optionally attempt to
+ * flush the buffer cache. The latter is basically only useful for
+ * system benchmarks and for torturing systems in burn-in tests. :)
+ */
+errcode_t ext2fs_sync_device(int fd, int flushb)
+{
+ /*
+ * We always sync the device in case we're running on old
+ * kernels for which we can lose data if we don't. (There
+ * still is a race condition for those kernels, but this
+ * reduces it greatly.)
+ */
+ if (fsync (fd) == -1)
+ return errno;
+
+ if (flushb) {
+
+#ifdef BLKFLSBUF
+ ioctl (fd, BLKFLSBUF, 0); /* In case this is a HD */
+#else
+ #warning BLKFLSBUF not defined
+#endif
+#ifdef FDFLUSH
+ ioctl (fd, FDFLUSH, 0); /* In case this is floppy */
+#else
+ #warning FDFLUSH not defined
+#endif
+ }
+ return 0;
+}
diff --git a/e2fslib/flushb.o b/e2fslib/flushb.o
new file mode 100644
index 0000000..46dcc84
--- /dev/null
+++ b/e2fslib/flushb.o
Binary files differ
diff --git a/e2fslib/freefs.c b/e2fslib/freefs.c
new file mode 100644
index 0000000..5cb3cf8
--- /dev/null
+++ b/e2fslib/freefs.c
@@ -0,0 +1,137 @@
+/*
+ * freefs.c --- free an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
+
+void ext2fs_free(ext2_filsys fs)
+{
+ if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
+ return;
+ if (fs->io) {
+ io_channel_close(fs->io);
+ }
+ if (fs->device_name)
+ ext2fs_free_mem((void **) &fs->device_name);
+ if (fs->super)
+ ext2fs_free_mem((void **) &fs->super);
+ if (fs->orig_super)
+ ext2fs_free_mem((void **) &fs->orig_super);
+ if (fs->group_desc)
+ ext2fs_free_mem((void **) &fs->group_desc);
+ if (fs->block_map)
+ ext2fs_free_block_bitmap(fs->block_map);
+ if (fs->inode_map)
+ ext2fs_free_inode_bitmap(fs->inode_map);
+
+ if (fs->badblocks)
+ ext2fs_badblocks_list_free(fs->badblocks);
+ fs->badblocks = 0;
+
+ if (fs->dblist)
+ ext2fs_free_dblist(fs->dblist);
+
+ if (fs->icache)
+ ext2fs_free_inode_cache(fs->icache);
+
+ fs->magic = 0;
+
+ ext2fs_free_mem((void **) &fs);
+}
+
+void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
+{
+ if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
+ return;
+
+ bitmap->magic = 0;
+ if (bitmap->description) {
+ ext2fs_free_mem((void **) &bitmap->description);
+ bitmap->description = 0;
+ }
+ if (bitmap->bitmap) {
+ ext2fs_free_mem((void **) &bitmap->bitmap);
+ bitmap->bitmap = 0;
+ }
+ ext2fs_free_mem((void **) &bitmap);
+}
+
+void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
+{
+ if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
+ return;
+
+ bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ ext2fs_free_generic_bitmap(bitmap);
+}
+
+void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
+{
+ if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
+ return;
+
+ bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ ext2fs_free_generic_bitmap(bitmap);
+}
+
+/*
+ * Free the inode cache structure
+ */
+static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
+{
+ if (--icache->refcount)
+ return;
+ if (icache->buffer)
+ ext2fs_free_mem((void **) &icache->buffer);
+ if (icache->cache)
+ ext2fs_free_mem((void **) &icache->cache);
+ icache->buffer_blk = 0;
+ ext2fs_free_mem((void **) &icache);
+}
+
+/*
+ * This procedure frees a badblocks list.
+ */
+void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
+{
+ if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+ return;
+
+ if (bb->list)
+ ext2fs_free_mem((void **) &bb->list);
+ bb->list = 0;
+ ext2fs_free_mem((void **) &bb);
+}
+
+/*
+ * Free a directory block list
+ */
+void ext2fs_free_dblist(ext2_dblist dblist)
+{
+ if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
+ return;
+
+ if (dblist->list)
+ ext2fs_free_mem((void **) &dblist->list);
+ dblist->list = 0;
+ if (dblist->fs && dblist->fs->dblist == dblist)
+ dblist->fs->dblist = 0;
+ dblist->magic = 0;
+ ext2fs_free_mem((void **) &dblist);
+}
+
diff --git a/e2fslib/freefs.o b/e2fslib/freefs.o
new file mode 100644
index 0000000..49787d6
--- /dev/null
+++ b/e2fslib/freefs.o
Binary files differ
diff --git a/e2fslib/gen_bitmap.c b/e2fslib/gen_bitmap.c
new file mode 100644
index 0000000..700affa
--- /dev/null
+++ b/e2fslib/gen_bitmap.c
@@ -0,0 +1,48 @@
+/*
+ * gen_bitmap.c --- Generic bitmap routines that used to be inlined.
+ *
+ * Copyright (C) 2001 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ __u32 bitno)
+{
+ if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
+ return 0;
+ }
+ return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
+}
+
+int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+ blk_t bitno)
+{
+ if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
+ return 0;
+ }
+ return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
+}
diff --git a/e2fslib/gen_bitmap.o b/e2fslib/gen_bitmap.o
new file mode 100644
index 0000000..c1a81d0
--- /dev/null
+++ b/e2fslib/gen_bitmap.o
Binary files differ
diff --git a/e2fslib/get_pathname.c b/e2fslib/get_pathname.c
new file mode 100644
index 0000000..e218f2e
--- /dev/null
+++ b/e2fslib/get_pathname.c
@@ -0,0 +1,158 @@
+/*
+ * get_pathname.c --- do directry/inode -> name translation
+ *
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ * ext2fs_get_pathname(fs, dir, ino, name)
+ *
+ * This function translates takes two inode numbers into a
+ * string, placing the result in <name>. <dir> is the containing
+ * directory inode, and <ino> is the inode number itself. If
+ * <ino> is zero, then ext2fs_get_pathname will return pathname
+ * of the the directory <dir>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct get_pathname_struct {
+ ext2_ino_t search_ino;
+ ext2_ino_t parent;
+ char *name;
+ errcode_t errcode;
+};
+
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+static int get_pathname_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data)
+{
+ struct get_pathname_struct *gp;
+ errcode_t retval;
+
+ gp = (struct get_pathname_struct *) priv_data;
+
+ if (((dirent->name_len & 0xFF) == 2) &&
+ !strncmp(dirent->name, "..", 2))
+ gp->parent = dirent->inode;
+ if (dirent->inode == gp->search_ino) {
+ retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
+ (void **) &gp->name);
+ if (retval) {
+ gp->errcode = retval;
+ return DIRENT_ABORT;
+ }
+ strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
+ gp->name[dirent->name_len & 0xFF] = '\0';
+ return DIRENT_ABORT;
+ }
+ return 0;
+}
+
+static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
+ ext2_ino_t ino, int maxdepth,
+ char *buf, char **name)
+{
+ struct get_pathname_struct gp;
+ char *parent_name, *ret;
+ errcode_t retval;
+
+ if (dir == ino) {
+ retval = ext2fs_get_mem(2, (void **)name);
+ if (retval)
+ return retval;
+ strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
+ return 0;
+ }
+
+ if (!dir || (maxdepth < 0)) {
+ retval = ext2fs_get_mem(4, (void **)name);
+ if (retval)
+ return retval;
+ strcpy(*name, "...");
+ return 0;
+ }
+
+ gp.search_ino = ino;
+ gp.parent = 0;
+ gp.name = 0;
+ gp.errcode = 0;
+
+ retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
+ if (retval)
+ goto cleanup;
+ if (gp.errcode) {
+ retval = gp.errcode;
+ goto cleanup;
+ }
+
+ retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
+ buf, &parent_name);
+ if (retval)
+ goto cleanup;
+ if (!ino) {
+ *name = parent_name;
+ return 0;
+ }
+
+ if (gp.name)
+ retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
+ (void **) &ret);
+ else
+ retval = ext2fs_get_mem(strlen(parent_name)+5,
+ (void **) &ret);
+ if (retval)
+ goto cleanup;
+
+ ret[0] = 0;
+ if (parent_name[1])
+ strcat(ret, parent_name);
+ strcat(ret, "/");
+ if (gp.name)
+ strcat(ret, gp.name);
+ else
+ strcat(ret, "???");
+ *name = ret;
+ ext2fs_free_mem((void **) &parent_name);
+ retval = 0;
+
+cleanup:
+ if (gp.name)
+ ext2fs_free_mem((void **) &gp.name);
+ return retval;
+}
+
+errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
+ char **name)
+{
+ char *buf;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+ if (dir == ino)
+ ino = 0;
+ retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+
+}
diff --git a/e2fslib/get_pathname.o b/e2fslib/get_pathname.o
new file mode 100644
index 0000000..7428dc2
--- /dev/null
+++ b/e2fslib/get_pathname.o
Binary files differ
diff --git a/e2fslib/getsize.c b/e2fslib/getsize.c
new file mode 100644
index 0000000..e8fadba
--- /dev/null
+++ b/e2fslib/getsize.c
@@ -0,0 +1,157 @@
+/*
+ * getsize.c --- get the size of a partition.
+ *
+ * Copyright (C) 1995, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_LINUX_FD_H
+#include <sys/ioctl.h>
+#include <linux/fd.h>
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
+#define BLKGETSIZE _IO(0x12,96) /* return device size */
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+static int valid_offset (int fd, ext2_loff_t offset)
+{
+ char ch;
+
+ if (ext2fs_llseek (fd, offset, 0) < 0)
+ return 0;
+ if (read (fd, &ch, 1) < 1)
+ return 0;
+ return 1;
+}
+
+/*
+ * Returns the number of blocks in a partition
+ */
+errcode_t ext2fs_get_device_size(const char *file, int blocksize,
+ blk_t *retblocks)
+{
+ int fd;
+#ifdef BLKGETSIZE
+ unsigned long size;
+#endif
+ ext2_loff_t high, low;
+#ifdef FDGETPRM
+ struct floppy_struct this_floppy;
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+ int part;
+ struct disklabel lab;
+ struct partition *pp;
+ char ch;
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+#ifdef HAVE_OPEN64
+ fd = open64(file, O_RDONLY);
+#else
+ fd = open(file, O_RDONLY);
+#endif
+ if (fd < 0)
+ return errno;
+
+#ifdef BLKGETSIZE
+ if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
+ close(fd);
+ *retblocks = size / (blocksize / 512);
+ return 0;
+ }
+#endif
+#ifdef FDGETPRM
+ if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
+ close(fd);
+ *retblocks = this_floppy.size / (blocksize / 512);
+ return 0;
+ }
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+ part = strlen(file) - 1;
+ if (part >= 0) {
+ ch = file[part];
+ if (isdigit(ch))
+ part = 0;
+ else if (ch >= 'a' && ch <= 'h')
+ part = ch - 'a';
+ else
+ part = -1;
+ }
+ if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
+ pp = &lab.d_partitions[part];
+ if (pp->p_size) {
+ close(fd);
+ *retblocks = pp->p_size / (blocksize / 512);
+ return 0;
+ }
+ }
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+ /*
+ * OK, we couldn't figure it out by using a specialized ioctl,
+ * which is generally the best way. So do binary search to
+ * find the size of the partition.
+ */
+ low = 0;
+ for (high = 1024; valid_offset (fd, high); high *= 2)
+ low = high;
+ while (low < high - 1)
+ {
+ const ext2_loff_t mid = (low + high) / 2;
+
+ if (valid_offset (fd, mid))
+ low = mid;
+ else
+ high = mid;
+ }
+ valid_offset (fd, 0);
+ close(fd);
+ *retblocks = (low + 1) / blocksize;
+ return 0;
+}
+
+#ifdef DEBUG
+int main(int argc, char **argv)
+{
+ blk_t blocks;
+ int retval;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s device\n", argv[0]);
+ exit(1);
+ }
+
+ retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
+ if (retval) {
+ com_err(argv[0], retval,
+ "while calling ext2fs_get_device_size");
+ exit(1);
+ }
+ printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
+ exit(0);
+}
+#endif
diff --git a/e2fslib/getsize.o b/e2fslib/getsize.o
new file mode 100644
index 0000000..533f3d9
--- /dev/null
+++ b/e2fslib/getsize.o
Binary files differ
diff --git a/e2fslib/icount.c b/e2fslib/icount.c
new file mode 100644
index 0000000..1ad3940
--- /dev/null
+++ b/e2fslib/icount.c
@@ -0,0 +1,482 @@
+/*
+ * icount.c --- an efficient inode count abstraction
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * The data storage strategy used by icount relies on the observation
+ * that most inode counts are either zero (for non-allocated inodes),
+ * one (for most files), and only a few that are two or more
+ * (directories and files that are linked to more than one directory).
+ *
+ * Also, e2fsck tends to load the icount data sequentially.
+ *
+ * So, we use an inode bitmap to indicate which inodes have a count of
+ * one, and then use a sorted list to store the counts for inodes
+ * which are greater than one.
+ *
+ * We also use an optional bitmap to indicate which inodes are already
+ * in the sorted list, to speed up the use of this abstraction by
+ * e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
+ * so this extra bitmap avoids searching the sorted list to see if a
+ * particular inode is on the sorted list already.
+ */
+
+struct ext2_icount_el {
+ ext2_ino_t ino;
+ __u16 count;
+};
+
+struct ext2_icount {
+ errcode_t magic;
+ ext2fs_inode_bitmap single;
+ ext2fs_inode_bitmap multiple;
+ ext2_ino_t count;
+ ext2_ino_t size;
+ ext2_ino_t num_inodes;
+ int cursor;
+ struct ext2_icount_el *list;
+};
+
+void ext2fs_free_icount(ext2_icount_t icount)
+{
+ if (!icount)
+ return;
+
+ icount->magic = 0;
+ if (icount->list)
+ ext2fs_free_mem((void **) &icount->list);
+ if (icount->single)
+ ext2fs_free_inode_bitmap(icount->single);
+ if (icount->multiple)
+ ext2fs_free_inode_bitmap(icount->multiple);
+ ext2fs_free_mem((void **) &icount);
+}
+
+errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
+ ext2_icount_t hint, ext2_icount_t *ret)
+{
+ ext2_icount_t icount;
+ errcode_t retval;
+ size_t bytes;
+ int i;
+
+ if (hint) {
+ EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
+ if (hint->size > size)
+ size = (size_t) hint->size;
+ }
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_icount), (void **) &icount);
+ if (retval)
+ return retval;
+ memset(icount, 0, sizeof(struct ext2_icount));
+
+ retval = ext2fs_allocate_inode_bitmap(fs, 0,
+ &icount->single);
+ if (retval)
+ goto errout;
+
+ if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
+ retval = ext2fs_allocate_inode_bitmap(fs, 0,
+ &icount->multiple);
+ if (retval)
+ goto errout;
+ } else
+ icount->multiple = 0;
+
+ if (size) {
+ icount->size = size;
+ } else {
+ /*
+ * Figure out how many special case inode counts we will
+ * have. We know we will need one for each directory;
+ * we also need to reserve some extra room for file links
+ */
+ retval = ext2fs_get_num_dirs(fs, &icount->size);
+ if (retval)
+ goto errout;
+ icount->size += fs->super->s_inodes_count / 50;
+ }
+
+ bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
+#if 0
+ printf("Icount allocated %d entries, %d bytes.\n",
+ icount->size, bytes);
+#endif
+ retval = ext2fs_get_mem(bytes, (void **) &icount->list);
+ if (retval)
+ goto errout;
+ memset(icount->list, 0, bytes);
+
+ icount->magic = EXT2_ET_MAGIC_ICOUNT;
+ icount->count = 0;
+ icount->cursor = 0;
+ icount->num_inodes = fs->super->s_inodes_count;
+
+ /*
+ * Populate the sorted list with those entries which were
+ * found in the hint icount (since those are ones which will
+ * likely need to be in the sorted list this time around).
+ */
+ if (hint) {
+ for (i=0; i < hint->count; i++)
+ icount->list[i].ino = hint->list[i].ino;
+ icount->count = hint->count;
+ }
+
+ *ret = icount;
+ return 0;
+
+errout:
+ ext2fs_free_icount(icount);
+ return(retval);
+}
+
+errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
+ ext2_icount_t *ret)
+{
+ return ext2fs_create_icount2(fs, flags, size, 0, ret);
+}
+
+/*
+ * insert_icount_el() --- Insert a new entry into the sorted list at a
+ * specified position.
+ */
+static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
+ ext2_ino_t ino, int pos)
+{
+ struct ext2_icount_el *el;
+ errcode_t retval;
+ ext2_ino_t new_size = 0;
+ int num;
+
+ if (icount->count >= icount->size) {
+ if (icount->count) {
+ new_size = icount->list[(unsigned)icount->count-1].ino;
+ new_size = (ext2_ino_t) (icount->count *
+ ((float) icount->num_inodes / new_size));
+ }
+ if (new_size < (icount->size + 100))
+ new_size = icount->size + 100;
+#if 0
+ printf("Reallocating icount %d entries...\n", new_size);
+#endif
+ retval = ext2fs_resize_mem((size_t) icount->size *
+ sizeof(struct ext2_icount_el),
+ (size_t) new_size *
+ sizeof(struct ext2_icount_el),
+ (void **) &icount->list);
+ if (retval)
+ return 0;
+ icount->size = new_size;
+ }
+ num = (int) icount->count - pos;
+ if (num < 0)
+ return 0; /* should never happen */
+ if (num) {
+ memmove(&icount->list[pos+1], &icount->list[pos],
+ sizeof(struct ext2_icount_el) * num);
+ }
+ icount->count++;
+ el = &icount->list[pos];
+ el->count = 0;
+ el->ino = ino;
+ return el;
+}
+
+/*
+ * get_icount_el() --- given an inode number, try to find icount
+ * information in the sorted list. If the create flag is set,
+ * and we can't find an entry, create one in the sorted list.
+ */
+static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
+ ext2_ino_t ino, int create)
+{
+ float range;
+ int low, high, mid;
+ ext2_ino_t lowval, highval;
+
+ if (!icount || !icount->list)
+ return 0;
+
+ if (create && ((icount->count == 0) ||
+ (ino > icount->list[(unsigned)icount->count-1].ino))) {
+ return insert_icount_el(icount, ino, (unsigned) icount->count);
+ }
+ if (icount->count == 0)
+ return 0;
+
+ if (icount->cursor >= icount->count)
+ icount->cursor = 0;
+ if (ino == icount->list[icount->cursor].ino)
+ return &icount->list[icount->cursor++];
+#if 0
+ printf("Non-cursor get_icount_el: %u\n", ino);
+#endif
+ low = 0;
+ high = (int) icount->count-1;
+ while (low <= high) {
+#if 0
+ mid = (low+high)/2;
+#else
+ if (low == high)
+ mid = low;
+ else {
+ /* Interpolate for efficiency */
+ lowval = icount->list[low].ino;
+ highval = icount->list[high].ino;
+
+ if (ino < lowval)
+ range = 0;
+ else if (ino > highval)
+ range = 1;
+ else
+ range = ((float) (ino - lowval)) /
+ (highval - lowval);
+ mid = low + ((int) (range * (high-low)));
+ }
+#endif
+ if (ino == icount->list[mid].ino) {
+ icount->cursor = mid+1;
+ return &icount->list[mid];
+ }
+ if (ino < icount->list[mid].ino)
+ high = mid-1;
+ else
+ low = mid+1;
+ }
+ /*
+ * If we need to create a new entry, it should be right at
+ * low (where high will be left at low-1).
+ */
+ if (create)
+ return insert_icount_el(icount, ino, low);
+ return 0;
+}
+
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
+{
+ errcode_t ret = 0;
+ int i;
+ const char *bad = "bad icount";
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (icount->count > icount->size) {
+ fprintf(out, "%s: count > size\n", bad);
+ return EXT2_ET_INVALID_ARGUMENT;
+ }
+ for (i=1; i < icount->count; i++) {
+ if (icount->list[i-1].ino >= icount->list[i].ino) {
+ fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
+ bad, i-1, icount->list[i-1].ino,
+ i, icount->list[i].ino);
+ ret = EXT2_ET_INVALID_ARGUMENT;
+ }
+ }
+ return ret;
+}
+
+errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
+{
+ struct ext2_icount_el *el;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (!ino || (ino > icount->num_inodes))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+ *ret = 1;
+ return 0;
+ }
+ if (icount->multiple &&
+ !ext2fs_test_inode_bitmap(icount->multiple, ino)) {
+ *ret = 0;
+ return 0;
+ }
+ el = get_icount_el(icount, ino, 0);
+ if (!el) {
+ *ret = 0;
+ return 0;
+ }
+ *ret = el->count;
+ return 0;
+}
+
+errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret)
+{
+ struct ext2_icount_el *el;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (!ino || (ino > icount->num_inodes))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+ /*
+ * If the existing count is 1, then we know there is
+ * no entry in the list.
+ */
+ el = get_icount_el(icount, ino, 1);
+ if (!el)
+ return EXT2_ET_NO_MEMORY;
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ el->count = 2;
+ } else if (icount->multiple) {
+ /*
+ * The count is either zero or greater than 1; if the
+ * inode is set in icount->multiple, then there should
+ * be an entry in the list, so find it using
+ * get_icount_el().
+ */
+ if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
+ el = get_icount_el(icount, ino, 1);
+ if (!el)
+ return EXT2_ET_NO_MEMORY;
+ el->count++;
+ } else {
+ /*
+ * The count was zero; mark the single bitmap
+ * and return.
+ */
+ zero_count:
+ ext2fs_mark_inode_bitmap(icount->single, ino);
+ if (ret)
+ *ret = 1;
+ return 0;
+ }
+ } else {
+ /*
+ * The count is either zero or greater than 1; try to
+ * find an entry in the list to determine which.
+ */
+ el = get_icount_el(icount, ino, 0);
+ if (!el) {
+ /* No entry means the count was zero */
+ goto zero_count;
+ }
+ el = get_icount_el(icount, ino, 1);
+ if (!el)
+ return EXT2_ET_NO_MEMORY;
+ el->count++;
+ }
+ if (icount->multiple)
+ ext2fs_mark_inode_bitmap(icount->multiple, ino);
+ if (ret)
+ *ret = el->count;
+ return 0;
+}
+
+errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 *ret)
+{
+ struct ext2_icount_el *el;
+
+ if (!ino || (ino > icount->num_inodes))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ if (icount->multiple)
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+ else {
+ el = get_icount_el(icount, ino, 0);
+ if (el)
+ el->count = 0;
+ }
+ if (ret)
+ *ret = 0;
+ return 0;
+ }
+
+ if (icount->multiple &&
+ !ext2fs_test_inode_bitmap(icount->multiple, ino))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ el = get_icount_el(icount, ino, 0);
+ if (!el || el->count == 0)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ el->count--;
+ if (el->count == 1)
+ ext2fs_mark_inode_bitmap(icount->single, ino);
+ if ((el->count == 0) && icount->multiple)
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+
+ if (ret)
+ *ret = el->count;
+ return 0;
+}
+
+errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+ __u16 count)
+{
+ struct ext2_icount_el *el;
+
+ if (!ino || (ino > icount->num_inodes))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (count == 1) {
+ ext2fs_mark_inode_bitmap(icount->single, ino);
+ if (icount->multiple)
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+ return 0;
+ }
+ if (count == 0) {
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ if (icount->multiple) {
+ /*
+ * If the icount->multiple bitmap is enabled,
+ * we can just clear both bitmaps and we're done
+ */
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+ } else {
+ el = get_icount_el(icount, ino, 0);
+ if (el)
+ el->count = 0;
+ }
+ return 0;
+ }
+
+ /*
+ * Get the icount element
+ */
+ el = get_icount_el(icount, ino, 1);
+ if (!el)
+ return EXT2_ET_NO_MEMORY;
+ el->count = count;
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ if (icount->multiple)
+ ext2fs_mark_inode_bitmap(icount->multiple, ino);
+ return 0;
+}
+
+ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
+{
+ if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
+ return 0;
+
+ return icount->size;
+}
diff --git a/e2fslib/icount.o b/e2fslib/icount.o
new file mode 100644
index 0000000..360baa9
--- /dev/null
+++ b/e2fslib/icount.o
Binary files differ
diff --git a/e2fslib/imager.c b/e2fslib/imager.c
new file mode 100644
index 0000000..242e36a
--- /dev/null
+++ b/e2fslib/imager.c
@@ -0,0 +1,380 @@
+/*
+ * image.c --- writes out the critical parts of the filesystem as a
+ * flat file.
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * Note: this uses the POSIX IO interfaces, unlike most of the other
+ * functions in this library. So sue me.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * This function returns 1 if the specified block is all zeros
+ */
+static int check_zero_block(char *buf, int blocksize)
+{
+ char *cp = buf;
+ int left = blocksize;
+
+ while (left > 0) {
+ if (*cp++)
+ return 0;
+ left--;
+ }
+ return 1;
+}
+
+/*
+ * Write the inode table out as a single block.
+ */
+#define BUF_BLOCKS 32
+
+errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
+{
+ unsigned int group, left, c, d;
+ char *buf, *cp;
+ blk_t blk;
+ ssize_t actual;
+ errcode_t retval;
+
+ buf = malloc(fs->blocksize * BUF_BLOCKS);
+ if (!buf)
+ return ENOMEM;
+
+ for (group = 0; group < fs->group_desc_count; group++) {
+ blk = fs->group_desc[(unsigned)group].bg_inode_table;
+ if (!blk)
+ return EXT2_ET_MISSING_INODE_TABLE;
+ left = fs->inode_blocks_per_group;
+ while (left) {
+ c = BUF_BLOCKS;
+ if (c > left)
+ c = left;
+ retval = io_channel_read_blk(fs->io, blk, c, buf);
+ if (retval)
+ goto errout;
+ cp = buf;
+ while (c) {
+ if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
+ d = c;
+ goto skip_sparse;
+ }
+ /* Skip zero blocks */
+ if (check_zero_block(cp, fs->blocksize)) {
+ c--;
+ blk++;
+ left--;
+ cp += fs->blocksize;
+ lseek(fd, fs->blocksize, SEEK_CUR);
+ continue;
+ }
+ /* Find non-zero blocks */
+ for (d=1; d < c; d++) {
+ if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
+ break;
+ }
+ skip_sparse:
+ actual = write(fd, cp, fs->blocksize * d);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != fs->blocksize * d) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto errout;
+ }
+ blk += d;
+ left -= d;
+ cp += fs->blocksize * d;
+ c -= d;
+ }
+ }
+ }
+ retval = 0;
+
+errout:
+ free(buf);
+ return retval;
+}
+
+/*
+ * Read in the inode table and stuff it into place
+ */
+errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags)
+{
+ unsigned int group, c, left;
+ char *buf;
+ blk_t blk;
+ ssize_t actual;
+ errcode_t retval;
+
+ buf = malloc(fs->blocksize * BUF_BLOCKS);
+ if (!buf)
+ return ENOMEM;
+
+ for (group = 0; group < fs->group_desc_count; group++) {
+ blk = fs->group_desc[(unsigned)group].bg_inode_table;
+ if (!blk) {
+ retval = EXT2_ET_MISSING_INODE_TABLE;
+ goto errout;
+ }
+ left = fs->inode_blocks_per_group;
+ while (left) {
+ c = BUF_BLOCKS;
+ if (c > left)
+ c = left;
+ actual = read(fd, buf, fs->blocksize * c);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != fs->blocksize * c) {
+ retval = EXT2_ET_SHORT_READ;
+ goto errout;
+ }
+ retval = io_channel_write_blk(fs->io, blk, c, buf);
+ if (retval)
+ goto errout;
+
+ blk += c;
+ left -= c;
+ }
+ }
+ retval = ext2fs_flush_icache(fs);
+
+errout:
+ free(buf);
+ return retval;
+}
+
+/*
+ * Write out superblock and group descriptors
+ */
+errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags)
+{
+ char *buf, *cp;
+ ssize_t actual;
+ errcode_t retval;
+
+ buf = malloc(fs->blocksize);
+ if (!buf)
+ return ENOMEM;
+
+ /*
+ * Write out the superblock
+ */
+ memset(buf, 0, fs->blocksize);
+ memcpy(buf, fs->super, SUPERBLOCK_SIZE);
+ actual = write(fd, buf, fs->blocksize);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != fs->blocksize) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto errout;
+ }
+
+ /*
+ * Now write out the block group descriptors
+ */
+ cp = (char *) fs->group_desc;
+ actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != fs->blocksize * fs->desc_blocks) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto errout;
+ }
+
+ retval = 0;
+
+errout:
+ free(buf);
+ return retval;
+}
+
+/*
+ * Read the superblock and group descriptors and overwrite them.
+ */
+errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags)
+{
+ char *buf;
+ ssize_t actual, size;
+ errcode_t retval;
+
+ size = fs->blocksize * (fs->group_desc_count + 1);
+ buf = malloc(size);
+ if (!buf)
+ return ENOMEM;
+
+ /*
+ * Read it all in.
+ */
+ actual = read(fd, buf, size);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != size) {
+ retval = EXT2_ET_SHORT_READ;
+ goto errout;
+ }
+
+ /*
+ * Now copy in the superblock and group descriptors
+ */
+ memcpy(fs->super, buf, SUPERBLOCK_SIZE);
+
+ memcpy(fs->group_desc, buf + fs->blocksize,
+ fs->blocksize * fs->group_desc_count);
+
+ retval = 0;
+
+errout:
+ free(buf);
+ return retval;
+}
+
+/*
+ * Write the block/inode bitmaps.
+ */
+errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
+{
+ char *ptr;
+ int c, size;
+ char zero_buf[1024];
+ ssize_t actual;
+ errcode_t retval;
+
+ if (flags & IMAGER_FLAG_INODEMAP) {
+ if (!fs->inode_map) {
+ retval = ext2fs_read_inode_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ ptr = fs->inode_map->bitmap;
+ size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+ } else {
+ if (!fs->block_map) {
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ ptr = fs->block_map->bitmap;
+ size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ }
+ size = size * fs->group_desc_count;
+
+ actual = write(fd, ptr, size);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != size) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto errout;
+ }
+ size = size % fs->blocksize;
+ memset(zero_buf, 0, sizeof(zero_buf));
+ if (size) {
+ size = fs->blocksize - size;
+ while (size) {
+ c = size;
+ if (c > sizeof(zero_buf))
+ c = sizeof(zero_buf);
+ actual = write(fd, zero_buf, c);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != c) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto errout;
+ }
+ size -= c;
+ }
+ }
+ retval = 0;
+errout:
+ return (retval);
+}
+
+
+/*
+ * Read the block/inode bitmaps.
+ */
+errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
+{
+ char *ptr, *buf = 0;
+ int size;
+ ssize_t actual;
+ errcode_t retval;
+
+ if (flags & IMAGER_FLAG_INODEMAP) {
+ if (!fs->inode_map) {
+ retval = ext2fs_read_inode_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ ptr = fs->inode_map->bitmap;
+ size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+ } else {
+ if (!fs->block_map) {
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ ptr = fs->block_map->bitmap;
+ size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ }
+ size = size * fs->group_desc_count;
+
+ buf = malloc(size);
+ if (!buf)
+ return ENOMEM;
+
+ actual = read(fd, buf, size);
+ if (actual == -1) {
+ retval = errno;
+ goto errout;
+ }
+ if (actual != size) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto errout;
+ }
+ memcpy(ptr, buf, size);
+
+ retval = 0;
+errout:
+ if (buf)
+ free(buf);
+ return (retval);
+}
diff --git a/e2fslib/imager.o b/e2fslib/imager.o
new file mode 100644
index 0000000..bc62f6b
--- /dev/null
+++ b/e2fslib/imager.o
Binary files differ
diff --git a/e2fslib/initialize.c b/e2fslib/initialize.c
new file mode 100644
index 0000000..821036e
--- /dev/null
+++ b/e2fslib/initialize.c
@@ -0,0 +1,326 @@
+/*
+ * initialize.c --- initialize a filesystem handle given superblock
+ * parameters. Used by mke2fs when initializing a filesystem.
+ *
+ * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#if defined(__linux__) && defined(EXT2_OS_LINUX)
+#define CREATOR_OS EXT2_OS_LINUX
+#elif defined(__GNU__) && defined(EXT2_OS_HURD)
+#define CREATOR_OS EXT2_OS_HURD
+#elif defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
+#define CREATOR_OS EXT2_OS_FREEBSD
+#elif defined(LITES) && defined(EXT2_OS_LITES)
+#define CREATOR_OS EXT2_OS_LITES
+#else
+#define CREATOR_OS EXT2_OS_LINUX /* by default */
+#endif
+
+/*
+ * Note we override the kernel include file's idea of what the default
+ * check interval (never) should be. It's a good idea to check at
+ * least *occasionally*, specially since servers will never rarely get
+ * to reboot, since Linux is so robust these days. :-)
+ *
+ * 180 days (six months) seems like a good value.
+ */
+#ifdef EXT2_DFL_CHECKINTERVAL
+#undef EXT2_DFL_CHECKINTERVAL
+#endif
+#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
+
+errcode_t ext2fs_initialize(const char *name, int flags,
+ struct ext2_super_block *param,
+ io_manager manager, ext2_filsys *ret_fs)
+{
+ ext2_filsys fs;
+ errcode_t retval;
+ struct ext2_super_block *super;
+ int frags_per_block;
+ int rem;
+ int overhead = 0;
+ blk_t group_block;
+ int i, j;
+ blk_t numblocks;
+ char *buf;
+
+ if (!param || !param->s_blocks_count)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys),
+ (void **) &fs);
+ if (retval)
+ return retval;
+
+ memset(fs, 0, sizeof(struct struct_ext2_filsys));
+ fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
+ fs->flags = flags | EXT2_FLAG_RW;
+#ifdef WORDS_BIGENDIAN
+ fs->flags |= EXT2_FLAG_SWAP_BYTES;
+#endif
+ retval = manager->open(name, IO_FLAG_RW, &fs->io);
+ if (retval)
+ goto cleanup;
+ fs->io->app_data = fs;
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &fs->device_name);
+ if (retval)
+ goto cleanup;
+
+ strcpy(fs->device_name, name);
+ retval = ext2fs_get_mem(SUPERBLOCK_SIZE, (void **) &super);
+ if (retval)
+ goto cleanup;
+ fs->super = super;
+
+ memset(super, 0, SUPERBLOCK_SIZE);
+
+#define set_field(field, default) (super->field = param->field ? \
+ param->field : (default))
+
+ super->s_magic = EXT2_SUPER_MAGIC;
+ super->s_state = EXT2_VALID_FS;
+
+ set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
+ set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
+ set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
+ set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
+ set_field(s_errors, EXT2_ERRORS_DEFAULT);
+ set_field(s_feature_compat, 0);
+ set_field(s_feature_incompat, 0);
+ set_field(s_feature_ro_compat, 0);
+ if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)
+ return EXT2_ET_UNSUPP_FEATURE;
+ if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)
+ return EXT2_ET_RO_UNSUPP_FEATURE;
+
+ set_field(s_rev_level, EXT2_GOOD_OLD_REV);
+ if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
+ set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
+ set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
+ }
+
+ set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
+ super->s_lastcheck = time(NULL);
+
+ super->s_creator_os = CREATOR_OS;
+
+ fs->blocksize = EXT2_BLOCK_SIZE(super);
+ fs->fragsize = EXT2_FRAG_SIZE(super);
+ frags_per_block = fs->blocksize / fs->fragsize;
+
+ /* default: (fs->blocksize*8) blocks/group */
+ set_field(s_blocks_per_group, fs->blocksize*8);
+ super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
+
+ super->s_blocks_count = param->s_blocks_count;
+ super->s_r_blocks_count = param->s_r_blocks_count;
+ if (super->s_r_blocks_count >= param->s_blocks_count) {
+ retval = EXT2_ET_INVALID_ARGUMENT;
+ goto cleanup;
+ }
+
+ /*
+ * If we're creating an external journal device, we don't need
+ * to bother with the rest.
+ */
+ if (super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+ fs->group_desc_count = 0;
+ ext2fs_mark_super_dirty(fs);
+ *ret_fs = fs;
+ return 0;
+ }
+
+retry:
+ fs->group_desc_count = (super->s_blocks_count -
+ super->s_first_data_block +
+ EXT2_BLOCKS_PER_GROUP(super) - 1)
+ / EXT2_BLOCKS_PER_GROUP(super);
+ if (fs->group_desc_count == 0)
+ return EXT2_ET_TOOSMALL;
+ fs->desc_blocks = (fs->group_desc_count +
+ EXT2_DESC_PER_BLOCK(super) - 1)
+ / EXT2_DESC_PER_BLOCK(super);
+
+ /* n.b., fs->blocksize is <= 4096 */
+ set_field(s_inodes_count, super->s_blocks_count/(4096/fs->blocksize));
+
+ /*
+ * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
+ * that we have enough inodes for the filesystem(!)
+ */
+ if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
+ super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
+
+ /*
+ * There should be at least as many inodes as the user
+ * requested. Figure out how many inodes per group that
+ * should be. But make sure that we don't allocate more than
+ * one bitmap's worth of inodes
+ */
+ super->s_inodes_per_group = (super->s_inodes_count +
+ fs->group_desc_count - 1) /
+ fs->group_desc_count;
+ if (super->s_inodes_per_group > fs->blocksize*8)
+ super->s_inodes_per_group = fs->blocksize*8;
+
+ /*
+ * Make sure the number of inodes per group completely fills
+ * the inode table blocks in the descriptor. If not, add some
+ * additional inodes/group. Waste not, want not...
+ */
+ fs->inode_blocks_per_group = (((super->s_inodes_per_group *
+ EXT2_INODE_SIZE(super)) +
+ EXT2_BLOCK_SIZE(super) - 1) /
+ EXT2_BLOCK_SIZE(super));
+ super->s_inodes_per_group = ((fs->inode_blocks_per_group *
+ EXT2_BLOCK_SIZE(super)) /
+ EXT2_INODE_SIZE(super));
+ /*
+ * Finally, make sure the number of inodes per group is a
+ * multiple of 8. This is needed to simplify the bitmap
+ * splicing code.
+ */
+ super->s_inodes_per_group &= ~7;
+ fs->inode_blocks_per_group = (((super->s_inodes_per_group *
+ EXT2_INODE_SIZE(super)) +
+ EXT2_BLOCK_SIZE(super) - 1) /
+ EXT2_BLOCK_SIZE(super));
+
+ /*
+ * adjust inode count to reflect the adjusted inodes_per_group
+ */
+ super->s_inodes_count = super->s_inodes_per_group *
+ fs->group_desc_count;
+ super->s_free_inodes_count = super->s_inodes_count;
+
+ /*
+ * Overhead is the number of bookkeeping blocks per group. It
+ * includes the superblock backup, the group descriptor
+ * backups, the inode bitmap, the block bitmap, and the inode
+ * table.
+ *
+ * XXX Not all block groups need the descriptor blocks, but
+ * being clever is tricky...
+ */
+ overhead = (int) (3 + fs->desc_blocks + fs->inode_blocks_per_group);
+
+ /*
+ * See if the last group is big enough to support the
+ * necessary data structures. If not, we need to get rid of
+ * it.
+ */
+ rem = (int) ((super->s_blocks_count - super->s_first_data_block) %
+ super->s_blocks_per_group);
+ if ((fs->group_desc_count == 1) && rem && (rem < overhead))
+ return EXT2_ET_TOOSMALL;
+ if (rem && (rem < overhead+50)) {
+ super->s_blocks_count -= rem;
+ goto retry;
+ }
+
+ /*
+ * At this point we know how big the filesystem will be. So
+ * we can do any and all allocations that depend on the block
+ * count.
+ */
+
+ retval = ext2fs_get_mem(strlen(fs->device_name) + 80,
+ (void **) &buf);
+ if (retval)
+ goto cleanup;
+
+ sprintf(buf, "block bitmap for %s", fs->device_name);
+ retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
+ if (retval)
+ goto cleanup;
+
+ sprintf(buf, "inode bitmap for %s", fs->device_name);
+ retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
+ if (retval)
+ goto cleanup;
+
+ ext2fs_free_mem((void **) &buf);
+
+ retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
+ (void **) &fs->group_desc);
+ if (retval)
+ goto cleanup;
+
+ memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
+
+ /*
+ * Reserve the superblock and group descriptors for each
+ * group, and fill in the correct group statistics for group.
+ * Note that although the block bitmap, inode bitmap, and
+ * inode table have not been allocated (and in fact won't be
+ * by this routine), they are accounted for nevertheless.
+ */
+ group_block = super->s_first_data_block;
+ super->s_free_blocks_count = 0;
+ for (i = 0; i < fs->group_desc_count; i++) {
+ if (i == fs->group_desc_count-1) {
+ numblocks = (fs->super->s_blocks_count -
+ fs->super->s_first_data_block) %
+ fs->super->s_blocks_per_group;
+ if (!numblocks)
+ numblocks = fs->super->s_blocks_per_group;
+ } else
+ numblocks = fs->super->s_blocks_per_group;
+
+ if (ext2fs_bg_has_super(fs, i)) {
+ for (j=0; j < fs->desc_blocks+1; j++)
+ ext2fs_mark_block_bitmap(fs->block_map,
+ group_block + j);
+ numblocks -= 1 + fs->desc_blocks;
+ }
+
+ numblocks -= 2 + fs->inode_blocks_per_group;
+
+ super->s_free_blocks_count += numblocks;
+ fs->group_desc[i].bg_free_blocks_count = numblocks;
+ fs->group_desc[i].bg_free_inodes_count =
+ fs->super->s_inodes_per_group;
+ fs->group_desc[i].bg_used_dirs_count = 0;
+
+ group_block += super->s_blocks_per_group;
+ }
+
+ ext2fs_mark_super_dirty(fs);
+ ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_ib_dirty(fs);
+
+ io_channel_set_blksize(fs->io, fs->blocksize);
+
+ *ret_fs = fs;
+ return 0;
+cleanup:
+ ext2fs_free(fs);
+ return retval;
+}
+
+
+
diff --git a/e2fslib/initialize.o b/e2fslib/initialize.o
new file mode 100644
index 0000000..833c89f
--- /dev/null
+++ b/e2fslib/initialize.o
Binary files differ
diff --git a/e2fslib/inline.c b/e2fslib/inline.c
new file mode 100644
index 0000000..5833b1d
--- /dev/null
+++ b/e2fslib/inline.c
@@ -0,0 +1,32 @@
+/*
+ * inline.c --- Includes the inlined functions defined in the header
+ * files as standalone functions, in case the application program
+ * is compiled with inlining turned off.
+ *
+ * Copyright (C) 1993, 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#define INCLUDE_INLINE_FUNCS
+#include "ext2fs.h"
+
diff --git a/e2fslib/inline.o b/e2fslib/inline.o
new file mode 100644
index 0000000..c727bb1
--- /dev/null
+++ b/e2fslib/inline.o
Binary files differ
diff --git a/e2fslib/inode.c b/e2fslib/inode.c
new file mode 100644
index 0000000..2da328c
--- /dev/null
+++ b/e2fslib/inode.c
@@ -0,0 +1,724 @@
+/*
+ * inode.c --- utility routines to read and write inodes
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+#include "e2image.h"
+
+struct ext2_struct_inode_scan {
+ errcode_t magic;
+ ext2_filsys fs;
+ ext2_ino_t current_inode;
+ blk_t current_block;
+ dgrp_t current_group;
+ ext2_ino_t inodes_left;
+ blk_t blocks_left;
+ dgrp_t groups_left;
+ blk_t inode_buffer_blocks;
+ char * inode_buffer;
+ int inode_size;
+ char * ptr;
+ int bytes_left;
+ char *temp_buffer;
+ errcode_t (*done_group)(ext2_filsys fs,
+ ext2_inode_scan scan,
+ dgrp_t group,
+ void * priv_data);
+ void * done_group_data;
+ int bad_block_ptr;
+ int scan_flags;
+ int reserved[6];
+};
+
+/*
+ * This routine flushes the icache, if it exists.
+ */
+errcode_t ext2fs_flush_icache(ext2_filsys fs)
+{
+ int i;
+
+ if (!fs->icache)
+ return 0;
+
+ for (i=0; i < fs->icache->cache_size; i++)
+ fs->icache->cache[i].ino = 0;
+
+ return 0;
+}
+
+static errcode_t create_icache(ext2_filsys fs)
+{
+ errcode_t retval;
+
+ if (fs->icache)
+ return 0;
+ retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache),
+ (void **) &fs->icache);
+ if (retval)
+ return retval;
+
+ memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &fs->icache->buffer);
+ if (retval) {
+ ext2fs_free_mem((void **) &fs->icache);
+ return retval;
+ }
+ fs->icache->buffer_blk = 0;
+ fs->icache->cache_last = -1;
+ fs->icache->cache_size = 4;
+ fs->icache->refcount = 1;
+ retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
+ * fs->icache->cache_size,
+ (void **) &fs->icache->cache);
+ if (retval) {
+ ext2fs_free_mem((void **) &fs->icache->buffer);
+ ext2fs_free_mem((void **) &fs->icache);
+ return retval;
+ }
+ ext2fs_flush_icache(fs);
+ return 0;
+}
+
+errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
+ ext2_inode_scan *ret_scan)
+{
+ ext2_inode_scan scan;
+ errcode_t retval;
+ errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ /*
+ * If fs->badblocks isn't set, then set it --- since the inode
+ * scanning functions require it.
+ */
+ if (fs->badblocks == 0) {
+ /*
+ * Temporarly save fs->get_blocks and set it to zero,
+ * for compatibility with old e2fsck's.
+ */
+ save_get_blocks = fs->get_blocks;
+ fs->get_blocks = 0;
+ retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
+ if (retval && fs->badblocks) {
+ ext2fs_badblocks_list_free(fs->badblocks);
+ fs->badblocks = 0;
+ }
+ fs->get_blocks = save_get_blocks;
+ }
+
+ retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan),
+ (void **) &scan);
+ if (retval)
+ return retval;
+ memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
+
+ scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
+ scan->fs = fs;
+ scan->inode_size = EXT2_INODE_SIZE(fs->super);
+ scan->bytes_left = 0;
+ scan->current_group = 0;
+ scan->groups_left = fs->group_desc_count - 1;
+ scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
+ scan->current_block = scan->fs->
+ group_desc[scan->current_group].bg_inode_table;
+ scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+ scan->blocks_left = scan->fs->inode_blocks_per_group;
+ retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
+ fs->blocksize),
+ (void **) &scan->inode_buffer);
+ scan->done_group = 0;
+ scan->done_group_data = 0;
+ scan->bad_block_ptr = 0;
+ if (retval) {
+ ext2fs_free_mem((void **) &scan);
+ return retval;
+ }
+ retval = ext2fs_get_mem(scan->inode_size,
+ (void **) &scan->temp_buffer);
+ if (retval) {
+ ext2fs_free_mem((void **) &scan->inode_buffer);
+ ext2fs_free_mem((void **) &scan);
+ return retval;
+ }
+ if (scan->fs->badblocks && scan->fs->badblocks->num)
+ scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
+ *ret_scan = scan;
+ return 0;
+}
+
+void ext2fs_close_inode_scan(ext2_inode_scan scan)
+{
+ if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+ return;
+
+ ext2fs_free_mem((void **) &scan->inode_buffer);
+ scan->inode_buffer = NULL;
+ ext2fs_free_mem((void **) &scan->temp_buffer);
+ scan->temp_buffer = NULL;
+ ext2fs_free_mem((void **) &scan);
+ return;
+}
+
+void ext2fs_set_inode_callback(ext2_inode_scan scan,
+ errcode_t (*done_group)(ext2_filsys fs,
+ ext2_inode_scan scan,
+ dgrp_t group,
+ void * priv_data),
+ void *done_group_data)
+{
+ if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+ return;
+
+ scan->done_group = done_group;
+ scan->done_group_data = done_group_data;
+}
+
+int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
+ int clear_flags)
+{
+ int old_flags;
+
+ if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+ return 0;
+
+ old_flags = scan->scan_flags;
+ scan->scan_flags &= ~clear_flags;
+ scan->scan_flags |= set_flags;
+ return old_flags;
+}
+
+/*
+ * This function is called by ext2fs_get_next_inode when it needs to
+ * get ready to read in a new blockgroup.
+ */
+static errcode_t get_next_blockgroup(ext2_inode_scan scan)
+{
+ scan->current_group++;
+ scan->groups_left--;
+
+ scan->current_block = scan->fs->
+ group_desc[scan->current_group].bg_inode_table;
+
+ scan->current_inode = scan->current_group *
+ EXT2_INODES_PER_GROUP(scan->fs->super);
+
+ scan->bytes_left = 0;
+ scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+ scan->blocks_left = scan->fs->inode_blocks_per_group;
+ return 0;
+}
+
+errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
+ int group)
+{
+ scan->current_group = group - 1;
+ scan->groups_left = scan->fs->group_desc_count - group;
+ return get_next_blockgroup(scan);
+}
+
+/*
+ * This function is called by get_next_blocks() to check for bad
+ * blocks in the inode table.
+ *
+ * This function assumes that badblocks_list->list is sorted in
+ * increasing order.
+ */
+static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
+ blk_t *num_blocks)
+{
+ blk_t blk = scan->current_block;
+ badblocks_list bb = scan->fs->badblocks;
+
+ /*
+ * If the inode table is missing, then obviously there are no
+ * bad blocks. :-)
+ */
+ if (blk == 0)
+ return 0;
+
+ /*
+ * If the current block is greater than the bad block listed
+ * in the bad block list, then advance the pointer until this
+ * is no longer the case. If we run out of bad blocks, then
+ * we don't need to do any more checking!
+ */
+ while (blk > bb->list[scan->bad_block_ptr]) {
+ if (++scan->bad_block_ptr >= bb->num) {
+ scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+ return 0;
+ }
+ }
+
+ /*
+ * If the current block is equal to the bad block listed in
+ * the bad block list, then handle that one block specially.
+ * (We could try to handle runs of bad blocks, but that
+ * only increases CPU efficiency by a small amount, at the
+ * expense of a huge expense of code complexity, and for an
+ * uncommon case at that.)
+ */
+ if (blk == bb->list[scan->bad_block_ptr]) {
+ scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
+ *num_blocks = 1;
+ if (++scan->bad_block_ptr >= bb->num)
+ scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+ return 0;
+ }
+
+ /*
+ * If there is a bad block in the range that we're about to
+ * read in, adjust the number of blocks to read so that we we
+ * don't read in the bad block. (Then the next block to read
+ * will be the bad block, which is handled in the above case.)
+ */
+ if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
+ *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
+
+ return 0;
+}
+
+/*
+ * This function is called by ext2fs_get_next_inode when it needs to
+ * read in more blocks from the current blockgroup's inode table.
+ */
+static errcode_t get_next_blocks(ext2_inode_scan scan)
+{
+ blk_t num_blocks;
+ errcode_t retval;
+
+ /*
+ * Figure out how many blocks to read; we read at most
+ * inode_buffer_blocks, and perhaps less if there aren't that
+ * many blocks left to read.
+ */
+ num_blocks = scan->inode_buffer_blocks;
+ if (num_blocks > scan->blocks_left)
+ num_blocks = scan->blocks_left;
+
+ /*
+ * If the past block "read" was a bad block, then mark the
+ * left-over extra bytes as also being bad.
+ */
+ if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
+ if (scan->bytes_left)
+ scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
+ scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
+ }
+
+ /*
+ * Do inode bad block processing, if necessary.
+ */
+ if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
+ retval = check_for_inode_bad_blocks(scan, &num_blocks);
+ if (retval)
+ return retval;
+ }
+
+ if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
+ (scan->current_block == 0)) {
+ memset(scan->inode_buffer, 0,
+ (size_t) num_blocks * scan->fs->blocksize);
+ } else {
+ retval = io_channel_read_blk(scan->fs->io,
+ scan->current_block,
+ (int) num_blocks,
+ scan->inode_buffer);
+ if (retval)
+ return EXT2_ET_NEXT_INODE_READ;
+ }
+ scan->ptr = scan->inode_buffer;
+ scan->bytes_left = num_blocks * scan->fs->blocksize;
+
+ scan->blocks_left -= num_blocks;
+ if (scan->current_block)
+ scan->current_block += num_blocks;
+ return 0;
+}
+
+#if 0
+/*
+ * Returns 1 if the entire inode_buffer has a non-zero size and
+ * contains all zeros. (Not just deleted inodes, since that means
+ * that part of the inode table was used at one point; we want all
+ * zeros, which means that the inode table is pristine.)
+ */
+static inline int is_empty_scan(ext2_inode_scan scan)
+{
+ int i;
+
+ if (scan->bytes_left == 0)
+ return 0;
+
+ for (i=0; i < scan->bytes_left; i++)
+ if (scan->ptr[i])
+ return 0;
+ return 1;
+}
+#endif
+
+errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
+ struct ext2_inode *inode)
+{
+ errcode_t retval;
+ int extra_bytes = 0;
+
+ EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
+
+ /*
+ * Do we need to start reading a new block group?
+ */
+ if (scan->inodes_left <= 0) {
+ force_new_group:
+ if (scan->done_group) {
+ retval = (scan->done_group)
+ (scan->fs, scan, scan->current_group,
+ scan->done_group_data);
+ if (retval)
+ return retval;
+ }
+ if (scan->groups_left <= 0) {
+ *ino = 0;
+ return 0;
+ }
+ retval = get_next_blockgroup(scan);
+ if (retval)
+ return retval;
+ }
+ /*
+ * This is done outside the above if statement so that the
+ * check can be done for block group #0.
+ */
+ if (scan->current_block == 0) {
+ if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
+ goto force_new_group;
+ } else
+ return EXT2_ET_MISSING_INODE_TABLE;
+ }
+
+
+ /*
+ * Have we run out of space in the inode buffer? If so, we
+ * need to read in more blocks.
+ */
+ if (scan->bytes_left < scan->inode_size) {
+ memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
+ extra_bytes = scan->bytes_left;
+
+ retval = get_next_blocks(scan);
+ if (retval)
+ return retval;
+#if 0
+ /*
+ * XXX test Need check for used inode somehow.
+ * (Note: this is hard.)
+ */
+ if (is_empty_scan(scan))
+ goto force_new_group;
+#endif
+ }
+
+ retval = 0;
+ if (extra_bytes) {
+ memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
+ scan->inode_size - extra_bytes);
+ scan->ptr += scan->inode_size - extra_bytes;
+ scan->bytes_left -= scan->inode_size - extra_bytes;
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+ ext2fs_swap_inode(scan->fs, inode,
+ (struct ext2_inode *) scan->temp_buffer, 0);
+ else
+#endif
+ *inode = *((struct ext2_inode *) scan->temp_buffer);
+ if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
+ retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
+ scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
+ } else {
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+ ext2fs_swap_inode(scan->fs, inode,
+ (struct ext2_inode *) scan->ptr, 0);
+ else
+#endif
+ *inode = *((struct ext2_inode *) scan->ptr);
+ scan->ptr += scan->inode_size;
+ scan->bytes_left -= scan->inode_size;
+ if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
+ retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
+ }
+
+ scan->inodes_left--;
+ scan->current_inode++;
+ *ino = scan->current_inode;
+ return retval;
+}
+
+/*
+ * Functions to read and write a single inode.
+ */
+errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode)
+{
+ unsigned long group, block, block_nr, offset;
+ char *ptr;
+ errcode_t retval;
+ int clen, length, i, inodes_per_block;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ /* Check to see if user has an override function */
+ if (fs->read_inode) {
+ retval = (fs->read_inode)(fs, ino, inode);
+ if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
+ return retval;
+ }
+ /* Create inode cache if not present */
+ if (!fs->icache) {
+ retval = create_icache(fs);
+ if (retval)
+ return retval;
+ }
+ /* Check to see if it's in the inode cache */
+ for (i=0; i < fs->icache->cache_size; i++) {
+ if (fs->icache->cache[i].ino == ino) {
+ *inode = fs->icache->cache[i].inode;
+ return 0;
+ }
+ }
+ if ((ino == 0) || (ino > fs->super->s_inodes_count))
+ return EXT2_ET_BAD_INODE_NUM;
+ if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
+ block_nr = fs->image_header->offset_inode / fs->blocksize;
+ block_nr += (ino - 1) / inodes_per_block;
+ offset = ((ino - 1) % inodes_per_block) *
+ EXT2_INODE_SIZE(fs->super);
+ } else {
+ group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
+ offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+ EXT2_INODE_SIZE(fs->super);
+ block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+ if (!fs->group_desc[(unsigned)group].bg_inode_table)
+ return EXT2_ET_MISSING_INODE_TABLE;
+ block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
+ block;
+ }
+ if (block_nr != fs->icache->buffer_blk) {
+ retval = io_channel_read_blk(fs->io, block_nr, 1,
+ fs->icache->buffer);
+ if (retval)
+ return retval;
+ fs->icache->buffer_blk = block_nr;
+ }
+ offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+ ptr = ((char *) fs->icache->buffer) + (unsigned) offset;
+
+ memset(inode, 0, sizeof(struct ext2_inode));
+ length = EXT2_INODE_SIZE(fs->super);
+ if (length > sizeof(struct ext2_inode))
+ length = sizeof(struct ext2_inode);
+
+ if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
+ clen = (int) (EXT2_BLOCK_SIZE(fs->super) - offset);
+ memcpy((char *) inode, ptr, clen);
+ length -= clen;
+
+ retval = io_channel_read_blk(fs->io, block_nr+1, 1,
+ fs->icache->buffer);
+ if (retval) {
+ fs->icache->buffer_blk = 0;
+ return retval;
+ }
+ fs->icache->buffer_blk = block_nr+1;
+
+ memcpy(((char *) inode) + clen,
+ fs->icache->buffer, length);
+ } else
+ memcpy((char *) inode, ptr, length);
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+ ext2fs_swap_inode(fs, inode, inode, 0);
+#endif
+
+ /* Update the inode cache */
+ fs->icache->cache_last = (fs->icache->cache_last + 1) %
+ fs->icache->cache_size;
+ fs->icache->cache[fs->icache->cache_last].ino = ino;
+ fs->icache->cache[fs->icache->cache_last].inode = *inode;
+
+ return 0;
+}
+
+errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode)
+{
+ unsigned long group, block, block_nr, offset;
+ errcode_t retval;
+ struct ext2_inode temp_inode;
+ char *ptr;
+ int clen, length, i;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ /* Check to see if user provided an override function */
+ if (fs->write_inode) {
+ retval = (fs->write_inode)(fs, ino, inode);
+ if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
+ return retval;
+ }
+
+ /* Check to see if the inode cache needs to be updated */
+ if (fs->icache) {
+ for (i=0; i < fs->icache->cache_size; i++) {
+ if (fs->icache->cache[i].ino == ino) {
+ fs->icache->cache[i].inode = *inode;
+ break;
+ }
+ }
+ } else {
+ retval = create_icache(fs);
+ if (retval)
+ return retval;
+ }
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ if ((ino == 0) || (ino > fs->super->s_inodes_count))
+ return EXT2_ET_BAD_INODE_NUM;
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
+ ext2fs_swap_inode(fs, &temp_inode, inode, 1);
+ else
+#endif
+ memcpy(&temp_inode, inode, sizeof(struct ext2_inode));
+
+ group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
+ offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+ EXT2_INODE_SIZE(fs->super);
+ block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+ if (!fs->group_desc[(unsigned) group].bg_inode_table)
+ return EXT2_ET_MISSING_INODE_TABLE;
+ block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
+ offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+ ptr = (char *) fs->icache->buffer + (unsigned) offset;
+
+ length = EXT2_INODE_SIZE(fs->super);
+ clen = length;
+ if (length > sizeof(struct ext2_inode))
+ length = sizeof(struct ext2_inode);
+
+ if (fs->icache->buffer_blk != block_nr) {
+ retval = io_channel_read_blk(fs->io, block_nr, 1,
+ fs->icache->buffer);
+ if (retval)
+ return retval;
+ fs->icache->buffer_blk = block_nr;
+ }
+
+ if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
+ clen = (int) (EXT2_BLOCK_SIZE(fs->super) - offset);
+ length -= clen;
+ } else {
+ length = 0;
+ }
+ memcpy(ptr, &temp_inode, clen);
+ retval = io_channel_write_blk(fs->io, block_nr, 1, fs->icache->buffer);
+ if (retval)
+ return retval;
+
+ if (length) {
+ retval = io_channel_read_blk(fs->io, ++block_nr, 1,
+ fs->icache->buffer);
+ if (retval) {
+ fs->icache->buffer_blk = 0;
+ return retval;
+ }
+ fs->icache->buffer_blk = block_nr;
+ memcpy(fs->icache->buffer, ((char *) &temp_inode) + clen,
+ length);
+
+ retval = io_channel_write_blk(fs->io, block_nr, 1,
+ fs->icache->buffer);
+ if (retval)
+ return retval;
+ }
+
+ fs->flags |= EXT2_FLAG_CHANGED;
+ return 0;
+}
+
+errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
+{
+ struct ext2_inode inode;
+ int i;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (ino > fs->super->s_inodes_count)
+ return EXT2_ET_BAD_INODE_NUM;
+
+ if (fs->get_blocks) {
+ if (!(*fs->get_blocks)(fs, ino, blocks))
+ return 0;
+ }
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval)
+ return retval;
+ for (i=0; i < EXT2_N_BLOCKS; i++)
+ blocks[i] = inode.i_block[i];
+ return 0;
+}
+
+errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
+{
+ struct ext2_inode inode;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (ino > fs->super->s_inodes_count)
+ return EXT2_ET_BAD_INODE_NUM;
+
+ if (fs->check_directory) {
+ retval = (fs->check_directory)(fs, ino);
+ if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
+ return retval;
+ }
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval)
+ return retval;
+ if (!LINUX_S_ISDIR(inode.i_mode))
+ return EXT2_ET_NO_DIRECTORY;
+ return 0;
+}
+
diff --git a/e2fslib/inode.o b/e2fslib/inode.o
new file mode 100644
index 0000000..1cd9784
--- /dev/null
+++ b/e2fslib/inode.o
Binary files differ
diff --git a/e2fslib/irel.h b/e2fslib/irel.h
new file mode 100644
index 0000000..9b943ce
--- /dev/null
+++ b/e2fslib/irel.h
@@ -0,0 +1,114 @@
+/*
+ * irel.h
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+struct ext2_inode_reference {
+ blk_t block;
+ __u16 offset;
+};
+
+struct ext2_inode_relocate_entry {
+ ext2_ino_t new;
+ ext2_ino_t orig;
+ __u16 flags;
+ __u16 max_refs;
+};
+
+typedef struct ext2_inode_relocation_table *ext2_irel;
+
+struct ext2_inode_relocation_table {
+ __u32 magic;
+ char *name;
+ ext2_ino_t current;
+ void *priv_data;
+
+ /*
+ * Add an inode relocation entry.
+ */
+ errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+ /*
+ * Get an inode relocation entry.
+ */
+ errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+
+ /*
+ * Get an inode relocation entry by its original inode number
+ */
+ errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+
+ /*
+ * Initialize for iterating over the inode relocation entries.
+ */
+ errcode_t (*start_iter)(ext2_irel irel);
+
+ /*
+ * The iterator function for the inode relocation entries.
+ * Returns an inode number of 0 when out of entries.
+ */
+ errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+
+ /*
+ * Add an inode reference (i.e., note the fact that a
+ * particular block/offset contains a reference to an inode)
+ */
+ errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
+ struct ext2_inode_reference *ref);
+
+ /*
+ * Initialize for iterating over the inode references for a
+ * particular inode.
+ */
+ errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
+
+ /*
+ * The iterator function for the inode references for an
+ * inode. The references for only one inode can be interator
+ * over at a time, as the iterator state is stored in ext2_irel.
+ */
+ errcode_t (*next_ref)(ext2_irel irel,
+ struct ext2_inode_reference *ref);
+
+ /*
+ * Move the inode relocation table from one inode number to
+ * another. Note that the inode references also must move.
+ */
+ errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
+
+ /*
+ * Remove an inode relocation entry, along with all of the
+ * inode references.
+ */
+ errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
+
+ /*
+ * Free the inode relocation table.
+ */
+ errcode_t (*free)(ext2_irel irel);
+};
+
+errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
+ ext2_irel *irel);
+
+#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
+#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
+#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
+ ((irel)->get_by_orig((irel), orig, old, ent))
+#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
+#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
+#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
+#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
+#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
+#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
+#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
+#define ext2fs_irel_free(irel) ((irel)->free((irel)))
diff --git a/e2fslib/irel_ma.c b/e2fslib/irel_ma.c
new file mode 100644
index 0000000..437c06f
--- /dev/null
+++ b/e2fslib/irel_ma.c
@@ -0,0 +1,373 @@
+/*
+ * irel_ma.c
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "irel.h"
+
+static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_start_iter(ext2_irel irel);
+static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
+ struct ext2_inode_reference *ref);
+static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
+static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
+static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
+static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
+static errcode_t ima_free(ext2_irel irel);
+
+/*
+ * This data structure stores the array of inode references; there is
+ * a structure for each inode.
+ */
+struct inode_reference_entry {
+ __u16 num;
+ struct ext2_inode_reference *refs;
+};
+
+struct irel_ma {
+ __u32 magic;
+ ext2_ino_t max_inode;
+ ext2_ino_t ref_current;
+ int ref_iter;
+ ext2_ino_t *orig_map;
+ struct ext2_inode_relocate_entry *entries;
+ struct inode_reference_entry *ref_entries;
+};
+
+errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
+ ext2_irel *new_irel)
+{
+ ext2_irel irel = 0;
+ errcode_t retval;
+ struct irel_ma *ma = 0;
+ size_t size;
+
+ *new_irel = 0;
+
+ /*
+ * Allocate memory structures
+ */
+ retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
+ (void **) &irel);
+ if (retval)
+ goto errout;
+ memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
+
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &irel->name);
+ if (retval)
+ goto errout;
+ strcpy(irel->name, name);
+
+ retval = ext2fs_get_mem(sizeof(struct irel_ma), (void **) &ma);
+ if (retval)
+ goto errout;
+ memset(ma, 0, sizeof(struct irel_ma));
+ irel->priv_data = ma;
+
+ size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
+ retval = ext2fs_get_mem(size, (void **) &ma->orig_map);
+ if (retval)
+ goto errout;
+ memset(ma->orig_map, 0, size);
+
+ size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
+ (max_inode+1));
+ retval = ext2fs_get_mem(size, (void **) &ma->entries);
+ if (retval)
+ goto errout;
+ memset(ma->entries, 0, size);
+
+ size = (size_t) (sizeof(struct inode_reference_entry) *
+ (max_inode+1));
+ retval = ext2fs_get_mem(size, (void **) &ma->ref_entries);
+ if (retval)
+ goto errout;
+ memset(ma->ref_entries, 0, size);
+ ma->max_inode = max_inode;
+
+ /*
+ * Fill in the irel data structure
+ */
+ irel->put = ima_put;
+ irel->get = ima_get;
+ irel->get_by_orig = ima_get_by_orig;
+ irel->start_iter = ima_start_iter;
+ irel->next = ima_next;
+ irel->add_ref = ima_add_ref;
+ irel->start_iter_ref = ima_start_iter_ref;
+ irel->next_ref = ima_next_ref;
+ irel->move = ima_move;
+ irel->delete = ima_delete;
+ irel->free = ima_free;
+
+ *new_irel = irel;
+ return 0;
+
+errout:
+ ima_free(irel);
+ return retval;
+}
+
+static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct inode_reference_entry *ref_ent;
+ struct irel_ma *ma;
+ errcode_t retval;
+ size_t size, old_size;
+
+ ma = irel->priv_data;
+ if (old > ma->max_inode)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ /*
+ * Force the orig field to the correct value; the application
+ * program shouldn't be messing with this field.
+ */
+ if (ma->entries[(unsigned) old].new == 0)
+ ent->orig = old;
+ else
+ ent->orig = ma->entries[(unsigned) old].orig;
+
+ /*
+ * If max_refs has changed, reallocate the refs array
+ */
+ ref_ent = ma->ref_entries + (unsigned) old;
+ if (ref_ent->refs && ent->max_refs !=
+ ma->entries[(unsigned) old].max_refs) {
+ size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
+ old_size = (sizeof(struct ext2_inode_reference) *
+ ma->entries[(unsigned) old].max_refs);
+ retval = ext2fs_resize_mem(old_size, size,
+ (void **) &ref_ent->refs);
+ if (retval)
+ return retval;
+ }
+
+ ma->entries[(unsigned) old] = *ent;
+ ma->orig_map[(unsigned) ent->orig] = old;
+ return 0;
+}
+
+static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+
+ ma = irel->priv_data;
+ if (old > ma->max_inode)
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned) old].new == 0)
+ return ENOENT;
+ *ent = ma->entries[(unsigned) old];
+ return 0;
+}
+
+static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+ ext2_ino_t ino;
+
+ ma = irel->priv_data;
+ if (orig > ma->max_inode)
+ return EXT2_ET_INVALID_ARGUMENT;
+ ino = ma->orig_map[(unsigned) orig];
+ if (ino == 0)
+ return ENOENT;
+ *old = ino;
+ *ent = ma->entries[(unsigned) ino];
+ return 0;
+}
+
+static errcode_t ima_start_iter(ext2_irel irel)
+{
+ irel->current = 0;
+ return 0;
+}
+
+static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+
+ ma = irel->priv_data;
+ while (++irel->current < ma->max_inode) {
+ if (ma->entries[(unsigned) irel->current].new == 0)
+ continue;
+ *old = irel->current;
+ *ent = ma->entries[(unsigned) irel->current];
+ return 0;
+ }
+ *old = 0;
+ return 0;
+}
+
+static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
+ struct ext2_inode_reference *ref)
+{
+ struct irel_ma *ma;
+ size_t size;
+ struct inode_reference_entry *ref_ent;
+ struct ext2_inode_relocate_entry *ent;
+ errcode_t retval;
+
+ ma = irel->priv_data;
+ if (ino > ma->max_inode)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ ref_ent = ma->ref_entries + (unsigned) ino;
+ ent = ma->entries + (unsigned) ino;
+
+ /*
+ * If the inode reference array doesn't exist, create it.
+ */
+ if (ref_ent->refs == 0) {
+ size = (size_t) ((sizeof(struct ext2_inode_reference) *
+ ent->max_refs));
+ retval = ext2fs_get_mem(size, (void **) &ref_ent->refs);
+ if (retval)
+ return retval;
+ memset(ref_ent->refs, 0, size);
+ ref_ent->num = 0;
+ }
+
+ if (ref_ent->num >= ent->max_refs)
+ return EXT2_ET_TOO_MANY_REFS;
+
+ ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
+ return 0;
+}
+
+static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
+{
+ struct irel_ma *ma;
+
+ ma = irel->priv_data;
+ if (ino > ma->max_inode)
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned) ino].new == 0)
+ return ENOENT;
+ ma->ref_current = ino;
+ ma->ref_iter = 0;
+ return 0;
+}
+
+static errcode_t ima_next_ref(ext2_irel irel,
+ struct ext2_inode_reference *ref)
+{
+ struct irel_ma *ma;
+ struct inode_reference_entry *ref_ent;
+
+ ma = irel->priv_data;
+
+ ref_ent = ma->ref_entries + ma->ref_current;
+
+ if ((ref_ent->refs == NULL) ||
+ (ma->ref_iter >= ref_ent->num)) {
+ ref->block = 0;
+ ref->offset = 0;
+ return 0;
+ }
+ *ref = ref_ent->refs[ma->ref_iter++];
+ return 0;
+}
+
+
+static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
+{
+ struct irel_ma *ma;
+
+ ma = irel->priv_data;
+ if ((old > ma->max_inode) || (new > ma->max_inode))
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned) old].new == 0)
+ return ENOENT;
+
+ ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
+ if (ma->ref_entries[(unsigned) new].refs)
+ ext2fs_free_mem((void **) &ma->ref_entries[(unsigned) new].refs);
+ ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
+
+ ma->entries[(unsigned) old].new = 0;
+ ma->ref_entries[(unsigned) old].num = 0;
+ ma->ref_entries[(unsigned) old].refs = 0;
+
+ ma->orig_map[ma->entries[new].orig] = new;
+ return 0;
+}
+
+static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
+{
+ struct irel_ma *ma;
+
+ ma = irel->priv_data;
+ if (old > ma->max_inode)
+ return EXT2_ET_INVALID_ARGUMENT;
+ if (ma->entries[(unsigned) old].new == 0)
+ return ENOENT;
+
+ ma->entries[old].new = 0;
+ if (ma->ref_entries[(unsigned) old].refs)
+ ext2fs_free_mem((void **) &ma->ref_entries[(unsigned) old].refs);
+ ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
+
+ ma->ref_entries[(unsigned) old].num = 0;
+ ma->ref_entries[(unsigned) old].refs = 0;
+ return 0;
+}
+
+static errcode_t ima_free(ext2_irel irel)
+{
+ struct irel_ma *ma;
+ ext2_ino_t ino;
+
+ if (!irel)
+ return 0;
+
+ ma = irel->priv_data;
+
+ if (ma) {
+ if (ma->orig_map)
+ ext2fs_free_mem((void **) &ma->orig_map);
+ if (ma->entries)
+ ext2fs_free_mem((void **) &ma->entries);
+ if (ma->ref_entries) {
+ for (ino = 0; ino <= ma->max_inode; ino++) {
+ if (ma->ref_entries[(unsigned) ino].refs)
+ ext2fs_free_mem((void **) &ma->ref_entries[(unsigned) ino].refs);
+ }
+ ext2fs_free_mem((void **) &ma->ref_entries);
+ }
+ ext2fs_free_mem((void **) &ma);
+ }
+ if (irel->name)
+ ext2fs_free_mem((void **) &irel->name);
+ ext2fs_free_mem((void **) &irel);
+ return 0;
+}
diff --git a/e2fslib/ismounted.c b/e2fslib/ismounted.c
new file mode 100644
index 0000000..1b145c6
--- /dev/null
+++ b/e2fslib/ismounted.c
@@ -0,0 +1,261 @@
+/*
+ * ismounted.c --- Check to see if the filesystem was mounted
+ *
+ * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
+#ifdef HAVE_GETMNTINFO
+#include <paths.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif /* HAVE_GETMNTINFO */
+#include <string.h>
+#include <sys/stat.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifdef HAVE_MNTENT_H
+/*
+ * Helper function which checks a file in /etc/mtab format to see if a
+ * filesystem is mounted. Returns an error if the file doesn't exist
+ * or can't be opened.
+ */
+static errcode_t check_mntent_file(const char *mtab_file, const char *file,
+ int *mount_flags, char *mtpt, int mtlen)
+{
+ struct mntent *mnt;
+ struct stat st_mntpnt, st_file;
+ errcode_t retval = 0;
+ FILE *f;
+ int fd;
+
+ *mount_flags = 0;
+ if ((f = setmntent (mtab_file, "r")) == NULL)
+ return errno;
+ while ((mnt = getmntent (f)) != NULL)
+ if (strcmp(file, mnt->mnt_fsname) == 0)
+ break;
+
+ if (mnt == 0) {
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+ /*
+ * Do an extra check to see if this is the root device. We
+ * can't trust /etc/mtab, and /proc/mounts will only list
+ * /dev/root for the root filesystem. Argh. Instead we
+ * check if the given device has the same major/minor number
+ * as the device that the root directory is on.
+ */
+ if (stat("/", &st_mntpnt) == 0 && stat(file, &st_file) == 0) {
+ if (st_mntpnt.st_dev == st_file.st_rdev) {
+ *mount_flags = EXT2_MF_MOUNTED;
+ if (mtpt)
+ strncpy(mtpt, "/", mtlen);
+ goto is_root;
+ }
+ }
+#endif
+ goto exit;
+ }
+#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
+ /* Validate the entry in case /etc/mtab is out of date */
+ /*
+ * We need to be paranoid, because some broken distributions
+ * (read: Slackware) don't initialize /etc/mtab before checking
+ * all of the non-root filesystems on the disk.
+ */
+ if (stat(mnt->mnt_dir, &st_mntpnt) < 0) {
+ retval = errno;
+ if (retval == ENOENT) {
+#ifdef DEBUG
+ printf("Bogus entry in %s! (%s does not exist)\n",
+ mtab_file, mnt->mnt_dir);
+#endif
+ retval = 0;
+ }
+ goto exit;
+ }
+ if (stat(file, &st_file) == 0) {
+ if (st_mntpnt.st_dev != st_file.st_rdev) {
+#ifdef DEBUG
+ printf("Bogus entry in %s! (%s not mounted on %s)\n",
+ mtab_file, file, mnt->mnt_dir);
+#endif
+ goto exit;
+ }
+ }
+#endif
+ *mount_flags = EXT2_MF_MOUNTED;
+
+ /* Check to see if the ro option is set */
+ if (hasmntopt(mnt, MNTOPT_RO))
+ *mount_flags |= EXT2_MF_READONLY;
+
+ if (mtpt)
+ strncpy(mtpt, mnt->mnt_dir, mtlen);
+ /*
+ * Check to see if we're referring to the root filesystem.
+ * If so, do a manual check to see if we can open /etc/mtab
+ * read/write, since if the root is mounted read/only, the
+ * contents of /etc/mtab may not be accurate.
+ */
+ if (!strcmp(mnt->mnt_dir, "/")) {
+is_root:
+#define TEST_FILE "/.ismount-test-file"
+ *mount_flags |= EXT2_MF_ISROOT;
+ fd = open(TEST_FILE, O_RDWR|O_CREAT);
+ if (fd < 0) {
+ if (errno == EROFS)
+ *mount_flags |= EXT2_MF_READONLY;
+ } else
+ close(fd);
+ (void) unlink(TEST_FILE);
+ }
+ retval = 0;
+exit:
+ endmntent (f);
+ return retval;
+}
+
+static errcode_t check_mntent(const char *file, int *mount_flags,
+ char *mtpt, int mtlen)
+{
+ errcode_t retval;
+
+#ifdef DEBUG
+ retval = check_mntent_file("/tmp/mtab", file, mount_flags,
+ mtpt, mtlen);
+ if (retval == 0)
+ return 0;
+#endif
+#ifdef __linux__
+ retval = check_mntent_file("/proc/mounts", file, mount_flags,
+ mtpt, mtlen);
+ if (retval == 0)
+ return 0;
+#endif
+ retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
+ return retval;
+}
+
+#elif defined(HAVE_GETMNTINFO)
+
+static errcode_t check_getmntinfo(const char *file, int *mount_flags,
+ char *mtpt, int mtlen)
+{
+ struct statfs *mp;
+ int len, n;
+ const char *s1;
+ char *s2;
+
+ n = getmntinfo(&mp, MNT_NOWAIT);
+ if (n == 0)
+ return errno;
+
+ len = sizeof(_PATH_DEV) - 1;
+ s1 = file;
+ if (strncmp(_PATH_DEV, s1, len) == 0)
+ s1 += len;
+
+ *mount_flags = 0;
+ while (--n >= 0) {
+ s2 = mp->f_mntfromname;
+ if (strncmp(_PATH_DEV, s2, len) == 0) {
+ s2 += len - 1;
+ *s2 = 'r';
+ }
+ if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
+ *mount_flags = EXT2_MF_MOUNTED;
+ break;
+ }
+ ++mp;
+ }
+ if (mtpt)
+ strncpy(mtpt, mp->f_mntonname, mtlen);
+ return 0;
+}
+#endif /* HAVE_GETMNTINFO */
+
+/*
+ * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
+ * otherwise. If mtpt is non-NULL, the directory where the device is
+ * mounted is copied to where mtpt is pointing, up to mtlen
+ * characters.
+ */
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
+ char *mtpt, int mtlen)
+{
+#ifdef HAVE_MNTENT_H
+ return check_mntent(device, mount_flags, mtpt, mtlen);
+#else
+#ifdef HAVE_GETMNTINFO
+ return check_getmntinfo(device, mount_flags, mtpt, mtlen);
+#else
+#warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
+ *mount_flags = 0;
+ return 0;
+#endif /* HAVE_GETMNTINFO */
+#endif /* HAVE_MNTENT_H */
+}
+
+/*
+ * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
+ * EXT2_MF_READONLY, and EXT2_MF_ROOT
+ *
+ */
+errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
+{
+ return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
+}
+
+#ifdef DEBUG
+int main(int argc, char **argv)
+{
+ int retval, mount_flags;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s device\n", argv[0]);
+ exit(1);
+ }
+
+ retval = ext2fs_check_if_mounted(argv[1], &mount_flags);
+ if (retval) {
+ com_err(argv[0], retval,
+ "while calling ext2fs_check_if_mounted");
+ exit(1);
+ }
+ printf("Device %s reports flags %02x\n", argv[1], mount_flags);
+ if (mount_flags & EXT2_MF_MOUNTED)
+ printf("\t%s is mounted.\n", argv[1]);
+
+ if (mount_flags & EXT2_MF_READONLY)
+ printf("\t%s is read-only.\n", argv[1]);
+
+ if (mount_flags & EXT2_MF_ISROOT)
+ printf("\t%s is the root filesystem.\n", argv[1]);
+
+ exit(0);
+}
+#endif
diff --git a/e2fslib/ismounted.o b/e2fslib/ismounted.o
new file mode 100644
index 0000000..7e06115
--- /dev/null
+++ b/e2fslib/ismounted.o
Binary files differ
diff --git a/e2fslib/jfs_dat.h b/e2fslib/jfs_dat.h
new file mode 100644
index 0000000..d6ad9c4
--- /dev/null
+++ b/e2fslib/jfs_dat.h
@@ -0,0 +1,64 @@
+/*
+ * jfs_dat.h --- stripped down header file which only contains the JFS
+ * on-disk data structures
+ */
+
+#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
+
+/*
+ * On-disk structures
+ */
+
+/*
+ * Descriptor block types:
+ */
+
+#define JFS_DESCRIPTOR_BLOCK 1
+#define JFS_COMMIT_BLOCK 2
+#define JFS_SUPERBLOCK 3
+
+/*
+ * Standard header for all descriptor blocks:
+ */
+typedef struct journal_header_s
+{
+ __u32 h_magic;
+ __u32 h_blocktype;
+ __u32 h_sequence;
+} journal_header_t;
+
+
+/*
+ * The block tag: used to describe a single buffer in the journal
+ */
+typedef struct journal_block_tag_s
+{
+ __u32 t_blocknr; /* The on-disk block number */
+ __u32 t_flags; /* See below */
+} journal_block_tag_t;
+
+/* Definitions for the journal tag flags word: */
+#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
+#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
+#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
+#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
+
+
+/*
+ * The journal superblock
+ */
+typedef struct journal_superblock_s
+{
+ journal_header_t s_header;
+
+ /* Static information describing the journal */
+ __u32 s_blocksize; /* journal device blocksize */
+ __u32 s_maxlen; /* total blocks in journal file */
+ __u32 s_first; /* first block of log information */
+
+ /* Dynamic information describing the current state of the log */
+ __u32 s_sequence; /* first commit ID expected in log */
+ __u32 s_start; /* blocknr of start of log */
+
+} journal_superblock_t;
+
diff --git a/e2fslib/jfs_user.h b/e2fslib/jfs_user.h
new file mode 100644
index 0000000..17a82c7
--- /dev/null
+++ b/e2fslib/jfs_user.h
@@ -0,0 +1,9 @@
+#ifndef _JFS_USER_H
+#define _JFS_USER_H
+
+typedef unsigned short kdev_t;
+
+#include <linux/jfs.h>
+
+
+#endif /* _JFS_USER_H */
diff --git a/e2fslib/libcom_err.a b/e2fslib/libcom_err.a
new file mode 100644
index 0000000..4c848dc
--- /dev/null
+++ b/e2fslib/libcom_err.a
Binary files differ
diff --git a/e2fslib/libext2fs.a b/e2fslib/libext2fs.a
new file mode 100644
index 0000000..2c8887b
--- /dev/null
+++ b/e2fslib/libext2fs.a
Binary files differ
diff --git a/e2fslib/link.c b/e2fslib/link.c
new file mode 100644
index 0000000..04ac00c
--- /dev/null
+++ b/e2fslib/link.c
@@ -0,0 +1,121 @@
+/*
+ * link.c --- create links in a ext2fs directory
+ *
+ * Copyright (C) 1993, 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct link_struct {
+ const char *name;
+ int namelen;
+ ext2_ino_t inode;
+ int flags;
+ int done;
+ struct ext2_super_block *sb;
+};
+
+static int link_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data)
+{
+ struct link_struct *ls = (struct link_struct *) priv_data;
+ struct ext2_dir_entry *next;
+ int rec_len, min_rec_len;
+ int ret = 0;
+
+ rec_len = EXT2_DIR_REC_LEN(ls->namelen);
+
+ /*
+ * See if the following directory entry (if any) is unused;
+ * if so, absorb it into this one.
+ */
+ next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
+ if ((offset + dirent->rec_len < blocksize - 8) &&
+ (next->inode == 0) &&
+ (offset + dirent->rec_len + next->rec_len <= blocksize)) {
+ dirent->rec_len += next->rec_len;
+ ret = DIRENT_CHANGED;
+ }
+
+ /*
+ * If the directory entry is used, see if we can split the
+ * directory entry to make room for the new name. If so,
+ * truncate it and return.
+ */
+ if (dirent->inode) {
+ min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
+ if (dirent->rec_len < (min_rec_len + rec_len))
+ return ret;
+ rec_len = dirent->rec_len - min_rec_len;
+ dirent->rec_len = min_rec_len;
+ next = (struct ext2_dir_entry *) (buf + offset +
+ dirent->rec_len);
+ next->inode = 0;
+ next->name_len = 0;
+ next->rec_len = rec_len;
+ return DIRENT_CHANGED;
+ }
+
+ /*
+ * If we get this far, then the directory entry is not used.
+ * See if we can fit the request entry in. If so, do it.
+ */
+ if (dirent->rec_len < rec_len)
+ return ret;
+ dirent->inode = ls->inode;
+ dirent->name_len = ls->namelen;
+ strncpy(dirent->name, ls->name, ls->namelen);
+ if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
+ dirent->name_len |= (ls->flags & 0x7) << 8;
+
+ ls->done++;
+ return DIRENT_ABORT|DIRENT_CHANGED;
+}
+
+/*
+ * Note: the low 3 bits of the flags field are used as the directory
+ * entry filetype.
+ */
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
+ ext2_ino_t ino, int flags)
+{
+ errcode_t retval;
+ struct link_struct ls;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ ls.name = name;
+ ls.namelen = name ? strlen(name) : 0;
+ ls.inode = ino;
+ ls.flags = flags;
+ ls.done = 0;
+ ls.sb = fs->super;
+
+ retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
+ 0, link_proc, &ls);
+ if (retval)
+ return retval;
+
+ return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
+}
diff --git a/e2fslib/link.o b/e2fslib/link.o
new file mode 100644
index 0000000..42913fc
--- /dev/null
+++ b/e2fslib/link.o
Binary files differ
diff --git a/e2fslib/linux/jfs.h b/e2fslib/linux/jfs.h
new file mode 100644
index 0000000..c00f4ed
--- /dev/null
+++ b/e2fslib/linux/jfs.h
@@ -0,0 +1,682 @@
+/*
+ * linux/include/linux/jfs.h
+ *
+ * Written by Stephen C. Tweedie <sct@redhat.com>
+ *
+ * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Definitions for transaction data structures for the buffer cache
+ * filesystem journaling support.
+ */
+
+#ifndef _LINUX_JFS_H
+#define _LINUX_JFS_H
+
+/* Allow this file to be included directly into e2fsprogs */
+#ifndef __KERNEL__
+#include "jfs_compat.h"
+#endif
+
+/*
+ * Debug code enabled by default for kernel builds
+ */
+#ifdef __KERNEL__
+#define JFS_DEBUG
+#endif
+
+extern int journal_enable_debug;
+
+#ifdef JFS_DEBUG
+#define jfs_debug(n, f, a...) \
+ do { \
+ if ((n) <= journal_enable_debug) { \
+ printk (KERN_DEBUG "JFS DEBUG: (%s, %d): %s: ", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ printk (f, ## a); \
+ } \
+ } while (0)
+#else
+#define jfs_debug(f, a...) /**/
+#endif
+
+#define JFS_MIN_JOURNAL_BLOCKS 1024
+
+/*
+ * Internal structures used by the logging mechanism:
+ */
+
+#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
+
+
+/*
+ * On-disk structures
+ */
+
+/*
+ * Descriptor block types:
+ */
+
+#define JFS_DESCRIPTOR_BLOCK 1
+#define JFS_COMMIT_BLOCK 2
+#define JFS_SUPERBLOCK_V1 3
+#define JFS_SUPERBLOCK_V2 4
+#define JFS_REVOKE_BLOCK 5
+
+/*
+ * Standard header for all descriptor blocks:
+ */
+typedef struct journal_header_s
+{
+ __u32 h_magic;
+ __u32 h_blocktype;
+ __u32 h_sequence;
+} journal_header_t;
+
+
+/*
+ * The block tag: used to describe a single buffer in the journal
+ */
+typedef struct journal_block_tag_s
+{
+ __u32 t_blocknr; /* The on-disk block number */
+ __u32 t_flags; /* See below */
+} journal_block_tag_t;
+
+/*
+ * The revoke descriptor: used on disk to describe a series of blocks to
+ * be revoked from the log
+ */
+typedef struct journal_revoke_header_s
+{
+ journal_header_t r_header;
+ int r_count; /* Count of bytes used in the block */
+} journal_revoke_header_t;
+
+
+/* Definitions for the journal tag flags word: */
+#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */
+#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */
+#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */
+#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
+
+
+/*
+ * The journal superblock. All fields are in big-endian byte order.
+ */
+typedef struct journal_superblock_s
+{
+/* 0x0000 */
+ journal_header_t s_header;
+
+/* 0x000C */
+ /* Static information describing the journal */
+ __u32 s_blocksize; /* journal device blocksize */
+ __u32 s_maxlen; /* total blocks in journal file */
+ __u32 s_first; /* first block of log information */
+
+/* 0x0018 */
+ /* Dynamic information describing the current state of the log */
+ __u32 s_sequence; /* first commit ID expected in log */
+ __u32 s_start; /* blocknr of start of log */
+
+/* 0x0020 */
+ /* Error value, as set by journal_abort(). */
+ __s32 s_errno;
+
+/* 0x0024 */
+ /* Remaining fields are only valid in a version-2 superblock */
+ __u32 s_feature_compat; /* compatible feature set */
+ __u32 s_feature_incompat; /* incompatible feature set */
+ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
+/* 0x0030 */
+ __u8 s_uuid[16]; /* 128-bit uuid for journal */
+
+/* 0x0040 */
+ __u32 s_nr_users; /* Nr of filesystems sharing log */
+
+ __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
+
+/* 0x0048 */
+ __u32 s_max_transaction; /* Limit of journal blocks per trans.*/
+ __u32 s_max_trans_data; /* Limit of data blocks per trans. */
+
+/* 0x0050 */
+ __u32 s_padding[44];
+
+/* 0x0100 */
+ __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
+/* 0x0400 */
+} journal_superblock_t;
+
+#define JFS_HAS_COMPAT_FEATURE(j,mask) \
+ ((j)->j_format_version >= 2 && \
+ ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask))))
+#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \
+ ((j)->j_format_version >= 2 && \
+ ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask))))
+#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \
+ ((j)->j_format_version >= 2 && \
+ ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
+
+#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001
+
+/* Features known to this kernel version: */
+#define JFS_KNOWN_COMPAT_FEATURES 0
+#define JFS_KNOWN_ROCOMPAT_FEATURES 0
+#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+
+
+#define J_ASSERT(assert) \
+ do { if (!(assert)) { \
+ printk (KERN_EMERG \
+ "Assertion failure in %s() at %s line %d: " \
+ "\"%s\"\n", \
+ __FUNCTION__, __FILE__, __LINE__, # assert); \
+ * ((char *) 0) = 0; \
+ } } while (0)
+
+
+struct jfs_revoke_table_s;
+
+/* The handle_t type represents a single atomic update being performed
+ * by some process. All filesystem modifications made by the process go
+ * through this handle. Recursive operations (such as quota operations)
+ * are gathered into a single update.
+ *
+ * The buffer credits field is used to account for journaled buffers
+ * being modified by the running process. To ensure that there is
+ * enough log space for all outstanding operations, we need to limit the
+ * number of outstanding buffers possible at any time. When the
+ * operation completes, any buffer credits not used are credited back to
+ * the transaction, so that at all times we know how many buffers the
+ * outstanding updates on a transaction might possibly touch. */
+
+struct handle_s
+{
+ /* Which compound transaction is this update a part of? */
+ transaction_t * h_transaction;
+
+ /* Number of remaining buffers we are allowed to dirty: */
+ int h_buffer_credits;
+
+ /* Reference count on this handle */
+ int h_ref;
+
+ /* Flags */
+ unsigned int h_sync : 1; /* sync-on-close */
+ unsigned int h_jdata : 1; /* force data journaling */
+};
+
+
+/* The transaction_t type is the guts of the journaling mechanism. It
+ * tracks a compound transaction through its various states:
+ *
+ * RUNNING: accepting new updates
+ * LOCKED: Updates still running but we don't accept new ones
+ * RUNDOWN: Updates are tidying up but have finished requesting
+ * new buffers to modify (state not used for now)
+ * FLUSH: All updates complete, but we are still writing to disk
+ * COMMIT: All data on disk, writing commit record
+ * FINISHED: We still have to keep the transaction for checkpointing.
+ *
+ * The transaction keeps track of all of the buffers modified by a
+ * running transaction, and all of the buffers committed but not yet
+ * flushed to home for finished transactions.
+ */
+
+struct transaction_s
+{
+ /* Pointer to the journal for this transaction. */
+ journal_t * t_journal;
+
+ /* Sequence number for this transaction */
+ tid_t t_tid;
+
+ /* Transaction's current state */
+ enum {
+ T_RUNNING,
+ T_LOCKED,
+ T_RUNDOWN,
+ T_FLUSH,
+ T_COMMIT,
+ T_FINISHED
+ } t_state;
+
+ /* Where in the log does this transaction's commit start? */
+ unsigned long t_log_start;
+
+ /* Doubly-linked circular list of all inodes owned by this
+ transaction */
+ struct inode * t_ilist;
+
+ /* Number of buffers on the t_buffers list */
+ int t_nr_buffers;
+
+ /* Doubly-linked circular list of all buffers reserved but not
+ yet modified by this transaction */
+ struct buffer_head * t_reserved_list;
+
+ /* Doubly-linked circular list of all metadata buffers owned by this
+ transaction */
+ struct buffer_head * t_buffers;
+
+ /* Doubly-linked circular list of all data buffers still to be
+ flushed before this transaction can be committed */
+ struct buffer_head * t_datalist;
+
+ /* Doubly-linked circular list of all forget buffers (superceded
+ buffers which we can un-checkpoint once this transaction
+ commits) */
+ struct buffer_head * t_forget;
+
+ /* Doubly-linked circular list of all buffers still to be
+ flushed before this transaction can be checkpointed */
+ struct buffer_head * t_checkpoint_list;
+
+ /* Doubly-linked circular list of temporary buffers currently
+ undergoing IO in the log */
+ struct buffer_head * t_iobuf_list;
+
+ /* Doubly-linked circular list of metadata buffers being
+ shadowed by log IO. The IO buffers on the iobuf list and the
+ shadow buffers on this list match each other one for one at
+ all times. */
+ struct buffer_head * t_shadow_list;
+
+ /* Doubly-linked circular list of control buffers being written
+ to the log. */
+ struct buffer_head * t_log_list;
+
+ /* Number of outstanding updates running on this transaction */
+ int t_updates;
+
+ /* Number of buffers reserved for use by all handles in this
+ * transaction handle but not yet modified. */
+ int t_outstanding_credits;
+
+ /* Forward and backward links for the circular list of all
+ * transactions awaiting checkpoint */
+ transaction_t *t_cpnext, *t_cpprev;
+
+ /* When will the transaction expire (become due for commit), in
+ * jiffies ? */
+ unsigned long t_expires;
+};
+
+
+/* The journal_t maintains all of the journaling state information for a
+ * single filesystem. It is linked to from the fs superblock structure.
+ *
+ * We use the journal_t to keep track of all outstanding transaction
+ * activity on the filesystem, and to manage the state of the log
+ * writing process. */
+
+struct journal_s
+{
+ /* General journaling state flags */
+ unsigned long j_flags;
+
+ /* Is there an outstanding uncleared error on the journal (from
+ * a prior abort)? */
+ int j_errno;
+
+ /* The superblock buffer */
+ struct buffer_head * j_sb_buffer;
+ journal_superblock_t * j_superblock;
+
+ /* Version of the superblock format */
+ int j_format_version;
+
+ /* Number of processes waiting to create a barrier lock */
+ int j_barrier_count;
+
+ /* The barrier lock itself */
+ struct semaphore j_barrier;
+
+ /* Transactions: The current running transaction... */
+ transaction_t * j_running_transaction;
+
+ /* ... the transaction we are pushing to disk ... */
+ transaction_t * j_committing_transaction;
+
+ /* ... and a linked circular list of all transactions waiting
+ * for checkpointing. */
+ transaction_t * j_checkpoint_transactions;
+
+ /* Wait queue for locking of the journal structure. */
+ struct wait_queue * j_wait_lock;
+
+ /* Wait queue for waiting for a locked transaction to start
+ committing, or for a barrier lock to be released */
+ struct wait_queue * j_wait_transaction_locked;
+
+ /* Wait queue for waiting for checkpointing to complete */
+ struct wait_queue * j_wait_logspace;
+
+ /* Wait queue for waiting for commit to complete */
+ struct wait_queue * j_wait_done_commit;
+
+ /* Wait queue to trigger checkpointing */
+ struct wait_queue * j_wait_checkpoint;
+
+ /* Wait queue to trigger commit */
+ struct wait_queue * j_wait_commit;
+
+ /* Wait queue to wait for updates to complete */
+ struct wait_queue * j_wait_updates;
+
+ /* Semaphore for locking against concurrent checkpoints */
+ struct semaphore j_checkpoint_sem;
+
+ /* Journal running state: */
+ /* The lock flag is *NEVER* touched from interrupts. */
+ unsigned int j_locked : 1;
+
+ /* Journal head: identifies the first unused block in the journal. */
+ unsigned long j_head;
+
+ /* Journal tail: identifies the oldest still-used block in the
+ * journal. */
+ unsigned long j_tail;
+
+ /* Journal free: how many free blocks are there in the journal? */
+ unsigned long j_free;
+
+ /* Journal start and end: the block numbers of the first usable
+ * block and one beyond the last usable block in the journal. */
+ unsigned long j_first, j_last;
+
+ /* Device, blocksize and starting block offset for the location
+ * where we store the journal. */
+ kdev_t j_dev;
+ int j_blocksize;
+ unsigned int j_blk_offset;
+
+ /* Total maximum capacity of the journal region on disk. */
+ unsigned int j_maxlen;
+
+ /* Optional inode where we store the journal. If present, all
+ * journal block numbers are mapped into this inode via
+ * bmap(). */
+ struct inode * j_inode;
+
+ /* Sequence number of the oldest transaction in the log */
+ tid_t j_tail_sequence;
+ /* Sequence number of the next transaction to grant */
+ tid_t j_transaction_sequence;
+ /* Sequence number of the most recently committed transaction */
+ tid_t j_commit_sequence;
+ /* Sequence number of the most recent transaction wanting commit */
+ tid_t j_commit_request;
+
+ /* Journal uuid: identifies the object (filesystem, LVM volume
+ * etc) backed by this journal. This will eventually be
+ * replaced by an array of uuids, allowing us to index multiple
+ * devices within a single journal and to perform atomic updates
+ * across them. */
+
+ __u8 j_uuid[16];
+
+ /* Pointer to the current commit thread for this journal */
+ struct task_struct * j_task;
+
+ /* Maximum number of metadata buffers to allow in a single
+ * compound commit transaction */
+ int j_max_transaction_buffers;
+
+ /* What is the maximum transaction lifetime before we begin a
+ * commit? */
+ unsigned long j_commit_interval;
+
+ /* The timer used to wakeup the commit thread: */
+ struct timer_list * j_commit_timer;
+ int j_commit_timer_active;
+
+ /* The revoke table: maintains the list of revoked blocks in the
+ current transaction. */
+ struct jfs_revoke_table_s *j_revoke;
+};
+
+/*
+ * Journal flag definitions
+ */
+#define JFS_UNMOUNT 0x001 /* Journal thread is being destroyed */
+#define JFS_SYNC 0x002 /* Perform synchronous transaction commits */
+#define JFS_ABORT 0x004 /* Journaling has been aborted for errors. */
+#define JFS_ACK_ERR 0x008 /* The errno in the sb has been acked */
+#define JFS_FLUSHED 0x010 /* The journal superblock has been flushed */
+#define JFS_LOADED 0x020 /* The journal superblock has been loaded */
+
+/*
+ * Journaling internal variables/parameters
+ */
+
+extern int journal_flush_nr_buffers;
+
+
+/*
+ * Function declarations for the journaling transaction and buffer
+ * management
+ */
+
+/* Filing buffers */
+extern void journal_unfile_buffer(struct buffer_head *);
+extern void journal_refile_buffer(struct buffer_head *);
+extern void journal_file_buffer(struct buffer_head *, transaction_t *, int);
+extern void journal_clean_data_list(transaction_t *transaction);
+
+/* Log buffer allocation */
+extern struct buffer_head * journal_get_descriptor_buffer(journal_t *);
+extern unsigned long journal_next_log_block(journal_t *);
+
+/* Commit management */
+extern void journal_commit_transaction(journal_t *);
+
+/* Checkpoint list management */
+extern void journal_remove_checkpoint(struct buffer_head *);
+extern void journal_insert_checkpoint(struct buffer_head *, transaction_t *);
+
+/* Buffer IO */
+extern int
+journal_write_metadata_buffer(transaction_t *transaction,
+ struct buffer_head *bh_in,
+ struct buffer_head **bh_out,
+ int blocknr);
+
+/* Create and destroy transactions */
+extern transaction_t * get_transaction (journal_t *);
+extern void put_transaction (transaction_t *);
+
+/* Notify state transitions (called by the log writer thread): */
+extern int set_transaction_state (transaction_t *, int);
+
+
+/* Transaction locking */
+extern void __wait_on_journal (journal_t *);
+
+/* Journal locking. In 2.2, we assume that the kernel lock is already
+ * held. */
+static inline void lock_journal (journal_t * journal)
+{
+#ifdef __SMP__
+ J_ASSERT(current->lock_depth >= 0);
+#endif
+ if (journal->j_locked)
+ __wait_on_journal(journal);
+ journal->j_locked = 1;
+}
+
+static inline int try_lock_journal (journal_t * journal)
+{
+ if (journal->j_locked)
+ return 1;
+ journal->j_locked = 1;
+ return 0;
+}
+
+static inline void unlock_journal (journal_t * journal)
+{
+ J_ASSERT (journal->j_locked);
+ journal->j_locked = 0;
+ wake_up(&journal->j_wait_lock);
+}
+
+/* This function is gross, but unfortunately we need it as long as
+ * existing filesystems want to guard against races by testing
+ * bh->b_count. @@@ Remove this? We no longer abuse b_count so badly!
+ */
+
+static inline int journal_is_buffer_shared(struct buffer_head *bh)
+{
+ int count = bh->b_count;
+ J_ASSERT (count >= 1);
+ return (count > 1);
+}
+
+/* The journaling code user interface:
+ *
+ * Create and destroy handles
+ * Register buffer modifications against the current transaction.
+ */
+
+extern handle_t *journal_start (journal_t *, int nblocks);
+extern int journal_restart (handle_t *, int nblocks);
+extern int journal_extend (handle_t *, int nblocks);
+extern int journal_get_write_access (handle_t *, struct buffer_head *);
+extern int journal_get_create_access (handle_t *, struct buffer_head *);
+extern int journal_get_undo_access (handle_t *, struct buffer_head *);
+extern int journal_dirty_data (handle_t *, struct buffer_head *);
+extern int journal_dirty_metadata (handle_t *, struct buffer_head *);
+extern void journal_release_buffer (handle_t *, struct buffer_head *);
+extern void journal_forget (handle_t *, struct buffer_head *);
+extern void journal_sync_buffer (struct buffer_head *);
+extern int journal_stop (handle_t *);
+extern int journal_flush (journal_t *);
+
+extern void journal_lock_updates (journal_t *);
+extern void journal_unlock_updates (journal_t *);
+
+extern journal_t * journal_init_dev (kdev_t, int start, int len, int bsize);
+extern journal_t * journal_init_inode (struct inode *);
+extern int journal_update_format (journal_t *);
+extern int journal_check_used_features
+ (journal_t *, unsigned long, unsigned long, unsigned long);
+extern int journal_check_available_features
+ (journal_t *, unsigned long, unsigned long, unsigned long);
+extern int journal_set_features
+ (journal_t *, unsigned long, unsigned long, unsigned long);
+extern int journal_create (journal_t *);
+extern int journal_load (journal_t *);
+extern void journal_release (journal_t *);
+extern int journal_wipe (journal_t *, int);
+extern int journal_skip_recovery (journal_t *);
+extern void journal_update_superblock (journal_t *, int);
+extern void __journal_abort (journal_t *);
+extern void journal_abort (journal_t *, int);
+extern int journal_errno (journal_t *);
+extern void journal_ack_err (journal_t *);
+extern int journal_clear_err (journal_t *);
+
+/* Primary revoke support */
+#define JOURNAL_REVOKE_DEFAULT_HASH 256
+extern int journal_revoke (handle_t *, unsigned long, struct buffer_head *);
+extern void journal_cancel_revoke(handle_t *, struct buffer_head *);
+extern void journal_write_revoke_records(journal_t *, transaction_t *);
+
+/* The log thread user interface:
+ *
+ * Request space in the current transaction, and force transaction commit
+ * transitions on demand.
+ */
+
+extern int log_space_left (journal_t *); /* Called with journal locked */
+extern void log_start_commit (journal_t *, transaction_t *);
+extern void log_wait_commit (journal_t *, tid_t);
+extern int log_do_checkpoint (journal_t *, int);
+
+extern void log_wait_for_space(journal_t *, int nblocks);
+extern void journal_drop_transaction(journal_t *, transaction_t *);
+extern int cleanup_journal_tail(journal_t *);
+
+
+/* Debugging code only: */
+
+#define jfs_ENOSYS() \
+do { \
+ printk (KERN_ERR "JFS unimplemented function " __FUNCTION__); \
+ current->state = TASK_UNINTERRUPTIBLE; \
+ schedule(); \
+} while (1)
+
+/*
+ * is_journal_abort
+ *
+ * Simple test wrapper function to test the JFS_ABORT state flag. This
+ * bit, when set, indicates that we have had a fatal error somewhere,
+ * either inside the journaling layer or indicated to us by the client
+ * (eg. ext3), and that we and should not commit any further
+ * transactions.
+ */
+
+static inline int is_journal_abort(journal_t *journal)
+{
+ return journal->j_flags & JFS_ABORT;
+}
+
+
+extern inline void mark_buffer_jdirty(struct buffer_head * bh)
+{
+ if (!test_and_set_bit(BH_JDirty, &bh->b_state))
+ set_writetime(bh, 0);
+}
+
+/* Not all architectures define BUG() */
+#ifndef BUG
+ #define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+ * ((char *) 0) = 0; \
+ } while (0)
+#endif /* BUG */
+
+#endif /* __KERNEL__ */
+
+/* Function prototypes, used by both user- and kernel- space */
+
+/* recovery.c */
+extern int journal_recover (journal_t *);
+
+/* revoke.c */
+ /* Primary recovery support */
+extern int journal_init_revoke(journal_t *, int);
+extern void journal_destroy_revoke(journal_t *);
+
+ /* Recovery revoke support */
+extern int journal_set_revoke(journal_t *, unsigned long, tid_t);
+extern int journal_test_revoke(journal_t *, unsigned long, tid_t);
+extern void journal_clear_revoke(journal_t *);
+
+
+/* Comparison functions for transaction IDs: perform comparisons using
+ * modulo arithmetic so that they work over sequence number wraps. */
+
+static inline int tid_gt(tid_t x, tid_t y)
+{
+ int difference = (x - y);
+ return (difference > 0);
+}
+
+static inline int tid_geq(tid_t x, tid_t y)
+{
+ int difference = (x - y);
+ return (difference >= 0);
+}
+
+#endif /* _LINUX_JFS_H */
diff --git a/e2fslib/linux/jfs_compat.h b/e2fslib/linux/jfs_compat.h
new file mode 100644
index 0000000..1318198
--- /dev/null
+++ b/e2fslib/linux/jfs_compat.h
@@ -0,0 +1,64 @@
+
+#ifndef _JFS_COMPAT_H
+#define _JFS_COMPAT_H
+
+#include <linux/list.h>
+#include <errno.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#define printk printf
+#define KERN_ERR ""
+#define KERN_DEBUG ""
+
+#define READ 0
+#define WRITE 1
+
+#define cpu_to_be32(n) htonl(n)
+#define be32_to_cpu(n) ntohl(n)
+
+typedef int tid_t;
+typedef struct journal_s journal_t;
+
+struct buffer_head;
+struct inode;
+
+struct journal_s
+{
+ unsigned long j_flags;
+ int j_errno;
+ struct buffer_head * j_sb_buffer;
+ struct journal_superblock_s *j_superblock;
+ int j_format_version;
+ unsigned long j_head;
+ unsigned long j_tail;
+ unsigned long j_free;
+ unsigned long j_first, j_last;
+ kdev_t j_dev;
+ int j_blocksize;
+ unsigned int j_blk_offset;
+ unsigned int j_maxlen;
+ struct inode * j_inode;
+ tid_t j_tail_sequence;
+ tid_t j_transaction_sequence;
+ __u8 j_uuid[16];
+ struct jfs_revoke_table_s *j_revoke;
+};
+
+#define J_ASSERT(assert) \
+ do { if (!(assert)) { \
+ printf ("Assertion failure in %s() at %s line %d: " \
+ "\"%s\"\n", \
+ __FUNCTION__, __FILE__, __LINE__, # assert); \
+ fatal_error(e2fsck_global_ctx, 0); \
+ } } while (0)
+
+#define is_journal_abort(x) 0
+
+/* Need this so we can compile with configure --enable-gcc-wall */
+#ifdef NO_INLINE_FUNCS
+#define inline
+#endif
+
+#endif /* _JFS_COMPAT_H */
diff --git a/e2fslib/linux/list.h b/e2fslib/linux/list.h
new file mode 100644
index 0000000..0e26f1f
--- /dev/null
+++ b/e2fslib/linux/list.h
@@ -0,0 +1,108 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = { &name, &name }
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/*
+ * Insert a new entry after the specified head..
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/*
+ * Insert a new entry at the tail
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Splice in "list" into "head"
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#endif
diff --git a/e2fslib/llseek.c b/e2fslib/llseek.c
new file mode 100644
index 0000000..e8be331
--- /dev/null
+++ b/e2fslib/llseek.c
@@ -0,0 +1,132 @@
+/*
+ * llseek.c -- stub calling the llseek system call
+ *
+ * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef __MSDOS__
+#include <io.h>
+#endif
+#include "et/com_err.h"
+#include "ext2_io.h"
+
+#ifdef __linux__
+
+#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
+
+#define my_llseek lseek64
+
+#elif defined(HAVE_LLSEEK)
+#include <syscall.h>
+
+#ifndef HAVE_LLSEEK_PROTOTYPE
+extern long long llseek (int fd, long long offset, int origin);
+#endif
+
+#define my_llseek llseek
+
+#else /* ! HAVE_LLSEEK */
+
+#if defined(__alpha__) || defined (__ia64__)
+
+#define llseek lseek
+
+#else /* !__alpha__ && !__ia64__*/
+
+#include <linux/unistd.h>
+
+#ifndef __NR__llseek
+#define __NR__llseek 140
+#endif
+
+#ifndef __i386__
+static int _llseek (unsigned int, unsigned long,
+ unsigned long, ext2_loff_t *, unsigned int);
+
+static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
+ unsigned long, offset_low,ext2_loff_t *,result,
+ unsigned int, origin)
+#endif
+
+static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
+{
+ ext2_loff_t result;
+ int retval;
+
+#ifndef __i386__
+ retval = _llseek(fd, ((unsigned long long) offset) >> 32,
+#else
+ retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
+#endif
+ ((unsigned long long) offset) & 0xffffffff,
+ &result, origin);
+ return (retval == -1 ? (ext2_loff_t) retval : result);
+}
+
+#endif /* __alpha__ || __ia64__ */
+
+#endif /* HAVE_LLSEEK */
+
+ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
+{
+ ext2_loff_t result;
+ static int do_compat = 0;
+
+ if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
+ (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
+ return lseek(fd, (off_t) offset, origin);
+
+ if (do_compat) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ result = my_llseek (fd, offset, origin);
+ if (result == -1 && errno == ENOSYS) {
+ /*
+ * Just in case this code runs on top of an old kernel
+ * which does not support the llseek system call
+ */
+ do_compat++;
+ errno = EINVAL;
+ }
+ return result;
+}
+
+#else /* !linux */
+
+#ifndef EINVAL
+#define EINVAL EXT2_ET_INVALID_ARGUMENT
+#endif
+
+ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
+{
+ if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
+ (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
+ errno = EINVAL;
+ return -1;
+ }
+ return lseek (fd, (off_t) offset, origin);
+}
+
+#endif /* linux */
+
+
diff --git a/e2fslib/llseek.o b/e2fslib/llseek.o
new file mode 100644
index 0000000..1be9537
--- /dev/null
+++ b/e2fslib/llseek.o
Binary files differ
diff --git a/e2fslib/lookup.c b/e2fslib/lookup.c
new file mode 100644
index 0000000..6010c45
--- /dev/null
+++ b/e2fslib/lookup.c
@@ -0,0 +1,69 @@
+/*
+ * lookup.c --- ext2fs directory lookup operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct lookup_struct {
+ const char *name;
+ int len;
+ ext2_ino_t *inode;
+ int found;
+};
+
+#ifdef __TURBOC__
+#pragma argsused
+#endif
+static int lookup_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data)
+{
+ struct lookup_struct *ls = (struct lookup_struct *) priv_data;
+
+ if (ls->len != (dirent->name_len & 0xFF))
+ return 0;
+ if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF)))
+ return 0;
+ *ls->inode = dirent->inode;
+ ls->found++;
+ return DIRENT_ABORT;
+}
+
+
+errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
+ int namelen, char *buf, ext2_ino_t *inode)
+{
+ errcode_t retval;
+ struct lookup_struct ls;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ ls.name = name;
+ ls.len = namelen;
+ ls.inode = inode;
+ ls.found = 0;
+
+ retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
+ if (retval)
+ return retval;
+
+ return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
+}
+
+
diff --git a/e2fslib/lookup.o b/e2fslib/lookup.o
new file mode 100644
index 0000000..a0f6e9c
--- /dev/null
+++ b/e2fslib/lookup.o
Binary files differ
diff --git a/e2fslib/mkdir.c b/e2fslib/mkdir.c
new file mode 100644
index 0000000..15a6863
--- /dev/null
+++ b/e2fslib/mkdir.c
@@ -0,0 +1,154 @@
+/*
+ * mkdir.c --- make a directory in the filesystem
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef EXT2_FT_DIR
+#define EXT2_FT_DIR 2
+#endif
+
+errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
+ const char *name)
+{
+ errcode_t retval;
+ struct ext2_inode parent_inode, inode;
+ ext2_ino_t ino = inum;
+ ext2_ino_t scratch_ino;
+ blk_t blk;
+ char *block = 0;
+ int group;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ /*
+ * Allocate an inode, if necessary
+ */
+ if (!ino) {
+ retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
+ 0, &ino);
+ if (retval)
+ goto cleanup;
+ }
+
+ /*
+ * Allocate a data block for the directory
+ */
+ retval = ext2fs_new_block(fs, 0, 0, &blk);
+ if (retval)
+ goto cleanup;
+
+ /*
+ * Create a scratch template for the directory
+ */
+ retval = ext2fs_new_dir_block(fs, ino, parent, &block);
+ if (retval)
+ goto cleanup;
+
+ /*
+ * Get the parent's inode, if necessary
+ */
+ if (parent != ino) {
+ retval = ext2fs_read_inode(fs, parent, &parent_inode);
+ if (retval)
+ goto cleanup;
+ } else
+ memset(&parent_inode, 0, sizeof(parent_inode));
+
+ /*
+ * Create the inode structure....
+ */
+ memset(&inode, 0, sizeof(struct ext2_inode));
+ inode.i_mode = LINUX_S_IFDIR | 0755;
+ inode.i_uid = inode.i_gid = 0;
+ inode.i_blocks = fs->blocksize / 512;
+ inode.i_block[0] = blk;
+ inode.i_links_count = 2;
+ inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
+ inode.i_size = fs->blocksize;
+
+ /*
+ * Write out the inode and inode data block
+ */
+ retval = ext2fs_write_dir_block(fs, blk, block);
+ if (retval)
+ goto cleanup;
+ retval = ext2fs_write_inode(fs, ino, &inode);
+ if (retval)
+ goto cleanup;
+
+ /*
+ * Link the directory into the filesystem hierarchy
+ */
+ if (name) {
+ retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
+ &scratch_ino);
+ if (!retval) {
+ retval = EXT2_ET_DIR_EXISTS;
+ name = 0;
+ goto cleanup;
+ }
+ if (retval != EXT2_ET_FILE_NOT_FOUND)
+ goto cleanup;
+ retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
+ if (retval)
+ goto cleanup;
+ }
+
+ /*
+ * Update parent inode's counts
+ */
+ if (parent != ino) {
+ parent_inode.i_links_count++;
+ retval = ext2fs_write_inode(fs, parent, &parent_inode);
+ if (retval)
+ goto cleanup;
+ }
+
+ /*
+ * Update accounting....
+ */
+ ext2fs_mark_block_bitmap(fs->block_map, blk);
+ ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_inode_bitmap(fs->inode_map, ino);
+ ext2fs_mark_ib_dirty(fs);
+
+ group = ext2fs_group_of_blk(fs, blk);
+ fs->group_desc[group].bg_free_blocks_count--;
+ group = ext2fs_group_of_ino(fs, ino);
+ fs->group_desc[group].bg_free_inodes_count--;
+ fs->group_desc[group].bg_used_dirs_count++;
+ fs->super->s_free_blocks_count--;
+ fs->super->s_free_inodes_count--;
+ ext2fs_mark_super_dirty(fs);
+
+cleanup:
+ if (block)
+ ext2fs_free_mem((void **) &block);
+ return retval;
+
+}
+
+
diff --git a/e2fslib/mkdir.o b/e2fslib/mkdir.o
new file mode 100644
index 0000000..87e01fd
--- /dev/null
+++ b/e2fslib/mkdir.o
Binary files differ
diff --git a/e2fslib/mkjournal.c b/e2fslib/mkjournal.c
new file mode 100644
index 0000000..606501d
--- /dev/null
+++ b/e2fslib/mkjournal.c
@@ -0,0 +1,408 @@
+/*
+ * mkjournal.c --- make a journal for a filesystem
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "ext2_fs.h"
+#include "e2p/e2p.h"
+#include "ext2fs.h"
+#include "jfs_user.h"
+
+/*
+ * This function automatically sets up the journal superblock and
+ * returns it as an allocated block.
+ */
+errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
+ __u32 size, int flags,
+ char **ret_jsb)
+{
+ errcode_t retval;
+ journal_superblock_t *jsb;
+
+ if (size < 1024)
+ return EXT2_ET_JOURNAL_TOO_SMALL;
+
+ if ((retval = ext2fs_get_mem(fs->blocksize, (void **) &jsb)))
+ return retval;
+
+ memset (jsb, 0, fs->blocksize);
+
+ jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
+ if (flags & EXT2_MKJOURNAL_V1_SUPER)
+ jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
+ else
+ jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+ jsb->s_blocksize = htonl(fs->blocksize);
+ jsb->s_maxlen = htonl(size);
+ jsb->s_nr_users = htonl(1);
+ jsb->s_first = htonl(1);
+ jsb->s_sequence = htonl(1);
+ memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
+ /*
+ * If we're creating an external journal device, we need to
+ * adjust these fields.
+ */
+ if (fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+ jsb->s_nr_users = 0;
+ if (fs->blocksize == 1024)
+ jsb->s_first = htonl(3);
+ else
+ jsb->s_first = htonl(2);
+ }
+
+ *ret_jsb = (char *) jsb;
+ return 0;
+}
+
+/*
+ * This function writes a journal using POSIX routines. It is used
+ * for creating external journals and creating journals on live
+ * filesystems.
+ */
+static errcode_t write_journal_file(ext2_filsys fs, char *filename,
+ blk_t size, int flags)
+{
+ errcode_t retval;
+ char *buf = 0;
+ int i, fd, ret_size;
+
+ if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
+ return retval;
+
+ /* Open the device or journal file */
+ if ((fd = open(filename, O_WRONLY)) < 0) {
+ retval = errno;
+ goto errout;
+ }
+
+ /* Write the superblock out */
+ retval = EXT2_ET_SHORT_WRITE;
+ ret_size = write(fd, buf, fs->blocksize);
+ if (ret_size < 0) {
+ retval = errno;
+ goto errout;
+ }
+ if (ret_size != fs->blocksize)
+ goto errout;
+ memset(buf, 0, fs->blocksize);
+
+ for (i = 1; i < size; i++) {
+ ret_size = write(fd, buf, fs->blocksize);
+ if (ret_size < 0) {
+ retval = errno;
+ goto errout;
+ }
+ if (ret_size != fs->blocksize)
+ goto errout;
+ }
+ close(fd);
+
+ retval = 0;
+errout:
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+/*
+ * Helper function for creating the journal using direct I/O routines
+ */
+struct mkjournal_struct {
+ int num_blocks;
+ int newblocks;
+ char *buf;
+ errcode_t err;
+};
+
+static int mkjournal_proc(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk_t ref_block,
+ int ref_offset,
+ void *priv_data)
+{
+ struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
+ blk_t new_blk;
+ static blk_t last_blk = 0;
+ errcode_t retval;
+ int group;
+
+ if (*blocknr) {
+ last_blk = *blocknr;
+ return 0;
+ }
+ retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
+ if (retval) {
+ es->err = retval;
+ return BLOCK_ABORT;
+ }
+ if (blockcnt > 0)
+ es->num_blocks--;
+
+ es->newblocks++;
+ retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
+
+ if (blockcnt == 0)
+ memset(es->buf, 0, fs->blocksize);
+
+ if (retval) {
+ es->err = retval;
+ return BLOCK_ABORT;
+ }
+ *blocknr = new_blk;
+ last_blk = new_blk;
+ ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+ ext2fs_mark_bb_dirty(fs);
+ group = ext2fs_group_of_blk(fs, new_blk);
+ fs->group_desc[group].bg_free_blocks_count--;
+ fs->super->s_free_blocks_count--;
+ ext2fs_mark_super_dirty(fs);
+
+ if (es->num_blocks == 0)
+ return (BLOCK_CHANGED | BLOCK_ABORT);
+ else
+ return BLOCK_CHANGED;
+
+}
+
+/*
+ * This function creates a journal using direct I/O routines.
+ */
+static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
+ blk_t size, int flags)
+{
+ char *buf;
+ errcode_t retval;
+ struct ext2_inode inode;
+ struct mkjournal_struct es;
+
+ if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
+ return retval;
+
+ if ((retval = ext2fs_read_bitmaps(fs)))
+ return retval;
+
+ if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
+ return retval;
+
+ if (inode.i_blocks > 0)
+ return EEXIST;
+
+ es.num_blocks = size;
+ es.newblocks = 0;
+ es.buf = buf;
+ es.err = 0;
+
+ retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
+ 0, mkjournal_proc, &es);
+ if (es.err) {
+ retval = es.err;
+ goto errout;
+ }
+
+ if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
+ goto errout;
+
+ inode.i_size += fs->blocksize * size;
+ inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
+ inode.i_mtime = inode.i_ctime = time(0);
+ inode.i_links_count = 1;
+ inode.i_mode = LINUX_S_IFREG | 0600;
+
+ if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
+ goto errout;
+ retval = 0;
+
+errout:
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+/*
+ * This function adds a journal device to a filesystem
+ */
+errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
+{
+ struct stat st;
+ errcode_t retval;
+ char buf[1024];
+ journal_superblock_t *jsb;
+ int i, start;
+ __u32 nr_users;
+
+ /* Make sure the device exists and is a block device */
+ if (stat(journal_dev->device_name, &st) < 0)
+ return errno;
+
+ if (!S_ISBLK(st.st_mode))
+ return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
+
+ /* Get the journal superblock */
+ start = 1;
+ if (journal_dev->blocksize == 1024)
+ start++;
+ if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf)))
+ return retval;
+
+ jsb = (journal_superblock_t *) buf;
+ if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+ (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
+ return EXT2_ET_NO_JOURNAL_SB;
+
+ if (ntohl(jsb->s_blocksize) != fs->blocksize)
+ return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+
+ /* Check and see if this filesystem has already been added */
+ nr_users = ntohl(jsb->s_nr_users);
+ for (i=0; i < nr_users; i++) {
+ if (memcmp(fs->super->s_uuid,
+ &jsb->s_users[i*16], 16) == 0)
+ break;
+ }
+ if (i >= nr_users) {
+ memcpy(&jsb->s_users[nr_users*16],
+ fs->super->s_uuid, 16);
+ jsb->s_nr_users = htonl(nr_users+1);
+ }
+
+ /* Writeback the journal superblock */
+ if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf)))
+ return retval;
+
+ fs->super->s_journal_inum = 0;
+ fs->super->s_journal_dev = st.st_rdev;
+ memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
+ sizeof(fs->super->s_journal_uuid));
+ fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+ ext2fs_mark_super_dirty(fs);
+ return 0;
+}
+
+/*
+ * This function adds a journal inode to a filesystem, using either
+ * POSIX routines if the filesystem is mounted, or using direct I/O
+ * functions if it is not.
+ */
+errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
+{
+ errcode_t retval;
+ ext2_ino_t journal_ino;
+ struct stat st;
+ char jfile[1024];
+ int fd, mount_flags, f;
+
+ if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
+ jfile, sizeof(jfile)-10)))
+ return retval;
+
+ if (mount_flags & EXT2_MF_MOUNTED) {
+ strcat(jfile, "/.journal");
+
+ /* Create the journal file */
+ if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
+ return errno;
+
+ if ((retval = write_journal_file(fs, jfile, size, flags)))
+ goto errout;
+
+ /* Get inode number of the journal file */
+ if (fstat(fd, &st) < 0)
+ goto errout;
+
+#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
+ retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
+#else
+#if HAVE_EXT2_IOCTLS
+ f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;;
+ retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
+#endif
+#endif
+ if (retval)
+ goto errout;
+
+ close(fd);
+ journal_ino = st.st_ino;
+ } else {
+ journal_ino = EXT2_JOURNAL_INO;
+ if ((retval = write_journal_inode(fs, journal_ino,
+ size, flags)))
+ return retval;
+ }
+
+ fs->super->s_journal_inum = journal_ino;
+ fs->super->s_journal_dev = 0;
+ memset(fs->super->s_journal_uuid, 0,
+ sizeof(fs->super->s_journal_uuid));
+ fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+
+ ext2fs_mark_super_dirty(fs);
+ return 0;
+errout:
+ close(fd);
+ return retval;
+}
+
+#ifdef DEBUG
+main(int argc, char **argv)
+{
+ errcode_t retval;
+ char *device_name;
+ ext2_filsys fs;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
+ exit(1);
+ }
+ device_name = argv[1];
+
+ retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
+ unix_io_manager, &fs);
+ if (retval) {
+ com_err(argv[0], retval, "while opening %s", device_name);
+ exit(1);
+ }
+
+ retval = ext2fs_add_journal_inode(fs, 1024);
+ if (retval) {
+ com_err(argv[0], retval, "while adding journal to %s",
+ device_name);
+ exit(1);
+ }
+ retval = ext2fs_flush(fs);
+ if (retval) {
+ printf("Warning, had trouble writing out superblocks.\n");
+ }
+ ext2fs_close(fs);
+ exit(0);
+
+}
+#endif
diff --git a/e2fslib/mkjournal.o b/e2fslib/mkjournal.o
new file mode 100644
index 0000000..b513e43
--- /dev/null
+++ b/e2fslib/mkjournal.o
Binary files differ
diff --git a/e2fslib/namei.c b/e2fslib/namei.c
new file mode 100644
index 0000000..18be0f1
--- /dev/null
+++ b/e2fslib/namei.c
@@ -0,0 +1,205 @@
+/*
+ * namei.c --- ext2fs directory lookup operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* #define NAMEI_DEBUG */
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
+ const char *pathname, size_t pathlen, int follow,
+ int link_count, char *buf, ext2_ino_t *res_inode);
+
+static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
+ ext2_ino_t inode, int link_count,
+ char *buf, ext2_ino_t *res_inode)
+{
+ char *pathname;
+ char *buffer = 0;
+ errcode_t retval;
+ struct ext2_inode ei;
+
+#ifdef NAMEI_DEBUG
+ printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
+ root, dir, inode, link_count);
+
+#endif
+ retval = ext2fs_read_inode (fs, inode, &ei);
+ if (retval) return retval;
+ if (!LINUX_S_ISLNK (ei.i_mode)) {
+ *res_inode = inode;
+ return 0;
+ }
+ if (link_count++ > 5) {
+ return EXT2_ET_SYMLINK_LOOP;
+ }
+ if (ei.i_blocks) {
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buffer);
+ if (retval)
+ return retval;
+ retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
+ if (retval) {
+ ext2fs_free_mem((void **) &buffer);
+ return retval;
+ }
+ pathname = buffer;
+ } else
+ pathname = (char *)&(ei.i_block[0]);
+ retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
+ link_count, buf, res_inode);
+ if (buffer)
+ ext2fs_free_mem((void **) &buffer);
+ return retval;
+}
+
+/*
+ * This routine interprets a pathname in the context of the current
+ * directory and the root directory, and returns the inode of the
+ * containing directory, and a pointer to the filename of the file
+ * (pointing into the pathname) and the length of the filename.
+ */
+static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
+ const char *pathname, int pathlen,
+ int link_count, char *buf,
+ const char **name, int *namelen,
+ ext2_ino_t *res_inode)
+{
+ char c;
+ const char *thisname;
+ int len;
+ ext2_ino_t inode;
+ errcode_t retval;
+
+ if ((c = *pathname) == '/') {
+ dir = root;
+ pathname++;
+ pathlen--;
+ }
+ while (1) {
+ thisname = pathname;
+ for (len=0; --pathlen >= 0;len++) {
+ c = *(pathname++);
+ if (c == '/')
+ break;
+ }
+ if (pathlen < 0)
+ break;
+ retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
+ if (retval) return retval;
+ retval = follow_link (fs, root, dir, inode,
+ link_count, buf, &dir);
+ if (retval) return retval;
+ }
+ *name = thisname;
+ *namelen = len;
+ *res_inode = dir;
+ return 0;
+}
+
+static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
+ const char *pathname, size_t pathlen, int follow,
+ int link_count, char *buf, ext2_ino_t *res_inode)
+{
+ const char *basename;
+ int namelen;
+ ext2_ino_t dir, inode;
+ errcode_t retval;
+
+#ifdef NAMEI_DEBUG
+ printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
+ root, base, pathlen, pathname, link_count);
+#endif
+ retval = dir_namei(fs, root, base, pathname, pathlen,
+ link_count, buf, &basename, &namelen, &dir);
+ if (retval) return retval;
+ if (!namelen) { /* special case: '/usr/' etc */
+ *res_inode=dir;
+ return 0;
+ }
+ retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
+ if (retval)
+ return retval;
+ if (follow) {
+ retval = follow_link(fs, root, dir, inode, link_count,
+ buf, &inode);
+ if (retval)
+ return retval;
+ }
+#ifdef NAMEI_DEBUG
+ printf("open_namei: (link_count=%d) returns %lu\n",
+ link_count, inode);
+#endif
+ *res_inode = inode;
+ return 0;
+}
+
+errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ const char *name, ext2_ino_t *inode)
+{
+ char *buf;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+
+ retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
+ buf, inode);
+
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ const char *name, ext2_ino_t *inode)
+{
+ char *buf;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+
+ retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
+ buf, inode);
+
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+ ext2_ino_t inode, ext2_ino_t *res_inode)
+{
+ char *buf;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+
+ retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
+
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
diff --git a/e2fslib/namei.o b/e2fslib/namei.o
new file mode 100644
index 0000000..c7b36d8
--- /dev/null
+++ b/e2fslib/namei.o
Binary files differ
diff --git a/e2fslib/native.c b/e2fslib/native.c
new file mode 100644
index 0000000..85d0989
--- /dev/null
+++ b/e2fslib/native.c
@@ -0,0 +1,27 @@
+/*
+ * native.c --- returns the ext2_flag for a native byte order
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+int ext2fs_native_flag(void)
+{
+#ifdef WORDS_BIGENDIAN
+ return EXT2_FLAG_SWAP_BYTES;
+#else
+ return 0;
+#endif
+}
+
+
+
diff --git a/e2fslib/native.o b/e2fslib/native.o
new file mode 100644
index 0000000..7c0cc21
--- /dev/null
+++ b/e2fslib/native.o
Binary files differ
diff --git a/e2fslib/newdir.c b/e2fslib/newdir.c
new file mode 100644
index 0000000..b8e593e
--- /dev/null
+++ b/e2fslib/newdir.c
@@ -0,0 +1,72 @@
+/*
+ * newdir.c --- create a new directory block
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef EXT2_FT_DIR
+#define EXT2_FT_DIR 2
+#endif
+
+/*
+ * Create new directory block
+ */
+errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
+ ext2_ino_t parent_ino, char **block)
+{
+ struct ext2_dir_entry *dir = NULL;
+ errcode_t retval;
+ char *buf;
+ int rec_len;
+ int filetype = 0;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (retval)
+ return retval;
+ memset(buf, 0, fs->blocksize);
+ dir = (struct ext2_dir_entry *) buf;
+ dir->rec_len = fs->blocksize;
+
+ if (dir_ino) {
+ if (fs->super->s_feature_incompat &
+ EXT2_FEATURE_INCOMPAT_FILETYPE)
+ filetype = EXT2_FT_DIR << 8;
+ /*
+ * Set up entry for '.'
+ */
+ dir->inode = dir_ino;
+ dir->name_len = 1 | filetype;
+ dir->name[0] = '.';
+ rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
+ dir->rec_len = EXT2_DIR_REC_LEN(1);
+
+ /*
+ * Set up entry for '..'
+ */
+ dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
+ dir->rec_len = rec_len;
+ dir->inode = parent_ino;
+ dir->name_len = 2 | filetype;
+ dir->name[0] = '.';
+ dir->name[1] = '.';
+
+ }
+ *block = buf;
+ return 0;
+}
diff --git a/e2fslib/newdir.o b/e2fslib/newdir.o
new file mode 100644
index 0000000..c76eaf5
--- /dev/null
+++ b/e2fslib/newdir.o
Binary files differ
diff --git a/e2fslib/nt_io.c b/e2fslib/nt_io.c
new file mode 100644
index 0000000..c39127c
--- /dev/null
+++ b/e2fslib/nt_io.c
@@ -0,0 +1,1513 @@
+/*
+ * 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 (andreys@ns.cr.cyco.com)
+ *
+ * %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 "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_NONALERT);
+
+ 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_NONALERT);
+
+ //
+ // 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_NONALERT);
+ }
+ }
+
+
+
+ //
+ // 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/e2fslib/openfs.c b/e2fslib/openfs.c
new file mode 100644
index 0000000..042e25a
--- /dev/null
+++ b/e2fslib/openfs.c
@@ -0,0 +1,240 @@
+/*
+ * openfs.c --- open an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "e2image.h"
+
+/*
+ * Note: if superblock is non-zero, block-size must also be non-zero.
+ * Superblock and block_size can be zero to use the default size.
+ *
+ * Valid flags for ext2fs_open()
+ *
+ * EXT2_FLAG_RW - Open the filesystem for read/write.
+ * EXT2_FLAG_FORCE - Open the filesystem even if some of the
+ * features aren't supported.
+ * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
+ */
+errcode_t ext2fs_open(const char *name, int flags, int superblock,
+ int block_size, io_manager manager, ext2_filsys *ret_fs)
+{
+ ext2_filsys fs;
+ errcode_t retval;
+ int i, j, groups_per_block;
+ blk_t group_block;
+ char *dest;
+ struct ext2_group_desc *gdp;
+
+ EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
+
+ retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys),
+ (void **) &fs);
+ if (retval)
+ return retval;
+
+ memset(fs, 0, sizeof(struct struct_ext2_filsys));
+ fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
+ fs->flags = flags;
+ retval = manager->open(name, (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0,
+ &fs->io);
+ if (retval)
+ goto cleanup;
+ fs->io->app_data = fs;
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &fs->device_name);
+ if (retval)
+ goto cleanup;
+ strcpy(fs->device_name, name);
+ retval = ext2fs_get_mem(SUPERBLOCK_SIZE, (void **) &fs->super);
+ if (retval)
+ goto cleanup;
+ if (flags & EXT2_FLAG_IMAGE_FILE) {
+ retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
+ (void **) &fs->image_header);
+ if (retval)
+ goto cleanup;
+ retval = io_channel_read_blk(fs->io, 0,
+ -sizeof(struct ext2_image_hdr),
+ fs->image_header);
+ if (retval)
+ goto cleanup;
+ if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
+ return EXT2_ET_MAGIC_E2IMAGE;
+ superblock = 1;
+ block_size = fs->image_header->fs_blocksize;
+ }
+
+ /*
+ * If the user specifies a specific block # for the
+ * superblock, then he/she must also specify the block size!
+ * Otherwise, read the master superblock located at offset
+ * SUPERBLOCK_OFFSET from the start of the partition.
+ *
+ * Note: we only save a backup copy of the superblock if we
+ * are reading the superblock from the primary superblock location.
+ */
+ if (superblock) {
+ if (!block_size) {
+ retval = EXT2_ET_INVALID_ARGUMENT;
+ goto cleanup;
+ }
+ io_channel_set_blksize(fs->io, block_size);
+ group_block = superblock + 1;
+ fs->orig_super = 0;
+ } else {
+ io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
+ superblock = 1;
+ group_block = 0;
+ retval = ext2fs_get_mem(SUPERBLOCK_SIZE,
+ (void **) &fs->orig_super);
+ if (retval)
+ goto cleanup;
+ }
+ retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
+ fs->super);
+ if (retval)
+ goto cleanup;
+ if (fs->orig_super)
+ memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
+ fs->flags |= EXT2_FLAG_SWAP_BYTES;
+
+ ext2fs_swap_super(fs->super);
+ }
+#endif
+
+ if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
+ printf("%x, %x\n",fs->super->s_magic, EXT2_SUPER_MAGIC);
+ retval = EXT2_ET_BAD_MAGIC;
+ goto cleanup;
+ }
+ if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
+ retval = EXT2_ET_REV_TOO_HIGH;
+ goto cleanup;
+ }
+
+ /*
+ * Check for feature set incompatibility
+ */
+ if (!(flags & EXT2_FLAG_FORCE)) {
+ if (fs->super->s_feature_incompat &
+ ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
+ retval = EXT2_ET_UNSUPP_FEATURE;
+ goto cleanup;
+ }
+ if ((flags & EXT2_FLAG_RW) &&
+ (fs->super->s_feature_ro_compat &
+ ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
+ retval = EXT2_ET_RO_UNSUPP_FEATURE;
+ goto cleanup;
+ }
+ if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
+ (fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ retval = EXT2_ET_UNSUPP_FEATURE;
+ goto cleanup;
+ }
+ }
+
+ fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
+ if (fs->blocksize == 0) {
+ retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+ goto cleanup;
+ }
+ fs->fragsize = EXT2_FRAG_SIZE(fs->super);
+ fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
+ EXT2_INODE_SIZE(fs->super) +
+ EXT2_BLOCK_SIZE(fs->super) - 1) /
+ EXT2_BLOCK_SIZE(fs->super));
+ if (block_size) {
+ if (block_size != fs->blocksize) {
+ retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+ goto cleanup;
+ }
+ }
+ /*
+ * Set the blocksize to the filesystem's blocksize.
+ */
+ io_channel_set_blksize(fs->io, fs->blocksize);
+
+ /*
+ * If this is an external journal device, don't try to read
+ * the group descriptors, because they're not there.
+ */
+ if (fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+ fs->group_desc_count = 0;
+ *ret_fs = fs;
+ return 0;
+ }
+
+ /*
+ * Read group descriptors
+ */
+ if ((EXT2_BLOCKS_PER_GROUP(fs->super)) == 0) {
+ retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+ goto cleanup;
+ }
+ fs->group_desc_count = (fs->super->s_blocks_count -
+ fs->super->s_first_data_block +
+ EXT2_BLOCKS_PER_GROUP(fs->super) - 1)
+ / EXT2_BLOCKS_PER_GROUP(fs->super);
+ fs->desc_blocks = (fs->group_desc_count +
+ EXT2_DESC_PER_BLOCK(fs->super) - 1)
+ / EXT2_DESC_PER_BLOCK(fs->super);
+ retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
+ (void **) &fs->group_desc);
+ if (retval)
+ goto cleanup;
+ if (!group_block)
+ group_block = fs->super->s_first_data_block + 1;
+ dest = (char *) fs->group_desc;
+ for (i=0 ; i < fs->desc_blocks; i++) {
+ retval = io_channel_read_blk(fs->io, group_block, 1, dest);
+ if (retval)
+ goto cleanup;
+ group_block++;
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+ gdp = (struct ext2_group_desc *) dest;
+ groups_per_block = fs->blocksize /
+ sizeof(struct ext2_group_desc);
+ for (j=0; j < groups_per_block; j++)
+ ext2fs_swap_group_desc(gdp++);
+ }
+#endif
+ dest += fs->blocksize;
+ }
+
+ *ret_fs = fs;
+ return 0;
+cleanup:
+ ext2fs_free(fs);
+ return retval;
+}
+
diff --git a/e2fslib/openfs.o b/e2fslib/openfs.o
new file mode 100644
index 0000000..d61e3a9
--- /dev/null
+++ b/e2fslib/openfs.o
Binary files differ
diff --git a/e2fslib/read_bb.c b/e2fslib/read_bb.c
new file mode 100644
index 0000000..5d847fb
--- /dev/null
+++ b/e2fslib/read_bb.c
@@ -0,0 +1,95 @@
+/*
+ * read_bb --- read the bad blocks inode
+ *
+ * Copyright (C) 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct read_bb_record {
+ ext2_badblocks_list bb_list;
+ errcode_t err;
+};
+
+/*
+ * Helper function for ext2fs_read_bb_inode()
+ */
+#ifdef __TURBOC__
+#pragma argsused
+#endif
+static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
+ e2_blkcnt_t blockcnt, blk_t ref_block,
+ int ref_offset, void *priv_data)
+{
+ struct read_bb_record *rb = (struct read_bb_record *) priv_data;
+
+ if (blockcnt < 0)
+ return 0;
+
+ if ((*block_nr < fs->super->s_first_data_block) ||
+ (*block_nr >= fs->super->s_blocks_count))
+ return 0; /* Ignore illegal blocks */
+
+ rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
+ if (rb->err)
+ return BLOCK_ABORT;
+ return 0;
+}
+
+/*
+ * Reads the current bad blocks from the bad blocks inode.
+ */
+errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
+{
+ errcode_t retval;
+ struct read_bb_record rb;
+ struct ext2_inode inode;
+ blk_t numblocks;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!*bb_list) {
+ retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
+ if (retval)
+ return retval;
+ if (inode.i_blocks < 500)
+ numblocks = (inode.i_blocks /
+ (fs->blocksize / 512)) + 20;
+ else
+ numblocks = 500;
+ retval = ext2fs_badblocks_list_create(bb_list, numblocks);
+ if (retval)
+ return retval;
+ }
+
+ rb.bb_list = *bb_list;
+ rb.err = 0;
+ retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0,
+ mark_bad_block, &rb);
+ if (retval)
+ return retval;
+
+ return rb.err;
+}
+
+
diff --git a/e2fslib/read_bb.o b/e2fslib/read_bb.o
new file mode 100644
index 0000000..5494cd4
--- /dev/null
+++ b/e2fslib/read_bb.o
Binary files differ
diff --git a/e2fslib/read_bb_file.c b/e2fslib/read_bb_file.c
new file mode 100644
index 0000000..7f54d6e
--- /dev/null
+++ b/e2fslib/read_bb_file.c
@@ -0,0 +1,96 @@
+/*
+ * read_bb_file.c --- read a list of bad blocks from a FILE *
+ *
+ * Copyright (C) 1994, 1995, 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Reads a list of bad blocks from a FILE *
+ */
+errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
+ ext2_badblocks_list *bb_list,
+ void *private,
+ void (*invalid)(ext2_filsys fs,
+ blk_t blk,
+ char *badstr,
+ void *private))
+{
+ errcode_t retval;
+ blk_t blockno;
+ int count;
+ char buf[128];
+
+ if (fs)
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!*bb_list) {
+ retval = ext2fs_badblocks_list_create(bb_list, 10);
+ if (retval)
+ return retval;
+ }
+
+ while (!feof (f)) {
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ break;
+ count = sscanf(buf, "%u", &blockno);
+ if (count <= 0)
+ continue;
+ if (fs &&
+ ((blockno < fs->super->s_first_data_block) ||
+ (blockno >= fs->super->s_blocks_count))) {
+ if (invalid)
+ (invalid)(fs, blockno, buf, private);
+ continue;
+ }
+ retval = ext2fs_badblocks_list_add(*bb_list, blockno);
+ if (retval)
+ return retval;
+ }
+ return 0;
+}
+
+static void call_compat_invalid(ext2_filsys fs, blk_t blk,
+ char *badstr, void *private)
+{
+ void (*invalid)(ext2_filsys, blk_t);
+
+ invalid = (void (*)(ext2_filsys, blk_t)) private;
+ if (invalid)
+ invalid(fs, blk);
+}
+
+
+/*
+ * Reads a list of bad blocks from a FILE *
+ */
+errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
+ ext2_badblocks_list *bb_list,
+ void (*invalid)(ext2_filsys fs, blk_t blk))
+{
+ return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid,
+ call_compat_invalid);
+}
+
+
diff --git a/e2fslib/read_bb_file.o b/e2fslib/read_bb_file.o
new file mode 100644
index 0000000..b76e770
--- /dev/null
+++ b/e2fslib/read_bb_file.o
Binary files differ
diff --git a/e2fslib/rs_bitmap.c b/e2fslib/rs_bitmap.c
new file mode 100644
index 0000000..30a9ef9
--- /dev/null
+++ b/e2fslib/rs_bitmap.c
@@ -0,0 +1,107 @@
+/*
+ * rs_bitmap.c --- routine for changing the size of a bitmap
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_generic_bitmap bmap)
+{
+ errcode_t retval;
+ size_t size, new_size;
+ __u32 bitno;
+
+ if (!bmap)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
+
+ /*
+ * If we're expanding the bitmap, make sure all of the new
+ * parts of the bitmap are zero.
+ */
+ if (new_end > bmap->end) {
+ bitno = bmap->real_end;
+ if (bitno > new_end)
+ bitno = new_end;
+ for (; bitno > bmap->end; bitno--)
+ ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
+ }
+ if (new_real_end == bmap->real_end) {
+ bmap->end = new_end;
+ return 0;
+ }
+
+ size = ((bmap->real_end - bmap->start) / 8) + 1;
+ new_size = ((new_real_end - bmap->start) / 8) + 1;
+
+ if (size != new_size) {
+ retval = ext2fs_resize_mem(size, new_size,
+ (void **) &bmap->bitmap);
+ if (retval)
+ return retval;
+ }
+ if (new_size > size)
+ memset(bmap->bitmap + size, 0, new_size - size);
+
+ bmap->end = new_end;
+ bmap->real_end = new_real_end;
+ return 0;
+}
+
+errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_inode_bitmap bmap)
+{
+ errcode_t retval;
+
+ if (!bmap)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
+
+ bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
+ bmap);
+ bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
+ return retval;
+}
+
+errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_block_bitmap bmap)
+{
+ errcode_t retval;
+
+ if (!bmap)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+ bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
+ bmap);
+ bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ return retval;
+}
+
diff --git a/e2fslib/rs_bitmap.o b/e2fslib/rs_bitmap.o
new file mode 100644
index 0000000..b774102
--- /dev/null
+++ b/e2fslib/rs_bitmap.o
Binary files differ
diff --git a/e2fslib/rw_bitmaps.c b/e2fslib/rw_bitmaps.c
new file mode 100644
index 0000000..89557db
--- /dev/null
+++ b/e2fslib/rw_bitmaps.c
@@ -0,0 +1,302 @@
+/*
+ * rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
+ *
+ * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "e2image.h"
+
+#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
+/*
+ * On the PowerPC, the big-endian variant of the ext2 filesystem
+ * has its bitmaps stored as 32-bit words with bit 0 as the LSB
+ * of each word. Thus a bitmap with only bit 0 set would be, as
+ * a string of bytes, 00 00 00 01 00 ...
+ * To cope with this, we byte-reverse each word of a bitmap if
+ * we have a big-endian filesystem, that is, if we are *not*
+ * byte-swapping other word-sized numbers.
+ */
+#define EXT2_BIG_ENDIAN_BITMAPS
+#endif
+
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
+{
+ __u32 *p = (__u32 *) bitmap;
+ int n;
+
+ for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
+ *p = ext2fs_swab32(*p);
+}
+#endif
+
+errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
+{
+ dgrp_t i;
+ size_t nbytes;
+ errcode_t retval;
+ char * inode_bitmap = fs->inode_map->bitmap;
+ char * bitmap_block = NULL;
+ blk_t blk;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+ if (!inode_bitmap)
+ return 0;
+ nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
+
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &bitmap_block);
+ if (retval)
+ return retval;
+ memset(bitmap_block, 0xff, fs->blocksize);
+ for (i = 0; i < fs->group_desc_count; i++) {
+ memcpy(bitmap_block, inode_bitmap, nbytes);
+ blk = fs->group_desc[i].bg_inode_bitmap;
+ if (blk) {
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+ if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
+ ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
+#endif
+ retval = io_channel_write_blk(fs->io, blk, 1,
+ bitmap_block);
+ if (retval)
+ return EXT2_ET_INODE_BITMAP_WRITE;
+ }
+ inode_bitmap += nbytes;
+ }
+ fs->flags |= EXT2_FLAG_CHANGED;
+ fs->flags &= ~EXT2_FLAG_IB_DIRTY;
+ ext2fs_free_mem((void **) &bitmap_block);
+ return 0;
+}
+
+errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
+{
+ dgrp_t i;
+ int j;
+ int nbytes;
+ int nbits;
+ errcode_t retval;
+ char * block_bitmap = fs->block_map->bitmap;
+ char * bitmap_block = NULL;
+ blk_t blk;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+ if (!block_bitmap)
+ return 0;
+ nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &bitmap_block);
+ if (retval)
+ return retval;
+ memset(bitmap_block, 0xff, fs->blocksize);
+ for (i = 0; i < fs->group_desc_count; i++) {
+ memcpy(bitmap_block, block_bitmap, nbytes);
+ if (i == fs->group_desc_count - 1) {
+ /* Force bitmap padding for the last group */
+ nbits = (int) ((fs->super->s_blocks_count
+ - fs->super->s_first_data_block)
+ % EXT2_BLOCKS_PER_GROUP(fs->super));
+ if (nbits)
+ for (j = nbits; j < fs->blocksize * 8; j++)
+ ext2fs_set_bit(j, bitmap_block);
+ }
+ blk = fs->group_desc[i].bg_block_bitmap;
+ if (blk) {
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+ if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
+ ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
+#endif
+ retval = io_channel_write_blk(fs->io, blk, 1,
+ bitmap_block);
+ if (retval)
+ return EXT2_ET_BLOCK_BITMAP_WRITE;
+ }
+ block_bitmap += nbytes;
+ }
+ fs->flags |= EXT2_FLAG_CHANGED;
+ fs->flags &= ~EXT2_FLAG_BB_DIRTY;
+ ext2fs_free_mem((void **) &bitmap_block);
+ return 0;
+}
+
+static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+{
+ dgrp_t i;
+ char *block_bitmap = 0, *inode_bitmap = 0;
+ char *buf;
+ errcode_t retval;
+ int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
+ blk_t blk;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ fs->write_bitmaps = ext2fs_write_bitmaps;
+
+ retval = ext2fs_get_mem(strlen(fs->device_name) + 80, (void **) &buf);
+ if (retval)
+ return retval;
+ if (do_block) {
+ if (fs->block_map)
+ ext2fs_free_block_bitmap(fs->block_map);
+ sprintf(buf, "block bitmap for %s", fs->device_name);
+ retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
+ if (retval)
+ goto cleanup;
+ block_bitmap = fs->block_map->bitmap;
+ }
+ if (do_inode) {
+ if (fs->inode_map)
+ ext2fs_free_inode_bitmap(fs->inode_map);
+ sprintf(buf, "inode bitmap for %s", fs->device_name);
+ retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
+ if (retval)
+ goto cleanup;
+ inode_bitmap = fs->inode_map->bitmap;
+ }
+ ext2fs_free_mem((void **) &buf);
+
+ if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ if (inode_bitmap) {
+ blk = (fs->image_header->offset_inodemap /
+ fs->blocksize);
+ retval = io_channel_read_blk(fs->io, blk,
+ -(inode_nbytes * fs->group_desc_count),
+ inode_bitmap);
+ if (retval)
+ goto cleanup;
+ }
+ if (block_bitmap) {
+ blk = (fs->image_header->offset_blockmap /
+ fs->blocksize);
+ retval = io_channel_read_blk(fs->io, blk,
+ -(block_nbytes * fs->group_desc_count),
+ block_bitmap);
+ if (retval)
+ goto cleanup;
+ }
+ return 0;
+ }
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ if (block_bitmap) {
+ blk = fs->group_desc[i].bg_block_bitmap;
+ if (blk) {
+ retval = io_channel_read_blk(fs->io, blk,
+ -block_nbytes, block_bitmap);
+ if (retval) {
+ retval = EXT2_ET_BLOCK_BITMAP_READ;
+ goto cleanup;
+ }
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+ if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
+ ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
+#endif
+ } else
+ memset(block_bitmap, 0, block_nbytes);
+ block_bitmap += block_nbytes;
+ }
+ if (inode_bitmap) {
+ blk = fs->group_desc[i].bg_inode_bitmap;
+ if (blk) {
+ retval = io_channel_read_blk(fs->io, blk,
+ -inode_nbytes, inode_bitmap);
+ if (retval) {
+ retval = EXT2_ET_INODE_BITMAP_READ;
+ goto cleanup;
+ }
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+ if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+ (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
+ ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
+#endif
+ } else
+ memset(inode_bitmap, 0, inode_nbytes);
+ inode_bitmap += inode_nbytes;
+ }
+ }
+ return 0;
+
+cleanup:
+ if (do_block) {
+ ext2fs_free_mem((void **) &fs->block_map);
+ fs->block_map = 0;
+ }
+ if (do_inode) {
+ ext2fs_free_mem((void **) &fs->inode_map);
+ fs->inode_map = 0;
+ }
+ if (buf)
+ ext2fs_free_mem((void **) &buf);
+ return retval;
+}
+
+errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
+{
+ return read_bitmaps(fs, 1, 0);
+}
+
+errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
+{
+ return read_bitmaps(fs, 0, 1);
+}
+
+errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
+{
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (fs->inode_map && fs->block_map)
+ return 0;
+
+ return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
+}
+
+errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
+{
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
+ retval = ext2fs_write_block_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
+ retval = ext2fs_write_inode_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ return 0;
+}
+
diff --git a/e2fslib/rw_bitmaps.o b/e2fslib/rw_bitmaps.o
new file mode 100644
index 0000000..a33ad45
--- /dev/null
+++ b/e2fslib/rw_bitmaps.o
Binary files differ
diff --git a/e2fslib/swapfs.c b/e2fslib/swapfs.c
new file mode 100644
index 0000000..f50a795
--- /dev/null
+++ b/e2fslib/swapfs.c
@@ -0,0 +1,145 @@
+/*
+ * swapfs.c --- swap ext2 filesystem data structures
+ *
+ * Copyright (C) 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+void ext2fs_swap_super(struct ext2_super_block * sb)
+{
+ sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count);
+ sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count);
+ sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count);
+ sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count);
+ sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count);
+ sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block);
+ sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size);
+ sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size);
+ sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group);
+ sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group);
+ sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group);
+ sb->s_mtime = ext2fs_swab32(sb->s_mtime);
+ sb->s_wtime = ext2fs_swab32(sb->s_wtime);
+ sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count);
+ sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count);
+ sb->s_magic = ext2fs_swab16(sb->s_magic);
+ sb->s_state = ext2fs_swab16(sb->s_state);
+ sb->s_errors = ext2fs_swab16(sb->s_errors);
+ sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level);
+ sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck);
+ sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval);
+ sb->s_creator_os = ext2fs_swab32(sb->s_creator_os);
+ sb->s_rev_level = ext2fs_swab32(sb->s_rev_level);
+ sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid);
+ sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid);
+ sb->s_first_ino = ext2fs_swab32(sb->s_first_ino);
+ sb->s_inode_size = ext2fs_swab16(sb->s_inode_size);
+ sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr);
+ sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat);
+ sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat);
+ sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat);
+ sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap);
+ sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
+ sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
+ sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
+}
+
+void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
+{
+ gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
+ gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
+ gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
+ gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
+ gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
+ gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
+}
+
+void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t,
+ struct ext2_inode *f, int hostorder)
+{
+ unsigned i;
+ int islnk = 0;
+
+ if (hostorder && LINUX_S_ISLNK(f->i_mode))
+ islnk = 1;
+ t->i_mode = ext2fs_swab16(f->i_mode);
+ if (!hostorder && LINUX_S_ISLNK(t->i_mode))
+ islnk = 1;
+ t->i_uid = ext2fs_swab16(f->i_uid);
+ t->i_size = ext2fs_swab32(f->i_size);
+ t->i_atime = ext2fs_swab32(f->i_atime);
+ t->i_ctime = ext2fs_swab32(f->i_ctime);
+ t->i_mtime = ext2fs_swab32(f->i_mtime);
+ t->i_dtime = ext2fs_swab32(f->i_dtime);
+ t->i_gid = ext2fs_swab16(f->i_gid);
+ t->i_links_count = ext2fs_swab16(f->i_links_count);
+ t->i_blocks = ext2fs_swab32(f->i_blocks);
+ t->i_flags = ext2fs_swab32(f->i_flags);
+ if (!islnk || f->i_blocks) {
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ t->i_block[i] = ext2fs_swab32(f->i_block[i]);
+ } else if (t != f) {
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ t->i_block[i] = f->i_block[i];
+ }
+ t->i_generation = ext2fs_swab32(f->i_generation);
+ t->i_file_acl = ext2fs_swab32(f->i_file_acl);
+ t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
+ t->i_faddr = ext2fs_swab32(f->i_faddr);
+
+ switch (fs->super->s_creator_os) {
+ case EXT2_OS_LINUX:
+ t->osd1.linux1.l_i_reserved1 =
+ ext2fs_swab32(f->osd1.linux1.l_i_reserved1);
+ t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag;
+ t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize;
+ t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1);
+ t->osd2.linux2.l_i_uid_high =
+ ext2fs_swab16 (f->osd2.linux2.l_i_uid_high);
+ t->osd2.linux2.l_i_gid_high =
+ ext2fs_swab16 (f->osd2.linux2.l_i_gid_high);
+ t->osd2.linux2.l_i_reserved2 =
+ ext2fs_swab32(f->osd2.linux2.l_i_reserved2);
+ break;
+ case EXT2_OS_HURD:
+ t->osd1.hurd1.h_i_translator =
+ ext2fs_swab32 (f->osd1.hurd1.h_i_translator);
+ t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag;
+ t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize;
+ t->osd2.hurd2.h_i_mode_high =
+ ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high);
+ t->osd2.hurd2.h_i_uid_high =
+ ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high);
+ t->osd2.hurd2.h_i_gid_high =
+ ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high);
+ t->osd2.hurd2.h_i_author =
+ ext2fs_swab32 (f->osd2.hurd2.h_i_author);
+ break;
+ case EXT2_OS_MASIX:
+ t->osd1.masix1.m_i_reserved1 =
+ ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
+ t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
+ t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
+ t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
+ t->osd2.masix2.m_i_reserved2[0] =
+ ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
+ t->osd2.masix2.m_i_reserved2[1] =
+ ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
+ break;
+ }
+}
+#endif
diff --git a/e2fslib/swapfs.o b/e2fslib/swapfs.o
new file mode 100644
index 0000000..55682fe
--- /dev/null
+++ b/e2fslib/swapfs.o
Binary files differ
diff --git a/e2fslib/test_io.c b/e2fslib/test_io.c
new file mode 100644
index 0000000..b259d0f
--- /dev/null
+++ b/e2fslib/test_io.c
@@ -0,0 +1,265 @@
+/*
+ * test_io.c --- This is the Test I/O interface.
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+ if ((struct)->magic != (code)) return (code)
+
+struct test_private_data {
+ int magic;
+ io_channel real;
+ void (*read_blk)(unsigned long block, int count, errcode_t err);
+ void (*write_blk)(unsigned long block, int count, errcode_t err);
+ void (*set_blksize)(int blksize, errcode_t err);
+ void (*write_byte)(unsigned long block, int count, errcode_t err);
+};
+
+static errcode_t test_open(const char *name, int flags, io_channel *channel);
+static errcode_t test_close(io_channel channel);
+static errcode_t test_set_blksize(io_channel channel, int blksize);
+static errcode_t test_read_blk(io_channel channel, unsigned long block,
+ int count, void *data);
+static errcode_t test_write_blk(io_channel channel, unsigned long block,
+ int count, const void *data);
+static errcode_t test_flush(io_channel channel);
+static errcode_t test_write_byte(io_channel channel, unsigned long offset,
+ int count, const void *buf);
+
+static struct struct_io_manager struct_test_manager = {
+ EXT2_ET_MAGIC_IO_MANAGER,
+ "Test I/O Manager",
+ test_open,
+ test_close,
+ test_set_blksize,
+ test_read_blk,
+ test_write_blk,
+ test_flush,
+ test_write_byte
+
+};
+
+io_manager test_io_manager = &struct_test_manager;
+
+/*
+ * These global variable can be set by the test program as
+ * necessary *before* calling test_open
+ */
+io_manager test_io_backing_manager = 0;
+void (*test_io_cb_read_blk)
+ (unsigned long block, int count, errcode_t err) = 0;
+void (*test_io_cb_write_blk)
+ (unsigned long block, int count, errcode_t err) = 0;
+void (*test_io_cb_set_blksize)
+ (int blksize, errcode_t err) = 0;
+void (*test_io_cb_write_byte)
+ (unsigned long block, int count, errcode_t err) = 0;
+
+static errcode_t test_open(const char *name, int flags, io_channel *channel)
+{
+ io_channel io = NULL;
+ struct test_private_data *data = NULL;
+ errcode_t retval;
+
+ if (name == 0)
+ return EXT2_ET_BAD_DEVICE_NAME;
+ retval = ext2fs_get_mem(sizeof(struct struct_io_channel),
+ (void **) &io);
+ if (retval)
+ return retval;
+ memset(io, 0, sizeof(struct struct_io_channel));
+ io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ retval = ext2fs_get_mem(sizeof(struct test_private_data),
+ (void **) &data);
+ if (retval) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto cleanup;
+ }
+ io->manager = test_io_manager;
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name);
+ if (retval)
+ goto cleanup;
+
+ strcpy(io->name, name);
+ io->private_data = data;
+ io->block_size = 1024;
+ io->read_error = 0;
+ io->write_error = 0;
+ io->refcount = 1;
+
+ memset(data, 0, sizeof(struct test_private_data));
+ data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
+ if (test_io_backing_manager) {
+ retval = test_io_backing_manager->open(name, flags,
+ &data->real);
+ if (retval)
+ goto cleanup;
+ } else
+ data->real = 0;
+ data->read_blk = test_io_cb_read_blk;
+ data->write_blk = test_io_cb_write_blk;
+ data->set_blksize = test_io_cb_set_blksize;
+ data->write_byte = test_io_cb_write_byte;
+
+ *channel = io;
+ return 0;
+
+cleanup:
+ if (io)
+ ext2fs_free_mem((void **) &io);
+ if (data)
+ ext2fs_free_mem((void **) &data);
+ return retval;
+}
+
+static errcode_t test_close(io_channel channel)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (--channel->refcount > 0)
+ return 0;
+
+ if (data->real)
+ retval = io_channel_close(data->real);
+
+ if (channel->private_data)
+ ext2fs_free_mem((void **) &channel->private_data);
+ if (channel->name)
+ ext2fs_free_mem((void **) &channel->name);
+ ext2fs_free_mem((void **) &channel);
+ return retval;
+}
+
+static errcode_t test_set_blksize(io_channel channel, int blksize)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_set_blksize(data->real, blksize);
+ if (data->set_blksize)
+ data->set_blksize(blksize, retval);
+ else
+ printf("Test_io: set_blksize(%d) returned %s\n",
+ blksize, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+
+static errcode_t test_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_read_blk(data->real, block, count, buf);
+ if (data->read_blk)
+ data->read_blk(block, count, retval);
+ else
+ printf("Test_io: read_blk(%lu, %d) returned %s\n",
+ block, count, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+static errcode_t test_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_write_blk(data->real, block, count, buf);
+ if (data->write_blk)
+ data->write_blk(block, count, retval);
+ else
+ printf("Test_io: write_blk(%lu, %d) returned %s\n",
+ block, count, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+static errcode_t test_write_byte(io_channel channel, unsigned long offset,
+ int count, const void *buf)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real && data->real->manager->write_byte)
+ retval = io_channel_write_byte(data->real, offset, count, buf);
+ if (data->write_byte)
+ data->write_byte(offset, count, retval);
+ else
+ printf("Test_io: write_byte(%lu, %d) returned %s\n",
+ offset, count, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t test_flush(io_channel channel)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_flush(data->real);
+
+ printf("Test_io: flush() returned %s\n",
+ retval ? error_message(retval) : "OK");
+
+ return retval;
+}
+
diff --git a/e2fslib/test_io.o b/e2fslib/test_io.o
new file mode 100644
index 0000000..f562c71
--- /dev/null
+++ b/e2fslib/test_io.o
Binary files differ
diff --git a/e2fslib/tst_badblocks.c b/e2fslib/tst_badblocks.c
new file mode 100644
index 0000000..c9389fa
--- /dev/null
+++ b/e2fslib/tst_badblocks.c
@@ -0,0 +1,237 @@
+/*
+ * This testing program makes sure the badblocks implementation works.
+ *
+ * Copyright (C) 1996 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
+blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1 };
+blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 };
+blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 };
+blk_t test4a[] = {
+ 20, 1,
+ 50, 1,
+ 3, 0,
+ 17, 1,
+ 18, 0,
+ 16, 0,
+ 11, 0,
+ 12, 1,
+ 13, 1,
+ 14, 0,
+ 80, 0,
+ 45, 0,
+ 66, 1,
+ 0 };
+
+static int test_fail = 0;
+
+static errcode_t create_test_list(blk_t *vec, badblocks_list *ret)
+{
+ errcode_t retval;
+ badblocks_list bb;
+ int i;
+
+ retval = ext2fs_badblocks_list_create(&bb, 5);
+ if (retval) {
+ com_err("create_test_list", retval, "while creating list");
+ return retval;
+ }
+ for (i=0; vec[i]; i++) {
+ retval = ext2fs_badblocks_list_add(bb, vec[i]);
+ if (retval) {
+ com_err("create_test_list", retval,
+ "while adding test vector %d", i);
+ ext2fs_badblocks_list_free(bb);
+ return retval;
+ }
+ }
+ *ret = bb;
+ return 0;
+}
+
+static void print_list(badblocks_list bb, int verify)
+{
+ errcode_t retval;
+ badblocks_iterate iter;
+ blk_t blk;
+ int i, ok;
+
+ retval = ext2fs_badblocks_list_iterate_begin(bb, &iter);
+ if (retval) {
+ com_err("print_list", retval, "while setting up iterator");
+ return;
+ }
+ ok = i = 1;
+ while (ext2fs_badblocks_list_iterate(iter, &blk)) {
+ printf("%d ", blk);
+ if (i++ != blk)
+ ok = 0;
+ }
+ ext2fs_badblocks_list_iterate_end(iter);
+ if (verify) {
+ if (ok)
+ printf("--- OK");
+ else {
+ printf("--- NOT OK");
+ test_fail++;
+ }
+ }
+}
+
+static void validate_test_seq(badblocks_list bb, blk_t *vec)
+{
+ int i, match, ok;
+
+ for (i = 0; vec[i]; i += 2) {
+ match = ext2fs_badblocks_list_test(bb, vec[i]);
+ if (match == vec[i+1])
+ ok = 1;
+ else {
+ ok = 0;
+ test_fail++;
+ }
+ printf("\tblock %d is %s --- %s\n", vec[i],
+ match ? "present" : "absent",
+ ok ? "OK" : "NOT OK");
+ }
+}
+
+int file_test(badblocks_list bb)
+{
+ char tmp_filename[20] = "#testXXXXXX";
+ badblocks_list new_bb = 0;
+ errcode_t retval;
+ FILE *f;
+
+ mktemp(tmp_filename);
+
+ unlink(tmp_filename);
+ f = fopen(tmp_filename, "w");
+ if (!f) {
+ fprintf(stderr, "Error opening temp file %s: %s\n",
+ tmp_filename, error_message(errno));
+ return 1;
+ }
+ retval = ext2fs_write_bb_FILE(bb, 0, f);
+ if (retval) {
+ com_err("file_test", retval, "while writing bad blocks");
+ return 1;
+ }
+ fclose(f);
+
+ f = fopen(tmp_filename, "r");
+ if (!f) {
+ fprintf(stderr, "Error re-opening temp file %s: %s\n",
+ tmp_filename, error_message(errno));
+ return 1;
+ }
+ retval = ext2fs_read_bb_FILE2(0, f, &new_bb, 0, 0);
+ if (retval) {
+ com_err("file_test", retval, "while reading bad blocks");
+ return 1;
+ }
+ fclose(f);
+
+ if (ext2fs_badblocks_equal(bb, new_bb)) {
+ printf("Block bitmap matched after reading and writing.\n");
+ } else {
+ printf("Block bitmap NOT matched.\n");
+ test_fail++;
+ }
+
+}
+
+
+int main(int argc, char *argv)
+{
+ badblocks_list bb1, bb2, bb3, bb4;
+ int equal;
+ errcode_t retval;
+
+ bb1 = bb2 = bb3 = bb4 = 0;
+
+ printf("test1: ");
+ retval = create_test_list(test1, &bb1);
+ if (retval == 0)
+ print_list(bb1, 1);
+ printf("\n");
+
+ printf("test2: ");
+ retval = create_test_list(test2, &bb2);
+ if (retval == 0)
+ print_list(bb2, 1);
+ printf("\n");
+
+ printf("test3: ");
+ retval = create_test_list(test3, &bb3);
+ if (retval == 0)
+ print_list(bb3, 1);
+ printf("\n");
+
+ printf("test4: ");
+ retval = create_test_list(test4, &bb4);
+ if (retval == 0) {
+ print_list(bb4, 0);
+ printf("\n");
+ validate_test_seq(bb4, test4a);
+ }
+ printf("\n");
+
+ if (bb1 && bb2 && bb3 && bb4) {
+ printf("Comparison tests:\n");
+ equal = ext2fs_badblocks_equal(bb1, bb2);
+ printf("bb1 and bb2 are %sequal.\n", equal ? "" : "NOT ");
+ if (equal)
+ test_fail++;
+
+ equal = ext2fs_badblocks_equal(bb1, bb3);
+ printf("bb1 and bb3 are %sequal.\n", equal ? "" : "NOT ");
+ if (!equal)
+ test_fail++;
+
+ equal = ext2fs_badblocks_equal(bb1, bb4);
+ printf("bb1 and bb4 are %sequal.\n", equal ? "" : "NOT ");
+ if (equal)
+ test_fail++;
+ printf("\n");
+ }
+
+ if (test_fail == 0)
+ printf("ext2fs library badblocks tests checks out OK!\n");
+
+ file_test(bb4);
+
+ if (bb1)
+ ext2fs_badblocks_list_free(bb1);
+ if (bb2)
+ ext2fs_badblocks_list_free(bb2);
+ if (bb3)
+ ext2fs_badblocks_list_free(bb3);
+ if (bb4)
+ ext2fs_badblocks_list_free(bb4);
+
+ return test_fail;
+
+}
diff --git a/e2fslib/tst_bitops.c b/e2fslib/tst_bitops.c
new file mode 100644
index 0000000..fb4d3ad
--- /dev/null
+++ b/e2fslib/tst_bitops.c
@@ -0,0 +1,44 @@
+/*
+ * This testing program makes sure the bitops functions work
+ *
+ * Copyright (C) 2001 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/* #define _EXT2_USE_C_VERSIONS_ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+unsigned char bitarray[] = {
+ 0x80, 0xF0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x10, 0x20, 0x00, 0x00
+ };
+
+main(int argc, char **argv)
+{
+ int i, size;
+
+ size = sizeof(bitarray)*8;
+ i = ext2fs_find_first_bit_set(bitarray, size);
+ while (i < size) {
+ printf("Bit set: %d\n", i);
+ i = ext2fs_find_next_bit_set(bitarray, size, i+1);
+ }
+}
diff --git a/e2fslib/tst_byteswap.c b/e2fslib/tst_byteswap.c
new file mode 100644
index 0000000..e747c1e
--- /dev/null
+++ b/e2fslib/tst_byteswap.c
@@ -0,0 +1,92 @@
+/*
+ * This testing program makes sure the byteswap functions work
+ *
+ * Copyright (C) 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+__u16 test1[] = {
+ 0x0001, 0x0100,
+ 0x1234, 0x3412,
+ 0xff00, 0x00ff,
+ 0x4000, 0x0040,
+ 0xfeff, 0xfffe,
+ 0x0000, 0x0000
+ };
+
+__u32 test2[] = {
+ 0x00000001, 0x01000000,
+ 0x80000000, 0x00000080,
+ 0x12345678, 0x78563412,
+ 0xffff0000, 0x0000ffff,
+ 0x00ff0000, 0x0000ff00,
+ 0xff000000, 0x000000ff,
+ 0x00000000, 0x00000000
+ };
+
+int main(int argc, char *argv)
+{
+ int i;
+ int errors = 0;
+
+ printf("Testing ext2fs_swab16\n");
+ i=0;
+ do {
+ printf("swab16(0x%04x) = 0x%04x\n", test1[i],
+ ext2fs_swab16(test1[i]));
+ if (ext2fs_swab16(test1[i]) != test1[i+1]) {
+ printf("Error!!! %04x != %04x\n",
+ ext2fs_swab16(test1[i]), test1[i+1]);
+ errors++;
+ }
+ if (ext2fs_swab16(test1[i+1]) != test1[i]) {
+ printf("Error!!! %04x != %04x\n",
+ ext2fs_swab16(test1[i+1]), test1[i]);
+ errors++;
+ }
+ i += 2;
+ } while (test1[i] != 0);
+
+ printf("Testing ext2fs_swab32\n");
+ i = 0;
+ do {
+ printf("swab32(0x%08x) = 0x%08x\n", test2[i],
+ ext2fs_swab32(test2[i]));
+ if (ext2fs_swab32(test2[i]) != test2[i+1]) {
+ printf("Error!!! %04x != %04x\n",
+ ext2fs_swab32(test2[i]), test2[i+1]);
+ errors++;
+ }
+ if (ext2fs_swab32(test2[i+1]) != test2[i]) {
+ printf("Error!!! %04x != %04x\n",
+ ext2fs_swab32(test2[i+1]), test2[i]);
+ errors++;
+ }
+ i += 2;
+ } while (test2[i] != 0);
+
+ if (!errors)
+ printf("No errors found in the byteswap implementation!\n");
+
+ return errors;
+}
diff --git a/e2fslib/tst_getsize.c b/e2fslib/tst_getsize.c
new file mode 100644
index 0000000..08bb8ed
--- /dev/null
+++ b/e2fslib/tst_getsize.c
@@ -0,0 +1,44 @@
+/*
+ * tst_getsize.c --- this function tests the getsize function
+ *
+ * Copyright (C) 1997 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+int main(int argc, const char *argv[])
+{
+ errcode_t retval;
+ blk_t blocks;
+
+ if (argc < 2) {
+ fprintf(stderr, "%s device\n", argv[0]);
+ exit(1);
+ }
+ retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
+ if (retval) {
+ com_err(argv[0], retval, "while getting device size");
+ exit(1);
+ }
+ printf("%s is device has %d blocks.\n", argv[1], blocks);
+ return 0;
+}
diff --git a/e2fslib/tst_iscan.c b/e2fslib/tst_iscan.c
new file mode 100644
index 0000000..2cf4336
--- /dev/null
+++ b/e2fslib/tst_iscan.c
@@ -0,0 +1,218 @@
+/*
+ * tst_inode.c --- this function tests the inode scan function
+ *
+ * Copyright (C) 1996 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+blk_t test_vec[] = { 8, 12, 24, 34, 43, 44, 100, 0 };
+
+ext2_filsys test_fs;
+ext2fs_block_bitmap bad_block_map, touched_map;
+ext2fs_inode_bitmap bad_inode_map;
+badblocks_list test_badblocks;
+
+int first_no_comma = 1;
+int failed = 0;
+
+static void test_read_blk(unsigned long block, int count, errcode_t err)
+{
+ int i;
+
+ if (first_no_comma)
+ first_no_comma = 0;
+ else
+ printf(", ");
+
+ if (count > 1)
+ printf("%lu-%lu", block, block+count-1);
+ else
+ printf("%lu", block);
+
+ for (i=0; i < count; i++, block++) {
+ if (ext2fs_test_block_bitmap(touched_map, block)) {
+ printf("\nDuplicate block?!? --- %lu\n", block);
+ failed++;
+ first_no_comma = 1;
+ }
+ ext2fs_mark_block_bitmap(touched_map, block);
+ }
+}
+
+/*
+ * Setup the variables for doing the inode scan test.
+ */
+static void setup(void)
+{
+ errcode_t retval;
+ int i;
+ struct ext2_super_block param;
+
+ initialize_ext2_error_table();
+
+ memset(&param, 0, sizeof(param));
+ param.s_blocks_count = 12000;
+
+
+ test_io_cb_read_blk = test_read_blk;
+
+ retval = ext2fs_initialize("test fs", 0, &param,
+ test_io_manager, &test_fs);
+ if (retval) {
+ com_err("setup", retval,
+ "While initializing filesystem");
+ exit(1);
+ }
+ retval = ext2fs_allocate_tables(test_fs);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating tables for test filesystem");
+ exit(1);
+ }
+ retval = ext2fs_allocate_block_bitmap(test_fs, "bad block map",
+ &bad_block_map);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating bad_block bitmap");
+ exit(1);
+ }
+ retval = ext2fs_allocate_block_bitmap(test_fs, "touched map",
+ &touched_map);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating touched block bitmap");
+ exit(1);
+ }
+ retval = ext2fs_allocate_inode_bitmap(test_fs, "bad inode map",
+ &bad_inode_map);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating bad inode bitmap");
+ exit(1);
+ }
+
+ retval = ext2fs_badblocks_list_create(&test_badblocks, 5);
+ if (retval) {
+ com_err("setup", retval, "while creating badblocks list");
+ exit(1);
+ }
+ for (i=0; test_vec[i]; i++) {
+ retval = ext2fs_badblocks_list_add(test_badblocks, test_vec[i]);
+ if (retval) {
+ com_err("setup", retval,
+ "while adding test vector %d", i);
+ exit(1);
+ }
+ ext2fs_mark_block_bitmap(bad_block_map, test_vec[i]);
+ }
+ test_fs->badblocks = test_badblocks;
+}
+
+/*
+ * Iterate using inode_scan
+ */
+static void iterate(void)
+{
+ struct ext2_inode inode;
+ ext2_inode_scan scan;
+ errcode_t retval;
+ ext2_ino_t ino;
+
+ retval = ext2fs_open_inode_scan(test_fs, 8, &scan);
+ if (retval) {
+ com_err("iterate", retval, "While opening inode scan");
+ exit(1);
+ }
+ printf("Reading blocks: ");
+ retval = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (retval) {
+ com_err("iterate", retval, "while reading first inode");
+ exit(1);
+ }
+ while (ino) {
+ retval = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
+ ext2fs_mark_inode_bitmap(bad_inode_map, ino);
+ continue;
+ }
+ if (retval) {
+ com_err("iterate", retval,
+ "while getting next inode");
+ exit(1);
+ }
+ }
+ printf("\n");
+ ext2fs_close_inode_scan(scan);
+}
+
+/*
+ * Verify the touched map
+ */
+static void check_map(void)
+{
+ int i, j, first=1;
+ unsigned long blk;
+
+ for (i=0; test_vec[i]; i++) {
+ if (ext2fs_test_block_bitmap(touched_map, test_vec[i])) {
+ printf("Bad block was touched --- %d\n", test_vec[i]);
+ failed++;
+ first_no_comma = 1;
+ }
+ ext2fs_mark_block_bitmap(touched_map, test_vec[i]);
+ }
+ for (i = 0; i < test_fs->group_desc_count; i++) {
+ for (j=0, blk = test_fs->group_desc[i].bg_inode_table;
+ j < test_fs->inode_blocks_per_group;
+ j++, blk++) {
+ if (!ext2fs_test_block_bitmap(touched_map, blk) &&
+ !ext2fs_test_block_bitmap(bad_block_map, blk)) {
+ printf("Missing block --- %lu\n", blk);
+ failed++;
+ }
+ }
+ }
+ printf("Bad inodes: ");
+ for (i=1; i <= test_fs->super->s_inodes_count; i++) {
+ if (ext2fs_test_inode_bitmap(bad_inode_map, i)) {
+ if (first)
+ first = 0;
+ else
+ printf(", ");
+ printf("%d", i);
+ }
+ }
+ printf("\n");
+}
+
+
+int main(int argc, char **argv)
+{
+ setup();
+ iterate();
+ check_map();
+ if (!failed)
+ printf("Inode scan tested OK!\n");
+ return failed;
+}
+
diff --git a/e2fslib/unix_io.c b/e2fslib/unix_io.c
new file mode 100644
index 0000000..40bb6c2
--- /dev/null
+++ b/e2fslib/unix_io.c
@@ -0,0 +1,556 @@
+/*
+ * unix_io.c --- This is the Unix I/O interface to the I/O manager.
+ *
+ * Implements a one-block write-through cache.
+ *
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+ if ((struct)->magic != (code)) return (code)
+
+struct unix_cache {
+ char *buf;
+ unsigned long block;
+ int access_time;
+ int dirty:1;
+ int in_use:1;
+};
+
+#define CACHE_SIZE 8
+#define WRITE_VIA_CACHE_SIZE 4 /* Must be smaller than CACHE_SIZE */
+
+struct unix_private_data {
+ int magic;
+ int dev;
+ int flags;
+ int access_time;
+ struct unix_cache cache[CACHE_SIZE];
+};
+
+static errcode_t unix_open(const char *name, int flags, io_channel *channel);
+static errcode_t unix_close(io_channel channel);
+static errcode_t unix_set_blksize(io_channel channel, int blksize);
+static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+ int count, void *data);
+static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+ int count, const void *data);
+static errcode_t unix_flush(io_channel channel);
+static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
+ int size, const void *data);
+
+static struct struct_io_manager struct_unix_manager = {
+ EXT2_ET_MAGIC_IO_MANAGER,
+ "Unix I/O Manager",
+ unix_open,
+ unix_close,
+ unix_set_blksize,
+ unix_read_blk,
+ unix_write_blk,
+ unix_flush,
+ unix_write_byte
+};
+
+io_manager unix_io_manager = &struct_unix_manager;
+
+/*
+ * Here are the raw I/O functions
+ */
+static errcode_t raw_read_blk(io_channel channel,
+ struct unix_private_data *data,
+ unsigned long block,
+ int count, void *buf)
+{
+ errcode_t retval;
+ size_t size;
+ ext2_loff_t location;
+ int actual = 0;
+
+ size = (count < 0) ? -count : count * channel->block_size;
+ location = (ext2_loff_t) block * channel->block_size;
+ if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
+ retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
+ goto error_out;
+ }
+ actual = read(data->dev, buf, size);
+ if (actual != size) {
+ if (actual < 0)
+ actual = 0;
+ retval = EXT2_ET_SHORT_READ;
+ goto error_out;
+ }
+ return 0;
+
+error_out:
+ memset((char *) buf+actual, 0, size-actual);
+ if (channel->read_error)
+ retval = (channel->read_error)(channel, block, count, buf,
+ size, actual, retval);
+ return retval;
+}
+
+static errcode_t raw_write_blk(io_channel channel,
+ struct unix_private_data *data,
+ unsigned long block,
+ int count, const void *buf)
+{
+ size_t size;
+ ext2_loff_t location;
+ int actual = 0;
+ errcode_t retval;
+
+ if (count == 1)
+ size = channel->block_size;
+ else {
+ if (count < 0)
+ size = -count;
+ else
+ size = count * channel->block_size;
+ }
+
+ location = (ext2_loff_t) block * channel->block_size;
+ if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
+ retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
+ goto error_out;
+ }
+
+ actual = write(data->dev, buf, size);
+ if (actual != size) {
+ retval = EXT2_ET_SHORT_WRITE;
+ goto error_out;
+ }
+ return 0;
+
+error_out:
+ if (channel->write_error)
+ retval = (channel->write_error)(channel, block, count, buf,
+ size, actual, retval);
+ return retval;
+}
+
+
+/*
+ * Here we implement the cache functions
+ */
+
+/* Allocate the cache buffers */
+static errcode_t alloc_cache(io_channel channel,
+ struct unix_private_data *data)
+{
+ errcode_t retval;
+ struct unix_cache *cache;
+ int i;
+
+ data->access_time = 0;
+ for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+ cache->block = 0;
+ cache->access_time = 0;
+ cache->dirty = 0;
+ cache->in_use = 0;
+ if ((retval = ext2fs_get_mem(channel->block_size,
+ (void **) &cache->buf)))
+ return retval;
+ }
+ return 0;
+}
+
+/* Free the cache buffers */
+static void free_cache(io_channel channel,
+ struct unix_private_data *data)
+{
+ struct unix_cache *cache;
+ int i;
+
+ data->access_time = 0;
+ for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+ cache->block = 0;
+ cache->access_time = 0;
+ cache->dirty = 0;
+ cache->in_use = 0;
+ if (cache->buf)
+ ext2fs_free_mem((void **) &cache->buf);
+ cache->buf = 0;
+ }
+}
+
+/*
+ * Try to find a block in the cache. If get_cache is non-zero, then
+ * if the block isn't in the cache, evict the oldest block in the
+ * cache and create a new cache entry for the requested block.
+ */
+static struct unix_cache *find_cached_block(io_channel channel,
+ struct unix_private_data *data,
+ unsigned long block,
+ int get_cache)
+{
+ struct unix_cache *cache, *unused_cache, *oldest_cache;
+ int i;
+
+ unused_cache = oldest_cache = 0;
+ for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+ if (!cache->in_use) {
+ unused_cache = cache;
+ continue;
+ }
+ if (cache->block == block) {
+ cache->access_time = ++data->access_time;
+ return cache;
+ }
+ if (!oldest_cache ||
+ (cache->access_time < oldest_cache->access_time))
+ oldest_cache = cache;
+ }
+ if (!get_cache)
+ return 0;
+
+ /*
+ * Try to allocate cache slot.
+ */
+ if (unused_cache)
+ cache = unused_cache;
+ else {
+ cache = oldest_cache;
+ if (cache->dirty)
+ raw_write_blk(channel, data,
+ cache->block, 1, cache->buf);
+ }
+ cache->in_use = 1;
+ cache->block = block;
+ cache->access_time = ++data->access_time;
+ return cache;
+}
+
+/*
+ * Flush all of the blocks in the cache
+ */
+static errcode_t flush_cached_blocks(io_channel channel,
+ struct unix_private_data *data,
+ int invalidate)
+
+{
+ struct unix_cache *cache;
+ errcode_t retval, retval2;
+ int i;
+
+ retval2 = 0;
+ for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+ if (!cache->in_use)
+ continue;
+
+ if (invalidate)
+ cache->in_use = 0;
+
+ if (!cache->dirty)
+ continue;
+
+ retval = raw_write_blk(channel, data,
+ cache->block, 1, cache->buf);
+ if (retval)
+ retval2 = retval;
+ else
+ cache->dirty = 0;
+ }
+ return retval2;
+}
+
+
+
+static errcode_t unix_open(const char *name, int flags, io_channel *channel)
+{
+ io_channel io = NULL;
+ struct unix_private_data *data = NULL;
+ errcode_t retval;
+ int open_flags;
+
+ if (name == 0)
+ return EXT2_ET_BAD_DEVICE_NAME;
+ retval = ext2fs_get_mem(sizeof(struct struct_io_channel),
+ (void **) &io);
+ if (retval)
+ return retval;
+ memset(io, 0, sizeof(struct struct_io_channel));
+ io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ retval = ext2fs_get_mem(sizeof(struct unix_private_data),
+ (void **) &data);
+ if (retval)
+ goto cleanup;
+
+ io->manager = unix_io_manager;
+ retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name);
+ if (retval)
+ goto cleanup;
+
+ strcpy(io->name, name);
+ io->private_data = data;
+ io->block_size = 1024;
+ io->read_error = 0;
+ io->write_error = 0;
+ io->refcount = 1;
+
+ memset(data, 0, sizeof(struct unix_private_data));
+ data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
+
+ if ((retval = alloc_cache(io, data)))
+ goto cleanup;
+
+ open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
+#ifdef HAVE_OPEN64
+ data->dev = open64(name, open_flags);
+#else
+ data->dev = open(name, open_flags);
+#endif
+ if (data->dev < 0) {
+ retval = errno;
+ goto cleanup;
+ }
+ *channel = io;
+ return 0;
+
+cleanup:
+ if (data) {
+ free_cache(io, data);
+ ext2fs_free_mem((void **) &data);
+ }
+ if (io)
+ ext2fs_free_mem((void **) &io);
+ return retval;
+}
+
+static errcode_t unix_close(io_channel channel)
+{
+ struct unix_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ if (--channel->refcount > 0)
+ return 0;
+
+ retval = flush_cached_blocks(channel, data, 0);
+
+ if (close(data->dev) < 0)
+ retval = errno;
+ free_cache(channel, data);
+ if (channel->private_data)
+ ext2fs_free_mem((void **) &channel->private_data);
+ if (channel->name)
+ ext2fs_free_mem((void **) &channel->name);
+ ext2fs_free_mem((void **) &channel);
+ return retval;
+}
+
+static errcode_t unix_set_blksize(io_channel channel, int blksize)
+{
+ struct unix_private_data *data;
+ errcode_t retval;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ if (channel->block_size != blksize) {
+ if ((retval = flush_cached_blocks(channel, data, 0)))
+ return retval;
+
+ channel->block_size = blksize;
+ free_cache(channel, data);
+ if ((retval = alloc_cache(channel, data)))
+ return retval;
+ }
+ return 0;
+}
+
+
+static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ struct unix_private_data *data;
+ struct unix_cache *cache;
+ errcode_t retval;
+ char *cp;
+ int i, j;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ /*
+ * If we're doing an odd-sized read, flush out the cache and
+ * then do a direct read.
+ */
+ if (count < 0) {
+ if ((retval = flush_cached_blocks(channel, data, 0)))
+ return retval;
+ return raw_read_blk(channel, data, block, count, buf);
+ }
+
+ cp = buf;
+ while (count > 0) {
+ /* If it's in the cache, use it! */
+ if ((cache = find_cached_block(channel, data, block, 0))) {
+#ifdef DEBUG
+ printf("Using cached block %d\n", block);
+#endif
+ memcpy(cp, cache->buf, channel->block_size);
+ count--;
+ block++;
+ cp += channel->block_size;
+ continue;
+ }
+ /*
+ * Find the number of uncached blocks so we can do a
+ * single read request
+ */
+ for (i=1; i < count; i++)
+ if (find_cached_block(channel, data, block+i, 0))
+ break;
+#ifdef DEBUG
+ printf("Reading %d blocks starting at %d\n", i, block);
+#endif
+ if ((retval = raw_read_blk(channel, data, block, i, cp)))
+ return retval;
+
+ /* Save the results in the cache */
+ for (j=0; j < i; j++) {
+ count--;
+ cache = find_cached_block(channel, data, block++, 1);
+ if (cache)
+ memcpy(cache->buf, cp, channel->block_size);
+ cp += channel->block_size;
+ }
+ }
+ return 0;
+}
+
+static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ struct unix_private_data *data;
+ struct unix_cache *cache;
+ errcode_t retval = 0, retval2;
+ const char *cp;
+ int writethrough;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ /*
+ * If we're doing an odd-sized write or a very large write,
+ * flush out the cache completely and then do a direct write.
+ */
+ if (count < 0 || count > WRITE_VIA_CACHE_SIZE) {
+ if ((retval = flush_cached_blocks(channel, data, 1)))
+ return retval;
+ return raw_write_blk(channel, data, block, count, buf);
+ }
+
+ /*
+ * For a moderate-sized multi-block write, first force a write
+ * if we're in write-through cache mode, and then fill the
+ * cache with the blocks.
+ */
+ writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
+ if (writethrough)
+ retval = raw_write_blk(channel, data, block, count, buf);
+
+ cp = buf;
+ while (count > 0) {
+ cache = find_cached_block(channel, data, block, 1);
+ if (!cache) {
+ /*
+ * Oh shit, we couldn't get cache descriptor.
+ * Force the write directly.
+ */
+ if ((retval2 = raw_write_blk(channel, data, block,
+ 1, cp)))
+ retval = retval2;
+ } else {
+ memcpy(cache->buf, cp, channel->block_size);
+ cache->dirty = !writethrough;
+ }
+ count--;
+ block++;
+ cp += channel->block_size;
+ }
+ return retval;
+}
+
+static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
+ int size, const void *buf)
+{
+ struct unix_private_data *data;
+ errcode_t retval = 0;
+ size_t actual;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ /*
+ * Flush out the cache completely
+ */
+ if ((retval = flush_cached_blocks(channel, data, 1)))
+ return retval;
+
+ if (lseek(data->dev, offset, SEEK_SET) < 0)
+ return errno;
+
+ actual = write(data->dev, buf, size);
+ if (actual != size)
+ return EXT2_ET_SHORT_WRITE;
+
+ return 0;
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t unix_flush(io_channel channel)
+{
+ struct unix_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct unix_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+ retval = flush_cached_blocks(channel, data, 0);
+ fsync(data->dev);
+ return retval;
+}
+
diff --git a/e2fslib/unix_io.o b/e2fslib/unix_io.o
new file mode 100644
index 0000000..beb3b61
--- /dev/null
+++ b/e2fslib/unix_io.o
Binary files differ
diff --git a/e2fslib/unlink.c b/e2fslib/unlink.c
new file mode 100644
index 0000000..03825c4
--- /dev/null
+++ b/e2fslib/unlink.c
@@ -0,0 +1,80 @@
+/*
+ * unlink.c --- delete links in a ext2fs directory
+ *
+ * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct link_struct {
+ const char *name;
+ int namelen;
+ ext2_ino_t inode;
+ int flags;
+ int done;
+};
+
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+static int unlink_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *priv_data)
+{
+ struct link_struct *ls = (struct link_struct *) priv_data;
+
+ if (ls->name && ((dirent->name_len & 0xFF) != ls->namelen))
+ return 0;
+ if (ls->name && strncmp(ls->name, dirent->name,
+ dirent->name_len & 0xFF))
+ return 0;
+ if (ls->inode && (dirent->inode != ls->inode))
+ return 0;
+
+ dirent->inode = 0;
+ ls->done++;
+ return DIRENT_ABORT|DIRENT_CHANGED;
+}
+
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
+ const char *name, ext2_ino_t ino,
+ int flags)
+{
+ errcode_t retval;
+ struct link_struct ls;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ ls.name = name;
+ ls.namelen = name ? strlen(name) : 0;
+ ls.inode = ino;
+ ls.flags = 0;
+ ls.done = 0;
+
+ retval = ext2fs_dir_iterate(fs, dir, 0, 0, unlink_proc, &ls);
+ if (retval)
+ return retval;
+
+ return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
+}
+
diff --git a/e2fslib/unlink.o b/e2fslib/unlink.o
new file mode 100644
index 0000000..f5bc490
--- /dev/null
+++ b/e2fslib/unlink.o
Binary files differ
diff --git a/e2fslib/util/.cvsignore b/e2fslib/util/.cvsignore
new file mode 100644
index 0000000..6073b06
--- /dev/null
+++ b/e2fslib/util/.cvsignore
@@ -0,0 +1 @@
+subst
diff --git a/e2fslib/util/ChangeLog b/e2fslib/util/ChangeLog
new file mode 100644
index 0000000..e3ad187
--- /dev/null
+++ b/e2fslib/util/ChangeLog
@@ -0,0 +1,132 @@
+2001-09-20 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.25
+
+2001-09-02 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.24a
+
+2001-08-30 Theodore Tso <tytso@thunk.org>
+
+ * Release of E2fsprogs 1.24
+
+2001-08-15 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.23
+
+2001-07-27 Theodore Tso <tytso@valinux.com>
+
+ * subst.conf.in: Enable documentation of the external journal
+ functionality in mke2fs, e2fsck, and tune2fs.
+
+2001-06-23 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.22
+
+2001-06-15 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.21
+
+2001-05-25 Theodore Tso <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.20
+
+2001-04-21 Theodore Tso <tytso@valinux.com>
+
+ * subst.conf.in: Add definition of JDEV for mke2fs' and tune2fs'
+ man page.
+
+2001-04-17 Theodore Tso <tytso@valinux.com>
+
+ * subst.c (replace_string): Fix replace_string so that it
+ correctly handles replacing a substitution variable with a
+ zero-length string.
+
+2001-01-14 Theodore Ts'o <tytso@valinux.com>
+
+ * gcc-wall-cleanup: Remove additional annoying warning messages
+ emited by gcc 2.95.2.
+
+2001-01-11 <tytso@snap.thunk.org>
+
+ * gcc-wall-cleanup: New file which is used to clean up unnecessary
+ crud from gcc -Wall that we're not interested in seeing
+
+2000-07-13 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.19
+
+2000-04-03 Theodore Ts'o <tytso@valinux.com>
+
+ * subst.c: For platforms that don't define optarg.h, manually
+ define optarg and optind.
+
+1999-11-19 <tytso@valinux.com>
+
+ * Makefile.in (distclean): Remove TAGS and Makefile.in.old from
+ the source directory.
+
+1999-11-10 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.18
+
+1999-10-26 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.17
+
+1999-10-26 <tytso@valinux.com>
+
+ * subst.c (substitute_line): Removed some unused variables.
+
+1999-10-22 <tytso@valinux.com>
+
+ * Release of E2fsprogs 1.16
+
+1999-07-18 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.15
+
+1999-07-03 <tytso@valinux.com>
+
+ * Makefile.in (subst): Build subst using $(BUILD_CC), since it's a
+ helper program which must be built using the native C
+ compiler during a cross-compilation.
+
+1999-01-09 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.14
+
+1998-12-15 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.13
+
+1998-12-15 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * subst.c (get_subst_symbol): Add [0-9] to the list of valid
+ characters for a substitution symbol.
+
+1998-08-01 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * subst.c: Add the ability to substitute apparent shell/make
+ variables such as ${prefix}, since this is needed to make
+ the shell scripts work correctly.
+
+ * subst.conf.in: Add ${prefix} to the list of substitutions which
+ subst should make.
+
+1998-07-09 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs 1.12
+
+1998-03-31 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * subst.conf.in: Add substitution for @datadir@
+
+Mon Jan 19 09:25:24 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * subst.c: Rename "new" to "new_f" to avoid C++ reserved word
+ clash.
+
+ * subst.c: Explicitly cast all assignments from void * to be
+ compatible with C++.
+
diff --git a/e2fslib/util/Makefile b/e2fslib/util/Makefile
new file mode 100644
index 0000000..2ae1be5
--- /dev/null
+++ b/e2fslib/util/Makefile
@@ -0,0 +1,231 @@
+# Generated automatically from Makefile.in by configure.
+#
+# Standard e2fsprogs prologue....
+#
+
+srcdir = .
+top_srcdir = ..
+top_builddir = ..
+my_dir = util
+INSTALL = /usr/bin/install -c
+
+SRCS = $(srcdir)/subst.c
+
+
+# Beginning of file MCONFIG
+
+all::
+
+check::
+
+SHELL = /bin/sh
+
+prefix = /usr
+root_prefix =
+exec_prefix = ${prefix}
+root_bindir = $(root_prefix)/bin
+root_sbindir = $(root_prefix)/sbin
+root_libdir = $(root_prefix)/lib
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+mandir = ${prefix}/man
+man1dir = $(mandir)/man1
+man3dir = $(mandir)/man3
+man8dir = $(mandir)/man8
+infodir = ${prefix}/info
+datadir = ${prefix}/share
+
+
+
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+CC = cc
+BUILD_CC = cc
+DEFS = -DENABLE_SWAPFS=1 -DPACKAGE=\"e2fsprogs\" -DVERSION=\"1.25\" -DSTDC_HEADERS=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DHAVE_ARGZ_H=1 -DHAVE_LIMITS_H=1 -DHAVE_LOCALE_H=1 -DHAVE_NL_TYPES_H=1 -DHAVE_MALLOC_H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_GETCWD=1 -DHAVE_MUNMAP=1 -DHAVE_PUTENV=1 -DHAVE_SETENV=1 -DHAVE_SETLOCALE=1 -DHAVE_STRCHR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRDUP=1 -DHAVE___ARGZ_COUNT=1 -DHAVE___ARGZ_STRINGIFY=1 -DHAVE___ARGZ_NEXT=1 -DHAVE_STPCPY=1 -DHAVE_STPCPY=1 -DHAVE_LC_MESSAGES=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1 -DHAVE_ERRNO_H=1 -DHAVE_MALLOC_H=1 -DHAVE_MNTENT_H=1 -DHAVE_PATHS_H=1 -DHAVE_DIRENT_H=1 -DHAVE_GETOPT_H=1 -DHAVE_SETJMP_H=1 -DHAVE_SIGNAL_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_LINUX_FD_H=1 -DHAVE_LINUX_MAJOR_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_MOUNT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_NET_IF_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_VPRINTF=1 -DHAVE_LSEEK64_PROTOTYPE=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DWORDS_BIGENDIAN=1 -DHAVE_GETRUSAGE=1 -DHAVE_LLSEEK=1 -DHAVE_LSEEK64=1 -DHAVE_OPEN64=1 -DHAVE_STRCASECMP=1 -DHAVE_SRANDOM=1 -DHAVE_FCHOWN=1 -DHAVE_MALLINFO=1 -DHAVE_FDATASYNC=1 -DHAVE_STRNLEN=1 -DHAVE_EXT2_IOCTLS=1
+CFLAGS = -g -O2
+CPPFLAGS =
+ALL_CFLAGS = $(CPPFLAGS) $(DEFS) $(USE_WFLAGS) $(CFLAGS) $(XTRA_CFLAGS) \
+ -I$(top_builddir)/lib -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/include $(LINUX_INCLUDE)
+LDFLAGS =
+ALL_LDFLAGS = $(LDFLAGS)
+RM = /bin/rm
+LN = /bin/ln
+LN_S = ln -s
+MV = /bin/mv
+CP = /bin/cp
+CHMOD = /bin/chmod
+AR = ar
+AWK = /usr/bin/awk
+SED = /bin/sed
+PERL = /usr/bin/perl
+RANLIB = ranlib
+STRIP = strip
+LD = $(PURE) cc
+ARUPD = $(AR) r
+LDCONFIG = :
+
+#
+# Library definitions
+#
+LIB = $(top_builddir)/lib
+LIBSS = $(LIB)/libss.a
+LIBCOM_ERR = $(LIB)/libcom_err.a
+LIBE2P = $(LIB)/libe2p.a
+LIBEXT2FS = $(LIB)/libext2fs.a
+LIBUUID = $(LIB)/libuuid.a
+DEPLIBUUID = $(LIB)/libuuid.a
+
+STATIC_LIBSS = $(LIB)/libss.a
+STATIC_LIBCOM_ERR = $(LIB)/libcom_err.a
+STATIC_LIBE2P = $(LIB)/libe2p.a
+STATIC_LIBEXT2FS = $(LIB)/libext2fs.a
+STATIC_LIBUUID = $(LIB)/libuuid.a
+DEPSTATIC_LIBUUID = $(LIB)/libuuid.a
+
+PROFILED_LIBSS = $(LIB)/libss
+PROFILED_LIBCOM_ERR = $(LIB)/libcom_err
+PROFILED_LIBE2P = $(LIB)/libe2p
+PROFILED_LIBEXT2FS = $(LIB)/libext2fs
+PROFILED_LIBUUID = $(LIB)/libuuid
+DEPPROFILED_LIBUUID = $(LIB)/libuuid
+
+#
+# Use these definitions is you use tools 2.x, x < 16
+#
+#DLL_BIN=/usr/dll/bin
+#JUMP_PREFIX=/usr/dll/jump/
+
+#
+# Use these definitions if you use tools 2.16 or above
+#
+DLL_BIN=/usr/bin
+JUMP_PREFIX=/usr/bin/jump
+
+# An include directive pointing to a directory holding enough linux-like
+# include files to satisfy some programs here
+LINUX_INCLUDE=
+
+#
+# A fast substitution command for fixing up man pages, shell scripts, etc.
+#
+SUBST_CONF=$(top_builddir)/util/subst.conf
+SUBSTITUTE= $(top_builddir)/util/subst -f $(SUBST_CONF)
+DEP_SUBSTITUTE= $(top_builddir)/util/subst $(SUBST_CONF)
+
+$(top_builddir)/util/subst:
+ cd $(top_builddir)/util ; $(MAKE) subst
+
+#
+# Warning flags
+#
+# Run make gcc-wall to do a build with warning messages.
+#
+#
+WFLAGS= -ansi -D_POSIX_SOURCE -pedantic \
+ -Wall -Wwrite-strings -Wpointer-arith \
+ -Wcast-qual -Wcast-align -Wtraditional \
+ -Wstrict-prototypes -Wmissing-prototypes \
+ -Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow
+
+gcc-wall-new:
+ (make USE_WFLAGS="$(WFLAGS)" > /dev/null) 2>&1 | sed -f $(top_srcdir)/util/gcc-wall-cleanup
+
+gcc-wall:
+ make clean > /dev/null
+ make gcc-wall-new
+
+#
+# Installation user and groups
+#
+BINGRP= bin
+BINOWN= bin
+BINMODE= 555
+INCGRP= bin
+INCOWN= bin
+INCMODE= 444
+LIBOWN= bin
+LIBGRP= bin
+LIBMODE= 444
+MANGRP= bin
+MANOWN= bin
+MANMODE= 444
+
+#
+# Autoconf magic...
+#
+
+DEP_LIB_MAKEFILES = $(top_srcdir)/lib/Makefile.elf-lib \
+ $(top_srcdir)/lib/Makefile.dll-lib $(top_srcdir)/lib/Makefile.bsd-lib \
+ $(top_srcdir)/lib/Makefile.checker $(top_srcdir)/lib/Makefile.profile
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir); ./config.status --recheck
+
+$(top_builddir)/lib/substitute_sh: $(top_srcdir)/lib/substitute_sh.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=lib/substitute_sh ./config.status
+
+$(top_builddir)/util/subst.conf: $(top_srcdir)/util/subst.conf.in \
+ $(top_builddir)/config.status
+ cd $(top_builddir); CONFIG_FILES=util/subst.conf ./config.status
+
+$(top_srcdir)/configure: $(top_srcdir)/configure.in
+ cd $(top_srcdir) && autoconf
+
+#
+# Make depend magic...
+#
+
+.depend: Makefile $(SRCS) $(top_srcdir)/depfix.sed $(top_srcdir)/wordwrap.pl
+ if test -n "$(SRCS)" ; then \
+ $(CC) -M $(ALL_CFLAGS) $(SRCS) | \
+ $(SED) -f $(top_srcdir)/depfix.sed \
+ -e 's; $(srcdir)/; $$(srcdir)/;g' \
+ -e 's; $(top_srcdir)/; $$(top_srcdir)/;g' \
+ -e 's; $(top_builddir)/; $$(top_builddir)/;g' \
+ -e 's; \./; ;g' \
+ -e '/^ *\\$$/d' | \
+ $(PERL) $(top_srcdir)/wordwrap.pl > .depend; \
+ else :; fi
+
+depend:: .depend
+ if test -n "$(SRCS)" ; then \
+ sed -e '/^# +++ Dependency line eater +++/,$$d' \
+ < $(srcdir)/Makefile.in | cat - .depend \
+ > $(srcdir)/Makefile.in.new; \
+ if cmp -s $(srcdir)/Makefile.in $(srcdir)/Makefile.in.new ; then \
+ $(RM) $(srcdir)/Makefile.in.new ; \
+ else \
+ $(MV) $(srcdir)/Makefile.in $(srcdir)/Makefile.in.old; \
+ $(MV) $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in; \
+ fi ; else :; fi
+
+# End of file MCONFIG
+
+.c.o:
+ $(BUILD_CC) -c $(ALL_CFLAGS) $< -o $@
+
+PROGS= subst
+
+all:: $(PROGS)
+
+subst: subst.o
+ $(BUILD_CC) $(ALL_LDFLAGS) -o subst subst.o
+
+clean:
+ $(RM) -f $(PROGS) \#* *.s *.o *.a *~ core
+
+mostlyclean: clean
+
+distclean: clean
+ $(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+subst.o: $(srcdir)/subst.c
diff --git a/e2fslib/util/Makefile.in b/e2fslib/util/Makefile.in
new file mode 100644
index 0000000..ed224a4
--- /dev/null
+++ b/e2fslib/util/Makefile.in
@@ -0,0 +1,39 @@
+#
+# Standard e2fsprogs prologue....
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ..
+my_dir = util
+INSTALL = @INSTALL@
+
+SRCS = $(srcdir)/subst.c
+
+@MCONFIG@
+
+.c.o:
+ $(BUILD_CC) -c $(ALL_CFLAGS) $< -o $@
+
+PROGS= subst
+
+all:: $(PROGS)
+
+subst: subst.o
+ $(BUILD_CC) $(ALL_LDFLAGS) -o subst subst.o
+
+clean:
+ $(RM) -f $(PROGS) \#* *.s *.o *.a *~ core
+
+mostlyclean: clean
+
+distclean: clean
+ $(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+subst.o: $(srcdir)/subst.c
diff --git a/e2fslib/util/gcc-wall-cleanup b/e2fslib/util/gcc-wall-cleanup
new file mode 100644
index 0000000..4d817b1
--- /dev/null
+++ b/e2fslib/util/gcc-wall-cleanup
@@ -0,0 +1,17 @@
+#!/bin/sed -f
+#
+# This script filters out gcc-wall crud that we're not interested in seeing.
+#
+/^cc /d
+/^kcc /d
+/^gcc /d
+/does not support `long long'/d
+/does not support the `ll' length modifier/d
+/ANSI C forbids long long integer constants/d
+/traditional C rejects string concatenation/d
+/integer constant is unsigned in ANSI C, signed with -traditional/d
+/At top level:/d
+/In file included from/d
+/In function `.*':/d
+/^[ ]*from/d
+
diff --git a/e2fslib/util/libecho.c b/e2fslib/util/libecho.c
new file mode 100644
index 0000000..352ce1e
--- /dev/null
+++ b/e2fslib/util/libecho.c
@@ -0,0 +1,78 @@
+/*
+ * libecho.c
+ *
+ * For each argument on the command line, echo it. Should expand
+ * DOS wildcards correctly.
+ *
+ * Syntax: libecho [-p prefix] list...
+ */
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+
+void echo_files(char *, char *);
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ char *prefix;
+
+ prefix = "";
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: libecho [-p prefix] list...\n");
+ return 1;
+ }
+
+ for (i = 1 ; i < argc ; i++)
+ if (!stricmp(argv[i], "-p"))
+ prefix = argv[++i];
+ else
+ echo_files(prefix, argv[i]);
+
+ return 0;
+}
+
+void
+echo_files(char *prefix, char *f)
+{
+ long ff;
+ struct _finddata_t fdt;
+ char *slash;
+ char filepath[256];
+
+ /*
+ * We're unix based quite a bit here. Look for normal slashes and
+ * make them reverse slashes.
+ */
+ while((slash = strrchr(f, '/')) != NULL)
+ *slash = '\\';
+
+ strcpy(filepath, f);
+
+ slash = strrchr(filepath, '\\');
+
+ if (slash) {
+ slash++;
+ *slash = 0;
+ } else {
+ filepath[0] = '\0';
+ }
+
+ ff = _findfirst(f, &fdt);
+
+ if (ff < 0) {
+ printf("%s%s\n", prefix, f);
+ return;
+ }
+
+ printf("%s%s%s\n", prefix, filepath, fdt.name);
+
+ for (;;) {
+ if (_findnext(ff, &fdt) < 0)
+ break;
+ printf("%s%s%s\n", prefix, filepath, fdt.name);
+ }
+ _findclose(ff);
+}
diff --git a/e2fslib/util/subst b/e2fslib/util/subst
new file mode 100755
index 0000000..47f1b05
--- /dev/null
+++ b/e2fslib/util/subst
Binary files differ
diff --git a/e2fslib/util/subst.c b/e2fslib/util/subst.c
new file mode 100644
index 0000000..7b7ba83
--- /dev/null
+++ b/e2fslib/util/subst.c
@@ -0,0 +1,374 @@
+/*
+ * subst.c --- substitution program
+ *
+ * Subst is used as a quicky program to do @ substitutions
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+
+
+struct subst_entry {
+ char *name;
+ char *value;
+ struct subst_entry *next;
+};
+
+struct subst_entry *subst_table = 0;
+
+static int add_subst(char *name, char *value)
+{
+ struct subst_entry *ent = 0;
+ int retval;
+
+ retval = ENOMEM;
+ ent = (struct subst_entry *) malloc(sizeof(struct subst_entry));
+ if (!ent)
+ goto fail;
+ ent->name = (char *) malloc(strlen(name)+1);
+ if (!ent->name)
+ goto fail;
+ ent->value = (char *) malloc(strlen(value)+1);
+ if (!ent->value)
+ goto fail;
+ strcpy(ent->name, name);
+ strcpy(ent->value, value);
+ ent->next = subst_table;
+ subst_table = ent;
+ return 0;
+fail:
+ if (ent) {
+ if (ent->name)
+ free(ent->name);
+ if (ent->value)
+ free(ent->value);
+ free(ent);
+ }
+ return retval;
+}
+
+static struct subst_entry *fetch_subst_entry(char *name)
+{
+ struct subst_entry *ent;
+
+ for (ent = subst_table; ent; ent = ent->next) {
+ if (strcmp(name, ent->name) == 0)
+ break;
+ }
+ return ent;
+}
+
+/*
+ * Given the starting and ending position of the replacement name,
+ * check to see if it is valid, and pull it out if it is.
+ */
+static char *get_subst_symbol(const char *begin, int len, char prefix)
+{
+ static char replace_name[128];
+ char *cp, *start;
+
+ start = replace_name;
+ if (prefix)
+ *start++ = prefix;
+
+ if (len > sizeof(replace_name)-2)
+ return NULL;
+ memcpy(start, begin, len);
+ start[len] = 0;
+
+ /*
+ * The substitution variable must all be in the of [0-9A-Za-z_].
+ * If it isn't, this must be an invalid symbol name.
+ */
+ for (cp = start; *cp; cp++) {
+ if (!(*cp >= 'a' && *cp <= 'z') &&
+ !(*cp >= 'A' && *cp <= 'Z') &&
+ !(*cp >= '0' && *cp <= '9') &&
+ !(*cp == '_'))
+ return NULL;
+ }
+ return (replace_name);
+}
+
+static void replace_string(char *begin, char *end, char *newstr)
+{
+ int replace_len, len;
+
+ replace_len = strlen(newstr);
+ len = end - begin;
+ if (replace_len == 0)
+ memmove(begin, end+1, strlen(end)+1);
+ else if (replace_len != len+1)
+ memmove(end+(replace_len-len-1), end,
+ strlen(end)+1);
+ memcpy(begin, newstr, replace_len);
+}
+
+static void substitute_line(char *line)
+{
+ char *ptr, *name_ptr, *end_ptr;
+ struct subst_entry *ent;
+ char *replace_name;
+ int len;
+
+ /*
+ * Expand all @FOO@ substitutions
+ */
+ ptr = line;
+ while (ptr) {
+ name_ptr = strchr(ptr, '@');
+ if (!name_ptr)
+ break; /* No more */
+ if (*(++name_ptr) == '@') {
+ /*
+ * Handle tytso@@mit.edu --> tytso@mit.edu
+ */
+ memmove(name_ptr-1, name_ptr, strlen(name_ptr)+1);
+ ptr = name_ptr+1;
+ continue;
+ }
+ end_ptr = strchr(name_ptr, '@');
+ if (!end_ptr)
+ break;
+ len = end_ptr - name_ptr;
+ replace_name = get_subst_symbol(name_ptr, len, 0);
+ if (!replace_name) {
+ ptr = name_ptr;
+ continue;
+ }
+ ent = fetch_subst_entry(replace_name);
+ if (!ent) {
+ fprintf(stderr, "Unfound expansion: '%s'\n",
+ replace_name);
+ ptr = end_ptr + 1;
+ continue;
+ }
+#if 0
+ fprintf(stderr, "Replace name = '%s' with '%s'\n",
+ replace_name, ent->value);
+#endif
+ ptr = name_ptr-1;
+ replace_string(ptr, end_ptr, ent->value);
+ }
+ /*
+ * Now do a second pass to expand ${FOO}
+ */
+ ptr = line;
+ while (ptr) {
+ name_ptr = strchr(ptr, '$');
+ if (!name_ptr)
+ break; /* No more */
+ if (*(++name_ptr) != '{') {
+ ptr = name_ptr;
+ continue;
+ }
+ name_ptr++;
+ end_ptr = strchr(name_ptr, '}');
+ if (!end_ptr)
+ break;
+ len = end_ptr - name_ptr;
+ replace_name = get_subst_symbol(name_ptr, len, '$');
+ if (!replace_name) {
+ ptr = name_ptr;
+ continue;
+ }
+ ent = fetch_subst_entry(replace_name);
+ if (!ent) {
+ ptr = end_ptr + 1;
+ continue;
+ }
+#if 0
+ fprintf(stderr, "Replace name = '%s' with '%s'\n",
+ replace_name, ent->value);
+#endif
+ ptr = name_ptr-2;
+ replace_string(ptr, end_ptr, ent->value);
+ }
+}
+
+static void parse_config_file(FILE *f)
+{
+ char line[2048];
+ char *cp, *ptr;
+
+ while (!feof(f)) {
+ memset(line, 0, sizeof(line));
+ if (fgets(line, sizeof(line), f) == NULL)
+ break;
+ /*
+ * Strip newlines and comments.
+ */
+ cp = strchr(line, '\n');
+ if (cp)
+ *cp = 0;
+ cp = strchr(line, '#');
+ if (cp)
+ *cp = 0;
+ /*
+ * Skip trailing and leading whitespace
+ */
+ for (cp = line + strlen(line) - 1; cp >= line; cp--) {
+ if (*cp == ' ' || *cp == '\t')
+ *cp = 0;
+ else
+ break;
+ }
+ cp = line;
+ while (*cp && isspace(*cp))
+ cp++;
+ ptr = cp;
+ /*
+ * Skip empty lines
+ */
+ if (*ptr == 0)
+ continue;
+ /*
+ * Ignore future extensions
+ */
+ if (*ptr == '@')
+ continue;
+ /*
+ * Parse substitutions
+ */
+ for (cp = ptr; *cp; cp++)
+ if (isspace(*cp))
+ break;
+ *cp = 0;
+ for (cp++; *cp; cp++)
+ if (!isspace(*cp))
+ break;
+#if 0
+ printf("Substitute: '%s' for '%s'\n", ptr, cp ? cp : "<NULL>");
+#endif
+ add_subst(ptr, cp);
+ }
+}
+
+/*
+ * Return 0 if the files are different, 1 if the files are the same.
+ */
+static int compare_file(const char *outfn, const char *newfn)
+{
+ FILE *old_f, *new_f;
+ char oldbuf[2048], newbuf[2048], *oldcp, *newcp;
+ int retval;
+
+ old_f = fopen(outfn, "r");
+ if (!old_f)
+ return 0;
+ new_f = fopen(newfn, "r");
+ if (!new_f)
+ return 0;
+
+ while (1) {
+ oldcp = fgets(oldbuf, sizeof(oldbuf), old_f);
+ newcp = fgets(newbuf, sizeof(newbuf), new_f);
+ if (!oldcp && !newcp) {
+ retval = 1;
+ break;
+ }
+ if (!oldcp || !newcp || strcmp(oldbuf, newbuf)) {
+ retval = 0;
+ break;
+ }
+ }
+ fclose(old_f);
+ fclose(new_f);
+ return retval;
+}
+
+
+
+
+int main(int argc, char **argv)
+{
+ char line[2048];
+ int c;
+ FILE *in, *out;
+ char *outfn = NULL, *newfn = NULL;
+ int verbose = 0;
+
+ while ((c = getopt (argc, argv, "f:v")) != EOF) {
+ switch (c) {
+ case 'f':
+ in = fopen(optarg, "r");
+ if (!in) {
+ perror(optarg);
+ exit(1);
+ }
+ parse_config_file(in);
+ fclose(in);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ fprintf(stderr, "%s: [-f config-file] [file]\n",
+ argv[0]);
+ break;
+ }
+ }
+ if (optind < argc) {
+ in = fopen(argv[optind], "r");
+ if (!in) {
+ perror(argv[optind]);
+ exit(1);
+ }
+ optind++;
+ } else
+ in = stdin;
+
+ if (optind < argc) {
+ outfn = argv[optind];
+ newfn = (char *) malloc(strlen(outfn)+20);
+ if (!newfn) {
+ fprintf(stderr, "Memory error! Exiting.\n");
+ exit(1);
+ }
+ strcpy(newfn, outfn);
+ strcat(newfn, ".new");
+ out = fopen(newfn, "w");
+ if (!out) {
+ perror(newfn);
+ exit(1);
+ }
+ } else {
+ out = stdout;
+ outfn = 0;
+ }
+
+ while (!feof(in)) {
+ if (fgets(line, sizeof(line), in) == NULL)
+ break;
+ substitute_line(line);
+ fputs(line, out);
+ }
+ fclose(in);
+ fclose(out);
+ if (outfn) {
+ if (compare_file(outfn, newfn)) {
+ if (verbose)
+ printf("No change, keeping %s.\n", outfn);
+ unlink(newfn);
+ } else {
+ if (verbose)
+ printf("Creating or replacing %s.\n", outfn);
+ rename(newfn, outfn);
+ }
+ }
+ return (0);
+}
+
+
diff --git a/e2fslib/util/subst.conf b/e2fslib/util/subst.conf
new file mode 100644
index 0000000..eaa3811
--- /dev/null
+++ b/e2fslib/util/subst.conf
@@ -0,0 +1,16 @@
+AWK /usr/bin/awk
+SED /bin/sed
+ET_DIR et
+SS_DIR et
+E2FSPROGS_MONTH September
+E2FSPROGS_YEAR 2001
+E2FSPROGS_VERSION 1.25
+SIZEOF_LONG_LONG 8
+SIZEOF_LONG 4
+SIZEOF_INT 4
+SIZEOF_SHORT 2
+datadir ${prefix}/share
+$prefix /usr
+# Enable the documentation for the journal device mke2fs, tune2fs, and
+# e2fsck's man page
+JDEV
diff --git a/e2fslib/util/subst.conf.in b/e2fslib/util/subst.conf.in
new file mode 100644
index 0000000..23c91f7
--- /dev/null
+++ b/e2fslib/util/subst.conf.in
@@ -0,0 +1,16 @@
+AWK @AWK@
+SED @SED@
+ET_DIR @ET_DIR@
+SS_DIR @SS_DIR@
+E2FSPROGS_MONTH @E2FSPROGS_MONTH@
+E2FSPROGS_YEAR @E2FSPROGS_YEAR@
+E2FSPROGS_VERSION @E2FSPROGS_VERSION@
+SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@
+SIZEOF_LONG @SIZEOF_LONG@
+SIZEOF_INT @SIZEOF_INT@
+SIZEOF_SHORT @SIZEOF_SHORT@
+datadir @datadir@
+$prefix @prefix@
+# Enable the documentation for the journal device mke2fs, tune2fs, and
+# e2fsck's man page
+JDEV
diff --git a/e2fslib/util/subst.o b/e2fslib/util/subst.o
new file mode 100644
index 0000000..0f4f55a
--- /dev/null
+++ b/e2fslib/util/subst.o
Binary files differ
diff --git a/e2fslib/valid_blk.c b/e2fslib/valid_blk.c
new file mode 100644
index 0000000..9e50ed5
--- /dev/null
+++ b/e2fslib/valid_blk.c
@@ -0,0 +1,45 @@
+/*
+ * valid_blk.c --- does the inode have valid blocks?
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * This function returns 1 if the inode's block entries actually
+ * contain block entries.
+ */
+int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
+{
+ /*
+ * Only directories, regular files, and some symbolic links
+ * have valid block entries.
+ */
+ if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
+ !LINUX_S_ISLNK(inode->i_mode))
+ return 0;
+
+ /*
+ * If the symbolic link is a "fast symlink", then the symlink
+ * target is stored in the block entries.
+ */
+ if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0)
+ return 0;
+
+ return 1;
+}
diff --git a/e2fslib/valid_blk.o b/e2fslib/valid_blk.o
new file mode 100644
index 0000000..1ffa4d4
--- /dev/null
+++ b/e2fslib/valid_blk.o
Binary files differ
diff --git a/e2fslib/version.c b/e2fslib/version.c
new file mode 100644
index 0000000..a352d25
--- /dev/null
+++ b/e2fslib/version.c
@@ -0,0 +1,50 @@
+/*
+ * version.c --- Return the version of the ext2 library
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#include "version.h"
+
+static const char *lib_version = E2FSPROGS_VERSION;
+static const char *lib_date = E2FSPROGS_DATE;
+
+int ext2fs_parse_version_string(const char *ver_string)
+{
+ const char *cp;
+ int version = 0;
+
+ for (cp = ver_string; *cp; cp++) {
+ if (!isdigit(*cp))
+ continue;
+ version = (version * 10) + (*cp - '0');
+ }
+ return version;
+}
+
+
+int ext2fs_get_library_version(const char **ver_string,
+ const char **date_string)
+{
+ if (ver_string)
+ *ver_string = lib_version;
+ if (date_string)
+ *date_string = lib_date;
+
+ return ext2fs_parse_version_string(lib_version);
+}
diff --git a/e2fslib/version.h b/e2fslib/version.h
new file mode 100644
index 0000000..19a7bc3
--- /dev/null
+++ b/e2fslib/version.h
@@ -0,0 +1,10 @@
+/*
+ * version.h --- controls the version number printed by the e2fs
+ * programs.
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001 by Theodore
+ * Ts'o. This file may be redistributed under the GNU Public License.
+ */
+
+#define E2FSPROGS_VERSION "1.25"
+#define E2FSPROGS_DATE "20-Sep-2001"
diff --git a/e2fslib/version.o b/e2fslib/version.o
new file mode 100644
index 0000000..e47c316
--- /dev/null
+++ b/e2fslib/version.o
Binary files differ
diff --git a/e2fslib/write_bb_file.c b/e2fslib/write_bb_file.c
new file mode 100644
index 0000000..011c480
--- /dev/null
+++ b/e2fslib/write_bb_file.c
@@ -0,0 +1,34 @@
+/*
+ * write_bb_file.c --- write a list of bad blocks to a FILE *
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
+ unsigned int flags,
+ FILE *f)
+{
+ badblocks_iterate bb_iter;
+ blk_t blk;
+ errcode_t retval;
+
+ retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
+ if (retval)
+ return retval;
+
+ while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
+ fprintf(f, "%d\n", blk);
+ }
+ ext2fs_badblocks_list_iterate_end(bb_iter);
+ return 0;
+}
diff --git a/e2fslib/write_bb_file.o b/e2fslib/write_bb_file.o
new file mode 100644
index 0000000..387f6ea
--- /dev/null
+++ b/e2fslib/write_bb_file.o
Binary files differ
diff --git a/etc/arcboot.conf b/etc/arcboot.conf
new file mode 100644
index 0000000..d107463
--- /dev/null
+++ b/etc/arcboot.conf
@@ -0,0 +1,13 @@
+# arcboot.conf
+#
+# copyright 2002 Guido Guenther <agx@sigxcpu.org>
+#
+label=linux
+ image=/vmlinux
+ append="root=/dev/sda1"
+
+# backup version
+label=old
+ image=/vmlinux.old
+ append="root=/dev/sda1"
+
diff --git a/ext2load/.cvsignore b/ext2load/.cvsignore
new file mode 100644
index 0000000..3f99037
--- /dev/null
+++ b/ext2load/.cvsignore
@@ -0,0 +1,2 @@
+ext2load
+ld.script
diff --git a/ext2load/Makefile b/ext2load/Makefile
new file mode 100644
index 0000000..af19224
--- /dev/null
+++ b/ext2load/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright 1999 Silicon Graphics, Inc.
+# 2001-04 Guido Guenther <agx@sigxcpu.org>
+#
+
+SUBARCH ?= IP22
+
+COMMONDIR = ../common
+
+E2FSINCLUDEDIR ?= /usr/include/ext2fs
+E2FSLIBDIR ?= /usr/lib
+EXT2LIB ?= $(E2FSLIBDIR)/libext2fs-nopic.a
+
+ARCINCLUDEDIR = ../arclib
+ARCLIBDIR = ../arclib
+ARCLIB = $(ARCLIBDIR)/libarc.a
+
+OBJECTS = loader.o ext2io.o conffile.o
+LIBS = $(EXT2LIB) $(ARCLIB)
+TARGETS = ext2load
+
+CFLAGS = -O2 -I$(COMMONDIR) -I$(ARCINCLUDEDIR) -I$(E2FSINCLUDEDIR) \
+ -W -Wall -mno-abicalls -G 0 -fno-pic \
+ -DSUBARCH=${SUBARCH}
+
+# uncomment for debugging
+#CFLAGS+=-DDEBUG
+
+LD = ld
+LDFLAGS = -N -T ld.script
+
+all: $(TARGETS)
+
+ext2load: $(OBJECTS) $(LIBS) ld.script ../common/subarch.h
+ rm -f $@
+ $(LD) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)
+
+ld.script: ld.script.in
+ $(MAKE) -C ../common SUBARCH=$(SUBARCH) print_loadaddr
+ LOADADDR=$$(../common/print_loadaddr $(SUBARCH)); \
+ OUTPUTFORMAT=$$(../common/print_outputformat $(SUBARCH)); \
+ sed -e "s/@@LOADADDR@@/$$LOADADDR/" \
+ -e "s/@@OUTPUTFORMAT@@/$$OUTPUTFORMAT/" <$< >$@
+
+install:
+
+clean:
+ rm -f $(TARGETS) *.a *.o tags ld.script
diff --git a/ext2load/arcboot.h b/ext2load/arcboot.h
new file mode 100644
index 0000000..e65dc8c
--- /dev/null
+++ b/ext2load/arcboot.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2001-03 Guido Guenther <agx@sigxcpu.org>
+ */
+
+#ifndef _ARCBOOT_H
+#define _ARCBOOT_H
+
+#include <version.h>
+
+/* loader.c */
+extern CHAR *OSLoadPartition;
+extern CHAR *OSLoadFilename;
+extern CHAR *OSLoadOptions;
+
+typedef enum { False = 0, True } Boolean;
+
+Boolean OpenFile(const char *partition, const char *filename, ext2_file_t* file);
+void Fatal(const CHAR * message, ...);
+
+/* conffile.c */
+CHAR** ReadConfFile(char **partition, const char *filename, char* config);
+
+/* ext2io.c */
+extern int arc_do_progress;
+void print_ext2fs_error(long status);
+#endif /* _ARCBOOT_H */
diff --git a/ext2load/conffile.c b/ext2load/conffile.c
new file mode 100644
index 0000000..518ccf1
--- /dev/null
+++ b/ext2load/conffile.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2001-2004 Guido Guenther <agx@sigxcpu.org>
+ *
+ * load arcboots configuration file and process the arguments
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <types.h>
+
+#include <sys/types.h>
+#include <ext2_fs.h>
+#include <ext2fs.h>
+#include "arcboot.h"
+#include <arc.h>
+
+#define _PARM_LIMIT 32
+
+static char *carray[_PARM_LIMIT+3]; /* 0 is the name,
+ 1 the boofile, ...
+ X is OSLoadOptions
+ X+1 ... _PARM_LIMIT are options given on the
+ command line */
+
+CHAR** GetConfig(char* config, char* name)
+{
+ char *t, *start, *end;
+ int i;
+
+ /* Loop on lines */
+ while(*config != 0x0) {
+
+ start=config;
+
+ while(*config != 0xa && *config != 0x0) {
+ /* Delete comments */
+ if (*config == '#')
+ *config=0x0;
+ config++;
+ }
+
+ /* Did we stop at the end of a line ? */
+ if (*config == 0xa) {
+ /* Terminate Line */
+ *config=0x0;
+ config++;
+ }
+
+ /* Skip leading spaces and tabs */
+ while(*start == ' ' || *start == '\t')
+ start++;
+
+ /* If the start of a line is the end - Next line */
+ if (*start == 0x0)
+ continue;
+
+ /* get the end pointer */
+ end=&start[strlen(start)-1];
+
+ /* Delete spaces and tabs at the end of a line */
+ while(*end == ' ' || *end == '\t')
+ *end--=0x0;
+
+ if (strncmp("label=",start,6) == 0) {
+ /* If we found the right profile or want the first */
+ if (carray[0])
+ if (((strcmp(carray[0], name) == 0) && (strcmp(name, carray[0]) == 0))) {
+ return carray;
+ }
+ /* Reset image & append */
+ carray[1]=carray[2]=0;
+ carray[0]=&start[6];
+ } else if (strncmp("image=",start,6) == 0) {
+ carray[1]=&start[6];
+ } else if (strncmp("append=",start,7) == 0) {
+ t=&start[7];
+ /* Does append start with " */
+ if (*t == '"') {
+ t++;
+ /* If so - append starts +1 */
+ carray[2]=t;
+ /* Search ending quote */
+ while(*t != '"' && *t != 0x0)
+ t++;
+ /* And delete */
+ if (*t == '"')
+ *t=0x0;
+ } else
+ carray[2]=&start[7];
+ t=carray[2];
+ i=3;
+ while(i<_PARM_LIMIT && *t != 0x0) {
+ t++;
+
+ if (*t == ' ' || *t == '\t') {
+ *t++=0x0;
+ if (*t != 0x0)
+ carray[i++]=t;
+ }
+ }
+ }
+ }
+ if (carray[0])
+ if ((name == NULL) ||
+ (strcmp(carray[0], name) == 0)) {
+ return carray;
+ }
+ /* Found nothing appropriate: */
+ return NULL;
+}
+
+CHAR** ReadConfFile(char** partition, const char *filename, char* label)
+{
+ ext2_file_t file;
+ unsigned size, num_read;
+ errcode_t status;
+ char *conf_file;
+
+ if(!OpenFile( *partition, filename, &file )){
+ /* OSLoadPartition seems to be wrong, but don't give up now */
+ int npart,i;
+ char *part,*spart;
+
+ /* the user wants to boot a file directly out of the filesystem
+ * don't try to fixup OSLoadPartition for him in this case */
+ if(label[0] == '/') {
+ return False;
+ }
+ printf("Can't open configuration file. Trying other partitions\n\r");
+ spart = ArcGetEnvironmentVariable("SystemPartition");
+ if(! spart ) {
+ printf("Couldn't get SystemPartition, weird.");
+ return False;
+ }
+ part = strdup(spart);
+ npart = part[strlen(part)-2] - '0';
+ for(i = 0; i < npart; i++) {
+ part[strlen(part)-2] = '0' + i;
+#if DEBUG
+ printf("Trying %s\n\r", part);
+#endif
+ /* we found it, good */
+ if(OpenFile( part, filename, &file )) {
+ printf("Please adjust OSLoadPartition to %s\n\r", part);
+ *partition = part;
+ break;
+ }
+ }
+ if( i == npart )
+ return False;
+ }
+
+ size = ext2fs_file_get_size(file);
+ conf_file = malloc(size);
+ if( !conf_file ) {
+ printf("Can't read configuration file - not enough memory\n\r");
+ return False;
+ }
+ status = ext2fs_file_read(file,(char*) conf_file, size, &num_read);
+ if( status ) {
+ print_ext2fs_error(status);
+ return False;
+ }
+ if( size != num_read ) {
+ printf("Wanted: %u, got %u bytes of configuration file\n\r", size, num_read);
+ return False;
+ }
+ return GetConfig(conf_file, label);
+}
diff --git a/ext2load/ext2io.c b/ext2load/ext2io.c
new file mode 100644
index 0000000..ccb79b8
--- /dev/null
+++ b/ext2load/ext2io.c
@@ -0,0 +1,781 @@
+/*
+ * extio.c
+ *
+ * Copyright 1999 Silicon Graphics, Inc.
+ * 2001-2004 Guido Guenther <agx@sigxcpu.org>
+ *
+ * Derived from e2fsprogs lib/ext2fs/unix_io.c
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ */
+/* #define ARC_IO_ALLOW_WRITE */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <ext2_fs.h>
+#include <ext2fs.h>
+#include <arc.h>
+
+/*
+ * All About the Cache
+ *
+ * Without this cache, reading is horribly slow - it can take 30-60 seconds
+ * (or even more) to read a kernel. While this is a bootloader and we only
+ * do it once, that's still a very long time for the user to sit there with
+ * nothing happening (a progress indicator has also been added). The
+ * read workload looks like this: reads of the inode and indirection blocks
+ * interleaved with single-block reads of what are essentially contiguous
+ * regions of data blocks. As a concrete example, we might see:
+ *
+ * 100, 200, 100, 201, 100, 202, 100, 101, 203, 100, 101, 204, ...
+ *
+ * Therefore we could simply cache the last 4 or so blocks and get an
+ * immediate 50-67% speedup with minimal waste. However, it's possible to
+ * do better - in fact, a lot better. The ARCS calls are so expensive that
+ * it's worthwhile also to try doing readahead. Unless the filesystem is
+ * horribly fragmented, this will up our hit ratio to at least 85% or so
+ * with just 16 cache blocks (in fact if the fs is 0% fragmented, we could
+ * see 99% hits on the indirection blocks and about 92% on the data blocks,
+ * or about 96% overall! - even 80% would be adequate however).
+ *
+ * We really have two caches: a traditional LRU single-block cache, and a
+ * readahead multiblock scatter/gather cache. They are however unified to
+ * speed lookup. CACHE_SIZE is the total number of cacheable blocks, and
+ * CACHE_SG_MAX is the maximum size of a s/g request. The overall
+ * implementation is based on the one in unix_io, but has a lot of changes
+ * to accomodate readahead.
+ *
+ * Lookup is straightforward: the cache is fully associative, so we do a
+ * linear search for the requested block number (it is only possible to
+ * search for one block at a time). Alloc requests are handled differently.
+ * We start with the age of the oldest block and work newer until we have
+ * enough blocks to satisfy the sg request. These blocks have their bufs
+ * point into the per-cache arc_sg_buf and the number of successfully allocated
+ * blocks is then returned after invalidating each allocated cache block and
+ * recording the block it will reference. A later call to fill_sg_blocks
+ * will perform a single read to fill the entire cache "line."
+ *
+ * When any sg cache block is reused, the sg cached data is first copied into
+ * the per-cache buffer for all sg cache blocks, and then all buffer pointers
+ * in the sg cache blocks are reset. Note that we only do this for the
+ * cache blocks we aren't going to immediately reuse.
+ *
+ * We don't have any reliable replacement for time(2), so instead we just use
+ * a monotonically increasing counter incremented by any function that looks
+ * into the cache. We do risk overflow, but if we do 2**32 cache lookups
+ * the machine has probably failed to do anything useful anyway.
+ *
+ * Important: there are two large simplifying assumptions here:
+ * (1) The filesystem is universally read-only. There are no other processes
+ * which can write to this filesystem on this or any remote system.
+ * (2) We are single-threaded.
+ *
+ * As such, we do not have code here to handle locking, coherency, or aliases.
+ * This is fine for a bootloader but dangerous in other situations. If
+ * ARC_IO_ALLOW_WRITE is enabled (it's off by default), then on any write will
+ * the cache will act as write-through, and the entire cache will be
+ * invalidated. This is the most naive correct implementation. If writing
+ * becomes an important task, this will need to be revisited; the unix_io
+ * writeback cache is a good starting point.
+ */
+
+#define CACHE_SIZE 16
+#define CACHE_SG_MAX 12
+
+#define CACHE_IS_SG(_cache) ((_cache)->buf != (_cache)->alloc_buf)
+
+struct arc_cache {
+ char *buf;
+ char *alloc_buf;
+ unsigned long block;
+ int last_use;
+ int in_use:1;
+};
+
+static struct arc_cache *sg_cblocks[CACHE_SG_MAX];
+static unsigned long virtual_time;
+
+struct arc_private_data {
+ int magic;
+ OPENMODE mode;
+ ULONG fileID;
+ struct arc_cache cache[CACHE_SIZE];
+ char *arc_sg_buf;
+ unsigned long total_read;
+ unsigned long seek_pos;
+ int seek_pos_valid:1;
+};
+
+static void arc_progress(struct arc_private_data *, unsigned long);
+
+static errcode_t alloc_cache(io_channel, struct arc_private_data *);
+static void free_cache(io_channel, struct arc_private_data *);
+static void reset_one_cache(io_channel, struct arc_private_data *,
+ struct arc_cache *, int);
+static void reset_sg_cache(io_channel, struct arc_private_data *, int);
+static struct arc_cache *find_cached_block(io_channel,
+ struct arc_private_data *, unsigned long);
+static int alloc_sg_blocks(io_channel, struct arc_private_data *,
+ unsigned long, int);
+static errcode_t fill_sg_blocks(io_channel, struct arc_private_data *, int);
+
+static errcode_t raw_read_blk(io_channel, struct arc_private_data *,
+ unsigned long, int, char *);
+static void mul64(unsigned long, int, LARGEINTEGER *);
+static errcode_t arc_seek(io_channel, unsigned long);
+
+static errcode_t arc_open(const char *name, int flags, io_channel * channel);
+static errcode_t arc_close(io_channel channel);
+static errcode_t arc_set_blksize(io_channel channel, int blksize);
+static errcode_t arc_read_blk
+ (io_channel channel, unsigned long block, int count, void *data);
+static errcode_t arc_write_blk
+ (io_channel channel, unsigned long block, int count, const void *data);
+static errcode_t arc_flush(io_channel channel);
+
+static struct struct_io_manager struct_arc_manager = {
+ .magic = EXT2_ET_MAGIC_IO_MANAGER,
+ .name = "ARC PROM I/O Manager",
+ .open = arc_open,
+ .close = arc_close,
+ .set_blksize = arc_set_blksize,
+ .read_blk = arc_read_blk,
+ .write_blk = arc_write_blk,
+ .flush = arc_flush,
+};
+io_manager arc_io_manager = &struct_arc_manager;
+
+int arc_do_progress = 0;
+
+static int hits, misses;
+
+static void
+arc_progress(struct arc_private_data *priv, unsigned long count)
+{
+ int hitrate_w = (hits * 1000) / (hits + misses) / 10;
+ int hitrate_f = (hits * 1000) / (hits + misses) % 10;
+
+ priv->total_read += count;
+ printf("\r%lx (cache: %u.%u%%)", priv->total_read, hitrate_w,
+ hitrate_f);
+
+#ifdef DEBUG
+ if ((hits + misses) % 100 == 0)
+ printf("hits: %u misses %u\n\r", hits, misses);
+#endif
+}
+
+/*
+ * Allocates memory for a single file's cache.
+ */
+static errcode_t
+alloc_cache(io_channel channel, struct arc_private_data *priv)
+{
+ errcode_t status;
+ struct arc_cache *cache;
+ int i;
+
+ for(i = 0, cache = priv->cache; i < CACHE_SIZE; i++, cache++) {
+ memset(cache, 0, sizeof (struct arc_cache));
+ if ((status = ext2fs_get_mem(channel->block_size,
+ (void **) &cache->alloc_buf)) != 0)
+ return (status);
+ cache->buf = cache->alloc_buf;
+ }
+
+ return (ext2fs_get_mem(channel->block_size * CACHE_SG_MAX,
+ (void **) &priv->arc_sg_buf));
+}
+
+/*
+ * Frees all memory associated with a single file's cache.
+ */
+static void
+free_cache(io_channel channel, struct arc_private_data *priv)
+{
+ struct arc_cache *cache;
+ int i;
+
+ for (i = 0, cache = priv->cache; i < CACHE_SIZE; i++, cache++) {
+ if (cache->alloc_buf)
+ ext2fs_free_mem((void **) &cache->alloc_buf);
+ memset(cache, 0, sizeof (struct arc_cache));
+ }
+
+ ext2fs_free_mem((void **) &priv->arc_sg_buf);
+}
+
+/*
+ * Resets a cache block. If the cache block is a valid sg block, the contents
+ * will be copied from the sg buffer into the private buffer. For all blocks,
+ * the private buffer will be current. If discard is set, the block will
+ * also be invalidated.
+ */
+static void
+reset_one_cache(io_channel channel, struct arc_private_data *priv,
+ struct arc_cache *cache, int discard)
+{
+ if (CACHE_IS_SG(cache) && discard == 0 && cache->in_use != 0)
+ memcpy(cache->alloc_buf, cache->buf, channel->block_size);
+
+ if (discard != 0)
+ cache->in_use = 0;
+
+ cache->buf = cache->alloc_buf;
+}
+
+/*
+ * Resets all sg cache blocks. If a block is in the first
+ * alloc_count entries in sg_cblocks (meaning it has been allocated for
+ * immediate reuse) then also discards the contents.
+ */
+static void
+reset_sg_cache(io_channel channel, struct arc_private_data *priv,
+ int alloc_count)
+{
+ struct arc_cache *cache;
+ int i, j, discard;
+
+ for (i = 0, cache = priv->cache; i < CACHE_SIZE; i++, cache++) {
+ if (CACHE_IS_SG(cache)) {
+ discard = 0;
+ for (j = 0; j < alloc_count; j++) {
+ if (sg_cblocks[j] == cache) {
+ discard = 1;
+ break;
+ }
+ }
+ reset_one_cache(channel, priv, cache, discard);
+ }
+ }
+}
+
+/*
+ * Read count blocks starting at block directly from channel into buf, which
+ * must be of size >= channel->block_size * count. No attempt is made to
+ * use or update any caches; however, if the last ARC read left the file
+ * pointer at the requested block, we avoid seeking.
+ */
+static errcode_t
+raw_read_blk(io_channel channel, struct arc_private_data *priv,
+ unsigned long block, int count, char *buf)
+{
+ errcode_t status;
+ size_t length = 0;
+
+ if (priv->seek_pos_valid == 0 || priv->seek_pos != block) {
+ status = arc_seek(channel, block);
+ priv->seek_pos = block + count;
+ } else {
+ status = 0;
+ }
+ /* If something fails, priv->seek_pos is bogus. */
+ priv->seek_pos_valid = 0;
+ if (status == 0) {
+ length = (count < 0) ? -count : count * channel->block_size;
+ ULONG nread = 0;
+
+ status = ArcRead(priv->fileID, buf, length, &nread);
+ if ((nread > 0) && (nread < length)) {
+ status = EXT2_ET_SHORT_READ;
+ memset(((char *) buf) + nread, 0, length - nread);
+ }
+ if (status != 0 && channel->read_error != NULL) {
+ status = (channel->read_error)
+ (channel, block, count, buf, length, nread, status);
+ }
+ } else {
+ status = EXT2_ET_BAD_BLOCK_NUM;
+ }
+
+ if (status == 0) {
+ priv->seek_pos_valid = 1;
+ if (arc_do_progress != 0)
+ arc_progress(priv, (unsigned long) length);
+ }
+
+ return (status);
+}
+
+/*
+ * For the file associated with channel and priv, find block in the cache.
+ * In the case of a miss, return NULL. The last access "time" will be
+ * updated to refresh the LRU. Note that this is much different from the
+ * unix_io.c version of the same function; because our allocation step is
+ * far more complex to cover readahead, it is dealt with in alloc_sg_blocks.
+ */
+static struct arc_cache *
+find_cached_block(io_channel channel, struct arc_private_data *priv,
+ unsigned long block)
+{
+ struct arc_cache *cache;
+ int i;
+
+ ++virtual_time;
+
+ for (i = 0, cache = priv->cache; i < CACHE_SIZE; i++, cache++)
+ if (cache->block == block) {
+ cache->last_use = virtual_time;
+ ++hits;
+ return (cache);
+ }
+
+ ++misses;
+ return (NULL);
+}
+
+/*
+ * Allocate a set of cache blocks whose buffers are contiguous. The cache
+ * blocks are found in sg_cblocks. The number of allocated blocks is the
+ * return value; a return value of 0 indicates an error. The cache blocks
+ * are not filled here; use fill_sg_blocks for that.
+ */
+static int
+alloc_sg_blocks(io_channel channel, struct arc_private_data *priv,
+ unsigned long block, int count)
+{
+ struct arc_cache *cache, *oldest_cache;
+ int i, unused_count, age_mark;
+
+ if (count > CACHE_SG_MAX)
+ count = CACHE_SG_MAX;
+
+ ++virtual_time;
+ oldest_cache = NULL;
+ unused_count = 0;
+
+ /* First use unused blocks, if any are available. */
+ for (i = 0, cache = priv->cache; i < CACHE_SIZE && unused_count < count;
+ i++, cache++) {
+ if (cache->in_use == 0) {
+ sg_cblocks[unused_count++] = cache;
+ continue;
+ }
+ if (!oldest_cache || cache->last_use < oldest_cache->last_use)
+ oldest_cache = cache;
+ }
+
+ /* If we don't have enough blocks yet, evict the LRUs. */
+ if (unused_count < count) {
+ for (age_mark = oldest_cache->last_use;
+ unused_count < count && age_mark <= virtual_time;
+ age_mark++) {
+ for (i = 0, cache = priv->cache;
+ i < CACHE_SIZE && unused_count < count;
+ i++, cache++) {
+ if (cache->in_use == 0)
+ continue;
+ if (cache->last_use == age_mark)
+ sg_cblocks[unused_count++] = cache;
+ }
+ }
+ }
+
+ /*
+ * At this point it's impossible not to have count blocks. However,
+ * even if we somehow don't, it's not fatal - perhaps someone
+ * decided to use some future lru timestamp to lock an entry or
+ * something. In this case, we just continue on, and make sure the
+ * caller knows we didn't allocate as much as was requested.
+ */
+
+ /*
+ * Now we set up the cache blocks. Their buffers need to be
+ * set to the sg buffer and they must be marked invalid (we will
+ * mark them valid once fill_sg_blocks fills them).
+ */
+ reset_sg_cache(channel, priv, count);
+
+ for (i = 0; i < count; i++) {
+ cache = sg_cblocks[i];
+ cache->in_use = 0;
+ cache->block = block + i;
+ cache->buf = priv->arc_sg_buf + i * channel->block_size;
+ }
+
+ return (count);
+}
+
+/*
+ * Fill the first count cache blocks in sg_cblocks with contiguous data from
+ * the file. The block numbers are already stored in the cache metadata
+ * by a mandatory previous call to alloc_sg_blocks. This can fail if there
+ * is an i/o error.
+ */
+static errcode_t
+fill_sg_blocks(io_channel channel, struct arc_private_data *priv, int count)
+{
+ errcode_t status;
+ int i;
+
+ status = raw_read_blk(channel, priv, sg_cblocks[0]->block, count,
+ priv->arc_sg_buf);
+
+ /*
+ * XXX Handle short read here: it may be that we've reached EOF and
+ * can mark some of the blocks valid.
+ */
+ if (status == 0) {
+ for (i = 0; i < count; i++) {
+ sg_cblocks[i]->in_use = 1;
+ sg_cblocks[i]->last_use = virtual_time;
+ }
+ }
+
+ return (status);
+}
+
+/*
+ * Mark the entire contents of the cache invalid, and reset any sg blocks
+ * to private buffers.
+ */
+static void
+cache_invalidate(io_channel channel, struct arc_private_data *priv)
+{
+ struct arc_cache *cache;
+ int i;
+
+ for (i = 0, cache = priv->cache; i < CACHE_SIZE; i++, cache++)
+ reset_one_cache(channel, priv, cache, 1);
+}
+
+static errcode_t
+arc_open(const char *name, int flags, io_channel * pchannel)
+{
+ io_channel channel = NULL;
+ struct arc_private_data *priv;
+ errcode_t status;
+
+ if (name == NULL)
+ return EXT2_ET_BAD_DEVICE_NAME;
+
+ status =
+ ext2fs_get_mem(sizeof(struct struct_io_channel),
+ (void **) &channel);
+
+ if (status == 0) {
+ memset(channel, 0, sizeof(struct struct_io_channel));
+
+ channel->name = NULL;
+ channel->private_data = NULL;
+ channel->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ channel->manager = arc_io_manager;
+ channel->block_size = 1024;
+ channel->read_error = NULL;
+ channel->write_error = NULL;
+ channel->refcount = 1;
+
+ status =
+ ext2fs_get_mem(strlen(name) + 1,
+ (void **) &channel->name);
+ if (status == 0) {
+ strcpy(channel->name, name);
+
+ status =
+ ext2fs_get_mem(sizeof(struct arc_private_data),
+ (void **) &priv);
+ if (status == 0) {
+ memset(priv, 0,
+ sizeof(struct arc_private_data));
+ channel->private_data = priv;
+ priv->magic = EXT2_ET_BAD_MAGIC;
+ priv->mode =
+ (flags & IO_FLAG_RW) ? OpenReadWrite :
+ OpenReadOnly;
+ status =
+ ArcOpen((char *) name, priv->mode,
+ &priv->fileID);
+ if( status ) {
+ status = EXT2_ET_BAD_DEVICE_NAME;
+ }
+ }
+ }
+ }
+
+ if (status == 0)
+ status = alloc_cache(channel, priv);
+
+ if (status == 0) {
+ *pchannel = channel;
+ } else if (channel != NULL) {
+ if (channel->name != NULL)
+ ext2fs_free_mem((void **) &channel->name);
+ if (channel->private_data != NULL)
+ ext2fs_free_mem((void **) &channel->private_data);
+ ext2fs_free_mem((void **) &channel);
+ }
+ return status;
+}
+
+
+static errcode_t arc_close(io_channel channel)
+{
+ struct arc_private_data *priv;
+ errcode_t status = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ priv = (struct arc_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(priv, EXT2_ET_BAD_MAGIC);
+
+ if (--channel->refcount == 0) {
+ status = ArcClose(priv->fileID);
+ free_cache(channel, priv);
+ if (channel->name != NULL)
+ ext2fs_free_mem((void **) &channel->name);
+ if (channel->private_data != NULL)
+ ext2fs_free_mem((void **) &channel->private_data);
+ ext2fs_free_mem((void **) &channel);
+ }
+
+ return status;
+}
+
+
+static errcode_t arc_set_blksize(io_channel channel, int blksize)
+{
+ struct arc_private_data *priv;
+ errcode_t status;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ priv = (struct arc_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(priv, EXT2_ET_BAD_MAGIC);
+
+ if (channel->block_size != blksize) {
+ channel->block_size = blksize;
+ free_cache(channel, priv);
+ if ((status = alloc_cache(channel, priv)) != 0)
+ return (status);
+ }
+ return 0;
+}
+
+static void
+mul64(unsigned long block, int blocksize, LARGEINTEGER *result)
+{
+ ULONG m1l = block & 0x0FFFF, m1h = (block >> 16) & 0x0FFFF;
+ ULONG m2l = blocksize & 0x0FFFF, m2h = (blocksize >> 16) & 0x0FFFF;
+ ULONG i1 = m1l * m2h, i2 = m1h * m2l;
+
+ result->HighPart =
+ (m1h * m2h) + ((i1 >> 16) & 0x0FFFF) + ((i2 >> 16) & 0x0FFFF);
+ i1 =
+ (i1 & 0x0FFFF) + (i2 & 0x0FFFF) +
+ (((m1l * m2l) >> 16) & 0x0FFFF);
+ result->LowPart = ((i1 & 0x0FFFF) << 16) + ((m1l * m2l) & 0x0FFFF);
+ result->HighPart += (i1 >> 16) & 0x0FFFF;
+}
+
+static errcode_t
+arc_seek(io_channel channel, unsigned long block)
+{
+ struct arc_private_data *priv;
+ LARGEINTEGER position;
+
+ priv = (struct arc_private_data *) channel->private_data;
+ mul64(block, channel->block_size, &position);
+ return ArcSeek(priv->fileID, &position, SeekAbsolute);
+}
+
+/*
+ * Perform a cacheable read. First, the cache will be checked for an
+ * existing copy of the blocks. If present, they are copied into buf.
+ * Otherwise, we set up and execute a readahead, then copy the results into
+ * buf. The unix_io way is a little nicer; since it doesn't have readahead
+ * it knows that buf is always big enough in multicount scenarios and thus
+ * dispenses with the extra memcpy. There is an opportunity to improve this.
+ */
+static errcode_t
+arc_read_blk(io_channel channel, unsigned long block, int count, void *buf)
+{
+ struct arc_private_data *priv;
+ errcode_t status = 0;
+ struct arc_cache *cache;
+ char *cbuf = (char *) buf;
+ int cb_alloc;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ priv = (struct arc_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(priv, EXT2_ET_BAD_MAGIC);
+
+#ifdef DEBUG
+ printf("req %lu id %lu count %u\n\r", block, priv->fileID, count);
+#endif
+
+ /* Odd-sized reads can't be cached. */
+ if (count < 0)
+ status = raw_read_blk(channel, priv, block, count, cbuf);
+
+ while (count > 0) {
+ if ((cache = find_cached_block(channel, priv, block)) == NULL)
+ break;
+#ifdef DEBUG
+ printf("Cache hit on block %lu\n\r", block);
+#endif
+ memcpy(cbuf, cache->buf, channel->block_size);
+ count--;
+ block++;
+ cbuf += channel->block_size;
+ }
+
+ /*
+ * Cache miss. Although it could be that there's just a hole
+ * in the cache, it's far more likely and easier to handle
+ * that we've reached the end of a readahead blockset. Thus
+ * we just stop looking in the cache for the rest until after
+ * we do a readahead. We could try to put in some
+ * heuristics here to avoid trashing the cache unnecessarily
+ * for reads we expect are not part of a sequential set.
+ */
+ while (count > 0) {
+#ifdef DEBUG
+ printf("Cache miss on block %lu (readahead %u)\n\r",
+ block, CACHE_SG_MAX);
+#endif
+ if ((cb_alloc = alloc_sg_blocks(channel, priv, block,
+ CACHE_SG_MAX)) == 0) {
+#ifdef DEBUG
+ printf("%s\n\r", "Cache error: can't alloc any blocks");
+#endif
+ /* Cache is broken, so do the raw read. */
+ cache_invalidate(channel, priv);
+ status = raw_read_blk(channel, priv, block, count,
+ cbuf);
+ break;
+ }
+
+ if ((status = fill_sg_blocks(channel, priv, cb_alloc)) != 0) {
+#ifdef DEBUG
+ printf("Cache error (status %lu at block %lu(%u)\n\r",
+ (unsigned long) status, block, count);
+#endif
+ /* Cache is broken, so do the raw read. */
+ cache_invalidate(channel, priv);
+ status = raw_read_blk(channel, priv, block, count,
+ cbuf);
+ break;
+ }
+
+ if (cb_alloc >= count) {
+ memcpy(cbuf, priv->arc_sg_buf,
+ count * channel->block_size);
+ return (0);
+ }
+
+ memcpy(cbuf, priv->arc_sg_buf, cb_alloc * channel->block_size);
+ count -= cb_alloc;
+ block += cb_alloc;
+ cbuf += cb_alloc * channel->block_size;
+ }
+
+ return (status);
+}
+
+static errcode_t
+arc_write_blk (io_channel channel, unsigned long block, int count,
+ const void *buf) {
+ struct arc_private_data *priv;
+ errcode_t status;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ priv = (struct arc_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(priv, EXT2_ET_BAD_MAGIC);
+
+ status = arc_seek(channel, block);
+#ifdef ARC_IO_ALLOW_WRITE
+ cache_invalidate(channel, priv);
+ priv->seek_pos_valid = 0;
+ if (status == 0) {
+ size_t length =
+ (count < 0) ? -count : count * channel->block_size;
+ ULONG nwritten = 0;
+
+ status =
+ ArcWrite(priv->fileID, (void *) buf, length,
+ &nwritten);
+ if ((nwritten > 0) && (nwritten < length))
+ status = EXT2_ET_SHORT_WRITE;
+ if ((status != ESUCCESS) && (channel->write_error != NULL)) {
+ status = (channel->write_error)
+ (channel, block, count, buf, length, nwritten, status);
+ }
+ }
+#endif /* ARC_IO_ALLOW_WRITE */
+
+ return status;
+}
+
+
+static errcode_t arc_flush(io_channel channel)
+{
+ struct arc_private_data *priv;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ priv = (struct arc_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(priv, EXT2_ET_BAD_MAGIC);
+
+ return 0;
+}
+
+
+/* Hack in some stuff to make ext2fs library work */
+time_t time(time_t *t)
+{
+ return 0;
+}
+
+/* We can get away with those two because libext2fs uses them only in
+ fileio.c for file size calculations, and the bootloader needs not
+ to read files >2GB (famous last words...). */
+unsigned long long __udivdi3(unsigned long long numerator,
+ unsigned long long denominator)
+{
+// printf("ARGH! %s\n", __FUNCTION__);
+ return ((unsigned int)(numerator)) / ((unsigned int)(denominator));
+}
+
+unsigned long long __umoddi3(unsigned long long val, unsigned long long mod)
+{
+// printf("ARGH! %s\n", __FUNCTION__);
+ return ((unsigned int)(val)) % ((unsigned int)(mod));
+}
+
+struct et_list {
+ struct et_list *next;
+ const struct error_table *table;
+};
+struct et_list *_et_list = NULL;
+
+void com_err(const char *whoami, long error, const char *format, ...)
+{
+ printf("com_err called with %lu\n", error);
+}
+
+const char *ext2fs_strerror(long error)
+{
+ struct et_list *list = _et_list;
+
+ while (list != NULL) {
+ if ((error >= list->table->base)
+ && (error < (list->table->base + list->table->n_msgs))) {
+ return list->table->msgs[error -
+ list->table->base];
+ }
+
+ list = list->next;
+ }
+ return NULL;
+}
+
+void print_ext2fs_error(long error)
+{
+ const char* msg;
+
+ msg = ext2fs_strerror(error);
+ if(msg)
+ printf("ext2fs - %s\n\r", msg);
+ else
+ printf("ext2fs - unknown error (%lu)\n\r", error);
+
+}
diff --git a/ext2load/ld.script.in b/ext2load/ld.script.in
new file mode 100644
index 0000000..8c5bb3f
--- /dev/null
+++ b/ext2load/ld.script.in
@@ -0,0 +1,73 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ /* XXX: place the loader after the kernel */
+ . = @@LOADADDR@@;
+
+ /* Read-only sections, merged into text segment: */
+ .text : {
+ _ftext = .;
+ *(.text)
+ *(.rodata*)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+
+ . = ALIGN(16);
+
+ .data : {
+ _fdata = .;
+ *(.data)
+ CONSTRUCTORS
+ }
+ _gp = ALIGN(16) + 0x7ff0;
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ PROVIDE (edata = .);
+
+ __bss_start = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ _fbss = .;
+ *(.dynbss)
+ *(.bss .bss.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ __bss_stop = .;
+ _end = .;
+ PROVIDE (end = .);
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ *(.stab)
+ *(.stabstr)
+ *(.pdr)
+ *(.note)
+ *(.reginfo)
+ *(.options)
+ *(.MIPS.options)
+ *(.debug*)
+ *(.line)
+ *(.mdebug*)
+ *(.comment*)
+ *(.gptab*)
+ *(.note)
+ }
+}
diff --git a/ext2load/loader.c b/ext2load/loader.c
new file mode 100644
index 0000000..45d1988
--- /dev/null
+++ b/ext2load/loader.c
@@ -0,0 +1,564 @@
+/*
+ * Copyright 1999, 2001 Silicon Graphics, Inc.
+ * Copyright 2001 Ralf Baechle
+ * 2001-04 Guido Guenther <agx@sigxcpu.org>
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <types.h>
+#include <stdint.h>
+
+#include <arc.h>
+#include <elf.h>
+
+#include <sys/types.h>
+#include <ext2_fs.h>
+#include <ext2fs.h>
+
+#include "arcboot.h"
+
+#include <subarch.h>
+
+#define KSEG0ADDR(addr) (((addr) & 0x1fffffff) | 0x80000000)
+
+#define ANSI_CLEAR "\033[2J"
+#define CONF_FILE "/etc/arcboot.conf"
+
+CHAR *OSLoadPartition = NULL;
+CHAR *OSLoadFilename = NULL;
+CHAR *OSLoadOptions = NULL;
+static int is64=0;
+
+
+typedef union {
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Ehdr header32;
+ Elf64_Ehdr header64;
+} Elf_Ehdr;
+
+static void Wait(const char *prompt)
+{
+ int ch;
+
+ if (prompt != NULL)
+ puts(prompt);
+
+ do {
+ ch = getchar();
+ } while ((ch != EOF) && (((char) ch) != ' '));
+}
+
+
+void Fatal(const CHAR * message, ...)
+{
+ va_list ap;
+
+ if (message != NULL) {
+ printf("FATAL ERROR: ");
+ va_start(ap, message);
+ vprintf(message, ap);
+ va_end(ap);
+ }
+
+ Wait("\n\r--- Press <spacebar> to enter ARC interactive mode ---");
+ ArcEnterInteractiveMode();
+}
+
+
+void InitMalloc(void)
+{
+ MEMORYDESCRIPTOR *current = NULL;
+ ULONG stack = (ULONG) &current;
+#ifdef DEBUG
+ printf("stack starts at: 0x%lx\n\r", stack);
+#endif
+
+ current = ArcGetMemoryDescriptor(current);
+ if(! current ) {
+ Fatal("Can't find any valid memory descriptors!\n\r");
+ }
+ while (current != NULL) {
+ /*
+ * The spec says we should have an adjacent FreeContiguous
+ * memory area that includes our stack. It would be much
+ * easier to just look for that and give it to malloc, but
+ * the Indy only shows FreeMemory areas, no FreeContiguous.
+ * Oh well.
+ */
+ if (current->Type == FreeMemory) {
+ ULONG start = KSEG0ADDR(current->BasePage * PAGE_SIZE);
+ ULONG end =
+ start + (current->PageCount * PAGE_SIZE);
+#if DEBUG
+ printf("Free Memory(%u) segment found at (0x%lx,0x%lx).\n\r",
+ current->Type, start, end);
+#endif
+
+ /* Leave some space for our stack */
+ if ((stack >= start) && (stack < end))
+ end =
+ (stack -
+ (STACK_PAGES *
+ PAGE_SIZE)) & ~(PAGE_SIZE - 1);
+ /* Don't use memory from reserved region */
+ if ((start >= kernel_load[SUBARCH].base )
+ && (start < (kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved )))
+ start = kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved;
+ if ((end > kernel_load[SUBARCH].base)
+ && (end <= (kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved )))
+ end = kernel_load[SUBARCH].base;
+ if (end > start) {
+#ifdef DEBUG
+ printf("Adding %lu bytes at 0x%lx to the list of available memory\n\r",
+ end-start, start);
+#endif
+ arclib_malloc_add(start, end - start);
+ }
+ }
+ current = ArcGetMemoryDescriptor(current);
+ }
+}
+
+int isEnvVar(const char* arg)
+{
+ unsigned int i;
+
+ for (i = 0; i < NENTS(env_vars); i++) {
+ if(strncmp( env_vars[i], arg, strlen(env_vars[i]) ) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+int ProcessArguments(LONG argc, CHAR * argv[])
+{
+ LONG arg;
+ CHAR *equals;
+ size_t len;
+
+ /* save some things we need later */
+ for (arg = 1; arg < argc; arg++) {
+ equals = strchr(argv[arg], '=');
+ if (equals != NULL) {
+ len = equals - argv[arg];
+ if (strncmp(argv[arg], "OSLoadPartition", len) == 0)
+ OSLoadPartition = equals + 1;
+ if (strncmp(argv[arg], "OSLoadFilename", len) == 0)
+ OSLoadFilename = equals + 1;
+ if (strncmp(argv[arg], "OSLoadOptions", len) == 0) {
+ /* Copy options to local memory to avoid overwrite later */
+ OSLoadOptions = strdup(equals + 1);
+ if (OSLoadOptions == NULL)
+ Fatal ("Cannot allocate memory for options string\n\r");
+ }
+ }
+ }
+ /*
+ * in case the user typed "boot a b c" the argv looks like:
+ * scsi(0)..(8)/arcboot a b c OSLoadPartition=.. SystemPartition=..
+ * argv: `0 `-1`-2`-3`-4 `-5
+ * we're interested in a,b,c so scan the command line and check for
+ * each argument if it is an environment variable. We're using a fixed
+ * list instead of ArcGetEnvironmentVariable since e.g. the prom sets
+ * "OSLoadOptions=auto" on reboot but
+ * EnvironmentVariable("OSLoadOptions") == NULL
+ */
+ for( arg = 1; arg < argc; arg++ ) {
+ if( isEnvVar(argv[arg])) {
+ return (arg-1);
+#ifdef DEBUG
+ } else {
+ printf("%s is not an envVar\n\r", argv[arg]);
+#endif
+ }
+ }
+ return 0;
+}
+
+int LoadProgramSegments32(ext2_file_t file, Elf_Ehdr * header, void *segments)
+{
+ int idx;
+ int loaded = 0;
+ Elf32_Phdr* segment=(Elf32_Phdr*)segments;
+ errcode_t status;
+ size_t size;
+
+ printf("Loading 32-bit executable\n\r");
+
+ for (idx = 0; idx < header->header32.e_phnum; idx++) {
+ if (segment->p_type == PT_LOAD) {
+ printf
+ ("Loading program segment %u at 0x%x, offset=0x%x, size = 0x%x\n\r",
+ idx + 1, KSEG0ADDR(segment->p_vaddr),
+ segment->p_offset, segment->p_filesz);
+
+ status =
+ ext2fs_file_lseek(file, segment->p_offset,
+ EXT2_SEEK_SET, NULL);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Cannot seek to program segment\n\r");
+ }
+
+ arc_do_progress = 1;
+ status = ext2fs_file_read(file,
+ (void *) (KSEG0ADDR(
+ segment->p_vaddr)),
+ segment->p_filesz, NULL);
+ printf("\n\n\r"); /* Clear progress */
+ arc_do_progress = 0;
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Cannot read program segment\n\r");
+ }
+
+ size = segment->p_memsz - segment->p_filesz;
+ if (size > 0) {
+ printf
+ ("Zeroing memory at 0x%x, size = 0x%x\n\r",
+ (KSEG0ADDR(segment->p_vaddr +
+ segment->p_filesz)), size);
+ memset((void *)
+ (KSEG0ADDR(segment->
+ p_vaddr + segment->p_filesz)), 0, size);
+ }
+
+ loaded = 1;
+ }
+
+ segment =
+ (Elf32_Phdr *) (((char *) segment) +
+ header->header32.e_phentsize);
+ }
+
+ return loaded;
+}
+
+int LoadProgramSegments64(ext2_file_t file, Elf_Ehdr * header, void *segments)
+{
+ int idx;
+ int loaded = 0;
+ Elf64_Phdr* segment=(Elf64_Phdr*)segments;
+ errcode_t status;
+ size_t size;
+
+ is64=1;
+ printf("Loading 64-bit executable\n\r");
+
+ for (idx = 0; idx < header->header64.e_phnum; idx++) {
+ if (segment->p_type == PT_LOAD) {
+ printf ("Loading program segment %u at 0x%x, "
+ "offset=0x%lx %lx, size = 0x%lx %lx\n\r",
+ idx + 1,
+ (int)KSEG0ADDR(segment->p_vaddr),
+ (long)(segment->p_offset>>32),
+ (long)(segment->p_offset&0xffffffff),
+ (long)(segment->p_filesz>>32),
+ (long)(segment->p_filesz&0xffffffff));
+
+ status =
+ ext2fs_file_lseek(file, segment->p_offset,
+ EXT2_SEEK_SET, NULL);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Cannot seek to program segment\n\r");
+ }
+
+ arc_do_progress = 1;
+ status = ext2fs_file_read(file,
+ (void *) (KSEG0ADDR(
+ segment->p_vaddr)),
+ segment->p_filesz, NULL);
+ arc_do_progress = 0;
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Cannot read program segment\n\r");
+ }
+
+ size = segment->p_memsz - segment->p_filesz;
+ if (size > 0) {
+ printf
+ ("Zeroing memory at 0x%lx, size = 0x%lx\n\r",
+ (KSEG0ADDR(segment->p_vaddr +
+ segment->p_filesz)), size);
+ memset((void *)
+ (KSEG0ADDR(segment->
+ p_vaddr + segment->p_filesz)), 0, size);
+ }
+
+ loaded = 1;
+ }
+
+ segment = (Elf64_Phdr *) (((char *) segment)
+ + header->header64.e_phentsize);
+ }
+
+ return loaded;
+}
+
+void LoadProgramSegments(ext2_file_t file, Elf_Ehdr * header)
+{
+ int idx;
+ Boolean loaded = False;
+ void *segments;
+ size_t size;
+ errcode_t status;
+
+ if (header->e_ident[EI_CLASS] == ELFCLASS32)
+ size = (size_t) (header->header32.e_phentsize *
+ header->header32.e_phnum);
+ else
+ size = (size_t) (header->header64.e_phentsize *
+ header->header64.e_phnum);
+
+ if (size <= 0)
+ Fatal("No program segments\n\r");
+
+ segments = malloc(size);
+ if (segments == NULL)
+ Fatal("Cannot allocate memory for segment headers\n\r");
+ else
+ printf("Allocated 0x%x bytes for segments\n\r",size);
+
+ if (header->e_ident[EI_CLASS] == ELFCLASS32) {
+ status = ext2fs_file_lseek(file,
+ (ext2_off_t) header->header32.e_phoff,
+ EXT2_SEEK_SET, NULL);
+ } else {
+ status = ext2fs_file_lseek(file,
+ (ext2_off_t) header->header64.e_phoff,
+ EXT2_SEEK_SET, NULL);
+ }
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Cannot seek to program segment headers\n\r");
+ }
+
+ status = ext2fs_file_read(file, segments, size, NULL);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Cannot read program segment headers\n\r");
+ }
+
+ if(header->e_ident[EI_CLASS] == ELFCLASS32)
+ loaded = LoadProgramSegments32(file, header, segments);
+ else
+ loaded = LoadProgramSegments64(file, header, segments);
+
+ if (!loaded)
+ Fatal("No loadable program segments found\n\r");
+
+ free(segments);
+}
+
+
+Elf64_Addr LoadKernelFile(ext2_file_t file)
+{
+ Elf_Ehdr header;
+ Elf64_Addr entry;
+ errcode_t status;
+
+ status =
+ ext2fs_file_read(file, (void *) &header, sizeof(header), NULL);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ Fatal("Can't read file header\n\r");
+ }
+
+ if (memcmp(&(header.e_ident[EI_MAG0]), ELFMAG, SELFMAG) != 0)
+ Fatal("Not an ELF file\n\r");
+
+ if (header.e_ident[EI_CLASS] != ELFCLASS32 &&
+ header.e_ident[EI_CLASS] != ELFCLASS64)
+ Fatal("Not a 32-bit or 64-bit file\n\r");
+
+ if (header.e_ident[EI_DATA] != ELFDATA2MSB)
+ Fatal("Not a big-endian file\n\r");
+
+ if (header.e_ident[EI_VERSION] != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ if (header.e_ident[EI_CLASS]==ELFCLASS32) {
+ if (header.header32.e_type != ET_EXEC)
+ Fatal("Not an executable file\n\r");
+
+ if (header.header32.e_machine != EM_MIPS)
+ Fatal("Unsupported machine type\n\r");
+
+ if (header.header32.e_version != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ entry = (Elf64_Addr) header.header32.e_entry;
+ } else {
+ if (header.header64.e_type != ET_EXEC)
+ Fatal("Not an executable file\n\r");
+
+ if (header.header64.e_machine != EM_MIPS)
+ Fatal("Unsupported machine type\n\r");
+
+ if (header.header64.e_version != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ entry = header.header64.e_entry;
+ }
+
+ LoadProgramSegments(file, &header);
+
+ return entry;
+}
+
+
+Boolean OpenFile(const char *partition, const char *filename, ext2_file_t* file)
+{
+ extern io_manager arc_io_manager;
+ ext2_filsys fs;
+ ext2_ino_t file_inode;
+ errcode_t status;
+
+ initialize_ext2_error_table();
+
+ status = ext2fs_open(partition, 0, 0, 0, arc_io_manager, &fs);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ return False;
+ }
+
+ status = ext2fs_namei_follow
+ (fs, EXT2_ROOT_INO, EXT2_ROOT_INO, filename, &file_inode);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ return False;
+ }
+
+ status = ext2fs_file_open(fs, file_inode, 0, file);
+ if (status != 0) {
+ print_ext2fs_error(status);
+ return False;
+ }
+ return True;
+}
+
+Elf64_Addr LoadKernel(const char *partition, const char *filename)
+{
+ ext2_file_t file;
+
+ if(!OpenFile( partition, filename, &file ))
+ Fatal("Can't load kernel!\n\r");
+ return LoadKernelFile(file);
+}
+
+void printCmdLine(int argc, CHAR *argv[])
+{
+ int i;
+
+ for(i = 0; i < argc; i++ )
+ printf("%u: %s\n\r", i, argv[i]);
+}
+
+void _start64(LONG argc, CHAR * argv[], CHAR * envp[],
+ unsigned long long *addr)
+{
+ __asm__ __volatile__(
+ ".set push\n"
+ "\t.set mips3\n"
+ "\t.set noreorder\n"
+ "\t.set noat\n"
+ "\tld $1, 0($7)\n"
+ "\tjr $1\n"
+ "\t nop\n"
+ "\t.set pop");
+}
+
+void _start(LONG argc, CHAR *argv[], CHAR *envp[])
+{
+ CHAR** nargv;
+ CHAR** params;
+ int nargc, nopt;
+
+ Elf32_Addr kernel_entry32;
+ Elf64_Addr kernel_entry64;
+
+ /* Print identification */
+ printf(ANSI_CLEAR "\n\rarcsboot: ARCS Linux ext2fs loader "
+ __ARCSBOOT_VERSION__ "\n\n\r");
+
+ InitMalloc();
+
+ nopt = ProcessArguments(argc, argv);
+
+#if DEBUG
+ printf("Command line: \n\r");
+ printCmdLine(argc, argv);
+#endif
+ if (nopt) { /* the user typed s.th. on the commandline */
+ OSLoadFilename = argv[1];
+ }
+
+ /* Fall back to "Linux" as default name. */
+ if (OSLoadFilename == NULL)
+ OSLoadFilename = "Linux";
+
+ if (OSLoadPartition == NULL)
+ Fatal("Invalid load partition\n\r");
+#if DEBUG
+ printf("OSLoadPartition: %s\n\r", OSLoadPartition);
+ printf("OSLoadFilename: %s\n\r", OSLoadFilename);
+#endif
+ /*
+ * XXX: let's play stupid for now: assume /etc/arcboot.conf
+ * is on OSLoadPartition
+ */
+ if( !(params = ReadConfFile(&OSLoadPartition, CONF_FILE, OSLoadFilename))) {
+ printf("Couldn't find label: %s in %s.\n\r", OSLoadFilename, CONF_FILE);
+ printf("Will try to boot %s%s.\n\r", OSLoadPartition, OSLoadFilename);
+ nargc = argc;
+ nargv = argv;
+ } else {
+ int i;
+ OSLoadFilename = params[1];
+ nargv = &params[1]; /* nargv[0] is the labels name */
+ for( nargc=0; nargv[nargc]; nargc++); /* count nargv argumnts */
+ if(OSLoadOptions != NULL) { /* append OSLoadOptions if present */
+ nargv[nargc] = OSLoadOptions;
+ nargc++;
+ }
+ /* append command line arguments */
+ for(i = 2; i <= nopt; i++) {
+ nargv[nargc] = argv[i];
+ nargc++;
+ }
+ }
+ printf("Loading %s from %s\n\r",(params) ? params[0] : OSLoadFilename, OSLoadPartition);
+ kernel_entry64 = LoadKernel(OSLoadPartition, OSLoadFilename);
+ kernel_entry32 = (Elf32_Addr) kernel_entry64;
+#if DEBUG
+ printf("Command line after config file: \n\r");
+ printCmdLine(nargc, nargv);
+ printf("Kernel entry: 0x%lx %lx\n\r",
+ (long)(kernel_entry64>>32),(long)(kernel_entry64&0xffffffff));
+ Wait("\n\r--- Debug: press <spacebar> to boot kernel ---");
+#endif
+ if( kernel_entry64 ) {
+ if(is64==0){
+ printf("Starting ELF32 kernel\n\r");
+ ArcFlushAllCaches();
+ ((void (*)(int argc, CHAR * argv[], CHAR * envp[]))
+ kernel_entry32)(nargc ,nargv, envp);
+ } else {
+ printf("Starting ELF64 kernel\n\r");
+ ArcFlushAllCaches();
+ _start64(nargc, nargv, envp, &kernel_entry64);
+ }
+ } else {
+ printf("Invalid kernel entry NULL\n\r");
+ }
+
+ /* Not likely to get back here in a functional state, but what the heck */
+ Wait("\n\r--- Press <spacebar> to restart ---");
+ ArcRestart();
+}
diff --git a/scripts/arcboot b/scripts/arcboot
new file mode 100644
index 0000000..6fe5623
--- /dev/null
+++ b/scripts/arcboot
@@ -0,0 +1,42 @@
+#!/bin/sh -e
+
+DVHTOOL=/usr/sbin/dvhtool
+ARCBOOT_IMG=/usr/lib/arcboot/arcboot.ip22
+ARCBOOT_CONF=/etc/arcboot.conf
+
+# Use the ip32 image if we're on an O2
+if grep -E -qs '^system type[[:space:]]*: SGI (IP32|O2)' /proc/cpuinfo; then
+ ARCBOOT_IMG=/usr/lib/arcboot/arcboot.ip32
+fi
+
+if [ ! -r $ARCBOOT_CONF ]; then
+ echo "No $ARCBOOT_CONF - giving up!"
+ exit 1
+fi
+
+if [ ! -x $DVHTOOL ]; then
+ echo "Can't find dvhtool - giving up!"
+ exit 1
+fi
+
+if [ -z "$1" ]; then
+ echo "Usage: arcboot <name_of_disk>"
+ exit 1
+fi
+
+echo -n "Putting `basename $ARCBOOT_IMG` into the volume header of $1..."
+$DVHTOOL -d $1 --unix-to-vh $ARCBOOT_IMG arcboot
+echo "done."
+
+# check if the "image=" lines in $ARCBOOT_IMG refer to valid ELF images
+for i in `grep "^[[:space:]]*image=" $ARCBOOT_CONF`; do
+ IMAGE=`echo $i | cut -d'=' -f2`;
+ if [ -L $IMAGE ]; then # if it's a symlink, follow it
+ IMAGE=`dirname $IMAGE`/`readlink $IMAGE`
+ fi
+ if [ "$(dd if=$IMAGE bs=4 count=1 2>/dev/null)" != "$(printf '\177ELF')" ]; then
+ echo "Warning: $IMAGE is not an ELF image. Booting it will fail!"
+ fi
+done
+
+# TODO: better sanity checking of $ARCBOOT_CONF
diff --git a/tip22/.cvsignore b/tip22/.cvsignore
new file mode 100644
index 0000000..c5aacb9
--- /dev/null
+++ b/tip22/.cvsignore
@@ -0,0 +1,6 @@
+ld.kernel.script.IP22
+ld.kernel.script.IP32
+ld.ramdisk.script.IP22
+ld.ramdisk.script.IP32
+ld.script.IP22
+ld.script.IP32
diff --git a/tip22/Makefile b/tip22/Makefile
new file mode 100644
index 0000000..2efe8ae
--- /dev/null
+++ b/tip22/Makefile
@@ -0,0 +1,73 @@
+#
+# Copyright 2002-2004 Guido Guenther <agx@sigxcpu.org>
+#
+
+ARCLIBDIR = ../arclib
+ARCLIB = $(ARCLIBDIR)/libarc.a
+
+COMMONDIR = ../common
+PRINT_LOADADDR = $(COMMONDIR)/print_loadaddr
+PRINT_OUTPUTFORMAT = $(COMMONDIR)/print_outputformat
+
+CFLAGS += -O2 -I$(COMMONDIR) -I$(ARCLIBDIR) -Wall -mno-abicalls -G 0 \
+ -fno-pic -DSUBARCH=${SUBARCH}
+
+ASFLAGS = -O2 -mno-abicalls -G 0 -fno-pic
+
+LIBDIR ?= /usr/lib/tip22
+BINDIR ?= /usr/sbin
+
+LIBS=${ARCLIB}
+BINS=tip22 tip32
+LD_SCRIPTS = ld.kernel.script.$(SUBARCH) ld.ramdisk.script.$(SUBARCH) ld.script.$(SUBARCH)
+OBJECTS = tftpload.$(SUBARCH).o
+TARGETS = $(OBJECTS) $(LD_SCRIPTS)
+
+# uncomment for debugging
+#CFLAGS+=-DDEBUG
+
+
+all: ${LIBS} ${BINS}
+ @$(MAKE) SUBARCH=IP32 archall
+ @$(MAKE) SUBARCH=IP22 archall
+
+archall: $(TARGETS)
+
+
+$(ARCLIB):
+ @$(MAKE) -C $(ARCLIBDIR)
+
+$(PRINT_LOADADDR):
+ @$(MAKE) -C $(COMMONDIR) SUBARCH=$(SUBARCH)
+
+
+%.$(SUBARCH).o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.script.$(SUBARCH): %.script.in $(PRINT_LOADADDR) $(PRINT_OUTPUTFORMAT)
+ LOADADDR=$$($(PRINT_LOADADDR) $(SUBARCH)); \
+ OUTPUTFORMAT=$$($(PRINT_OUTPUTFORMAT) $(SUBARCH)); \
+ sed -e "s/@@LOADADDR@@/$$LOADADDR/" \
+ -e "s/@@OUTPUTFORMAT@@/$$OUTPUTFORMAT/" <$< >$@
+
+clean:
+ @$(MAKE) SUBARCH=IP32 archclean
+ @$(MAKE) SUBARCH=IP22 archclean
+ rm -f tags *~
+
+archclean:
+ @$(MAKE) -C $(ARCLIBDIR) clean
+ @$(MAKE) -C $(COMMONDIR) clean
+ rm -f $(TARGETS)
+
+install: all
+ install -d ${PREFIX}/${BINDIR}
+ install -m 755 ${BINS} ${PREFIX}/${BINDIR}
+ @$(MAKE) SUBARCH=IP32 archinstall
+ @$(MAKE) SUBARCH=IP22 archinstall
+
+archinstall:
+ $(foreach tg,$(TARGETS),install -m 644 $(tg) ${PREFIX}/${LIBDIR};)
+
+
+.PHONY: all archall clean archclean install archinstall
diff --git a/tip22/README b/tip22/README
new file mode 100644
index 0000000..becc313
--- /dev/null
+++ b/tip22/README
@@ -0,0 +1,32 @@
+How to create the boot image:
+-----------------------------------
+
+tip22 <vmlinux> <initrd> <outputfile>
+tip32 <vmlinux> <initrd> <outputfile>
+
+- vmlinux is an ELF Linux kernel. For versions before 2.6.9 you need to
+ apply an extra patch for correct commandline parsing, see
+ /usr/share/doc/tip22/examples.
+- initrd is the gzip compressed initial ramdisk you want add
+- outputfile is the bootimage. It is in ECOFF format for ip22 and in
+ ELF format for ip32. You can for example tfpboot this image on an SGI
+ Indy using the bootp(): command in the prom.
+
+it basically works like this:
+-----------------------------
+- tftpload.o is a relocatable object created during package build time
+- the tip22 script converts the ramdisk and vmlinux to relocatable
+ objects using linker scripts including symbols that mark the begin
+ and the end of kernel and ramdisk
+- those are linked together into the output file using yet another
+ linker script
+- when executed by the prom the embedded loader:
+ - memcopies the kernel to its loadaddress
+ - memcopies the initrd after the kernel to a page boundary
+ - parses the command line and everything within an append="..."
+ statement is passed on to the kernel, e.g.
+ 'bootp(): append="console=ttyS0"'
+ - jumps into the kernel passing the start address and size of the
+ initrd on the command line
+
+ -- Thu, 15 May 2002 23:07:18 +0200 Guido Guenther <agx@sigxcpu.org>
diff --git a/tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff b/tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff
new file mode 100644
index 0000000..c1bd785
--- /dev/null
+++ b/tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff
@@ -0,0 +1,88 @@
+Index: arch/mips/kernel/setup.c
+===================================================================
+RCS file: /cvs/linux/arch/mips/kernel/setup.c,v
+retrieving revision 1.96.2.12
+diff -u -u -r1.96.2.12 setup.c
+--- arch/mips/kernel/setup.c 2002/02/15 21:05:48 1.96.2.12
++++ arch/mips/kernel/setup.c 2002/05/09 17:17:59
+@@ -650,6 +650,38 @@
+ }
+ }
+
++static inline void parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
++{
++ char c = ' ', *to = command_line, *from = saved_command_line;
++ int len = 0;
++ unsigned long rd_size = 0;
++
++ for (;;) {
++ /*
++ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
++ * "rd_size=0xNN" it's size
++ */
++ if (c == ' ' && !memcmp(from, "rd_start=", 9)) {
++ if (to != command_line)
++ to--;
++ (*rd_start) = memparse(from + 9, &from);
++ }
++ if (c == ' ' && !memcmp(from, "rd_size=", 8)) {
++ if (to != command_line)
++ to--;
++ rd_size = memparse(from + 8, &from);
++ }
++ c = *(from++);
++ if (!c)
++ break;
++ if (CL_SIZE <= ++len)
++ break;
++ *(to++) = c;
++ }
++ *to = '\0';
++ (*rd_end) = (*rd_start) + rd_size;
++}
++
+ void __init setup_arch(char **cmdline_p)
+ {
+ void atlas_setup(void);
+@@ -674,10 +706,7 @@
+
+ unsigned long bootmap_size;
+ unsigned long start_pfn, max_pfn, max_low_pfn, first_usable_pfn;
+-#ifdef CONFIG_BLK_DEV_INITRD
+- unsigned long tmp;
+- unsigned long* initrd_header;
+-#endif
++ unsigned long end = &_end;
+
+ int i;
+
+@@ -828,22 +857,18 @@
+ #define MAXMEM_PFN PFN_DOWN(MAXMEM)
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+- tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+- if (tmp < (unsigned long)&_end)
+- tmp += PAGE_SIZE;
+- initrd_header = (unsigned long *)tmp;
+- if (initrd_header[0] == 0x494E5244) {
+- initrd_start = (unsigned long)&initrd_header[2];
+- initrd_end = initrd_start + initrd_header[1];
++ parse_rd_cmdline(&initrd_start, &initrd_end);
++ if(initrd_start && initrd_end)
++ end = initrd_end;
++ else {
++ initrd_start = initrd_end = 0;
+ }
+- start_pfn = PFN_UP(__pa((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
+-#else
++#endif /* CONFIG_BLK_DEV_INITRD */
+ /*
+ * Partially used pages are not usable - thus
+ * we are rounding upwards.
+ */
+- start_pfn = PFN_UP(__pa(&_end));
+-#endif /* CONFIG_BLK_DEV_INITRD */
++ start_pfn = PFN_UP(__pa(end));
+
+ /* Find the highest page frame number we have available. */
+ max_pfn = 0;
diff --git a/tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff b/tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff
new file mode 100644
index 0000000..504dd66
--- /dev/null
+++ b/tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff
@@ -0,0 +1,172 @@
+Index: arch/mips/kernel/setup.c
+===================================================================
+RCS file: /home/cvs/linux/arch/mips/kernel/setup.c,v
+retrieving revision 1.171
+diff -u -p -r1.171 setup.c
+--- arch/mips/kernel/setup.c 28 Jun 2004 21:04:12 -0000 1.171
++++ arch/mips/kernel/setup.c 19 Nov 2004 00:45:23 -0000
+@@ -194,6 +194,68 @@ static inline void parse_cmdline_early(v
+ }
+ }
+
++static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
++{
++ /*
++ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
++ * "rd_size=0xNN" it's size
++ */
++ unsigned long start = 0;
++ unsigned long size = 0;
++ unsigned long end;
++ char cmd_line[CL_SIZE];
++ char *start_str;
++ char *size_str;
++ char *tmp;
++
++ strcpy(cmd_line, command_line);
++ *command_line = 0;
++ tmp = cmd_line;
++ /* Ignore "rd_start=" strings in other parameters. */
++ start_str = strstr(cmd_line, "rd_start=");
++ if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
++ start_str = strstr(start_str, " rd_start=");
++ while (start_str) {
++ if (start_str != cmd_line)
++ strncat(command_line, tmp, start_str - tmp);
++ start = memparse(start_str + 9, &start_str);
++ tmp = start_str + 1;
++ start_str = strstr(start_str, " rd_start=");
++ }
++ if (*tmp)
++ strcat(command_line, tmp);
++
++ strcpy(cmd_line, command_line);
++ *command_line = 0;
++ tmp = cmd_line;
++ /* Ignore "rd_size" strings in other parameters. */
++ size_str = strstr(cmd_line, "rd_size=");
++ if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
++ size_str = strstr(size_str, " rd_size=");
++ while (size_str) {
++ if (size_str != cmd_line)
++ strncat(command_line, tmp, size_str - tmp);
++ size = memparse(size_str + 8, &size_str);
++ tmp = size_str + 1;
++ size_str = strstr(size_str, " rd_size=");
++ }
++ if (*tmp)
++ strcat(command_line, tmp);
++
++#ifdef CONFIG_MIPS64
++ /* HACK: Guess if the sign extension was forgotten */
++ if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
++ start |= 0xffffffff00000000;
++#endif
++
++ end = start + size;
++ if (start && end) {
++ *rd_start = start;
++ *rd_end = end;
++ return 1;
++ }
++ return 0;
++}
+
+ #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+ #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+@@ -205,30 +267,45 @@ static inline void parse_cmdline_early(v
+ static inline void bootmem_init(void)
+ {
+ unsigned long start_pfn;
++ unsigned long reserved_end = (unsigned long)&_end;
+ #ifndef CONFIG_SGI_IP27
+- unsigned long bootmap_size, max_low_pfn, first_usable_pfn;
++ unsigned long first_usable_pfn;
++ unsigned long bootmap_size;
+ int i;
+ #endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+- unsigned long tmp;
+- unsigned long *initrd_header;
++ int initrd_reserve_bootmem = 0;
+
+- tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+- if (tmp < (unsigned long)&_end)
+- tmp += PAGE_SIZE;
+- initrd_header = (unsigned long *)tmp;
+- if (initrd_header[0] == 0x494E5244) {
+- initrd_start = (unsigned long)&initrd_header[2];
+- initrd_end = initrd_start + initrd_header[1];
++ /* Board specific code should have set up initrd_start and initrd_end */
++ ROOT_DEV = Root_RAM0;
++ if (&__rd_start != &__rd_end) {
++ initrd_start = (unsigned long)&__rd_start;
++ initrd_end = (unsigned long)&__rd_end;
++ } else if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
++ reserved_end = max(reserved_end, initrd_end);
++ initrd_reserve_bootmem = 1;
++ } else {
++ unsigned long tmp;
++ unsigned long *initrd_header;
++
++ tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
++ if (tmp < reserved_end)
++ tmp += PAGE_SIZE;
++ initrd_header = (unsigned long *)tmp;
++ if (initrd_header[0] == 0x494E5244) {
++ initrd_start = (unsigned long)&initrd_header[2];
++ initrd_end = initrd_start + initrd_header[1];
++ reserved_end = max(reserved_end, initrd_end);
++ initrd_reserve_bootmem = 1;
++ }
+ }
+- start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
+-#else
++#endif /* CONFIG_BLK_DEV_INITRD */
++
+ /*
+ * Partially used pages are not usable - thus
+ * we are rounding upwards.
+ */
+- start_pfn = PFN_UP(CPHYSADDR(&_end));
+-#endif /* CONFIG_BLK_DEV_INITRD */
++ start_pfn = PFN_UP(CPHYSADDR(reserved_end));
+
+ #ifndef CONFIG_SGI_IP27
+ /* Find the highest page frame number we have available. */
+@@ -341,21 +418,14 @@ static inline void bootmem_init(void)
+
+ /* Reserve the bootmap memory. */
+ reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
+-#endif
++#endif /* CONFIG_SGI_IP27 */
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+- /* Board specific code should have set up initrd_start and initrd_end */
+- ROOT_DEV = Root_RAM0;
+- if (&__rd_start != &__rd_end) {
+- initrd_start = (unsigned long)&__rd_start;
+- initrd_end = (unsigned long)&__rd_end;
+- }
+ initrd_below_start_ok = 1;
+ if (initrd_start) {
+ unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
+ printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+- (void *)initrd_start,
+- initrd_size);
++ (void *)initrd_start, initrd_size);
+
+ if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+ printk("initrd extends beyond end of memory "
+@@ -363,7 +433,11 @@ static inline void bootmem_init(void)
+ sizeof(long) * 2, CPHYSADDR(initrd_end),
+ sizeof(long) * 2, PFN_PHYS(max_low_pfn));
+ initrd_start = initrd_end = 0;
++ initrd_reserve_bootmem = 0;
+ }
++
++ if (initrd_reserve_bootmem)
++ reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
+ }
+ #endif /* CONFIG_BLK_DEV_INITRD */
+ }
diff --git a/tip22/ld.kernel.script.in b/tip22/ld.kernel.script.in
new file mode 100644
index 0000000..df01e37
--- /dev/null
+++ b/tip22/ld.kernel.script.in
@@ -0,0 +1,11 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ .data :
+ {
+ __kernel_start = .;
+ *(.data)
+ __kernel_end = .;
+ }
+}
diff --git a/tip22/ld.ramdisk.script.in b/tip22/ld.ramdisk.script.in
new file mode 100644
index 0000000..38f11d2
--- /dev/null
+++ b/tip22/ld.ramdisk.script.in
@@ -0,0 +1,11 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ .data :
+ {
+ __rd_start = .;
+ *(.data)
+ __rd_end = .;
+ }
+}
diff --git a/tip22/ld.script.in b/tip22/ld.script.in
new file mode 100644
index 0000000..4f5597c
--- /dev/null
+++ b/tip22/ld.script.in
@@ -0,0 +1,78 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ /* XXX: place the loader after the kernel */
+ . = @@LOADADDR@@;
+
+ /* read-only */
+ _text = .; /* Text and read-only data */
+ .text : {
+ _ftext = .;
+ *(.text .text.*)
+ *(.rodata*)
+ } =0
+
+ _etext = .; /* End of text section */
+ PROVIDE (etext = .);
+
+ . = ALIGN(16);
+
+ /* writeable */
+ .data : {
+ _fdata = .;
+ *(.data .data.*)
+ } =0
+
+ _gp = ALIGN(16) + 0x7ff0;
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __bss_start = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ _fbss = .;
+ *(.dynbss)
+ *(.bss .bss.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ __bss_stop = .;
+ _end = .;
+ PROVIDE (end = .);
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ *(.stab)
+ *(.stabstr)
+ *(.pdr)
+ *(.note)
+ *(.reginfo)
+ *(.options)
+ *(.MIPS.options)
+ *(.debug*)
+ *(.line)
+ *(.mdebug*)
+ *(.comment*)
+ *(.gptab*)
+ *(.note)
+ }
+}
diff --git a/tip22/tftpload.c b/tip22/tftpload.c
new file mode 100644
index 0000000..c0bf0a2
--- /dev/null
+++ b/tip22/tftpload.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2002-04 Guido Guenther <agx@sigxcpu.org>
+ *
+ * based on arcboot/ext2load/loader.c
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <types.h>
+
+#include <arc.h>
+#include <elf.h>
+
+#include <sys/types.h>
+
+#include <version.h>
+#include <subarch.h>
+
+#define KSEG0ADDR(addr) (((addr) & 0x1fffffff) | 0x80000000)
+
+#define ANSI_CLEAR "\033[2J"
+
+typedef enum { False = 0, True } Boolean;
+
+extern void* __kernel_start;
+extern void* __kernel_end;
+extern void* __rd_start;
+extern void* __rd_end;
+
+static void Wait(const char *prompt)
+{
+ int ch;
+
+ if (prompt != NULL)
+ puts(prompt);
+
+ do {
+ ch = getchar();
+ } while ((ch != EOF) && (((char) ch) != ' '));
+}
+
+
+static void Fatal(const CHAR * message, ...)
+{
+ va_list ap;
+
+ if (message != NULL) {
+ printf("FATAL ERROR: ");
+ va_start(ap, message);
+ vprintf(message, ap);
+ va_end(ap);
+ }
+
+ Wait("\n\r--- Press <spacebar> to enter ARC interactive mode ---");
+ ArcEnterInteractiveMode();
+}
+
+
+static void InitMalloc(void)
+{
+ MEMORYDESCRIPTOR *current = NULL;
+ ULONG stack = (ULONG) & current;
+#ifdef DEBUG
+ printf("stack starts at: 0x%lx\n\r", stack);
+#endif
+
+ current = ArcGetMemoryDescriptor(current);
+ if(! current ) {
+ Fatal("Can't find any valid memory descriptors!\n\r");
+ }
+ while (current != NULL) {
+ /*
+ * The spec says we should have an adjacent FreeContiguous
+ * memory area that includes our stack. It would be much
+ * easier to just look for that and give it to malloc, but
+ * the Indy only shows FreeMemory areas, no FreeContiguous.
+ * Oh well.
+ */
+ if (current->Type == FreeMemory) {
+ ULONG start = KSEG0ADDR(current->BasePage * PAGE_SIZE);
+ ULONG end =
+ start + (current->PageCount * PAGE_SIZE);
+#if DEBUG
+ printf("Free Memory(%u) segment found at (0x%lx,0x%lx).\n\r",
+ current->Type, start, end);
+#endif
+
+ /* Leave some space for our stack */
+ if ((stack >= start) && (stack < end))
+ end =
+ (stack -
+ (STACK_PAGES *
+ PAGE_SIZE)) & ~(PAGE_SIZE - 1);
+ /* Don't use memory from reserved region */
+ if ((start >= kernel_load[SUBARCH].base )
+ && (start < (kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved )))
+ start = kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved;
+ if ((end > kernel_load[SUBARCH].base)
+ && (end <= (kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved )))
+ end = kernel_load[SUBARCH].base;
+ if (end > start) {
+#ifdef DEBUG
+ printf("Adding %lu bytes at 0x%lx to the list of available memory\n\r",
+ end-start, start);
+#endif
+ arclib_malloc_add(start, end - start);
+ }
+ }
+ current = ArcGetMemoryDescriptor(current);
+ }
+}
+
+/* convert an offset in the kernel image to an address in the loaded tftpboot image */
+static void* offset2addr(unsigned long offset)
+{
+ void* address = (void*)((ULONG)&(__kernel_start) + offset);
+ return address;
+}
+
+/* copy program segments to the locations the kernel expects */
+static ULONG CopyProgramSegments32(Elf32_Ehdr * header)
+{
+ int idx;
+ Boolean loaded = False;
+ Elf32_Phdr *segment, *segments;
+ size_t size = header->e_phentsize * header->e_phnum;
+ ULONG kernel_end=0L;
+
+ if (size <= 0)
+ Fatal("No program segments\n\r");
+
+ segments = malloc(size);
+ if (segments == NULL)
+ Fatal("Cannot allocate memory for segment headers\n\r");
+
+ segments = (Elf32_Phdr*)offset2addr(header->e_phoff);
+
+ segment = segments;
+ for (idx = 0; idx < header->e_phnum; idx++) {
+ if (segment->p_type == PT_LOAD) {
+ printf
+ ("Loading program segment %u at 0x%x, size = 0x%x\n\r",
+ idx + 1, KSEG0ADDR(segment->p_vaddr), segment->p_filesz);
+
+ memcpy((void *)segment->p_vaddr, offset2addr(segment->p_offset), segment->p_filesz);
+ /* determine the highest address used by the kernel's memory image */
+ if( kernel_end < segment->p_vaddr + segment->p_memsz ) {
+ kernel_end = segment->p_vaddr + segment->p_memsz;
+ }
+
+ size = segment->p_memsz - segment->p_filesz;
+ if (size > 0) {
+ printf
+ ("Zeroing memory at 0x%x, size = 0x%x\n\r",
+ (KSEG0ADDR(segment->p_vaddr +
+ segment->p_filesz)), size);
+ memset((void *)
+ (KSEG0ADDR(segment->
+ p_vaddr + segment->p_filesz)), 0, size);
+ }
+ loaded = True;
+ }
+ segment =
+ (Elf32_Phdr *) (((char *) segment) +
+ header->e_phentsize);
+ }
+
+ if (!loaded)
+ Fatal("No loadable program segments found\n\r");
+
+ free(segments);
+ return kernel_end;
+}
+
+static ULONG CopyProgramSegments64(Elf64_Ehdr * header)
+{
+ int idx;
+ Boolean loaded = False;
+ Elf64_Phdr *segment, *segments;
+ size_t size = header->e_phentsize * header->e_phnum;
+ ULONG kernel_end=0L;
+
+ if (size <= 0)
+ Fatal("No program segments\n\r");
+
+ segments = malloc(size);
+ if (segments == NULL)
+ Fatal("Cannot allocate memory for segment headers\n\r");
+
+ segments = (Elf64_Phdr*)offset2addr(header->e_phoff);
+
+ segment = segments;
+ for (idx = 0; idx < header->e_phnum; idx++) {
+ if (segment->p_type == PT_LOAD) {
+ printf("Loading program segment %u at 0x%x, size = 0x%llx\n\r",
+ idx + 1, KSEG0ADDR(segment->p_vaddr), segment->p_filesz);
+
+ memcpy((void *)(long)(segment->p_vaddr), offset2addr(segment->p_offset), segment->p_filesz);
+ /* determine the highest address used by the kernel's memory image */
+ if( kernel_end < segment->p_vaddr + segment->p_memsz ) {
+ kernel_end = segment->p_vaddr + segment->p_memsz;
+ }
+
+ size = segment->p_memsz - segment->p_filesz;
+ if (size > 0) {
+ printf
+ ("Zeroing memory at 0x%x, size = 0x%x\n\r",
+ (KSEG0ADDR(segment->p_vaddr +
+ segment->p_filesz)), size);
+ memset((void *)
+ (KSEG0ADDR(segment->
+ p_vaddr + segment->p_filesz)), 0, size);
+ }
+ loaded = True;
+ }
+ segment =
+ (Elf64_Phdr *) (((char *) segment) +
+ header->e_phentsize);
+ }
+
+ if (!loaded)
+ Fatal("No loadable program segments found\n\r");
+
+ free(segments);
+ return kernel_end;
+}
+
+static ULONG CopyKernel(ULONG* kernel_end)
+{
+ Elf32_Ehdr *header = (Elf32_Ehdr*)offset2addr(0L);
+ Elf64_Ehdr *header64 = (Elf64_Ehdr*)header;
+
+ if (memcmp(&(header->e_ident[EI_MAG0]), ELFMAG, SELFMAG) != 0)
+ Fatal("Not an ELF file\n\r");
+
+ if (header->e_ident[EI_CLASS] == ELFCLASS32) {
+ if (header->e_ident[EI_DATA] != ELFDATA2MSB)
+ Fatal("Not a big-endian file\n\r");
+ if (header->e_ident[EI_VERSION] != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+ if (header->e_type != ET_EXEC)
+ Fatal("Not an executable file\n\r");
+ if (header->e_machine != EM_MIPS)
+ Fatal("Unsupported machine type\n\r");
+ if (header->e_version != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ (*kernel_end) = CopyProgramSegments32(header);
+
+ printf("Starting kernel; entry point = 0x%lx\n\r",
+ ((ULONG) KSEG0ADDR(header->e_entry)));
+ return KSEG0ADDR(header->e_entry);
+ } else if (header->e_ident[EI_CLASS] == ELFCLASS64) {
+ if (header64->e_ident[EI_DATA] != ELFDATA2MSB)
+ Fatal("Not a big-endian file\n\r");
+ if (header64->e_ident[EI_VERSION] != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+ if (header64->e_type != ET_EXEC)
+ Fatal("Not an executable file\n\r");
+ if (header64->e_machine != EM_MIPS)
+ Fatal("Unsupported machine type\n\r");
+ if (header64->e_version != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ (*kernel_end) = CopyProgramSegments64(header64);
+
+ printf("Starting kernel; entry point = 0x%lx\n\r",
+ ((ULONG) KSEG0ADDR(header64->e_entry)));
+ return KSEG0ADDR(header64->e_entry);
+ } else
+ Fatal("Neither an ELF32 nor an ELF64 kernel\n\r");
+
+ return 0L;
+}
+
+static void copyRamdisk(void* rd_vaddr, void* rd_start, ULONG rd_size)
+{
+ memcpy(rd_vaddr, rd_start, rd_size);
+ printf("Copied initrd from 0x%p to 0x%p (0x%lx bytes)\n\r",
+ rd_start, rd_vaddr, rd_size);
+}
+
+void _start(LONG argc, CHAR * argv[], CHAR * envp[])
+{
+ char* nargv[3];
+ int nargc,i;
+ char argv_rd[128]; /* passed to the kernel on its commandline */
+ ULONG kernel_end = 0L;
+ ULONG rd_size= ((char*)&__rd_end) - ((char*)&__rd_start);
+ char* rd_vaddr=NULL;
+ void (*kernel_entry)(int argc, CHAR * argv[], CHAR * envp[]);
+
+ /* Print identification */
+#if (SUBARCH == IP22)
+ printf(ANSI_CLEAR "\n\rtip22: IP22 Linux tftpboot loader " __ARCSBOOT_VERSION__ "\n\r");
+#elif (SUBARCH == IP32)
+ printf(ANSI_CLEAR "\n\rtip32: IP32 Linux tftpboot loader " __ARCSBOOT_VERSION__ "\n\r");
+#endif
+
+ InitMalloc();
+
+ /* copy the kernel to its load address */
+#ifdef DEBUG
+ printf("Embedded kernel image starts 0x%p, ends 0x%p\n\r",
+ &__kernel_start, &__kernel_end);
+ printf("Embedded ramdisk image starts 0x%p, ends 0x%p\n\r",
+ &__rd_start, &__rd_end);
+#endif
+ kernel_entry = (void (*)(int, CHAR *[], CHAR *[]))CopyKernel(&kernel_end);
+
+ /* align to page boundary */
+ rd_vaddr = (char*)(((kernel_end + PAGE_SIZE) / PAGE_SIZE ) * PAGE_SIZE);
+ copyRamdisk( rd_vaddr, (char*)&__rd_start, rd_size);
+
+ /* tell the kernel about the ramdisk */
+ sprintf(argv_rd, "rd_start=0x%p rd_size=0x%lx", rd_vaddr, rd_size);
+
+ nargv[0] = argv[0];
+ nargv[1] = argv_rd;
+ nargc=2;
+ for(i=1; i < argc; i++) {
+ if( !memcmp(argv[i],"append=",7) )
+ break;
+ }
+ if( i < argc ) { /* we're asked to pass s.th. to the kernel */
+ nargv[2] = argv[i]+7;
+ nargc++;
+ }
+
+#ifdef DEBUG
+ printf("Arguments passed to kernel:\n\r");
+ for(i = 0; i < nargc; i++ )
+ printf("%u: %s\n\r", i, nargv[i]);
+ Wait("\n\r--- Debug: press <spacebar> to boot kernel ---");
+#endif
+ /* Finally jump into the kernel */
+ ArcFlushAllCaches();
+ if( kernel_entry )
+ (*kernel_entry)(nargc ,nargv, envp);
+ else
+ printf("Invalid kernel entry NULL\n\r");
+
+ /* Not likely to get back here in a functional state,
+ * but what the heck */
+ Wait("\n\r--- Press <spacebar> to restart ---");
+ ArcRestart();
+}
diff --git a/tip22/tip22 b/tip22/tip22
new file mode 100644
index 0000000..86a5eb9
--- /dev/null
+++ b/tip22/tip22
@@ -0,0 +1,51 @@
+#! /bin/sh -e
+#
+# Merges kernel and ramdisk into one ECOFF bootimage
+
+SUBARCH=IP22
+
+LIBDIR=/usr/lib/tip22
+TIP22=$LIBDIR/tftpload.$SUBARCH.o
+ARCLIB=$LIBDIR/libarc.a
+LD_KERNEL=$LIBDIR/ld.kernel.script.$SUBARCH
+LD_RAMDISK=$LIBDIR/ld.ramdisk.script.$SUBARCH
+LD_SCRIPT=$LIBDIR/ld.script.$SUBARCH
+LDFLAGS="-N"
+LD=/usr/bin/ld
+MKTEMP=/bin/mktemp
+
+usage() {
+ echo "`basename $0` vmlinux initrd outfile"
+ exit 1
+}
+
+if [ "$#" != "3" ]; then
+ usage
+fi
+
+if ! file $2 | grep 'gzip compressed data' > /dev/null 2>&1; then
+ echo "$2 is no gzip compressed ramdisk".
+ usage
+fi
+
+if ! file $1 | grep 'ELF .* MIPS' > /dev/null 2>&1; then
+ echo "$1 is no ELF kernel".
+ usage
+fi
+
+if [ ! -x $MKTEMP ]; then
+ echo "Need mktemp."
+ exit 1
+fi
+
+if ! TMPDIR=`mktemp -d`; then
+ echo "mktemp failed."
+ exit 1
+fi
+
+echo -n "Merging kernel \"$1\" and ramdisk \"$2\" into bootimage \"$3\"..."
+${LD} -T $LD_KERNEL -b binary -o $TMPDIR/kernel.o $1
+${LD} -T $LD_RAMDISK -b binary -o $TMPDIR/ramdisk.o $2
+${LD} -T $LD_SCRIPT ${LDFLAGS} -o $3 ${TIP22} ${ARCLIB} $TMPDIR/kernel.o $TMPDIR/ramdisk.o
+rm -rf $TMPDIR
+echo "done."
diff --git a/tip22/tip32 b/tip22/tip32
new file mode 100755
index 0000000..0e91bb2
--- /dev/null
+++ b/tip22/tip32
@@ -0,0 +1,51 @@
+#! /bin/sh -e
+#
+# Merges kernel and ramdisk into one ELF bootimage
+
+SUBARCH=IP32
+
+LIBDIR=/usr/lib/tip22
+TIP22=$LIBDIR/tftpload.$SUBARCH.o
+ARCLIB=$LIBDIR/libarc.a
+LD_KERNEL=$LIBDIR/ld.kernel.script.$SUBARCH
+LD_RAMDISK=$LIBDIR/ld.ramdisk.script.$SUBARCH
+LD_SCRIPT=$LIBDIR/ld.script.$SUBARCH
+LDFLAGS="-n"
+LD=/usr/bin/ld
+MKTEMP=/bin/mktemp
+
+usage() {
+ echo "`basename $0` vmlinux initrd outfile"
+ exit 1
+}
+
+if [ "$#" != "3" ]; then
+ usage
+fi
+
+if ! file $2 | grep 'gzip compressed data' > /dev/null 2>&1; then
+ echo "$2 is no gzip compressed ramdisk".
+ usage
+fi
+
+if ! file $1 | grep 'ELF .* MIPS' > /dev/null 2>&1; then
+ echo "$1 is no ELF kernel".
+ usage
+fi
+
+if [ ! -x $MKTEMP ]; then
+ echo "Need mktemp."
+ exit 1
+fi
+
+if ! TMPDIR=`mktemp -d`; then
+ echo "mktemp failed."
+ exit 1
+fi
+
+echo -n "Merging kernel \"$1\" and ramdisk \"$2\" into bootimage \"$3\"..."
+${LD} -T $LD_KERNEL -b binary -o $TMPDIR/kernel.o $1
+${LD} -T $LD_RAMDISK -b binary -o $TMPDIR/ramdisk.o $2
+${LD} -T $LD_SCRIPT ${LDFLAGS} -o $3 ${TIP22} ${ARCLIB} $TMPDIR/kernel.o $TMPDIR/ramdisk.o
+rm -rf $TMPDIR
+echo "done."