chattr.1.in: Document the compression attribute flags E, X, and
	Z, and explain that chattr can't set or set these flags.
	(Addresses Debian Bug #151990)

fsetflags.c (fsetflags), fgetflags.c (fgetflags.c), setflags.c
	(setflags), getflags.c (getflags): Check to make sure the
	file is a regular file or a directory before attempting to
	use the ext2 ioctls.  Otherwise, return EOPNOTSUPP.
	(Addresses Debian Bug #152029).

diff --git a/lib/e2p/ChangeLog b/lib/e2p/ChangeLog
index 5dfc86d..e2b1ebc 100644
--- a/lib/e2p/ChangeLog
+++ b/lib/e2p/ChangeLog
@@ -1,3 +1,11 @@
+2002-08-17  Theodore Ts'o  <tytso@mit.edu>
+
+	* fsetflags.c (fsetflags), fgetflags.c (fgetflags.c), setflags.c
+		(setflags), getflags.c (getflags): Check to make sure the
+		file is a regular file or a directory before attempting to
+		use the ext2 ioctls.  Otherwise, return EOPNOTSUPP.
+		(Addresses Debian Bug #152029).
+
 2002-07-14  Theodore Ts'o  <tytso@mit.edu>
 
 	* fsetflags.c (fsetflags), fgetflags.c (fgetflags,
diff --git a/lib/e2p/fgetflags.c b/lib/e2p/fgetflags.c
index ed4ade9..f2d0399 100644
--- a/lib/e2p/fgetflags.c
+++ b/lib/e2p/fgetflags.c
@@ -23,9 +23,9 @@
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#if HAVE_STAT_FLAGS
+#include <sys/types.h>
 #include <sys/stat.h>
-#else
+#if HAVE_EXT2_IOCTLS
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #endif
@@ -40,8 +40,8 @@
 
 int fgetflags (const char * name, unsigned long * flags)
 {
-#if HAVE_STAT_FLAGS
 	struct stat buf;
+#if HAVE_STAT_FLAGS
 
 	if (stat (name, &buf) == -1)
 		return -1;
@@ -65,6 +65,11 @@
 #if HAVE_EXT2_IOCTLS
 	int fd, r, f, save_errno = 0;
 
+	if (!stat(name, &buf) &&
+	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
+		close(fd);
+		goto notsupp;
+	}
 	fd = open (name, OPEN_FLAGS);
 	if (fd == -1)
 		return -1;
@@ -76,10 +81,9 @@
 	if (save_errno)
 		errno = save_errno;
 	return r;
-#else /* ! HAVE_EXT2_IOCTLS */
-	extern int errno;
+#endif /* HAVE_EXT2_IOCTLS */
+#endif
+notsupp:
 	errno = EOPNOTSUPP;
 	return -1;
-#endif /* ! HAVE_EXT2_IOCTLS */
-#endif
 }
diff --git a/lib/e2p/fsetflags.c b/lib/e2p/fsetflags.c
index 6942c04..f12af1c 100644
--- a/lib/e2p/fsetflags.c
+++ b/lib/e2p/fsetflags.c
@@ -23,9 +23,9 @@
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#if HAVE_CHFLAGS
-#include <sys/stat.h>		/* For the flag values.  */
-#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#if HAVE_EXT2_IOCTLS
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #endif
@@ -40,6 +40,7 @@
 
 int fsetflags (const char * name, unsigned long flags)
 {
+	struct stat buf;
 #if HAVE_CHFLAGS
 	unsigned long bsd_flags = 0;
 
@@ -61,6 +62,11 @@
 #if HAVE_EXT2_IOCTLS
 	int fd, r, f, save_errno = 0;
 
+	if (!stat(name, &buf) &&
+	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
+		close(fd);
+		goto notsupp;
+	}
 	fd = open (name, OPEN_FLAGS);
 	if (fd == -1)
 		return -1;
@@ -72,10 +78,9 @@
 	if (save_errno)
 		errno = save_errno;
 	return r;
-#else /* ! HAVE_EXT2_IOCTLS */
-	extern int errno;
+#endif /* HAVE_EXT2_IOCTLS */
+#endif
+notsupp:
 	errno = EOPNOTSUPP;
 	return -1;
-#endif /* ! HAVE_EXT2_IOCTLS */
-#endif
 }
diff --git a/lib/e2p/getflags.c b/lib/e2p/getflags.c
index 477cb9b..acf7a12 100644
--- a/lib/e2p/getflags.c
+++ b/lib/e2p/getflags.c
@@ -17,9 +17,9 @@
 #if HAVE_ERRNO_H
 #include <errno.h>
 #endif
-#if HAVE_STAT_FLAGS
+#include <sys/types.h>
 #include <sys/stat.h>
-#else
+#if HAVE_EXT2_IOCTLS
 #include <sys/ioctl.h>
 #endif
 
@@ -27,8 +27,8 @@
 
 int getflags (int fd, unsigned long * flags)
 {
-#if HAVE_STAT_FLAGS
 	struct stat buf;
+#if HAVE_STAT_FLAGS
 
 	if (fstat (fd, &buf) == -1)
 		return -1;
@@ -52,13 +52,15 @@
 #if HAVE_EXT2_IOCTLS
 	int r, f;
 	
+	if (!fstat(fd, &buf) &&
+	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode))
+		goto notsupp;
 	r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
 	*flags = f;
 	return r;
-#else /* ! HAVE_EXT2_IOCTLS */
-	extern int errno;
+#endif /* HAVE_EXT2_IOCTLS */
+#endif
+notsupp:
 	errno = EOPNOTSUPP;
 	return -1;
-#endif /* ! HAVE_EXT2_IOCTLS */
-#endif
 }
diff --git a/lib/e2p/setflags.c b/lib/e2p/setflags.c
index 2bf47fa..1693035 100644
--- a/lib/e2p/setflags.c
+++ b/lib/e2p/setflags.c
@@ -17,10 +17,9 @@
 #if HAVE_ERRNO_H
 #include <errno.h>
 #endif
-#if HAVE_CHFLAGS
 #include <sys/types.h>
-#include <sys/stat.h>		/* For the flag values.  */
-#else
+#include <sys/stat.h>
+#if HAVE_EXT2_IOCTLS
 #include <sys/ioctl.h>
 #endif
 
@@ -28,6 +27,7 @@
 
 int setflags (int fd, unsigned long flags)
 {
+	struct stat buf;
 #if HAVE_CHFLAGS
 	unsigned long bsd_flags = 0;
 
@@ -49,12 +49,15 @@
 #if HAVE_EXT2_IOCTLS
 	int	f;
 
+	if (!fstat(fd, &buf) &&
+	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
+		errno = EOPNOTSUPP;
+		return -1;
+	}
 	f = (int) flags;
 	return ioctl (fd, EXT2_IOC_SETFLAGS, &f);
-#else /* ! HAVE_EXT2_IOCTLS */
-	extern int errno;
+#endif /* HAVE_EXT2_IOCTLS */
+#endif
 	errno = EOPNOTSUPP;
 	return -1;
-#endif /* ! HAVE_EXT2_IOCTLS */
-#endif
 }
diff --git a/misc/ChangeLog b/misc/ChangeLog
index 59325b6..ec3e1e9 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -1,5 +1,9 @@
 2002-08-17  Theodore Ts'o  <tytso@mit.edu>
 
+	* chattr.1.in: Document the compression attribute flags E, X, and
+		Z, and explain that chattr can't set or set these flags.
+		(Addresses Debian Bug #151990)
+
 	* fsck.8.in: Fix typo in man page, and clarified text regarding
 		options specifiers for -t option.  (Addresses Debian bug 
 		#145044)
diff --git a/misc/chattr.1.in b/misc/chattr.1.in
index 590cca0..218a291 100644
--- a/misc/chattr.1.in
+++ b/misc/chattr.1.in
@@ -53,10 +53,21 @@
 by the kernel. A read from this file returns uncompressed data. A write to
 this file compresses data before storing them on the disk.
 .PP
+When a directory with the `D' attribute set is modified,
+the changes are written synchronously on the disk; this is equivalent to
+the `dirsync' mount option applied to a subset of the files.
+.PP
 A file with the `d' attribute set is not candidate for backup when the
 .BR dump (8)
 program is run.
 .PP
+The 'E' attribute is used by the experimental compression patches to 
+indicate that a compressed file has a compression error.  It may not be
+set or reset using 
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
 A file with the `i' attribute cannot be modified: it cannot be deleted or
 renamed, no link can be created to this file and no data can be written
 to the file. Only the superuser can set or clear this attribute.
@@ -74,10 +85,6 @@
 the changes are written synchronously on the disk; this is equivalent to
 the `sync' mount option applied to a subset of the files.
 .PP
-When a directory with the `D' attribute set is modified,
-the changes are written synchronously on the disk; this is equivalent to
-the `dirsync' mount option applied to a subset of the files.
-.PP
 A file with the 't' attribute will not have a partial block fragment at
 the of the file merged with other files (for those filesystems which
 support tail-merging).  This is necessary for applications such as LILO 
@@ -87,6 +94,19 @@
 When a file with the `u' attribute set is deleted, its contents are saved.
 This allows the user to ask for its undeletion.
 .PP
+The 'X' attribute is used by the experimental compression patches to 
+indicate that a raw contents of a compressed file can be accessed
+directly.  It currently may not be set or reset using 
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
+The 'Z' attribute is used by the experimental compression patches to 
+indicate a compressed file is dirty.  It may not be set or reset using 
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
 .SH AUTHOR
 .B chattr
 was written by Remy Card <Remy.Card@linux.org>.