bpo-41103: Resurrect the old buffer protocol. (GH-27437) (GH-27441)

Revert "bpo-41103: Remove old buffer protocol support (GH-21117)"

This reverts commit 6f8a6ee59cb7f99f68df8ee9c3e8c8cf19af3eed.
(cherry picked from commit ce5e1a6809b714eb0383219190a076d9f883e008)

Co-authored-by: Inada Naoki <songofacandy@gmail.com>
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 842c367..8ad1910 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -293,6 +293,85 @@ PyObject_CheckBuffer(PyObject *obj)
 }
 
 
+/* We release the buffer right after use of this function which could
+   cause issues later on.  Don't use these functions in new code.
+ */
+int
+PyObject_CheckReadBuffer(PyObject *obj)
+{
+    PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer;
+    Py_buffer view;
+
+    if (pb == NULL ||
+        pb->bf_getbuffer == NULL)
+        return 0;
+    if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE) == -1) {
+        PyErr_Clear();
+        return 0;
+    }
+    PyBuffer_Release(&view);
+    return 1;
+}
+
+static int
+as_read_buffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len)
+{
+    Py_buffer view;
+
+    if (obj == NULL || buffer == NULL || buffer_len == NULL) {
+        null_error();
+        return -1;
+    }
+    if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
+        return -1;
+
+    *buffer = view.buf;
+    *buffer_len = view.len;
+    PyBuffer_Release(&view);
+    return 0;
+}
+
+int
+PyObject_AsCharBuffer(PyObject *obj,
+                      const char **buffer,
+                      Py_ssize_t *buffer_len)
+{
+    return as_read_buffer(obj, (const void **)buffer, buffer_len);
+}
+
+int PyObject_AsReadBuffer(PyObject *obj,
+                          const void **buffer,
+                          Py_ssize_t *buffer_len)
+{
+    return as_read_buffer(obj, buffer, buffer_len);
+}
+
+int PyObject_AsWriteBuffer(PyObject *obj,
+                           void **buffer,
+                           Py_ssize_t *buffer_len)
+{
+    PyBufferProcs *pb;
+    Py_buffer view;
+
+    if (obj == NULL || buffer == NULL || buffer_len == NULL) {
+        null_error();
+        return -1;
+    }
+    pb = Py_TYPE(obj)->tp_as_buffer;
+    if (pb == NULL ||
+        pb->bf_getbuffer == NULL ||
+        ((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "expected a writable bytes-like object");
+        return -1;
+    }
+
+    *buffer = view.buf;
+    *buffer_len = view.len;
+    PyBuffer_Release(&view);
+    return 0;
+}
+
 /* Buffer C-API for Python 3.0 */
 
 int