FanFicFare/fanficfare/browsercache/share_open.py

77 lines
2.6 KiB
Python

# -*- 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