mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-08-05 08:40:13 -04:00
Improve file locking on windows for config files. Should fix #2598 (Calibre 0.6b6 Crash While Converting)
This commit is contained in:
parent
c1b818d639
commit
e1aec91911
@ -140,7 +140,7 @@ class OEBReader(object):
|
|||||||
mi.language = get_lang()
|
mi.language = get_lang()
|
||||||
meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
|
meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
|
||||||
bookid = "urn:uuid:%s" % str(uuid.uuid4()) if mi.application_id is None \
|
bookid = "urn:uuid:%s" % str(uuid.uuid4()) if mi.application_id is None \
|
||||||
else mi.applicaion_id
|
else mi.application_id
|
||||||
self.oeb.metadata.add('identifier', bookid, id='calibre-uuid')
|
self.oeb.metadata.add('identifier', bookid, id='calibre-uuid')
|
||||||
self.oeb.uid = self.oeb.metadata.identifier[0]
|
self.oeb.uid = self.oeb.metadata.identifier[0]
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ def pdftohtml(output_dir, pdf_path, no_images):
|
|||||||
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
||||||
raise DRMError()
|
raise DRMError()
|
||||||
|
|
||||||
with open(index, 'rb+wb') as i:
|
with open(index, 'r+b') as i:
|
||||||
raw = i.read()
|
raw = i.read()
|
||||||
raw = '<!-- created by calibre\'s pdftohtml -->\n' + raw
|
raw = '<!-- created by calibre\'s pdftohtml -->\n' + raw
|
||||||
i.seek(0)
|
i.seek(0)
|
||||||
|
@ -13,6 +13,96 @@ import time, atexit, os
|
|||||||
class LockError(Exception):
|
class LockError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class WindowsExclFile(object):
|
||||||
|
|
||||||
|
def __init__(self, path, timeout=20):
|
||||||
|
self.name = path
|
||||||
|
import win32file as w
|
||||||
|
import pywintypes
|
||||||
|
|
||||||
|
while timeout > 0:
|
||||||
|
timeout -= 1
|
||||||
|
try:
|
||||||
|
self._handle = w.CreateFile(path,
|
||||||
|
w.GENERIC_READ|w.GENERIC_WRITE, # Open for reading and writing
|
||||||
|
0, # Open exclusive
|
||||||
|
None, # No security attributes
|
||||||
|
w.OPEN_ALWAYS, # If file does not exist, create it
|
||||||
|
w.FILE_ATTRIBUTE_NORMAL, #Normal attributes
|
||||||
|
None, #No template file
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except pywintypes.error, err:
|
||||||
|
if getattr(err, 'args', [-1])[0] in (0x20, 0x21):
|
||||||
|
time.sleep(1)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def seek(self, amt, frm=0):
|
||||||
|
import win32file as w
|
||||||
|
if frm not in (0, 1, 2):
|
||||||
|
raise ValueError('Invalid from for seek: %s'%frm)
|
||||||
|
frm = {0:w.FILE_BEGIN, 1: w.FILE_CURRENT, 2:w.FILE_END}[frm]
|
||||||
|
if frm is w.FILE_END:
|
||||||
|
amt = 0 - amt
|
||||||
|
w.SetFilePointer(self._handle, amt, frm)
|
||||||
|
|
||||||
|
def tell(self):
|
||||||
|
import win32file as w
|
||||||
|
return w.SetFilePointer(self._handle, 0, w.FILE_CURRENT)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
import win32file as w
|
||||||
|
w.FlushFileBuffers(self._handle)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self._handle is not None:
|
||||||
|
import win32file as w
|
||||||
|
self.flush()
|
||||||
|
w.CloseHandle(self._handle)
|
||||||
|
self._handle = None
|
||||||
|
|
||||||
|
def read(self, bytes=-1):
|
||||||
|
import win32file as w
|
||||||
|
sz = w.GetFileSize(self._handle)
|
||||||
|
max = sz - self.tell()
|
||||||
|
if bytes < 0: bytes = max
|
||||||
|
bytes = min(max, bytes)
|
||||||
|
if bytes < 1:
|
||||||
|
return ''
|
||||||
|
hr, ans = w.ReadFile(self._handle, bytes, None)
|
||||||
|
if hr != 0:
|
||||||
|
raise IOError('Error reading file: %s'%hr)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def readlines(self, sizehint=-1):
|
||||||
|
return self.read().splitlines()
|
||||||
|
|
||||||
|
def write(self, bytes):
|
||||||
|
if isinstance(bytes, unicode):
|
||||||
|
bytes = bytes.encode('utf-8')
|
||||||
|
import win32file as w
|
||||||
|
w.WriteFile(self._handle, bytes, None)
|
||||||
|
|
||||||
|
def truncate(self, size=None):
|
||||||
|
import win32file as w
|
||||||
|
pos = self.tell()
|
||||||
|
if size is None:
|
||||||
|
size = pos
|
||||||
|
t = min(size, pos)
|
||||||
|
self.seek(t)
|
||||||
|
w.SetEndOfFile(self._handle)
|
||||||
|
self.seek(pos)
|
||||||
|
|
||||||
|
def isatty(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def closed(self):
|
||||||
|
return self._handle is None
|
||||||
|
|
||||||
|
|
||||||
class ExclusiveFile(object):
|
class ExclusiveFile(object):
|
||||||
|
|
||||||
def __init__(self, path, timeout=15):
|
def __init__(self, path, timeout=15):
|
||||||
@ -20,17 +110,10 @@ class ExclusiveFile(object):
|
|||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.file = open(self.path, 'a+b')
|
self.file = WindowsExclFile(self.path, self.timeout) if iswindows else open(self.path, 'a+b')
|
||||||
self.file.seek(0)
|
self.file.seek(0)
|
||||||
timeout = self.timeout
|
timeout = self.timeout
|
||||||
if iswindows:
|
if not iswindows:
|
||||||
name = ('Local\\'+(__appname__+self.file.name).replace('\\', '_'))[:201]
|
|
||||||
while self.timeout < 0 or timeout >= 0:
|
|
||||||
self.mutex = win32event.CreateMutex(None, False, name)
|
|
||||||
if win32api.GetLastError() != winerror.ERROR_ALREADY_EXISTS: break
|
|
||||||
time.sleep(1)
|
|
||||||
timeout -= 1
|
|
||||||
else:
|
|
||||||
while self.timeout < 0 or timeout >= 0:
|
while self.timeout < 0 or timeout >= 0:
|
||||||
try:
|
try:
|
||||||
fcntl.lockf(self.file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
|
fcntl.lockf(self.file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
|
||||||
@ -38,14 +121,12 @@ class ExclusiveFile(object):
|
|||||||
except IOError:
|
except IOError:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
timeout -= 1
|
timeout -= 1
|
||||||
if timeout < 0 and self.timeout >= 0:
|
if timeout < 0 and self.timeout >= 0:
|
||||||
self.file.close()
|
self.file.close()
|
||||||
raise LockError
|
raise LockError('Failed to lock')
|
||||||
return self.file
|
return self.file
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, type, value, traceback):
|
||||||
if iswindows:
|
|
||||||
win32api.CloseHandle(self.mutex)
|
|
||||||
self.file.close()
|
self.file.close()
|
||||||
|
|
||||||
def _clean_lock_file(file):
|
def _clean_lock_file(file):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user