Closes #10142: Support for SEEK_HOLE/SEEK_DATA
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 8a9ae47..dc723b1 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1157,9 +1157,20 @@
     if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
         return NULL;
     }
-    if (whence < 0 || whence > 2) {
+
+    /* Do some error checking instead of trusting OS 'seek()'
+    ** error detection, just in case.
+    */
+    if ((whence < 0 || whence >2)
+#ifdef SEEK_HOLE
+        && (whence != SEEK_HOLE)
+#endif
+#ifdef SEEK_DATA
+        && (whence != SEEK_DATA)
+#endif
+        ) {
         PyErr_Format(PyExc_ValueError,
-                     "whence must be between 0 and 2, not %d", whence);
+                     "whence value %d unsupported", whence);
         return NULL;
     }
 
@@ -1172,7 +1183,11 @@
     if (target == -1 && PyErr_Occurred())
         return NULL;
 
-    if (whence != 2 && self->readable) {
+    /* SEEK_SET and SEEK_CUR are special because we could seek inside the
+       buffer. Other whence values must be managed without this optimization.
+       Some Operating Systems can provide additional values, like
+       SEEK_HOLE/SEEK_DATA. */
+    if (((whence == 0) || (whence == 1)) && self->readable) {
         Py_off_t current, avail;
         /* Check if seeking leaves us inside the current buffer,
            so as to return quickly if possible. Also, we needn't take the