On windows add a wait when hardlinking to account for broken network

filesystems
This commit is contained in:
Kovid Goyal 2013-07-22 10:46:29 +05:30
parent f5eda364e6
commit 3b345d3ff5

View File

@ -3,7 +3,7 @@ Make strings safe for use as ASCII filenames, while trying to preserve as much
meaning as possible.
'''
import os, errno
import os, errno, time
from math import ceil
from calibre import sanitize_file_name, isbytestring, force_unicode
@ -257,6 +257,19 @@ def samefile(src, dst):
os.path.normcase(os.path.abspath(dst)))
return samestring
def windows_get_size(path):
''' On windows file sizes are only accurately stored in the actual file,
not in the directory entry (which could be out of date). So we open the
file, and get the actual size. '''
import win32file
h = win32file.CreateFile(
path, 0, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE | win32file.FILE_SHARE_DELETE,
None, win32file.OPEN_EXISTING, 0, None)
try:
return win32file.GetFileSize(h)
finally:
win32file.CloseHandle(h)
def windows_hardlink(src, dest):
import win32file, pywintypes
try:
@ -264,17 +277,21 @@ def windows_hardlink(src, dest):
except pywintypes.error as e:
msg = u'Creating hardlink from %s to %s failed: %%s' % (src, dest)
raise Exception(msg % e)
src_size = os.path.getsize(src)
# We open and close dest, to ensure its directory entry is updated
# see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx
h = win32file.CreateFile(
dest, 0, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE | win32file.FILE_SHARE_DELETE,
None, win32file.OPEN_EXISTING, 0, None)
for i in range(10):
# If we are on a network filesystem, we have to wait for some indeterminate time, since
# network file systems are the best thing since sliced bread
try:
sz = win32file.GetFileSize(h)
finally:
win32file.CloseHandle(h)
if windows_get_size(dest) == src_size:
return
except EnvironmentError:
pass
time.sleep(0.3)
if sz != os.path.getsize(src):
sz = windows_get_size(dest)
if sz != src_size:
msg = u'Creating hardlink from %s to %s failed: %%s' % (src, dest)
raise Exception(msg % ('hardlink size: %d not the same as source size' % sz))