Many files:
  unix.c (main): If compression is enabled on the filesystem, print a
  	warning message (for now).
  message.c: Add new compression shortcut: @c == compress
  problem.c, problem.h (PR_1_COMPR_SET): Add new error code.
  pass1.c (check_blocks): If the inode has EXT2_COMPRBLK_FL flag set,
  	check to see if the filesystem supports compression.  If it does pass
  	this information down to process_block() so it can treat the
  	compressed block flag words correctly.  If not, offer to clear the
  	flag, since it shouldn't be set.
  	(process_block): If an inode has the compressed inode flag set, allow
  	EXT2FS_COMPRESSED_BLKADDR.
  pass1b.c (process_pass1b_block, delete_file_block, clone_file_block):
  pass2.c (deallocate_inode_block): Use HOLE_BLKADDR to check to see if
  	the block can be skipped.
ChangeLog, Makefile.in:
  Makefile.in: Exclude the internationalization files from being
  	distributed.
ChangeLog, configure, configure.in:
  configure.in: Add support for --enable-compression.  This is
  	experimental code only for now, which is why it's under --enable test.
  	Once it's stable, it will always be compiled in.
TODO:
  Commit additional TODO items.

diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 32a43ad..89c2133 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,26 @@
+2000-02-11    <tytso@snap.thunk.org>
+
+	* unix.c (main): If compression is enabled on the filesystem,
+		print a warning message (for now).
+
+	* message.c: Add new compression shortcut: @c == compress
+
+	* problem.c, problem.h (PR_1_COMPR_SET): Add new error code.
+
+	* pass1.c (check_blocks): If the inode has EXT2_COMPRBLK_FL flag
+		set, check to see if the filesystem supports compression.
+		If it does pass this information down to process_block()
+		so it can treat the compressed block flag words
+		correctly.  If not, offer to clear the flag, since it
+		shouldn't be set.  
+		(process_block): If an inode has the compressed inode flag
+		set, allow EXT2FS_COMPRESSED_BLKADDR.
+
+	* pass1b.c (process_pass1b_block, delete_file_block,
+		clone_file_block):
+	* pass2.c (deallocate_inode_block): Use HOLE_BLKADDR to check to
+		see if the block can be skipped.
+
 2000-02-08    <tytso@snap.thunk.org>
 
 	* util.c: Make resource tracking message more concise.
diff --git a/e2fsck/message.c b/e2fsck/message.c
index bace3c5..3018cc0 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -50,6 +50,7 @@
  * 	@A	error allocating
  * 	@b	block
  * 	@B	bitmap
+ * 	@c	compress
  * 	@C	conflicts with some other fs block
  * 	@i	inode
  * 	@I	illegal
@@ -95,6 +96,7 @@
 	N_("Aerror allocating"),
 	N_("bblock"),
 	N_("Bbitmap"),
+	N_("ccompress"),
 	N_("Cconflicts with some other fs @b"),
 	N_("iinode"),
 	N_("Iillegal"),
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index cf30ef6..771c505 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -72,7 +72,8 @@
 
 struct process_block_struct {
 	ino_t		ino;
-	int		is_dir:1, clear:1, suppress:1, fragmented:1;
+	int		is_dir:1, clear:1, suppress:1,
+				fragmented:1, compressed:1;
 	blk_t		num_blocks;
 	e2_blkcnt_t	last_block;
 	int		num_illegal_blocks;
@@ -773,12 +774,27 @@
 	pb.num_illegal_blocks = 0;
 	pb.suppress = 0; pb.clear = 0;
 	pb.fragmented = 0;
+	pb.compressed = 0;
 	pb.previous_block = 0;
 	pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
 	pb.inode = inode;
 	pb.pctx = pctx;
 	pb.ctx = ctx;
 	pctx->ino = ino;
+
+	if (inode->i_flags & EXT2_COMPRBLK_FL) {
+		if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+				      EXT2_FEATURE_INCOMPAT_COMPRESSION))
+			pb.compressed = 1;
+		else {
+			if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
+				inode->i_flags &= ~EXT2_COMPRBLK_FL;
+				e2fsck_write_inode(ctx, ino, inode,
+						   "check_blocks");
+			}
+		}
+	}
+
 	pctx->errcode = ext2fs_block_iterate2(fs, ino,
 				       pb.is_dir ? BLOCK_FLAG_HOLE : 0,
 				       block_buf, process_block, &pb);
@@ -941,6 +957,28 @@
 	pctx = p->pctx;
 	ctx = p->ctx;
 
+	if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
+		/* todo: Check that the comprblk_fl is high, that the
+		   blkaddr pattern looks right (all non-holes up to
+		   first EXT2FS_COMPRESSED_BLKADDR, then all
+		   EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
+		   that the feature_incompat bit is high, and that the
+		   inode is a regular file.  If we're doing a "full
+		   check" (a concept introduced to e2fsck by e2compr,
+		   meaning that we look at data blocks as well as
+		   metadata) then call some library routine that
+		   checks the compressed data.  I'll have to think
+		   about this, because one particularly important
+		   problem to be able to fix is to recalculate the
+		   cluster size if necessary.  I think that perhaps
+		   we'd better do most/all e2compr-specific checks
+		   separately, after the non-e2compr checks.  If not
+		   doing a full check, it may be useful to test that
+		   the personality is linux; e.g. if it isn't then
+		   perhaps this really is just an illegal block. */
+		return 0;
+	}
+	
 	if (blk == 0) {
 		if (p->is_dir == 0) {
 			/*
@@ -976,7 +1014,7 @@
 	 * file be contiguous.  (Which can never be true for really
 	 * big files that are greater than a block group.)
 	 */
-	if (p->previous_block) {
+	if (!HOLE_BLKADDR(p->previous_block)) {
 		if (p->previous_block+1 != blk)
 			p->fragmented = 1;
 	}
@@ -1057,6 +1095,11 @@
 	struct problem_context *pctx;
 	e2fsck_t	ctx;
 
+	/*
+	 * Note: This function processes blocks for the bad blocks
+	 * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
+	 */
+
 	if (!blk)
 		return 0;
 	
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index a1cbf18..5db39ab 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -241,7 +241,7 @@
 	int i;
 	e2fsck_t ctx;
 
-	if (!*block_nr)
+	if (HOLE_BLKADDR(*block_nr))
 		return 0;
 	p = (struct process_block_struct *) priv_data;
 	ctx = p->ctx;
@@ -493,7 +493,7 @@
 	pb = (struct process_block_struct *) priv_data;
 	ctx = pb->ctx;
 
-	if (!*block_nr)
+	if (HOLE_BLKADDR(*block_nr))
 		return 0;
 
 	if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
@@ -567,7 +567,7 @@
 
 	ctx = cs->ctx;
 	
-	if (!*block_nr)
+	if (HOLE_BLKADDR(*block_nr))
 		return 0;
 
 	if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 826c0dc..6b95900 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -605,7 +605,7 @@
 {
 	e2fsck_t	ctx = (e2fsck_t) priv_data;
 	
-	if (!*block_nr)
+	if (HOLE_BLKADDR(*block_nr))
 		return 0;
 	ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
 	ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 96509d8..0a72061 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -423,6 +423,11 @@
 	  N_("Special (device/socket/fifo) @i %i has immutable flag set.  "),
 	  PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
 
+	/* Imagic flag set on an inode when filesystem doesn't support it */
+	{ PR_1_COMPR_SET,
+	  N_("@i %i has @cion flag set on @f without @cion support.  "),
+	  PROMPT_CLEAR, 0 },
+
 	/* Pass 1b errors */
 
 	/* Pass 1B: Rescan for duplicate/bad blocks */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 9aa2cc9..1de1dc9 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -241,7 +241,10 @@
 
 /* Immutable flag set on a device or socket inode */
 #define PR_1_SET_IMMUTABLE		0x010030
-	
+
+/* Compression flag set on a non-compressed filesystem */
+#define PR_1_COMPR_SET			0x010031
+
 /*
  * Pass 1b errors
  */
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index fbe5980..9696a77 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -757,6 +757,11 @@
 			"(%s)", ctx->filesystem_name);
 		goto get_newer;
 	}
+#ifdef ENABLE_COMPRESSION
+	if (s->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
+		com_err(ctx->program_name, 0,
+			_("Warning: compression support is experimental.\n"));
+#endif
 	if (ctx->device_name == 0 &&
 	    (s->s_volume_name[0] != 0)) {
 		char *cp = malloc(sizeof(s->s_volume_name)+1);