mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Merge from trunk
This commit is contained in:
commit
db1ad1a5c0
@ -106,10 +106,12 @@ def sanitize_file_name(name, substitute='_', as_unicode=False):
|
||||
name = name.encode(filesystem_encoding, 'ignore')
|
||||
one = _filename_sanitize.sub(substitute, name)
|
||||
one = re.sub(r'\s', ' ', one).strip()
|
||||
one = re.sub(r'^\.+$', '_', one)
|
||||
bname, ext = os.path.splitext(one)
|
||||
one = re.sub(r'^\.+$', '_', bname)
|
||||
if as_unicode:
|
||||
one = one.decode(filesystem_encoding)
|
||||
one = one.replace('..', substitute)
|
||||
one += ext
|
||||
# Windows doesn't like path components that end with a period
|
||||
if one and one[-1] in ('.', ' '):
|
||||
one = one[:-1]+'_'
|
||||
@ -132,8 +134,10 @@ def sanitize_file_name_unicode(name, substitute='_'):
|
||||
name]
|
||||
one = u''.join(chars)
|
||||
one = re.sub(r'\s', ' ', one).strip()
|
||||
one = re.sub(r'^\.+$', '_', one)
|
||||
bname, ext = os.path.splitext(one)
|
||||
one = re.sub(r'^\.+$', '_', bname)
|
||||
one = one.replace('..', substitute)
|
||||
one += ext
|
||||
# Windows doesn't like path components that end with a period or space
|
||||
if one and one[-1] in ('.', ' '):
|
||||
one = one[:-1]+'_'
|
||||
|
@ -64,14 +64,24 @@ int do_mount(const char *dev, const char *mp) {
|
||||
snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev");
|
||||
snprintf(uids, 100, "%d", getuid());
|
||||
snprintf(gids, 100, "%d", getgid());
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
snprintf(options, 1000, "rw,noexec,nosuid,sync,-u=%d,-g=%d",getuid(),getgid());
|
||||
#else
|
||||
snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev,quiet,shortname=mixed,uid=%d,gid=%d,umask=077,fmask=0177,dmask=0077,utf8,iocharset=iso8859-1", getuid(), getgid());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ensure_root();
|
||||
|
||||
#ifdef __NetBSD__
|
||||
execlp("mount_msdos", "mount_msdos", "-u", uids, "-g", gids, "-o", options, dev, mp, NULL);
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
execlp("mount", "mount", "-t", "msdosfs", "-o", options, dev, mp, NULL);
|
||||
#else
|
||||
execlp("mount", "mount", "-t", "auto", "-o", options, dev, mp, NULL);
|
||||
#endif
|
||||
#endif
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to mount with error: %s\n", strerror(errsv));
|
||||
@ -91,8 +101,12 @@ int call_eject(const char *dev, const char *mp) {
|
||||
ensure_root();
|
||||
#ifdef __NetBSD__
|
||||
execlp("eject", "eject", dev, NULL);
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
execlp("umount", "umount", dev, NULL);
|
||||
#else
|
||||
execlp("eject", "eject", "-s", dev, NULL);
|
||||
#endif
|
||||
#endif
|
||||
/* execlp failed */
|
||||
errsv = errno;
|
||||
@ -121,7 +135,11 @@ int call_umount(const char *dev, const char *mp) {
|
||||
|
||||
if (pid == 0) { /* Child process */
|
||||
ensure_root();
|
||||
#ifdef __FreeBSD__
|
||||
execlp("umount", "umount", mp, NULL);
|
||||
#else
|
||||
execlp("umount", "umount", "-l", mp, NULL);
|
||||
#endif
|
||||
/* execlp failed */
|
||||
errsv = errno;
|
||||
fprintf(stderr, "Failed to umount with error: %s\n", strerror(errsv));
|
||||
|
@ -17,7 +17,7 @@ from itertools import repeat
|
||||
from calibre.devices.interface import DevicePlugin
|
||||
from calibre.devices.errors import DeviceError, FreeSpaceError
|
||||
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
||||
from calibre.constants import iswindows, islinux, isosx, plugins
|
||||
from calibre.constants import iswindows, islinux, isosx, isfreebsd, plugins
|
||||
from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to
|
||||
|
||||
if isosx:
|
||||
@ -701,7 +701,152 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
self._card_a_prefix = self._card_b_prefix
|
||||
self._card_b_prefix = None
|
||||
|
||||
# ------------------------------------------------------
|
||||
#
|
||||
# open for FreeBSD
|
||||
# find the device node or nodes that match the S/N we already have from the scanner
|
||||
# and attempt to mount each one
|
||||
# 1. get list of disk devices from sysctl
|
||||
# 2. compare that list with the one from camcontrol
|
||||
# 3. and see if it has a matching s/n
|
||||
# 6. find any partitions/slices associated with each node
|
||||
# 7. attempt to mount, using calibre-mount-helper, each one
|
||||
# 8. when finished, we have a list of mount points and associated device nodes
|
||||
#
|
||||
def open_freebsd(self):
|
||||
|
||||
# this gives us access to the S/N, etc. of the reader that the scanner has found
|
||||
# and the match routines for some of that data, like s/n, vendor ID, etc.
|
||||
d=self.detected_device
|
||||
|
||||
if not d.serial:
|
||||
raise DeviceError("Device has no S/N. Can't continue")
|
||||
return False
|
||||
|
||||
devs={}
|
||||
di=0
|
||||
ndevs=4 # number of possible devices per reader (main, carda, cardb, launcher)
|
||||
|
||||
#get list of disk devices
|
||||
p=subprocess.Popen(["sysctl", "kern.disks"], stdout=subprocess.PIPE)
|
||||
kdsks=subprocess.Popen(["sed", "s/kern.disks: //"], stdin=p.stdout, stdout=subprocess.PIPE).communicate()[0]
|
||||
p.stdout.close()
|
||||
#print kdsks
|
||||
for dvc in kdsks.split():
|
||||
# for each one that's also in the list of cam devices ...
|
||||
p=subprocess.Popen(["camcontrol", "devlist"], stdout=subprocess.PIPE)
|
||||
devmatch=subprocess.Popen(["grep", dvc], stdin=p.stdout, stdout=subprocess.PIPE).communicate()[0]
|
||||
p.stdout.close()
|
||||
if devmatch:
|
||||
#print "Checking ", devmatch
|
||||
# ... see if we can get a S/N from the actual device node
|
||||
sn=subprocess.Popen(["camcontrol", "inquiry", dvc, "-S"], stdout=subprocess.PIPE).communicate()[0]
|
||||
sn=sn[0:-1] # drop the trailing newline
|
||||
#print "S/N = ", sn
|
||||
if sn and d.match_serial(sn):
|
||||
# we have a matching s/n, record this device node
|
||||
#print "match found: ", dvc
|
||||
devs[di]=dvc
|
||||
di += 1
|
||||
|
||||
# sort the list of devices
|
||||
for i in range(1,ndevs+1):
|
||||
for j in reversed(range(1,i)):
|
||||
if devs[j-1] > devs[j]:
|
||||
x=devs[j-1]
|
||||
devs[j-1]=devs[j]
|
||||
devs[j]=x
|
||||
#print devs
|
||||
|
||||
# now we need to see if any of these have slices/partitions
|
||||
mtd=0
|
||||
label="READER" # could use something more unique, like S/N or productID...
|
||||
cmd = '/usr/local/bin/calibre-mount-helper'
|
||||
cmd = [cmd, 'mount']
|
||||
for i in range(0,ndevs):
|
||||
cmd2="ls /dev/"+devs[i]+"*"
|
||||
p=subprocess.Popen(cmd2, shell=True, stdout=subprocess.PIPE)
|
||||
devs[i]=subprocess.Popen(["cut", "-d", "/", "-f" "3"], stdin=p.stdout, stdout=subprocess.PIPE).communicate()[0]
|
||||
p.stdout.close()
|
||||
|
||||
# try all the nodes to see what we can mount
|
||||
for dev in devs[i].split():
|
||||
mp='/media/'+label+'-'+dev
|
||||
#print "trying ", dev, "on", mp
|
||||
try:
|
||||
p = subprocess.Popen(cmd + ["/dev/"+dev, mp])
|
||||
except OSError:
|
||||
raise DeviceError(_('Could not find mount helper: %s.')%cmd[0])
|
||||
while p.poll() is None:
|
||||
time.sleep(0.1)
|
||||
|
||||
if p.returncode == 0:
|
||||
#print " mounted", dev
|
||||
if i == 0:
|
||||
self._main_prefix = mp
|
||||
self._main_dev = "/dev/"+dev
|
||||
#print "main = ", self._main_dev, self._main_prefix
|
||||
if i == 1:
|
||||
self._card_a_prefix = mp
|
||||
self._card_a_dev = "/dev/"+dev
|
||||
#print "card a = ", self._card_a_dev, self._card_a_prefix
|
||||
if i == 2:
|
||||
self._card_b_prefix = mp
|
||||
self._card_b_dev = "/dev/"+dev
|
||||
#print "card b = ", self._card_b_dev, self._card_b_prefix
|
||||
|
||||
mtd += 1
|
||||
break
|
||||
|
||||
if mtd > 0:
|
||||
return True
|
||||
else :
|
||||
return False
|
||||
#
|
||||
# ------------------------------------------------------
|
||||
#
|
||||
# this one is pretty simple:
|
||||
# just umount each of the previously
|
||||
# mounted filesystems, using the mount helper
|
||||
#
|
||||
def eject_freebsd(self):
|
||||
cmd = '/usr/local/bin/calibre-mount-helper'
|
||||
cmd = [cmd, 'eject']
|
||||
|
||||
if self._main_prefix:
|
||||
#print "umount main:", cmd, self._main_dev, self._main_prefix
|
||||
try:
|
||||
p = subprocess.Popen(cmd + [self._main_dev, self._main_prefix])
|
||||
except OSError:
|
||||
raise DeviceError(
|
||||
_('Could not find mount helper: %s.')%cmd[0])
|
||||
while p.poll() is None:
|
||||
time.sleep(0.1)
|
||||
|
||||
if self._card_a_prefix:
|
||||
#print "umount card a:", cmd, self._card_a_dev, self._card_a_prefix
|
||||
try:
|
||||
p = subprocess.Popen(cmd + [self._card_a_dev, self._card_a_prefix])
|
||||
except OSError:
|
||||
raise DeviceError(
|
||||
_('Could not find mount helper: %s.')%cmd[0])
|
||||
while p.poll() is None:
|
||||
time.sleep(0.1)
|
||||
|
||||
if self._card_b_prefix:
|
||||
#print "umount card b:", cmd, self._card_b_dev, self._card_b_prefix
|
||||
try:
|
||||
p = subprocess.Popen(cmd + [self._card_b_dev, self._card_b_prefix])
|
||||
except OSError:
|
||||
raise DeviceError(
|
||||
_('Could not find mount helper: %s.')%cmd[0])
|
||||
while p.poll() is None:
|
||||
time.sleep(0.1)
|
||||
|
||||
self._main_prefix = None
|
||||
self._card_a_prefix = None
|
||||
self._card_b_prefix = None
|
||||
# ------------------------------------------------------
|
||||
|
||||
def open(self, library_uuid):
|
||||
time.sleep(5)
|
||||
@ -712,6 +857,14 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
except DeviceError:
|
||||
time.sleep(7)
|
||||
self.open_linux()
|
||||
if isfreebsd:
|
||||
self._main_dev = self._card_a_dev = self._card_b_dev = None
|
||||
try:
|
||||
self.open_freebsd()
|
||||
except DeviceError:
|
||||
subprocess.Popen(["camcontrol", "rescan", "all"])
|
||||
time.sleep(2)
|
||||
self.open_freebsd()
|
||||
if iswindows:
|
||||
try:
|
||||
self.open_windows()
|
||||
@ -800,6 +953,11 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
self.eject_linux()
|
||||
except:
|
||||
pass
|
||||
if isfreebsd:
|
||||
try:
|
||||
self.eject_freebsd()
|
||||
except:
|
||||
pass
|
||||
if iswindows:
|
||||
try:
|
||||
self.eject_windows()
|
||||
|
@ -54,7 +54,7 @@ cpalmdoc_decompress(PyObject *self, PyObject *args) {
|
||||
// Map chars to bytes
|
||||
for (j = 0; j < input_len; j++)
|
||||
input[j] = (_input[j] < 0) ? _input[j]+256 : _input[j];
|
||||
output = (char *)PyMem_Malloc(sizeof(char)*(MAX(BUFFER, 5*input_len)));
|
||||
output = (char *)PyMem_Malloc(sizeof(char)*(MAX(BUFFER, 8*input_len)));
|
||||
if (output == NULL) return PyErr_NoMemory();
|
||||
|
||||
while (i < input_len) {
|
||||
|
@ -957,7 +957,10 @@ def get_metadata(stream):
|
||||
return get_metadata(stream)
|
||||
from calibre.utils.logging import Log
|
||||
log = Log()
|
||||
mi = MetaInformation(os.path.basename(stream.name), [_('Unknown')])
|
||||
try:
|
||||
mi = MetaInformation(os.path.basename(stream.name), [_('Unknown')])
|
||||
except:
|
||||
mi = MetaInformation(_('Unknown'), [_('Unknown')])
|
||||
mh = MetadataHeader(stream, log)
|
||||
if mh.title and mh.title != _('Unknown'):
|
||||
mi.title = mh.title
|
||||
|
@ -587,9 +587,10 @@ class TagsView(QTreeView): # {{{
|
||||
def show_item_at_index(self, idx, box=False,
|
||||
position=QTreeView.PositionAtCenter):
|
||||
if idx.isValid() and idx.data(Qt.UserRole).toPyObject() is not self._model.root_item:
|
||||
self.setExpanded(idx, True) # Needed otherwise Qt segfaults if the
|
||||
# node is buried in a collapsed, off
|
||||
# screen hierarchy
|
||||
self.expand(self._model.parent(idx)) # Needed otherwise Qt sometimes segfaults if the
|
||||
# node is buried in a collapsed, off
|
||||
# screen hierarchy
|
||||
self.setCurrentIndex(idx)
|
||||
self.scrollTo(idx, position)
|
||||
if box:
|
||||
self._model.set_boxed(idx)
|
||||
|
@ -1245,6 +1245,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
ret = tempfile.SpooledTemporaryFile(max_size=SPOOL_SIZE)
|
||||
shutil.copyfileobj(f, ret)
|
||||
ret.seek(0)
|
||||
ret.name = f.name
|
||||
else:
|
||||
ret = f.read()
|
||||
return ret
|
||||
|
Loading…
x
Reference in New Issue
Block a user