
On Fri, Apr 29, 2016 at 12:18:46PM -0400, Random832 wrote:
On Fri, Apr 29, 2016, at 10:45, Marcos Dione wrote:
One possible solution hat was suggested to me in the #python IRC channel was to use that, then test if the resulting value is negative, and adjust accordingly, but I wonder if there is a cleaner, more general solution (for instance, what if the type was something else, like loff_t, although for that one in particular there *is* a convertion function/macro).
In principle, you could just use PyLong_AsUnsignedLong (or LongLong), and raise OverflowError manually if the value happens to be out of size_t's range. (99% sure that on every linux platform unsigned long is the same size as size_t.
But it's not like it'd be the first function in OS to call a system call that takes a size_t. Read just uses Py_ssize_t. Write uses the buffer protocol, which uses Py_ssize_t. How concerned are you really about the lost range here? What does the system call return (its return type is ssize_t) if it writes more than SSIZE_MAX bytes? (This shouldn't be hard to test, just try copying a >2GB file on a 32-bit system)
It's a very good point, but I don't have any 32 bits systems around with a kernel-4.5. I'll try to figure it out and/or ask in the kernel ML.
I'm more curious about what your calling convention is going to be for off_in and off_out. I can't think of any other interfaces that have optional output parameters. Python functions generally deal with output parameters in the underlying C function (there are a few examples in math) by returning a tuple.
These are not output parameters, even if they're pointers. they'r using the NULL pointer to signal that the current offsets should not be touched, to differentiate from a offset of 0. Something that in Python we would use None.

On Fri, Apr 29, 2016, at 14:11, Marcos Dione wrote:
These are not output parameters, even if they're pointers. they'r using the NULL pointer to signal that the current offsets should not be touched, to differentiate from a offset of 0. Something that in Python we would use None.
That's not actually true according to the documentation. (And if it were, they could simply use -1 rather than a null pointer) If you pass a null pointer in, the file's offset is used and *is* updated, same as if you used an ordinary read/write call. If you pass a value in, that value is used *and updated* (which makes it an output parameter) and the file's offset is left alone. Documentation below, I've >>>highlighted<<< the part that shows they are used as output parameters: The following semantics apply for off_in, and similar statements apply to off_out: * If off_in is NULL, then bytes are read from fd_in starting from the file offset, and the file offset is adjusted by the number of bytes copied. * If off_in is not NULL, then off_in must point to a buffer that specifies the starting offset where bytes from fd_in will be read. The file offset of fd_in is not changed, >>>but off_in is adjusted appropriately.<<<

On 29 April 2016 at 18:25, Random832 <random832@fastmail.com> wrote:
On Fri, Apr 29, 2016, at 14:11, Marcos Dione wrote:
These are not output parameters, even if they're pointers. they'r using the NULL pointer to signal that the current offsets should not be touched, to differentiate from a offset of 0. Something that in Python we would use None.
That's not actually true according to the documentation. (And if it were, they could simply use -1 rather than a null pointer) . . . * If off_in is not NULL, then off_in must point to a buffer that specifies the starting offset where bytes from fd_in will be read. The file offset of fd_in is not changed, >>>but off_in is adjusted appropriately.<<<
Linux’s sendfile() syscall takes a similar offset parameter that may be updated, but Python’s os.sendfile() wrapper does not return the updated offset. Do you think we need to return the updated offsets for copy_file_range()?

On 29 April 2016 at 18:11, Marcos Dione <mdione@grulic.org.ar> wrote:
On Fri, Apr 29, 2016 at 12:18:46PM -0400, Random832 wrote:
On Fri, Apr 29, 2016, at 10:45, Marcos Dione wrote:
One possible solution hat was suggested to me in the #python IRC channel was to use that, then test if the resulting value is negative, and adjust accordingly, but I wonder if there is a cleaner, more general solution (for instance, what if the type was something else, like loff_t, although for that one in particular there *is* a convertion function/macro).
In principle, you could just use PyLong_AsUnsignedLong (or LongLong), and raise OverflowError manually if the value happens to be out of size_t's range. (99% sure that on every linux platform unsigned long is the same size as size_t.
But it's not like it'd be the first function in OS to call a system call that takes a size_t. Read just uses Py_ssize_t. Write uses the buffer protocol, which uses Py_ssize_t. How concerned are you really about the lost range here? What does the system call return (its return type is ssize_t) if it writes more than SSIZE_MAX bytes? (This shouldn't be hard to test, just try copying a >2GB file on a 32-bit system)
I would probably just use Py_ssize_t, since that is what the return value is. Otherwise, a large positive count input could return a negative value, which would be inconsistent, and could be mistaken as an error.
It's a very good point, but I don't have any 32 bits systems around with a kernel-4.5. I'll try to figure it out and/or ask in the kernel ML.
Maybe you can compile a 32-bit program and run it on a 64-bit computer (gcc -m32).
participants (3)
-
Marcos Dione
-
Martin Panter
-
Random832