Ignore wipe operation on non-block devices.

The implementation of make_ext4fs() calls make_ext4fs_internal() by
forcing the |wipe| parameter to true, which is problematic when the
library is used within the emulator (the wipe operation will always
fail on non-Linux platforms).

This patch does the following:

- Add a 'is_block_device_fd()' function to check that a file descriptor
  points to a real block device.

- Modify the implementation of wipe_block_device() uses it to return
  silently when trying to wipe a non-block-device file.

- Add a WIPE_IS_SUPPORTED flag in wipe.h that indicates whether
  block device wiping is supported on the current platform
  (for now, this is only the case on Linux).

BUG=NONE

Change-Id: I62b62b7c3e99b465c3b876154231e7c2fe541b23
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index 3755fee..bb6c863 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -393,6 +393,20 @@
 	return size;
 }
 
+int is_block_device_fd(int fd)
+{
+#ifdef USE_MINGW
+	return 0;
+#else
+	struct stat st;
+	int ret = fstat(fd, &st);
+	if (ret < 0)
+		return 0;
+
+	return S_ISBLK(st.st_mode);
+#endif
+}
+
 u64 get_file_size(int fd)
 {
 	struct stat buf;
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 447d416..c6f52b5 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -140,6 +140,7 @@
 void ext4_update_free(void);
 void ext4_queue_sb(void);
 u64 get_block_device_size(int fd);
+int is_block_device_fd(int fd);
 u64 get_file_size(int fd);
 u64 parse_num(const char *arg);
 void ext4_parse_sb_info(struct ext4_super_block *sb);
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index f164883..6a0f875 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -623,8 +623,9 @@
 			aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
 			aux_info.sb->s_blocks_count_lo);
 
-	if (wipe)
+	if (wipe && WIPE_IS_SUPPORTED) {
 		wipe_block_device(fd, info.len);
+	}
 
 	write_ext4_image(fd, gzip, sparse, crc);
 
diff --git a/ext4_utils/wipe.c b/ext4_utils/wipe.c
index 3bd33e5..5766632 100644
--- a/ext4_utils/wipe.c
+++ b/ext4_utils/wipe.c
@@ -17,6 +17,8 @@
 #include "ext4_utils.h"
 #include "wipe.h"
 
+#if WIPE_IS_SUPPORTED
+
 #if defined(__linux__)
 
 #include <linux/fs.h>
@@ -35,6 +37,11 @@
 	u64 range[2];
 	int ret;
 
+	if (!is_block_device_fd(fd)) {
+		// Wiping only makes sense on a block device.
+		return 0;
+	}
+
 	range[0] = 0;
 	range[1] = len;
 	ret = ioctl(fd, BLKSECDISCARD, &range);
@@ -53,11 +60,17 @@
 
 	return 0;
 }
-#else
-int wipe_block_device(int fd, s64 len)
-{
-	error("wipe not supported on non-linux platforms");
-	return 1;
-}
+
+#else  /* __linux__ */
+#error "Missing block device wiping implementation for this platform!"
 #endif
 
+#else  /* WIPE_IS_SUPPORTED */
+
+int wipe_block_device(int fd, s64 len)
+{
+	/* Wiping is not supported on this platform. */
+	return 1;
+}
+
+#endif  /* WIPE_IS_SUPPORTED */
diff --git a/ext4_utils/wipe.h b/ext4_utils/wipe.h
index ecde9c1..bd119e3 100644
--- a/ext4_utils/wipe.h
+++ b/ext4_utils/wipe.h
@@ -19,6 +19,15 @@
 
 #include "ext4_utils.h"
 
+/* Set WIPE_IS_SUPPORTED to 1 if the current platform supports
+ * wiping of block devices. 0 otherwise. For now, only Linux does.
+ */
+#ifdef __linux__
+#  define WIPE_IS_SUPPORTED 1
+#else
+#  define WIPE_IS_SUPPORTED 0
+#endif
+
 int wipe_block_device(int fd, s64 len);
 
 #endif