Merge branch 'cl/remove-masix' into next
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 37dbeba..8261d18 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -785,7 +785,8 @@
 
 	sprintf(buf, format, *val);
 	printf("%30s    [%s] ", prompt, buf);
-	fgets(buf, sizeof(buf), stdin);
+	if (!fgets(buf, sizeof(buf), stdin))
+		return;
 	if (buf[strlen (buf) - 1] == '\n')
 		buf[strlen (buf) - 1] = '\0';
 	if (!buf[0])
@@ -806,7 +807,8 @@
 
 	sprintf(buf, format, *val);
 	printf("%30s    [%s] ", prompt, buf);
-	fgets(buf, sizeof(buf), stdin);
+	if (!fgets(buf, sizeof(buf), stdin))
+		return;
 	if (buf[strlen (buf) - 1] == '\n')
 		buf[strlen (buf) - 1] = '\0';
 	if (!buf[0])
@@ -827,7 +829,8 @@
 
 	sprintf(buf, format, *val);
 	printf("%30s    [%s] ", prompt, buf);
-	fgets(buf, sizeof(buf), stdin);
+	if (!fgets(buf, sizeof(buf), stdin))
+		return;
 	if (buf[strlen (buf) - 1] == '\n')
 		buf[strlen (buf) - 1] = '\0';
 	if (!buf[0])
diff --git a/doc/libext2fs.texinfo b/doc/libext2fs.texinfo
index 1277c3a..82661d0 100644
--- a/doc/libext2fs.texinfo
+++ b/doc/libext2fs.texinfo
@@ -7,11 +7,9 @@
 
 @ifinfo
 @dircategory Development
-@format
-START-INFO-DIR-ENTRY
+@direntry
 * libext2fs: (libext2fs.info).                  The EXT2FS library.
-END-INFO-DIR-ENTRY
-@end format
+@end direntry
 @end ifinfo
 
 @c smallbook
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index d072e73..56218ae 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -316,7 +316,7 @@
 
 	/* simple remove all possible EA(s) */
 	*((__u32 *)start) = 0UL;
-	e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *) inode,
+	e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
 				EXT2_INODE_SIZE(sb), "pass1");
 }
 
diff --git a/lib/blkid/blkid.pc.in b/lib/blkid/blkid.pc.in
index 510aa84..ff51782 100644
--- a/lib/blkid/blkid.pc.in
+++ b/lib/blkid/blkid.pc.in
@@ -8,4 +8,5 @@
 Version: @E2FSPROGS_VERSION@
 Requires: uuid @DEVMAPPER_REQ@
 Cflags: -I${includedir} 
-Libs: -L${libdir} -lblkid @DEVMAPPER_PC_LIBS@
+Libs: -L${libdir} -lblkid
+Libs.private: @DEVMAPPER_PC_LIBS@
diff --git a/lib/blkid/test_probe.in b/lib/blkid/test_probe.in
index 02d42bb..ce8c42f 100644
--- a/lib/blkid/test_probe.in
+++ b/lib/blkid/test_probe.in
@@ -8,7 +8,7 @@
 	done
 fi
 
-mkdir -p tests
+mkdir -p tests/tmp
 
 for i in $TESTS
 do
@@ -19,9 +19,9 @@
 		echo "non-existent"
 		continue
 	fi
-	bunzip2 < $SRCDIR/tests/$i.img.bz2 > /tmp/test.img.$$
-	./tst_probe /tmp/test.img.$$ > tests/$i.out
-	/bin/rm -f /tmp/test.img.$$ tests/$i.ok tests/$i.failed
+	bunzip2 < $SRCDIR/tests/$i.img.bz2 > tests/tmp/test.img.$$
+	./tst_probe tests/tmp/test.img.$$ > tests/$i.out
+	/bin/rm -f tests/tmp/test.img.$$ tests/$i.ok tests/$i.failed
 	cmp -s tests/$i.out $SRCDIR/tests/$i.results
 	if [ $? = 0 ];  then
 		echo ok
diff --git a/lib/e2p/fgetflags.c b/lib/e2p/fgetflags.c
index 0aed6c8..372304f 100644
--- a/lib/e2p/fgetflags.c
+++ b/lib/e2p/fgetflags.c
@@ -65,7 +65,7 @@
 #if HAVE_EXT2_IOCTLS
 	int fd, r, f, save_errno = 0;
 
-	if (!stat(name, &buf) &&
+	if (!lstat(name, &buf) &&
 	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
 		goto notsupp;
 	}
diff --git a/lib/e2p/fsetflags.c b/lib/e2p/fsetflags.c
index 2f1277f..3a05324 100644
--- a/lib/e2p/fsetflags.c
+++ b/lib/e2p/fsetflags.c
@@ -71,7 +71,7 @@
 #if HAVE_EXT2_IOCTLS
 	int fd, r, f, save_errno = 0;
 
-	if (!stat(name, &buf) &&
+	if (!lstat(name, &buf) &&
 	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
 		goto notsupp;
 	}
diff --git a/lib/e2p/iod.c b/lib/e2p/iod.c
index 808d3a3..84c9709 100644
--- a/lib/e2p/iod.c
+++ b/lib/e2p/iod.c
@@ -27,7 +27,7 @@
 {
 	DIR * dir;
 	struct dirent *de, *dep;
-	int	max_len = -1, len;
+	int	max_len = -1, len, ret = 0;
 
 #if HAVE_PATHCONF && defined(_PC_NAME_MAX) 
 	max_len = pathconf(dir_name, _PC_NAME_MAX);
@@ -64,9 +64,10 @@
 			len = max_len;
 #endif
 		memcpy(de, dep, len);
-		(*func) (dir_name, de, private);
+		if ((*func)(dir_name, de, private))
+			ret++;
 	}
 	free(de);
 	closedir(dir);
-	return 0;
+	return ret;
 }
diff --git a/lib/et/com_err.texinfo b/lib/et/com_err.texinfo
index def088c..7a00ffe 100644
--- a/lib/et/com_err.texinfo
+++ b/lib/et/com_err.texinfo
@@ -19,11 +19,9 @@
 
 @ifinfo
 @dircategory Development
-@format
-START-INFO-DIR-ENTRY
+@direntry
 * Com_err: (com_err).   A Common Error Description Library for UNIX.
-END-INFO-DIR-ENTRY
-@end format
+@end direntry
 @end ifinfo
 
 @iftex
diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c
index 24246e0..cb563fd 100644
--- a/lib/ext2fs/ismounted.c
+++ b/lib/ext2fs/ismounted.c
@@ -251,10 +251,8 @@
 	if (!(f = fopen("/proc/swaps", "r")))
 		return 0;
 	/* Skip the first line */
-	fgets(buf, sizeof(buf), f);
-	while (!feof(f)) {
-		if (!fgets(buf, sizeof(buf), f))
-			break;
+	if (fgets(buf, sizeof(buf), f))
+	while (fgets(buf, sizeof(buf), f)) {
 		if ((cp = strchr(buf, ' ')) != NULL)
 			*cp = 0;
 		if ((cp = strchr(buf, '\t')) != NULL)
diff --git a/lib/ss/ss.pc.in b/lib/ss/ss.pc.in
index 0218fd5..ce284fc 100644
--- a/lib/ss/ss.pc.in
+++ b/lib/ss/ss.pc.in
@@ -8,4 +8,5 @@
 Version: @E2FSPROGS_VERSION@
 Requires: com_err
 Cflags: -I${includedir} 
-Libs: -L${libdir} -lss @DLOPEN_LIB@
+Libs: -L${libdir} -lss
+Libs.private: @DLOPEN_LIB@
diff --git a/misc/badblocks.c b/misc/badblocks.c
index 29c5a5c..709effe 100644
--- a/misc/badblocks.c
+++ b/misc/badblocks.c
@@ -67,13 +67,13 @@
 static int force = 0;			/* force check of mounted device */
 static int t_flag = 0;			/* number of test patterns */
 static int t_max = 0;			/* allocated test patterns */
-static unsigned long *t_patts = NULL;	/* test patterns */
+static unsigned int *t_patts = NULL;	/* test patterns */
 static int current_O_DIRECT = 0;	/* Current status of O_DIRECT flag */
 static int exclusive_ok = 0;
 
 #define T_INC 32
 
-int sys_page_size = 4096;
+unsigned int sys_page_size = 4096;
 
 static void usage(void)
 {
@@ -90,8 +90,8 @@
 	exit(1);
 }
 
-static unsigned long currently_testing = 0;
-static unsigned long num_blocks = 0;
+static blk_t currently_testing = 0;
+static blk_t num_blocks = 0;
 static ext2_badblocks_list bb_list = NULL;
 static FILE *out;
 static blk_t next_bad = 0;
@@ -124,14 +124,14 @@
  * This routine reports a new bad block.  If the bad block has already
  * been seen before, then it returns 0; otherwise it returns 1.
  */
-static int bb_output (unsigned long bad)
+static int bb_output (blk_t bad)
 {
 	errcode_t errcode;
 
 	if (ext2fs_badblocks_list_test(bb_list, bad))
 		return 0;
 
-	fprintf(out, "%lu\n", bad);
+	fprintf(out, "%lu\n", (unsigned long) bad);
 	fflush(out);
 
 	errcode = ext2fs_badblocks_list_add (bb_list, bad);
@@ -151,7 +151,8 @@
 
 static void print_status(void)
 {
-	fprintf(stderr, "%15ld/%15ld", currently_testing, num_blocks);
+	fprintf(stderr, "%15lu/%15lu", (unsigned long) currently_testing, 
+		(unsigned long) num_blocks);
 	fputs("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", stderr);
 	fflush (stderr);
 }
@@ -197,7 +198,7 @@
 }
 
 static void set_o_direct(int dev, unsigned char *buffer, size_t size,
-			 unsigned long current_block)
+			 blk_t current_block)
 {
 #ifdef O_DIRECT
 	int new_flag = O_DIRECT;
@@ -221,13 +222,13 @@
 }
 
 
-static void pattern_fill(unsigned char *buffer, unsigned long pattern,
+static void pattern_fill(unsigned char *buffer, unsigned int pattern,
 			 size_t n)
 {
 	unsigned int	i, nb;
 	unsigned char	bpattern[sizeof(pattern)], *ptr;
 	
-	if (pattern == (unsigned long) ~0) {
+	if (pattern == (unsigned int) ~0) {
 		for (ptr = buffer; ptr < buffer + n; ptr++) {
 			(*ptr) = random() % (1 << (8 * sizeof(char)));
 		}
@@ -262,8 +263,8 @@
  * Perform a read of a sequence of blocks; return the number of blocks
  *    successfully sequentially read.
  */
-static long do_read (int dev, unsigned char * buffer, int try, int block_size,
-		     unsigned long current_block)
+static int do_read (int dev, unsigned char * buffer, int try, int block_size,
+		    blk_t current_block)
 {
 	long got;
 
@@ -291,8 +292,8 @@
  * Perform a write of a sequence of blocks; return the number of blocks
  *    successfully sequentially written.
  */
-static long do_write (int dev, unsigned char * buffer, int try, int block_size,
-		     unsigned long current_block)
+static int do_write(int dev, unsigned char * buffer, int try, int block_size,
+		    unsigned long current_block)
 {
 	long got;
 
@@ -327,13 +328,13 @@
 		com_err(program_name, retval, _("during ext2fs_sync_device"));
 }
 
-static unsigned int test_ro (int dev, unsigned long last_block,
-			     int block_size, unsigned long from_count,
-			     unsigned long blocks_at_once)
+static unsigned int test_ro (int dev, blk_t last_block,
+			     int block_size, blk_t from_count,
+			     unsigned int blocks_at_once)
 {
 	unsigned char * blkbuf;
 	int try;
-	long got;
+	int got;
 	unsigned int bb_count = 0;
 	errcode_t errcode;
 
@@ -358,8 +359,9 @@
 		exit (1);
 	}
 	if (v_flag) {
-	    fprintf (stderr, _("Checking blocks %lu to %lu\n"), from_count,
-		     last_block - 1);
+		fprintf (stderr, _("Checking blocks %lu to %lu\n"), 
+			 (unsigned long) from_count, 
+			 (unsigned long) last_block - 1);
 	}
 	if (t_flag) {
 		fputs(_("Checking for bad blocks in read-only mode\n"), stderr);
@@ -404,7 +406,7 @@
 		if (got == try) {
 			try = blocks_at_once;
 			/* recover page-aligned offset for O_DIRECT */
-			if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9)
+			if ( (blocks_at_once >= sys_page_size >> 9)
 			     && (currently_testing % (sys_page_size >> 9)!= 0))
 				try -= (sys_page_size >> 9)
 					- (currently_testing 
@@ -430,13 +432,13 @@
 	return bb_count;
 }
 
-static unsigned int test_rw (int dev, unsigned long last_block,
-			     int block_size, unsigned long from_count,
-			     unsigned long blocks_at_once)
+static unsigned int test_rw (int dev, blk_t last_block,
+			     int block_size, blk_t from_count,
+			     unsigned int blocks_at_once)
 {
 	unsigned char *buffer, *read_buffer;
-	const unsigned long patterns[] = {0xaa, 0x55, 0xff, 0x00};
-	const unsigned long *pattern;
+	const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00};
+	const unsigned int *pattern;
 	int i, try, got, nr_pattern, pat_idx;
 	unsigned int bb_count = 0;
 
@@ -454,7 +456,8 @@
 		fputs(_("Checking for bad blocks in read-write mode\n"), 
 		      stderr);
 		fprintf(stderr, _("From block %lu to %lu\n"),
-			 from_count, last_block);
+			(unsigned long) from_count, 
+			(unsigned long) last_block);
 	}
 	if (t_flag) {
 		pattern = t_patts;
@@ -484,7 +487,7 @@
 			if (got == try) {
 				try = blocks_at_once;
 				/* recover page-aligned offset for O_DIRECT */
-				if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9)
+				if ( (blocks_at_once >= sys_page_size >> 9)
 				     && (currently_testing % 
 					 (sys_page_size >> 9)!= 0))
 					try -= (sys_page_size >> 9)
@@ -528,7 +531,7 @@
 			}
 			currently_testing += got;
 			/* recover page-aligned offset for O_DIRECT */
-			if ( blocks_at_once >= (unsigned long) (sys_page_size >> 9)
+			if ( (blocks_at_once >= sys_page_size >> 9)
 			     && (currently_testing % (sys_page_size >> 9)!= 0))
 				try = blocks_at_once - (sys_page_size >> 9)
 					- (currently_testing 
@@ -555,17 +558,18 @@
 	int	num;
 };
 
-static unsigned int test_nd (int dev, unsigned long last_block,
-			     int block_size, unsigned long from_count,
-			     unsigned long blocks_at_once)
+static unsigned int test_nd (int dev, blk_t last_block,
+			     int block_size, blk_t from_count,
+			     unsigned int blocks_at_once)
 {
 	unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr;
 	unsigned char *test_base, *save_base, *read_base;
 	int try, i;
-	const unsigned long patterns[] = { ~0 };
-	const unsigned long *pattern;
+	const unsigned int patterns[] = { ~0 };
+	const unsigned int *pattern;
 	int nr_pattern, pat_idx;
-	long got, used2, written, save_currently_testing;
+	int got, used2, written;
+	blk_t save_currently_testing;
 	struct saved_blk_record *test_record;
 	/* This is static to prevent being clobbered by the longjmp */
 	static int num_saved;
@@ -601,7 +605,8 @@
 	flush_bufs();
 	if (v_flag) {
 	    fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr);
-	    fprintf (stderr, _("From block %lu to %lu\n"), from_count, last_block);
+	    fprintf (stderr, _("From block %lu to %lu\n"), 
+		     (unsigned long) from_count, (unsigned long) last_block);
 	}
 	if (s_flag || v_flag > 1) {
 		fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr);
@@ -682,7 +687,8 @@
 			if (written != got)
 				com_err (program_name, errno,
 					 _("during test data write, block %lu"),
-					 currently_testing + written);
+					 (unsigned long) currently_testing + 
+					 written);
 
 			buf_used += got;
 			save_ptr += got * block_size;
@@ -813,27 +819,43 @@
 
 }
 
+/*
+ * This function will convert a string to an unsigned long, printing
+ * an error message if it fails, and returning success or failure in err.
+ */
+static unsigned int parse_uint(const char *str, const char *descr)
+{
+	char		*tmp;
+	unsigned long	ret;
+	
+	ret = strtoul(str, &tmp, 0);
+	if (*tmp || errno || (ret > UINT_MAX) ||
+	    (ret == ULONG_MAX && errno == ERANGE)) {
+		com_err (program_name, 0, _("invalid %s - %s"), descr, str);
+		exit (1);
+	}
+	return ret;
+}
 
 int main (int argc, char ** argv)
 {
 	int c;
-	char * tmp;
 	char * device_name;
 	char * host_device_name = NULL;
 	char * input_file = NULL;
 	char * output_file = NULL;
 	FILE * in = NULL;
 	int block_size = 1024;
-	unsigned long blocks_at_once = 64;
+	unsigned int blocks_at_once = 64;
 	blk_t last_block, from_count;
 	int num_passes = 0;
 	int passes_clean = 0;
 	int dev;
 	errcode_t errcode;
-	unsigned long pattern;
-	unsigned int (*test_func)(int, unsigned long,
-				  int, unsigned long,
-				  unsigned long);
+	unsigned int pattern;
+	unsigned int (*test_func)(int, blk_t,
+				  int, blk_t,
+				  unsigned int);
 	int open_flag = 0;
 	long sysval;
 
@@ -865,8 +887,8 @@
 	while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:t:X")) != EOF) {
 		switch (c) {
 		case 'b':
-			block_size = strtoul (optarg, &tmp, 0);
-			if (*tmp || block_size > 4096) {
+			block_size = parse_uint(optarg, "block size");
+			if (block_size > 4096) {
 				com_err (program_name, 0,
 					 _("bad block size - %s"), optarg);
 				exit (1);
@@ -900,27 +922,18 @@
 			w_flag = 2;
 			break;
 		case 'c':
-			blocks_at_once = strtoul (optarg, &tmp, 0);
-			if (*tmp) {
-				com_err (program_name, 0,
-					 "bad simultaneous block count - %s", optarg);
-				exit (1);
-			}
+			blocks_at_once = parse_uint(optarg, "blocks at once");
 			break;
 		case 'p':
-			num_passes = strtoul (optarg, &tmp, 0);
-			if (*tmp) {
-				com_err (program_name, 0,
-				    "bad number of clean passes - %s", optarg);
-				exit (1);
-			}
+			num_passes = parse_uint(optarg, 
+						"number of clean passes");
 			break;
 		case 'h':
 			host_device_name = optarg;
 			break;
 		case 't':
 			if (t_flag + 1 > t_max) {
-				unsigned long *t_patts_new;
+				unsigned int *t_patts_new;
 
 				t_patts_new = realloc(t_patts, t_max + T_INC);
 				if (!t_patts_new) {
@@ -936,14 +949,8 @@
 			if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) {
 				t_patts[t_flag++] = ~0;
 			} else {
-				pattern = strtoul(optarg, &tmp, 0);
-				if (*tmp) {
-					com_err(program_name, 0,
-					_("invalid test_pattern: %s\n"),
-						optarg);
-					exit(1);
-				}
-				if (pattern == (unsigned long) ~0)
+				pattern = parse_uint(optarg, "test pattern");
+				if (pattern == (unsigned int) ~0)
 					pattern = 0xffff;
 				t_patts[t_flag++] = pattern;
 			}
@@ -962,7 +969,7 @@
 			  "in read-only mode"));
 			exit(1);
 		}
-		if (t_patts && (t_patts[0] == (unsigned long) ~0)) {
+		if (t_patts && (t_patts[0] == (unsigned int) ~0)) {
 			com_err(program_name, 0,
 			_("Random test_pattern is not allowed "
 			  "in read-only mode"));
@@ -989,27 +996,15 @@
 		}
 	} else {
 		errno = 0;
-		last_block = strtoul (argv[optind], &tmp, 0);
+		last_block = parse_uint(argv[optind], "last block");
 		printf("last_block = %d (%s)\n", last_block, argv[optind]);
-		if (*tmp || errno || 
-		    (last_block == ULONG_MAX && errno == ERANGE)) {
-			com_err (program_name, 0, _("invalid blocks count - %s"),
-				 argv[optind]);
-			exit (1);
-		}
 		last_block++;
 		optind++;
 	}
 	if (optind <= argc-1) {
 		errno = 0;
-		from_count = strtoul (argv[optind], &tmp, 0);
+		from_count = parse_uint(argv[optind], "start block");
 		printf("from_count = %d\n", from_count);
-		if (*tmp || errno ||
-		    (from_count == ULONG_MAX && errno == ERANGE)) {
-			com_err (program_name, 0, _("invalid starting block - %s"),
-				 argv[optind]);
-			exit (1);
-		}
 	} else from_count = 0;
 	if (from_count >= last_block) {
 	    com_err (program_name, 0, _("invalid starting block (%lu): must be less than %lu"),
diff --git a/misc/chattr.1.in b/misc/chattr.1.in
index 2b48fb0..2334675 100644
--- a/misc/chattr.1.in
+++ b/misc/chattr.1.in
@@ -5,7 +5,7 @@
 .SH SYNOPSIS
 .B chattr
 [
-.B \-RV
+.B \-RVf
 ]
 [
 .B \-v
@@ -34,12 +34,13 @@
 .TP
 .B \-R
 Recursively change attributes of directories and their contents.
-Symbolic links encountered during recursive directory traversals are
-ignored.
 .TP
 .B \-V
 Be verbose with chattr's output and print the program version.
 .TP
+.B \-f
+Suppress most error messages.
+.TP
 .BI \-v " version"
 Set the file's version/generation number.
 .SH ATTRIBUTES
diff --git a/misc/chattr.c b/misc/chattr.c
index c6d8d9f..efaa559 100644
--- a/misc/chattr.c
+++ b/misc/chattr.c
@@ -65,6 +65,7 @@
 
 static int recursive;
 static int verbose;
+static int silent;
 
 static unsigned long af;
 static unsigned long rf;
@@ -80,8 +81,8 @@
 
 static void usage(void)
 {
-	fprintf(stderr, 
-		_("Usage: %s [-RV] [-+=AacDdijsSu] [-v version] files...\n"),
+	fprintf(stderr,
+		_("Usage: %s [-RVf] [-+=AacDdijsSu] [-v version] files...\n"),
 		program_name);
 	exit(1);
 }
@@ -137,6 +138,10 @@
 				verbose = 1;
 				continue;
 			}
+			if (*p == 'f') {
+				silent = 1;
+				continue;
+			}
 			if (*p == 'v') {
 				(*i)++;
 				if (*i >= argc)
@@ -144,7 +149,7 @@
 				version = strtol (argv[*i], &tmp, 0);
 				if (*tmp) {
 					com_err (program_name, 0,
-						 _("bad version - %s\n"), 
+						 _("bad version - %s\n"),
 						 argv[*i]);
 					usage ();
 				}
@@ -182,26 +187,17 @@
 
 static int chattr_dir_proc (const char *, struct dirent *, void *);
 
-static void change_attributes (const char * name)
+static int change_attributes (const char * name, int cmdline)
 {
 	unsigned long flags;
 	STRUCT_STAT	st;
 
 	if (LSTAT (name, &st) == -1) {
-		com_err (program_name, errno, _("while trying to stat %s"), 
-			 name);
-		return;
+		if (!silent)
+			com_err (program_name, errno,
+				 _("while trying to stat %s"), name);
+		return -1;
 	}
-	if (S_ISLNK(st.st_mode) && recursive)
-		return;
-
-	/* Don't try to open device files, fifos etc.  We probably
-           ought to display an error if the file was explicitly given
-           on the command line (whether or not recursive was
-           requested).  */
-	if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) &&
-	    !S_ISDIR(st.st_mode))
-		return;
 
 	if (set) {
 		if (verbose) {
@@ -212,10 +208,12 @@
 		if (fsetflags (name, sf) == -1)
 			perror (name);
 	} else {
-		if (fgetflags (name, &flags) == -1)
-			com_err (program_name, errno,
-			         _("while reading flags on %s"), name);
-		else {
+		if (fgetflags (name, &flags) == -1) {
+			if (!silent)
+				com_err (program_name, errno,
+					 _("while reading flags on %s"), name);
+			return -1;
+		} else {
 			if (rem)
 				flags &= ~rf;
 			if (add)
@@ -227,25 +225,36 @@
 			}
 			if (!S_ISDIR(st.st_mode))
 				flags &= ~EXT2_DIRSYNC_FL;
-			if (fsetflags (name, flags) == -1)
-				com_err (program_name, errno,
-				         _("while setting flags on %s"), name);
+			if (fsetflags (name, flags) == -1) {
+				if (!silent)
+					com_err(program_name, errno,
+						_("while setting flags on %s"),
+						name);
+				return -1;
+			}
 		}
 	}
 	if (set_version) {
 		if (verbose)
 			printf (_("Version of %s set as %lu\n"), name, version);
-		if (fsetversion (name, version) == -1)
-			com_err (program_name, errno,
-			         _("while setting version on %s"), name);
+		if (fsetversion (name, version) == -1) {
+			if (!silent)
+				com_err (program_name, errno,
+					 _("while setting version on %s"),
+					 name);
+			return -1;
+		}
 	}
 	if (S_ISDIR(st.st_mode) && recursive)
-		iterate_on_dir (name, chattr_dir_proc, NULL);
+		return iterate_on_dir (name, chattr_dir_proc, NULL);
+	return 0;
 }
 
 static int chattr_dir_proc (const char * dir_name, struct dirent * de,
 			    void * private EXT2FS_ATTR((unused)))
 {
+	int ret = 0;
+
 	if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
 	        char *path;
 
@@ -253,19 +262,20 @@
 		if (!path) {
 			fprintf(stderr, _("Couldn't allocate path variable "
 					  "in chattr_dir_proc"));
-			exit(1);
+			return -1;
 		}
-		sprintf (path, "%s/%s", dir_name, de->d_name);
-		change_attributes (path);
+		sprintf(path, "%s/%s", dir_name, de->d_name);
+		ret = change_attributes(path, 0);
 		free(path);
 	}
-	return 0;
+	return ret;
 }
 
 int main (int argc, char ** argv)
 {
 	int i, j;
 	int end_arg = 0;
+	int err, retval = 0;
 
 #ifdef ENABLE_NLS
 	setlocale(LC_MESSAGES, "");
@@ -303,7 +313,10 @@
 	if (verbose)
 		fprintf (stderr, "chattr %s (%s)\n",
 			 E2FSPROGS_VERSION, E2FSPROGS_DATE);
-	for (j = i; j < argc; j++)
-		change_attributes (argv[j]);
-	exit(0);
+	for (j = i; j < argc; j++) {
+		err = change_attributes (argv[j], 1);
+		if (err)
+			retval = 1;
+	}
+	exit(retval);
 }
diff --git a/misc/e2image.c b/misc/e2image.c
index 1fbb267..44f4897 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -126,8 +126,7 @@
 	hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE;
 	strcpy(hdr.magic_descriptor, "Ext2 Image 1.0");
 	gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname));
-	strncat(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name));
-	hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0;
+	strncat(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name) - 1);
 	hdr.fs_blocksize = fs->blocksize;
 	
 	if (stat(device_name, &st) == 0)
diff --git a/misc/util.c b/misc/util.c
index 6a4c40c..7c99a2a 100644
--- a/misc/util.c
+++ b/misc/util.c
@@ -71,8 +71,8 @@
 	fflush(stderr);
 	fputs(_("Proceed anyway? (y,n) "), stdout);
 	buf[0] = 0;
-	fgets(buf, sizeof(buf), stdin);
-	if (strchr(short_yes, buf[0]) == 0)
+	if (!fgets(buf, sizeof(buf), stdin) ||
+	    strchr(short_yes, buf[0]) == 0)
 		exit(1);
 }