Author eryksun
Recipients Rotkraut, demian.brecht, eryksun, harobed, martin.panter, matrixise, orsenthil, petri.lehtinen, piotr.dobrogost, pitrou, python-dev, vstinner, whitemice
Date 2016-08-24.11:30:00
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1472038201.65.0.801615517174.issue12319@psf.upfronthosting.co.za>
In-reply-to
Content
> on Windows? Will tell() and seek() reliably fail on a pipe 
> or other unseekable file?

No they will not reliably fail. 

The file position is stored in the FILE_OBJECT CurrentByteOffset. This value can be queried and set using the WinAPI function SetFilePointerEx, which is implemented via the system calls NtQueryInformationFile and NtSetInformationFile with the information class FilePositionInformation. 

For files opened in synchronous mode, which is the only mode that the CRT supports, there's a fast path in the I/O manager to bypass the I/O request packet (IRP) path that would normally call the device driver. This fast-path code trivially updates the CurrentByteOffset field, regardless of the file type. In synchronous mode, a seek will only fail if the file is opened without buffering and the new position isn't sector-aligned, as is documented for SetFilePointerEx and NtSetInformationFile: FilePositionInformation.

Prior to Windows 8, seek() and tell() will also fail for a console handle because it's not actually a kernel File handle that can be used with I/O system calls. OTOH, Windows 8+ uses the ConDrv device driver, so console handles trivially allow seek() and tell() to succeed, though the console itself ignores the CurrentByteOffset in the File object. Console screen-buffer files have a positionable cursor, which is similar but not quite the same.

A fun fact is that for files opened in asynchronous mode, for FilePositionInformation the I/O manager does a regular device driver  call with an IRP_MJ_QUERY_INFORMATION or IRP_MJ_SET_INFORMATION packet. It probably does this instead of using its fast path because there's no inherent meaning to the file position in asynchronous mode. I played around with this a bit with aynchronous named pipes. For setting FilePositionInformation, the NamedPipe filesystem driver always returns STATUS_INVALID_PARAMETER. However, querying the file 'position' returns the number of unread bytes in the queue for the handle's end of the pipe. This can only be non-zero if the handle allows reading, which depends on whether the pipe was created as duplex, inbound, or outbound. Querying this requires the NT API because SetFilePointerEx always calls NtSetInformationFile and fails.
History
Date User Action Args
2016-08-24 11:30:01eryksunsetrecipients: + eryksun, orsenthil, pitrou, vstinner, harobed, python-dev, petri.lehtinen, martin.panter, piotr.dobrogost, demian.brecht, matrixise, whitemice, Rotkraut
2016-08-24 11:30:01eryksunsetmessageid: <1472038201.65.0.801615517174.issue12319@psf.upfronthosting.co.za>
2016-08-24 11:30:01eryksunlinkissue12319 messages
2016-08-24 11:30:00eryksuncreate