346
352
self._read_lock = None
349
356
_lock_classes.append(('fcntl', _fcntl_WriteLock, _fcntl_ReadLock))
359
if have_pywin32 and sys.platform == 'win32':
360
win32file_CreateFile = win32file.CreateFileW
362
class _w32c_FileLock(_OSLock):
364
def _open(self, filename, access, share, cflags, pymode):
365
self.filename = osutils.realpath(filename)
367
self._handle = win32file_CreateFile(filename, access, share,
368
None, win32file.OPEN_ALWAYS,
369
win32file.FILE_ATTRIBUTE_NORMAL, None)
370
except pywintypes.error as e:
371
if e.args[0] == winerror.ERROR_ACCESS_DENIED:
372
raise errors.LockFailed(filename, e)
373
if e.args[0] == winerror.ERROR_SHARING_VIOLATION:
374
raise errors.LockContention(filename, e)
376
fd = win32file._open_osfhandle(self._handle, cflags)
377
self.f = os.fdopen(fd, pymode)
385
class _w32c_ReadLock(_w32c_FileLock):
386
def __init__(self, filename):
387
super(_w32c_ReadLock, self).__init__()
388
self._open(filename, win32file.GENERIC_READ,
389
win32file.FILE_SHARE_READ, os.O_RDONLY, "rb")
391
def temporary_write_lock(self):
392
"""Try to grab a write lock on the file.
394
On platforms that support it, this will upgrade to a write lock
395
without unlocking the file.
396
Otherwise, this will release the read lock, and try to acquire a
399
:return: A token which can be used to switch back to a read lock.
401
# I can't find a way to upgrade a read lock to a write lock without
402
# unlocking first. So here, we do just that.
405
wlock = _w32c_WriteLock(self.filename)
406
except errors.LockError:
407
return False, _w32c_ReadLock(self.filename)
411
class _w32c_WriteLock(_w32c_FileLock):
412
def __init__(self, filename):
413
super(_w32c_WriteLock, self).__init__()
415
win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
418
def restore_read_lock(self):
419
"""Restore the original ReadLock."""
420
# For win32 we had to completely let go of the original lock, so we
421
# just unlock and create a new read lock.
423
return _w32c_ReadLock(self.filename)
426
_lock_classes.append(('pywin32', _w32c_WriteLock, _w32c_ReadLock))
352
429
if have_ctypes_win32:
353
from ctypes.wintypes import DWORD, LPWSTR
354
LPSECURITY_ATTRIBUTES = ctypes.c_void_p # used as NULL no need to declare
355
HANDLE = ctypes.c_int # rather than unsigned as in ctypes.wintypes
430
from ctypes.wintypes import DWORD, LPCSTR, LPCWSTR
431
LPSECURITY_ATTRIBUTES = ctypes.c_void_p # used as NULL no need to declare
432
HANDLE = ctypes.c_int # rather than unsigned as in ctypes.wintypes
356
433
_function_name = "CreateFileW"
358
435
# CreateFile <http://msdn.microsoft.com/en-us/library/aa363858.aspx>
359
436
_CreateFile = ctypes.WINFUNCTYPE(
360
HANDLE, # return value
362
DWORD, # dwDesiredAccess
364
LPSECURITY_ATTRIBUTES, # lpSecurityAttributes
365
DWORD, # dwCreationDisposition
366
DWORD, # dwFlagsAndAttributes
367
HANDLE # hTemplateFile
437
HANDLE, # return value
439
DWORD, # dwDesiredAccess
441
LPSECURITY_ATTRIBUTES, # lpSecurityAttributes
442
DWORD, # dwCreationDisposition
443
DWORD, # dwFlagsAndAttributes
444
HANDLE # hTemplateFile
368
445
)((_function_name, ctypes.windll.kernel32))
370
447
INVALID_HANDLE_VALUE = -1
383
460
def _open(self, filename, access, share, cflags, pymode):
384
461
self.filename = osutils.realpath(filename)
385
462
handle = _CreateFile(filename, access, share, None, OPEN_ALWAYS,
386
FILE_ATTRIBUTE_NORMAL, 0)
463
FILE_ATTRIBUTE_NORMAL, 0)
387
464
if handle in (INVALID_HANDLE_VALUE, 0):
388
465
e = ctypes.WinError()
389
466
if e.args[0] == ERROR_ACCESS_DENIED: