Passing all scanner usage through local saned
Guillaume Girol via sane-devel <[email protected]>
| Newsgroups | gmane.comp.graphics.scanning.sane.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello, I'm a downstream maintainer of SANE on NixOS, a linux distribution. I consider modifying NixOS to make it so all application using libsane would actually only use saned, and never load the backends to directly access scanners themselves. I send this message to the mailing list to know if I missed reasons it could be a bad idea. Rationale ========= NixOS is quite different from typical linux distributions in that there is no globally installed library. /usr/lib does not exist and without special packaging care, dlopen() never finds anything. Each library is installed in a unique prefix /nix/store/unique-id/lib/foo.so so several versions of the same library can coexist. Exeecutable find the libraries they depend on via explicit RPATH. As a result I can have an old version of python in /nix/store/some-id/bin/python using an old version of glibc in /nix/store/other-id/lib/libc.so via RPATH and the rest of the system using a newer version of glibc in /nix/store/yet- another-id/lib/libc.so also via RPATH. This does not work for SANE as it uses dlopen() to find backends depending on a single, global configuration file. For now we have an exception to the "no lib installed globally" design for SANE. However this is not perfect: if I use an old version of, say, simple-scan, it may dlopen() more recent version of some SANE backend, which depends on a more recent glibc than the version that old simple-scan brings with its RPATH. Thus dlopen() fails. In practice this means that software installed from the past or the future often fails to scan, whereas this usually works quite well for other functionnality. Solution considered =================== To solve this, I want applications using SANE to stop using dlopen() to access the scanner, but to use a network protocol instead. This is a bit like glibc can talk to nscd over a socket instead of dlopening nss modules. The solution I'm considering consists in linking all normal applications to a stripped-down variant of libsane which only has the network backend and is configured to connect to a saned instance on localhost (instead of obeying what you would find in /etc/sane.d on typical distros). Each application comes with its own copy of this libsane, it's not global anymore. (Don't mind the disk space cost, all of NixOS works this way, this is part of the tradeoff). When the user configures their system for scanner support, a global instance of saned is setup which is linked against a full-fledged copy of libsane obeying the full configuration files you would typically find in /etc/sane.d. When an old application attempts to scan, it uses its own, old version of libsane to talk to a recent saned which dlopen()s sane backends of matching version, so all works fine. Possible issues? ================ Any issues with this design I missed? In my light testing, it appears to work quite fine. The problems I found: - all users can use the scanners instead of just users in the lp or scanner group previously. I suppose this can be solved with a firewall (firewalls can filter the uid of local sockets). - network scanners are not available. I propose a fix in https://gitlab.com/sane-project/backends/-/merge_requests/834 - is the network protocol that saned uses stable across versions? In my testing, it is, but maybe it's by sheer luck. - maybe stuff I have not considered. Cheers, Guillaume Girol