Fix FreeBSD portability problem caused by it using character mode disk devices
We were using S_ISBLK() to test if a device could be used as a disk
device. This doesn't work for FreeBSD. We need to test for S_ISBLK()
|| S_ISCHR().
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
diff --git a/lib/blkid/blkidP.h b/lib/blkid/blkidP.h
index b90bfed..b3fe4a6 100644
--- a/lib/blkid/blkidP.h
+++ b/lib/blkid/blkidP.h
@@ -15,6 +15,12 @@
#include <sys/types.h>
#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
#include <blkid/blkid.h>
@@ -152,6 +158,15 @@
extern void blkid_debug_dump_tag(blkid_tag tag);
#endif
+static inline int blkidP_is_disk_device(mode_t mode)
+{
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ return S_ISBLK(mode) || S_ISCHR(mode);
+#else
+ return S_ISBLK(mode);
+#endif
+}
+
/* devno.c */
struct dir_list {
char *name;
diff --git a/lib/blkid/devname.c b/lib/blkid/devname.c
index 671e781..f3956da 100644
--- a/lib/blkid/devname.c
+++ b/lib/blkid/devname.c
@@ -231,7 +231,8 @@
dev->bid_devno == devno)
goto set_pri;
- if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
+ if (stat(device, &st) == 0 &&
+ blkidP_is_disk_device(st.st_mode) &&
st.st_rdev == devno) {
devname = blkid_strdup(device);
goto get_dev;
diff --git a/lib/blkid/devno.c b/lib/blkid/devno.c
index 480030f..34ceb3c 100644
--- a/lib/blkid/devno.c
+++ b/lib/blkid/devno.c
@@ -119,7 +119,7 @@
if (stat(path, &st) < 0)
continue;
- if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
+ if (blkidP_is_disk_device(st.st_mode) && st.st_rdev == devno) {
*devname = blkid_strdup(path);
DBG(DEBUG_DEVNO,
printf("found 0x%llx at %s (%p)\n", (long long)devno,
diff --git a/lib/blkid/getsize.c b/lib/blkid/getsize.c
index 8e8eb4c..4e2835f 100644
--- a/lib/blkid/getsize.c
+++ b/lib/blkid/getsize.c
@@ -149,7 +149,7 @@
* character) devices, so we need to check for S_ISCHR, too.
*/
if (fstat(fd, &st) >= 0 &&
- (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
+ blkidP_is_disk_device(st.st_mode))
part = st.st_rdev & 7;
if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
diff --git a/lib/ext2fs/blkmap64_rb.c b/lib/ext2fs/blkmap64_rb.c
index 7e7e29d..448318c 100644
--- a/lib/ext2fs/blkmap64_rb.c
+++ b/lib/ext2fs/blkmap64_rb.c
@@ -9,6 +9,7 @@
* %End-Header%
*/
+#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h
index 8de9d33..9d001d5 100644
--- a/lib/ext2fs/ext2fsP.h
+++ b/lib/ext2fs/ext2fsP.h
@@ -9,10 +9,23 @@
* %End-Header%
*/
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
#include "ext2fs.h"
#define EXT2FS_MAX_NESTED_LINKS 8
+static inline int ext2fsP_is_disk_device(mode_t mode)
+{
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ return S_ISBLK(mode) || S_ISCHR(mode);
+#else
+ return S_ISBLK(mode);
+#endif
+}
+
/*
* Badblocks list
*/
diff --git a/lib/ext2fs/finddev.c b/lib/ext2fs/finddev.c
index 62fa0db..cd85ef5 100644
--- a/lib/ext2fs/finddev.c
+++ b/lib/ext2fs/finddev.c
@@ -104,7 +104,8 @@
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) {
+ if (ext2fsP_is_disk_device(st.st_mode) &&
+ st.st_rdev == device) {
cp = malloc(strlen(path)+1);
if (!cp) {
closedir(dir);
diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c
index 120299c..6cd497d 100644
--- a/lib/ext2fs/ismounted.c
+++ b/lib/ext2fs/ismounted.c
@@ -55,6 +55,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"
+#include "ext2fsP.h"
#ifdef HAVE_SETMNTENT
/*
@@ -115,7 +116,7 @@
return errno;
}
if (stat(file, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
+ if (ext2fsP_is_disk_device(st_buf.st_mode)) {
#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
file_rdev = st_buf.st_rdev;
#endif /* __GNU__ */
@@ -130,7 +131,7 @@
if (strcmp(file, mnt->mnt_fsname) == 0)
break;
if (stat(mnt->mnt_fsname, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
+ if (ext2fsP_is_disk_device(st_buf.st_mode)) {
#ifndef __GNU__
if (file_rdev && (file_rdev == st_buf.st_rdev))
break;
@@ -310,7 +311,7 @@
file_dev = 0;
#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
if ((stat(file, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode))
+ ext2fsP_is_disk_device(st_buf.st_mode))
file_dev = st_buf.st_rdev;
#endif /* __GNU__ */
@@ -337,7 +338,7 @@
}
#ifndef __GNU__
if (file_dev && (stat(buf, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode) &&
+ ext2fsP_is_disk_device(st_buf.st_mode) &&
file_dev == st_buf.st_rdev) {
ret++;
break;
@@ -404,7 +405,8 @@
{
struct stat st_buf;
- if (stat(device, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
+ if (stat(device, &st_buf) == 0 &&
+ ext2fsP_is_disk_device(st_buf.st_mode)) {
int fd = open(device, O_RDONLY | O_EXCL);
if (fd >= 0)
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 6414195..c2ce9a1 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -76,6 +76,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"
+#include "ext2fsP.h"
/*
* For checking structure magic numbers...
@@ -611,7 +612,7 @@
* zero.
*/
if (ext2fs_fstat(data->dev, &st) == 0) {
- if (S_ISBLK(st.st_mode))
+ if (ext2fsP_is_disk_device(st.st_mode))
io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE;
else
io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES;
@@ -682,7 +683,7 @@
(ut.release[4] == '1') && (ut.release[5] >= '0') &&
(ut.release[5] < '8')) &&
(ext2fs_fstat(data->dev, &st) == 0) &&
- (S_ISBLK(st.st_mode))) {
+ (ext2fsP_is_disk_device(st.st_mode))) {
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
diff --git a/misc/e2image.c b/misc/e2image.c
index e0c3188..030f9cb 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -43,6 +43,7 @@
#include "ext2fs/ext2_fs.h"
#include "ext2fs/ext2fs.h"
+#include "ext2fs/ext2fsP.h"
#include "et/com_err.h"
#include "uuid/uuid.h"
#include "e2p/e2p.h"
@@ -1620,7 +1621,7 @@
_("Can not stat output\n"));
exit(1);
}
- if (S_ISBLK(st.st_mode))
+ if (ext2fsP_is_disk_device(st.st_mode))
output_is_blk = 1;
}
if (flags & E2IMAGE_IS_QCOW2_FLAG) {