mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Speedup windows_get_fileid
Also make it more robust by avoiding registry/time lookups. Fixes #1898110 [Cannot load Calibre 64 bit](https://bugs.launchpad.net/calibre/+bug/1898110)
This commit is contained in:
parent
b94819be9e
commit
b180fea7d6
@ -9,6 +9,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
from calibre import force_unicode, isbytestring, prints, sanitize_file_name
|
from calibre import force_unicode, isbytestring, prints, sanitize_file_name
|
||||||
from calibre.constants import (
|
from calibre.constants import (
|
||||||
@ -218,9 +219,10 @@ def case_preserving_open_file(path, mode='wb', mkdir_mode=0o777):
|
|||||||
return ans, fpath
|
return ans, fpath
|
||||||
|
|
||||||
|
|
||||||
def windows_get_fileid(path):
|
def old_windows_get_fileid(path):
|
||||||
''' The fileid uniquely identifies actual file contents (it is the same for
|
# we dont use this anymore as the win32 implementation reads the windows
|
||||||
all hardlinks to a file). Similar to inode number on linux. '''
|
# registry to convert file times which is slow and breaks on systems with
|
||||||
|
# registry issues.
|
||||||
import win32file
|
import win32file
|
||||||
from pywintypes import error
|
from pywintypes import error
|
||||||
if isbytestring(path):
|
if isbytestring(path):
|
||||||
@ -237,6 +239,20 @@ def windows_get_fileid(path):
|
|||||||
return data[4], data[8], data[9]
|
return data[4], data[8], data[9]
|
||||||
|
|
||||||
|
|
||||||
|
def windows_get_fileid(path):
|
||||||
|
''' The fileid uniquely identifies actual file contents (it is the same for
|
||||||
|
all hardlinks to a file). Similar to inode number on linux. '''
|
||||||
|
try:
|
||||||
|
get_file_id = plugins['winutil'][0].get_file_id
|
||||||
|
except AttributeError:
|
||||||
|
# running from source without updating binary
|
||||||
|
return old_windows_get_fileid(path)
|
||||||
|
if isbytestring(path):
|
||||||
|
path = path.decode(filesystem_encoding)
|
||||||
|
with suppress(OSError):
|
||||||
|
return get_file_id(path)
|
||||||
|
|
||||||
|
|
||||||
def samefile_windows(src, dst):
|
def samefile_windows(src, dst):
|
||||||
samestring = (os.path.normcase(os.path.abspath(src)) ==
|
samestring = (os.path.normcase(os.path.abspath(src)) ==
|
||||||
os.path.normcase(os.path.abspath(dst)))
|
os.path.normcase(os.path.abspath(dst)))
|
||||||
|
@ -380,6 +380,7 @@ extern PyObject *winutil_friendly_name(PyObject *self, PyObject *args);
|
|||||||
extern PyObject *winutil_notify_associations_changed(PyObject *self, PyObject *args);
|
extern PyObject *winutil_notify_associations_changed(PyObject *self, PyObject *args);
|
||||||
extern PyObject *winutil_move_to_trash(PyObject *self, PyObject *args);
|
extern PyObject *winutil_move_to_trash(PyObject *self, PyObject *args);
|
||||||
extern PyObject *winutil_manage_shortcut(PyObject *self, PyObject *args);
|
extern PyObject *winutil_manage_shortcut(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_get_file_id(PyObject *self, PyObject *args);
|
||||||
|
|
||||||
static PyMethodDef winutil_methods[] = {
|
static PyMethodDef winutil_methods[] = {
|
||||||
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
||||||
@ -471,6 +472,10 @@ be a unicode string. Returns unicode strings."
|
|||||||
"manage_shortcut()\n\nManage a shortcut"
|
"manage_shortcut()\n\nManage a shortcut"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"get_file_id", (PyCFunction)winutil_get_file_id, METH_VARARGS,
|
||||||
|
"get_file_id(path)\n\nGet the windows file id (volume_num, file_index_high, file_index_low)"
|
||||||
|
},
|
||||||
|
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,6 +114,23 @@ py_to_wchar(PyObject *obj, wchar_raii *output) {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_get_file_id(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar, &path)) return NULL;
|
||||||
|
if (path.ptr()) {
|
||||||
|
HANDLE h = CreateFileW(path.ptr(), 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
BY_HANDLE_FILE_INFORMATION info = {0};
|
||||||
|
BOOL ok = GetFileInformationByHandle(h, &info);
|
||||||
|
CloseHandle(h);
|
||||||
|
if (!ok) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
unsigned long volnum = info.dwVolumeSerialNumber, index_high = info.nFileIndexHigh, index_low = info.nFileIndexLow;
|
||||||
|
return Py_BuildValue("kkk", volnum, index_high, index_low);
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
winutil_add_to_recent_docs(PyObject *self, PyObject *args) {
|
winutil_add_to_recent_docs(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path, app_id;
|
wchar_raii path, app_id;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user