Index: /trunk/include/iprt/file.h
===================================================================
--- /trunk/include/iprt/file.h	(revision 85874)
+++ /trunk/include/iprt/file.h	(revision 85875)
@@ -594,4 +594,17 @@
 
 /**
+ * Queries the sector size (/ logical block size) for a disk or similar.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_FUNCTION if not a disk/similar.  Could also be returned
+ *          if not really implemented.
+ * @param   hFile       Handle to the disk.  This must typically be a device
+ *                      rather than a file or directory, though this may vary
+ *                      from OS to OS.
+ * @param   pcbSector   Where to store the sector size.
+ */
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector);
+
+/**
  * Gets the current file position.
  *
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 85874)
+++ /trunk/include/iprt/mangling.h	(revision 85875)
@@ -965,4 +965,5 @@
 # define RTFileQueryFsSizes                             RT_MANGLER(RTFileQueryFsSizes)
 # define RTFileQueryInfo                                RT_MANGLER(RTFileQueryInfo)
+# define RTFileQuerySectorSize                          RT_MANGLER(RTFileQuerySectorSize)
 # define RTFileQuerySize                                RT_MANGLER(RTFileQuerySize)
 # define RTFileRead                                     RT_MANGLER(RTFileRead)
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 85874)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 85875)
@@ -908,4 +908,5 @@
 	r3/win/env-win.cpp \
 	r3/win/RTCrStoreCreateSnapshotById-win.cpp \
+	r3/win/RTFileQuerySectorSize-win.cpp \
 	r3/win/RTHandleGetStandard-win.cpp \
 	r3/win/RTLocaleQueryNormalizedBaseLocaleName-win.cpp \
@@ -999,4 +1000,5 @@
 	r3/linux/thread-affinity-linux.cpp \
 	r3/linux/RTFileCopyPartEx-linux.cpp \
+	r3/linux/RTFileQuerySectorSize-linux.cpp \
 	r3/linux/RTFileSetAllocationSize-linux.cpp \
 	r3/linux/RTProcIsRunningByName-linux.cpp \
@@ -1079,4 +1081,5 @@
 	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
+	generic/RTFileQuerySectorSize-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
@@ -1187,4 +1190,5 @@
 	r3/darwin/RTCrStoreCreateSnapshotById-darwin.cpp \
 	r3/darwin/filelock-darwin.cpp \
+	r3/darwin/RTFileQuerySectorSize-darwin.cpp \
 	r3/darwin/krnlmod-darwin.cpp \
 	r3/darwin/mp-darwin.cpp \
@@ -1278,4 +1282,5 @@
 	generic/RTThreadGetNativeState-generic.cpp \
 	r3/freebsd/fileaio-freebsd.cpp \
+	r3/freebsd/RTFileQuerySectorSize-freebsd.cpp \
 	r3/freebsd/mp-freebsd.cpp \
 	r3/freebsd/systemmem-freebsd.cpp \
@@ -1339,4 +1344,5 @@
 	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
+	generic/RTFileQuerySectorSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
@@ -1491,4 +1497,5 @@
 	r3/posix/utf8-posix.cpp \
 	r3/solaris/fileaio-solaris.cpp \
+	r3/solaris/RTFileQuerySectorSize-solaris.cpp \
 	r3/solaris/krnlmod-solaris.cpp \
 	r3/solaris/systemmem-solaris.cpp \
@@ -1522,4 +1529,5 @@
 	generic/RTFileCopyPartEx-generic.cpp \
 	generic/RTFileMove-generic.cpp \
+	generic/RTFileQuerySectorSize-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
Index: /trunk/src/VBox/Runtime/generic/RTFileQuerySectorSize-generic.cpp
===================================================================
--- /trunk/src/VBox/Runtime/generic/RTFileQuerySectorSize-generic.cpp	(revision 85875)
+++ /trunk/src/VBox/Runtime/generic/RTFileQuerySectorSize-generic.cpp	(revision 85875)
@@ -0,0 +1,45 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileQuerySectorSize, generic.
+ */
+
+/*
+ * Copyright (C) 2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/file.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+
+
+
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector)
+{
+    AssertPtrReturn(pcbSector, VERR_INVALID_PARAMETER);
+    AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
+    AssertFailedReturn(VERR_INVALID_FUNCTION);
+}
+
Index: /trunk/src/VBox/Runtime/r3/darwin/RTFileQuerySectorSize-darwin.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/darwin/RTFileQuerySectorSize-darwin.cpp	(revision 85875)
+++ /trunk/src/VBox/Runtime/r3/darwin/RTFileQuerySectorSize-darwin.cpp	(revision 85875)
@@ -0,0 +1,79 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileQuerySectorSize, Darwin.
+ */
+
+/*
+ * Copyright (C) 2017-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/file.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+
+#include <sys/stat.h>
+#include <sys/disk.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector)
+{
+    AssertPtrReturn(pcbSector, VERR_INVALID_PARAMETER);
+
+    int rc;
+    int const fd = (int)RTFileToNative(hFile);
+    struct stat DevStat = { 0 };
+    if (!fstat(fd, &DevStat))
+    {
+        if (S_ISBLK(DevStat.st_mode) || S_ISCHR(DevStat.st_mode))
+        {
+            uint32_t cbLogicalBlock = 0;
+            if (!ioctl(fd, DKIOCGETBLOCKSIZE, &cbLogicalBlock))
+            {
+                AssertReturn(cbLogicalBlock > 0, VERR_INVALID_FUNCTION);
+                *pcbSector = cbLogicalBlock;
+                return VINF_SUCCESS;
+            }
+
+            rc = RTErrConvertFromErrno(errno);
+            AssertMsgFailed(("ioctl failed: errno=%d / %Rrc\n", errno, rc));
+        }
+        else
+        {
+            AssertMsgFailed(("not a block or character device.\n"));
+            rc = VERR_INVALID_FUNCTION;
+        }
+    }
+    else
+    {
+        rc = RTErrConvertFromErrno(errno);
+        AssertMsgFailed(("fstat failed: errno=%d / %Rrc\n", errno, rc));
+    }
+    return rc;
+}
+
Index: /trunk/src/VBox/Runtime/r3/freebsd/RTFileQuerySectorSize-freebsd.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/freebsd/RTFileQuerySectorSize-freebsd.cpp	(revision 85875)
+++ /trunk/src/VBox/Runtime/r3/freebsd/RTFileQuerySectorSize-freebsd.cpp	(revision 85875)
@@ -0,0 +1,78 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileQuerySectorSize, FreeBSD.
+ */
+
+/*
+ * Copyright (C) 2017-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/file.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+
+#include <errno.h>
+#include <sys/disk.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+
+
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector)
+{
+    AssertPtrReturn(pcbSector, VERR_INVALID_PARAMETER);
+
+    int rc;
+    int const fd = (int)RTFileToNative(hFile);
+    struct stat DevStat = { 0 };
+    if (!fstat(fd, &DevStat))
+    {
+        if (S_ISCHR(DevStat.st_mode))
+        {
+            u_int cbSector = 0;
+            if (!ioctl(fd, DIOCGSECTORSIZE, &cbSector))
+            {
+                AssertReturn(cbSector > 0, VERR_INVALID_FUNCTION);
+                *pcbSector = cbSector;
+                return VINF_SUCCESS;
+            }
+            rc = RTErrConvertFromErrno(errno);
+            AssertMsgFailed(("ioctl failed: errno=%d / %Rrc\n", errno, rc));
+        }
+        else
+        {
+            AssertMsgFailed(("not a character device.\n"));
+            rc = VERR_INVALID_FUNCTION;
+        }
+    }
+    else
+    {
+        rc = RTErrConvertFromErrno(errno);
+        AssertMsgFailed(("fstat failed: errno=%d / %Rrc\n", errno, rc));
+    }
+    return rc;
+}
+
Index: /trunk/src/VBox/Runtime/r3/linux/RTFileQuerySectorSize-linux.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/linux/RTFileQuerySectorSize-linux.cpp	(revision 85875)
+++ /trunk/src/VBox/Runtime/r3/linux/RTFileQuerySectorSize-linux.cpp	(revision 85875)
@@ -0,0 +1,78 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileQuerySectorSize, Linux implementation.
+ */
+
+/*
+ * Copyright (C) 2017-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/file.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+
+#include <errno.h>
+#include <linux/fs.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector)
+{
+    AssertPtrReturn(pcbSector, VERR_INVALID_PARAMETER);
+
+    int rc;
+    int const fd = (int)RTFileToNative(hFile);
+    struct stat DevStat = { 0 };
+    if (!fstat(fd, &DevStat))
+    {
+        if (S_ISBLK(DevStat.st_mode))
+        {
+            int cbLogicalBlock = 0;
+            if (!ioctl(fd, BLKSSZGET, &cbLogicalBlock))
+            {
+                AssertReturn(cbLogicalBlock > 0, VERR_INVALID_FUNCTION);
+                *pcbSector = cbLogicalBlock;
+                return VINF_SUCCESS;
+            }
+
+            rc = RTErrConvertFromErrno(errno);
+            AssertMsgFailed(("ioctl failed: errno=%d / %Rrc\n", errno, rc));
+        }
+        else
+        {
+            AssertMsgFailed(("not a block device.\n"));
+            rc = VERR_INVALID_FUNCTION;
+        }
+    }
+    else
+    {
+        rc = RTErrConvertFromErrno(errno);
+        AssertMsgFailed(("fstat failed: errno=%d / %Rrc\n", errno, rc));
+    }
+    return rc;
+}
+
Index: /trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp	(revision 85874)
+++ /trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp	(revision 85875)
@@ -680,7 +680,7 @@
         *pcbSize = st.st_size;
         if (   st.st_size != 0
-#if defined(RT_OS_SOLARIS)
+#if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
             || (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
-#elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD)
+#elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_DARWIN)
             || !S_ISCHR(st.st_mode)
 #else
@@ -705,5 +705,9 @@
             }
         }
-        /* must be a block device, fail on failure. */
+
+        /* Always fail block devices.  Character devices doesn't all need to be
+           /dev/rdisk* nodes, they should return ENOTTY but include EINVAL too. */
+        if (!S_ISBLK(st.st_mode) && (errno == ENOTTY || errno == EINVAL))
+            return VINF_SUCCESS;
 
 #elif defined(RT_OS_SOLARIS)
Index: /trunk/src/VBox/Runtime/r3/solaris/RTFileQuerySectorSize-solaris.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/solaris/RTFileQuerySectorSize-solaris.cpp	(revision 85875)
+++ /trunk/src/VBox/Runtime/r3/solaris/RTFileQuerySectorSize-solaris.cpp	(revision 85875)
@@ -0,0 +1,80 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileQuerySectorSize, Solaris.
+ */
+
+/*
+ * Copyright (C) 2017-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/file.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+
+#include <errno.h>
+#include <stropts.h>
+#include <sys/types.h>
+#include <sys/dkio.h>
+#include <sys/vtoc.h>
+#include <sys/stat.h>
+
+
+
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector)
+{
+    AssertPtrReturn(pcbSector, VERR_INVALID_PARAMETER);
+
+    int rc;
+    int const fd = (int)RTFileToNative(hFile);
+    struct stat DevStat = { 0 };
+    if (!fstat(fd, &DevStat))
+    {
+        if (S_ISBLK(DevStat.st_mode) || S_ISCHR(DevStat.st_mode))
+        {
+            struct dk_minfo MediaInfo;
+            if (!ioctl(fd, DKIOCGMEDIAINFO, &MediaInfo))
+            {
+                AssertReturn(MediaInfo.dki_lbsize > 0, VERR_INVALID_FUNCTION);
+                *pcbSector = MediaInfo.dki_lbsize;
+                return rc;
+            }
+            rc = RTErrConvertFromErrno(errno);
+            AssertMsgFailed(("ioctl failed: errno=%d / %Rrc\n", errno, rc));
+        }
+        else
+        {
+            AssertMsgFailed(("not a block or character device.\n"));
+            rc = VERR_INVALID_FUNCTION;
+        }
+    }
+    else
+    {
+        rc = RTErrConvertFromErrno(errno);
+        AssertMsgFailed(("fstat failed: errno=%d / %Rrc\n", errno, rc));
+    }
+    return rc;
+}
+
Index: /trunk/src/VBox/Runtime/r3/win/RTFileQuerySectorSize-win.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/RTFileQuerySectorSize-win.cpp	(revision 85875)
+++ /trunk/src/VBox/Runtime/r3/win/RTFileQuerySectorSize-win.cpp	(revision 85875)
@@ -0,0 +1,61 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTFileQuerySectorSize, Windows.
+ */
+
+/*
+ * Copyright (C) 2017-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/file.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#include <iprt/string.h>
+
+#include <iprt/win/windows.h>
+
+
+
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector)
+{
+    AssertPtrReturn(pcbSector, VERR_INVALID_PARAMETER);
+
+    DISK_GEOMETRY DriveGeo;
+    RT_ZERO(DriveGeo);
+    DWORD cbDriveGeo = 0;
+    if (DeviceIoControl((HANDLE)RTFileToNative(hFile),
+                        IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
+                        &DriveGeo, sizeof(DriveGeo), &cbDriveGeo, NULL))
+    {
+        AssertReturn(DriveGeo.BytesPerSector > 0, VERR_INVALID_PARAMETER);
+        *pcbSector = DriveGeo.BytesPerSector;
+        return VINF_SUCCESS;
+    }
+    int rc = RTErrConvertFromWin32(GetLastError());
+    AssertMsgFailed(("%d / %Rrc\n", GetLastError(), rc));
+    return rc;
+}
+
