public
Last active

A function written with ctypes called is_append_mode_win32 which, given a file object, can determine, on Windows, if it was opened in append mode (regardless of what its mode string says). In UNIX this would be equivalent to fcntl(fd, F_GETFL) & O_APPEND. These are the hoops we have to go through to get the same functionality on Windows.

  • Download Gist
win32_is_append_mode.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
from ctypes import (cdll, c_size_t, c_void_p, c_int, c_char, Structure,
POINTER, cast)
from ctypes.util import find_msvcrt
 
 
msvcrt = cdll.LoadLibrary(find_msvcrt())
 
 
# Constants
IOINFO_L2E = 5
IOINFO_ARRAY_ELTS = 1 << IOINFO_L2E
IOINFO_ARRAYS = 64
FAPPEND = 0x20
_NO_CONSOLE_FILENO = -2
 
 
# Types
intptr_t = POINTER(c_int)
 
class my_ioinfo(Structure):
_fields_ = [('osfhnd', intptr_t),
('osfile', c_char)]
 
# Functions
_msize = msvcrt._msize
_msize.argtypes = (c_void_p,)
_msize.restype = c_size_t
 
# Variables
# Since we don't know how large the ioinfo struct is just treat the __pioinfo
# array as an array of byte pointers
__pioinfo = cast(msvcrt.__pioinfo, POINTER(POINTER(c_char)))
 
 
_sizeof_ioinfo = None
def is_append_mode_win32(fileobj):
global _sizeof_ioinfo
if _sizeof_ioinfo is None:
if __pioinfo[0] is not None:
_sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS
#else:
# this shouldn't happen but...
fd = fileobj.fileno()
if fd != _NO_CONSOLE_FILENO:
idx1 = fd >> IOINFO_L2E # The index into the __pioinfo array
# The n-th ioinfo pointer in __pioinfo[idx1]
idx2 = fd & ((1 << IOINFO_L2E) - 1)
if 0 <= idx1 < IOINFO_ARRAYS and __pioinfo[idx1] is not None:
# Doing pointer arithmetic in ctypes is irritating
pio = c_void_p(cast(__pioinfo[idx1], c_void_p).value +
idx2 * _sizeof_ioinfo)
ioinfo = cast(pio, POINTER(my_ioinfo)).contents
return bool(ord(ioinfo.osfile) & FAPPEND)
return False

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.