Use RAII for delete and create_folder

This commit is contained in:
Kovid Goyal 2021-04-23 10:08:32 +05:30
parent 481474aae2
commit b69f48cc73
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 29 additions and 136 deletions

View File

@ -577,13 +577,15 @@ def main():
dev.filesystem_cache.dump()
print('Prefix for main mem:', dev.prefix_for_location(None), flush=True)
raw = os.urandom(32 * 1024)
f = dev.put_file(dev.filesystem_cache.entries[0], 'developing-mtp-driver.bin', io.BytesIO(raw), len(raw))
folder = dev.create_folder(dev.filesystem_cache.entries[0], 'developing-mtp-driver')
f = dev.put_file(folder, 'developing-mtp-driver.bin', io.BytesIO(raw), len(raw))
print('Put file:', f, flush=True)
buf = io.BytesIO()
dev.get_file(f.mtp_id_path, buf)
if buf.getvalue() != raw:
raise ValueError('Getting previously put file did not return expected data')
print('Successfully got previously put file', flush=True)
dev.recursive_delete(f)
finally:
dev.shutdown()

View File

@ -591,82 +591,65 @@ wpd::get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest,
PyObject*
wpd::create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name) { // {{{
IPortableDeviceContent *content = NULL;
IPortableDeviceValues *values = NULL;
IPortableDeviceProperties *devprops = NULL;
IPortableDeviceKeyCollection *properties = NULL;
wchar_t *newid = NULL;
PyObject *ans = NULL;
CComPtr<IPortableDeviceContent> content;
CComPtr<IPortableDeviceValues> values;
CComPtr<IPortableDeviceProperties> devprops;
CComPtr<IPortableDeviceKeyCollection> properties;
HRESULT hr;
values = create_object_properties(parent_id, name, WPD_CONTENT_TYPE_FOLDER, 0);
if (values == NULL) goto end;
if (!values) return NULL;
Py_BEGIN_ALLOW_THREADS;
hr = device->Content(&content);
Py_END_ALLOW_THREADS;
if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); goto end; }
if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); return NULL; }
hr = content->Properties(&devprops);
if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); goto end; }
if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); return NULL; }
properties = create_filesystem_properties_collection();
if (properties == NULL) goto end;
if (!properties) return NULL;
wchar_raii newid;
Py_BEGIN_ALLOW_THREADS;
hr = content->CreateObjectWithPropertiesOnly(values, &newid);
hr = content->CreateObjectWithPropertiesOnly(values, newid.unsafe_address());
Py_END_ALLOW_THREADS;
if (FAILED(hr) || newid == NULL) { hresult_set_exc("Failed to create folder", hr); goto end; }
ans = get_object_properties(devprops, properties, newid);
end:
if (content != NULL) content->Release();
if (values != NULL) values->Release();
if (devprops != NULL) devprops->Release();
if (properties != NULL) properties->Release();
if (newid != NULL) CoTaskMemFree(newid);
return ans;
if (FAILED(hr) || !newid) { hresult_set_exc("Failed to create folder", hr); return NULL; }
return get_object_properties(devprops, properties, newid.ptr());
} // }}}
PyObject*
wpd::delete_object(IPortableDevice *device, const wchar_t *object_id) { // {{{
IPortableDeviceContent *content = NULL;
CComPtr<IPortableDeviceContent> content;
CComPtr<IPortableDevicePropVariantCollection> object_ids;
HRESULT hr;
BOOL ok = FALSE;
PROPVARIANT pv;
IPortableDevicePropVariantCollection *object_ids = NULL;
PropVariantInit(&pv);
pv.vt = VT_LPWSTR;
Py_BEGIN_ALLOW_THREADS;
hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&object_ids));
hr = object_ids.CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER);
Py_END_ALLOW_THREADS;
if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); goto end; }
if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); return NULL; }
prop_variant pv(VT_LPWSTR);
pv.pwszVal = (wchar_t*)object_id;
hr = object_ids->Add(&pv);
pv.pwszVal = NULL;
if (FAILED(hr)) { hresult_set_exc("Failed to add device id to propvariantcollection", hr); goto end; }
if (FAILED(hr)) { hresult_set_exc("Failed to add device id to propvariantcollection", hr); return NULL; }
Py_BEGIN_ALLOW_THREADS;
hr = device->Content(&content);
Py_END_ALLOW_THREADS;
if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); goto end; }
if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); return NULL; }
hr = content->Delete(PORTABLE_DEVICE_DELETE_NO_RECURSION, object_ids, NULL);
if (hr == E_ACCESSDENIED) PyErr_SetString(WPDError, "Do not have permission to delete this object");
else if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)) PyErr_SetString(WPDError, "Cannot delete object as it has children");
else if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) || SUCCEEDED(hr)) ok = TRUE;
else hresult_set_exc("Cannot delete object", hr);
if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) || SUCCEEDED(hr)) {Py_RETURN_NONE;}
end:
PropVariantClear(&pv);
if (content != NULL) content->Release();
if (object_ids != NULL) object_ids->Release();
if (!ok) return NULL;
Py_RETURN_NONE;
if (hr == E_ACCESSDENIED) { PyErr_SetExcFromWindowsErr(WPDError, ERROR_ACCESS_DENIED); }
else if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)) {
PyErr_SetString(WPDError, "Cannot delete object as it has children"); }
else hresult_set_exc("Cannot delete object", hr);
return NULL;
} // }}}

View File

@ -1,92 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import subprocess, os, pprint, signal, time, glob, io
pprint, io
from polyglot.builtins import environ_item
def build(mod='wpd'):
master = subprocess.Popen('ssh -MN getafix'.split())
master2 = subprocess.Popen('ssh -MN win64'.split())
try:
while not glob.glob(os.path.expanduser('~/.ssh/*kovid@win64*')):
time.sleep(0.05)
builder = subprocess.Popen('ssh win64 ~/build-wpd'.split())
if builder.wait() != 0:
raise Exception('Failed to build plugin')
while not glob.glob(os.path.expanduser('~/.ssh/*kovid@getafix*')):
time.sleep(0.05)
syncer = subprocess.Popen('ssh getafix ~/update-calibre'.split())
if syncer.wait() != 0:
raise Exception('Failed to rsync to getafix')
subprocess.check_call(
('scp win64:build/calibre/src/calibre/plugins/%s.pyd /tmp'%mod).split())
subprocess.check_call(
('scp /tmp/%s.pyd getafix:calibre-src/src/calibre/devices/mtp/windows'%mod).split())
p = subprocess.Popen(
'ssh getafix calibre-debug -e calibre-src/src/calibre/devices/mtp/windows/remote.py'.split())
p.wait()
print()
finally:
for m in (master2, master):
m.send_signal(signal.SIGHUP)
for m in (master2, master):
m.wait()
def main():
fp, d = os.path.abspath(__file__), os.path.dirname
if 'CALIBRE_DEVELOP_FROM' not in os.environ:
env = os.environ.copy()
env['CALIBRE_DEVELOP_FROM'] = environ_item(d(d(d(d(d(fp))))))
subprocess.call(['calibre-debug', '-e', fp], env=env)
return
# from calibre.devices.mtp.test import run
# run()
# return
from calibre.devices.winusb import scan_usb_devices
from calibre.devices.mtp.driver import MTP_DEVICE
dev = MTP_DEVICE(None)
dev.startup()
print(dev.wpd, dev.wpd_error)
try:
devices = scan_usb_devices()
pnp_id = dev.detect_managed_devices(devices)
if not pnp_id:
raise ValueError('Failed to detect device')
# pprint.pprint(dev.detected_devices)
print('Trying to connect to:', pnp_id)
dev.open(pnp_id, '')
pprint.pprint(dev.dev.data)
print('Connected to:', dev.get_gui_name())
print('Total space', dev.total_space())
print('Free space', dev.free_space())
# pprint.pprint(dev.dev.create_folder(dev.filesystem_cache.entries[0].object_id,
# 'zzz'))
# print ('Fetching file: oFF (198214 bytes)')
# stream = dev.get_file('oFF')
# print ("Fetched size: ", stream.tell())
# size = 4
# stream = io.BytesIO(b'a'*size)
# name = 'zzz-test-file.txt'
# stream.seek(0)
# f = dev.put_file(dev.filesystem_cache.entries[0], name, stream, size)
# print ('Put file:', f)
dev.filesystem_cache.dump()
finally:
dev.shutdown()
print('Device connection shutdown')
if __name__ == '__main__':
main()