# -*- coding: utf-8 -*- # Copyright 2021 FanFicFare team # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import absolute_import ''' On windows, simple built-in open() fails on cache files due to a lock--even when opening read-only. Need to jump through various hoops to *really* open read-only--different hoops in CLI and Calibre, too. ''' import logging logger = logging.getLogger(__name__) ## CLI version: import sys _plat = sys.platform.lower() iswindows = 'win32' in _plat or 'win64' in _plat if iswindows: try: ## Calibre has already had to solve the same problem. from calibre.utils.shared_file import share_open except ImportError: ## not stealing calibre's version because read-only is all we ## need. import os import win32file import msvcrt def share_open(path,*args,**kargs): # logger.debug("share_open(%s)"%path) # does need all three file share flags. handle = win32file.CreateFile(path, win32file.GENERIC_READ, win32file.FILE_SHARE_DELETE | win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, None, win32file.OPEN_EXISTING, 0, None) # detach the handle detached_handle = handle.Detach() # get a file descriptor associated to the handle file_descriptor = msvcrt.open_osfhandle(detached_handle, os.O_RDONLY) ## these can be called *before* the with open read, so ## clearly they don't matter to that and I don't want to ## risk leaking file descriptors. handle.close() win32file.CloseHandle(handle) # open the file descriptor # this will still allow for "with share_open():" return open(file_descriptor,*args,**kargs) else: ## use normal open. share_open = open