mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Support for detecting and mounting reader devices on FreeBSD. Fixes #802708 (Patches for Devices on FreeBSD)
This commit is contained in:
parent
f87375c45e
commit
fe1695b742
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user