You are not logged in.
Hello everybody,
New to Arch Linux, but having a blast so far.
The driver package on the AUR for my printer (Brother MFC-L8690CDW) did not work for me. I took it as an opportunity to try and create my own.
In the process, I learned a lot about the Linux file system structure, pacman, makepkg, etc. It was intense but rewarding.
The basic issue is that Brother only supply Linux drivers as .deb or .rpm packages. So for use on Arch, they need to be adapted.
So of course I read all relevant wiki entries, which btw, the wiki is incredible, so much knowledge, and easy to follow for the most part.
Starting with Packaging Brother printer drivers, looking at existing packages for brother printers in the AUR, rading the package gudelines and the PGKBUILD article.
I noticed many different approaches depending on who created the PKGBUILD file for a specific printer, but it was hard to understand what exactly the reasoning behind certain steps were. So I also looked at the contents of the .deb archive and reverse engineered the installer that way. And some of those scripts were not pretty, let me tell you...
Unlike other brother driver packages on the AUR, my goal was to emulate the functionality of the original installer as much and as precisely as possible. This is why the end result is a bit more complex than other packages. Maybe not all of those steps are neccessary for everyone, but they do no harm either.
This is what i have come up with:
PKGBUILD:
# Maintainer: Bin Martig <bbbbmb97@gmail.com>
# Contributor: Frederick Gnodtke <frederick@gnodtke.net>
_model=mfcl8690cdw
pkgname=brother-mfc-l8690cdw
pkgver=1.5.0
pkgrel=1
pkgdesc="LPR driver and CUPS wrapper for Brother MFC-L8690CDW printer"
arch=("x86_64")
url="https://support.brother.com/g/b/downloadlist.aspx?c=eu_ot&lang=en&prod=mfcl8690cdw_eu_as&os=128"
license=("LicenseRef-BROTHER-EULA")
depends=("gcc-libs"
"perl"
"bash")
conflicts=("brother-mfcl8690cdw-lpr-bin"
"brother-mfcl8690cdw-cups-bin")
install="${pkgname}.install"
source=("${_model}-lpr::https://download.brother.com/welcome/dlf103241/${_model}lpr-${pkgver}-0.i386.deb"
"${_model}-cupswrapper::https://download.brother.com/welcome/dlf103250/${_model}cupswrapper-${pkgver}-0.i386.deb"
"BROTHER-EULA"
"setupPrintcapij.patch"
"cupswrappermfcl8690cdw.patch")
noextract=("${_model}-lpr")
b2sums=("36fe8cbf97cde9848ad401cf235b6c685c88330b4b66e2d733673a6a5448d8ec2f1f79b07f81010e7e718b79a7da9075d1325c475726fc92eca621952284e976"
"194d40f619abacf8655e08ff4a1b66f45cac26be1ee29ce33925a421a5dde6686d5e951ebb012f19048774a300deac18a9a426e7e78927b9e6dec844670ed416"
"a89bdc1fe13befa9a1813e61ca09e9b5ab4b528bce707a4cbd93d819341e9274fe886336f173e84b11819ed97eb5cd2ef0caea1dec8517fb34ddc60dd2c79e0c"
"dce87cd454f4571f974d23eb1733aa397790a594e1061808a2850ec51b7fceddaae72b3c58321306f6d232302cccea1c62ef2d519bb3c96148bd9901f6e8767c"
"d28a38238e8e6dfd4d56f58fc124bc9633def099a3033565dd840a8414aa0307b8a3e7a86cfb579be3285cfbf7e72941b13eab6e2d528f3dde7daa9690cd807e")
prepare() {
# Manually exctract sources so nothing gets overwritten
ar -x "${_model}-lpr" data.tar.gz
tar -xf data.tar.gz
rm data.tar.gz
ar -x "${_model}-cupswrapper" data.tar.gz
tar -xf data.tar.gz
rm data.tar.gz
# Patch post-install scripts to work with lprNG and systemd
cd "${srcdir}/opt/brother/Printers/${_model}/inf"
patch < "${srcdir}/setupPrintcapij.patch"
cd "${srcdir}/opt/brother/Printers/${_model}/cupswrapper"
patch < "${srcdir}/cupswrappermfcl8690cdw.patch"
}
package() {
# Install files
cd "${srcdir}/opt/brother/Printers/${_model}"
# LPR
install -Dm755 "lpd/x86_64/brmfcl8690cdwfilter" "${pkgdir}/opt/brother/Printers/${_model}/lpd/brmfcl8690cdwfilter"
install -Dm755 "lpd/x86_64/brprintconf_mfcl8690cdw" "${pkgdir}/opt/brother/Printers/${_model}/lpd/brprintconf_mfcl8690cdw"
install -Dm755 "lpd/filter_mfcl8690cdw" "${pkgdir}/opt/brother/Printers/${_model}/lpd/filter_mfcl8690cdw"
cp -r "inf" "${pkgdir}/opt/brother/Printers/${_model}"
chmod 755 "${pkgdir}/opt/brother/Printers/${_model}/inf"
# CUPS
install -Dm755 "cupswrapper/brother_lpdwrapper_mfcl8690cdw" "${pkgdir}/opt/brother/Printers/${_model}/cupswrapper/brother_lpdwrapper_mfcl8690cdw"
install -Dm755 "cupswrapper/cupswrappermfcl8690cdw" "${pkgdir}/opt/brother/Printers/${_model}/cupswrapper/cupswrappermfcl8690cdw"
install -Dm644 "cupswrapper/brother_mfcl8690cdw_printer_en.ppd" "${pkgdir}/opt/brother/Printers/${_model}/cupswrapper/brother_mfcl8690cdw_printer_en.ppd"
mkdir -p "${pkgdir}/usr/bin"
ln -s "/opt/brother/Printers/mfcl8690cdw/lpd/brprintconf_mfcl8690cdw" "${pkgdir}/usr/bin/brprintconf_mfcl8690cdw"
install -Dm644 "${srcdir}/BROTHER-EULA" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}
brother-mfc-l8690cdw.install:
post_install() {
echo "Adding an entry to /etc/printcap.local"
/opt/brother/Printers/mfcl8690cdw/inf/setupPrintcapij mfcl8690cdw -i
echo "Adding CUPS printer"
/opt/brother/Printers/mfcl8690cdw/cupswrapper/cupswrappermfcl8690cdw
chmod 755 /opt/brother/Printers/mfcl8690cdw/cupswrapper
if [ "$(which semanage 2> /dev/null)" != '' ];then
semanage fcontext -a -t cupsd_rw_etc_t '/opt/brother/Printers/mfcl8690cdw/inf(/.*)?'
semanage fcontext -a -t bin_t '/opt/brother/Printers/mfcl8690cdw/lpd(/.*)?'
semanage fcontext -a -t bin_t '/opt/brother/Printers/mfcl8690cdw/cupswrapper(/.*)?'
if [ "$(which restorecon 2> /dev/null)" != '' ];then
restorecon -R /opt/brother/Printers/mfcl8690cdw
fi
fi
if systemctl is-active --quiet cups; then
echo "restarting CUPS service"
systemctl restart cups
elif systemctl is-active --quiet lpd; then
echo "restarting LPRng service"
systemctl restart lpd
fi
}
pre_remove(){
echo "Removing CUPS printer"
/opt/brother/Printers/mfcl8690cdw/cupswrapper/cupswrappermfcl8690cdw -e
echo "Removing printer entry from /etc/printcap.local"
/opt/brother/Printers/mfcl8690cdw/inf/setupPrintcapij mfcl8690cdw -e
}
post_remove() {
rm -f /tmp/mfcl8690cdw_latest_print_info
if [ "$(which semanage 2> /dev/null)" != '' ];then
semanage fcontext -d -t cupsd_rw_etc_t '/opt/brother/Printers/mfcl8690cdw/inf(/.*)?'
semanage fcontext -d -t bin_t '/opt/brother/Printers/mfcl8690cdw/lpd(/.*)?'
semanage fcontext -d -t bin_t '/opt/brother/Printers/mfcl8690cdw/cupswrapper(/.*)?'
if [ "$(which restorecon 2> /dev/null)" != '' ];then
restorecon -R /opt/brother/Printers/mfcl8690cdw
fi
fi
if systemctl is-active --quiet cups; then
echo "restarting CUPS service"
systemctl restart cups
elif systemctl is-active --quiet lpd; then
echo "restarting LPRng service"
systemctl restart lpd
fi
}
setupPrintcapij.patch:
--- /home/JohannaNIX/Downloads/test/setupPrintcapij 2020-01-21 03:17:26.000000000 +0100
+++ /home/JohannaNIX/Downloads/test/setupPrintcapij_mod 2025-01-24 13:32:31.703664176 +0100
@@ -26,8 +26,4 @@
DEVICE_IF=/dev/usb/lp0
-if [ ! -f $PRINTCAP_NAME ]; then
- PRINTCAP_NAME=/etc/printcap
-fi
-
case "$2" in
-i)
@@ -35,5 +31,5 @@
mkdir -p $SPOOLER_NAME
fi
- chown lp $SPOOLER_NAME
+ chown daemon $SPOOLER_NAME
chgrp lp $SPOOLER_NAME
chmod 700 $SPOOLER_NAME
cupswrappermfcl8690cdw.patch:
--- /home/JohannaNIX/Downloads/brother-mfc-l8690cdw-cupswrapper/cupswrappermfcl8690cdw 2025-01-24 15:33:12.351893332 +0100
+++ /home/JohannaNIX/Downloads/brother-mfc-l8690cdw-cupswrapper/cupswrappermfcl8690cdw_mod 2025-01-24 15:39:47.945298669 +0100
@@ -49,8 +49,6 @@
rm -f /opt/brother/${device_model}/${printer_model}/cupswrapper/brother_lpdwrapper_${printer_model}
# rm -f /usr/local/Brother/${device_model}/${printer_model}/cupswrapper/brcupsconfpt1
-if [ -e /etc/init.d/cups ]; then
- /etc/init.d/cups restart
-elif [ -e /etc/init.d/cupsys ]; then
- /etc/init.d/cupsys restart
+if systemctl is-active --quiet cups; then
+ systemctl restart cups
fi
# /etc/init.d/cups restart
@@ -59,8 +57,6 @@
if [ "$1" = "-r" ]; then
lpadmin -x ${printer_name}
-if [ -e /etc/init.d/cups ]; then
- /etc/init.d/cups restart
-elif [ -e /etc/init.d/cupsys ]; then
- /etc/init.d/cupsys restart
+if systemctl is-active --quiet cups; then
+ systemctl restart cups
fi
# /etc/init.d/cups restart
@@ -292,16 +288,10 @@
#chmod a+w /opt/brother/${device_model}/${printer_model}/inf/br${printer_model}rc
#chmod a+w /opt/brother/${device_model}/${printer_model}/inf
-if [ -e /etc/init.d/lpd ]; then
- /etc/init.d/lpd stop
-fi
-if [ -e /etc/init.d/lprng ]; then
- /etc/init.d/lprng stop
+if systemctl is-active --quiet lpd; then
+ systemctl restart lpd
fi
-
-if [ -e /etc/init.d/cups ]; then
- /etc/init.d/cups restart
-elif [ -e /etc/init.d/cupsys ]; then
- /etc/init.d/cupsys restart
+if systemctl is-active --quiet cups; then
+ systemctl restart cups
fi
BROTHER-EULA:
License Agreement
This Agreement provides terms and conditions for license grant from Brother Industries, Ltd ("Brother"). Brother, who owns all copyrights to the software that is distributed with this Agreement ("Software") to recipients thereof ("User"), for use of the Software. User shall have the right to use the Software only in accordance with the terms and conditions of this Agreement. Any use by User of the Software shall be deemed as its agreement hereto.
Brother retains any and all copyrights to the Software. In no case this Agreement shall be construed to assign or otherwise transfer from Brother to User any copyrights or other intellectual property rights to whole or any part of the Software.
Brother grants User a non-exclusive license: to reproduce and/or distribute (via Internet or in any other manner) the Software. Further, Brother grants User a non-exclusive license to modify, alter, translate or otherwise prepare derivative works of the Software and to reproduce and distribute (via Internet or in any other manner) such modification, alteration, translation or other derivative works for any purpose.
The license of the Software from Brother hereunder is granted "AS IS." BROTHER HEREBY DISCLAIMS ANY WARRANTIES WITH RESPECT TO THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTY FOR THE QUALITY, MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE OR NON-INFRINGEMENT. Brother shall have no liability in contract, tort (including negligence or breach of statutory duty) or otherwise for any interruption of use, loss of data, or for any indirect, incidental, punitive or consequential loss or damage, or for any loss of profit, revenue, data, goodwill or anticipated savings that arises under, out of, or in contemplation of this Agreement or otherwise arises due to any error, inaccuracy or defect in the Software even if Brother has been advised of the possibility of such loss or damage. Further, Brother shall have no liability to disclose and/or distribute the source code of the Software to User under any circumstances. In no case shall the above license by Brother to modify, alter, translate or otherwise prepare derivative works of the Software be construed as Brother's implied agreement or undertakings to disclose and/or distribute the source code of the Software.
The result has been checked with namcap, and tested to work as intended on my machine. Some things were not possible to do the way intended by the manual (e.g. Brother does not publish checksums, so I calculated them on my end), but wherever possible, I stuck to the guidelines.
The existing package for my printer (https://aur.archlinux.org/packages/brother-mfc-l8690cdw) is orphaned, and, as I mentioned before, does not work for me. If you deem my work worthy and usable, I would love to adopt it and push my "updated" version to the AUR!
Looking forward to your comments!
Offline
No idea about printers but it is considered best practice to use `command -v` rather than `which` when trying to identify installed executables:
Para todos todo, para nosotros nada
Offline
No idea about printers but it is considered best practice to use `command -v` rather than `which` when trying to identify installed executables:
Good to know, thank you. This code is copied straight from Brothers post install script, I just verified what it does (set SELinux policies if necessary), not how it's written.
I think I'll keep it this way, just to make sure it's easier to adapt if an update ever comes out, i.e. just a copy-paste action instead of rewriting.
But as an exercise, am I correct that the concerned should be written like this?
if command -v semanage > /dev/null 2>&1; then
semanage fcontext -a -t cupsd_rw_etc_t '/opt/brother/Printers/mfcl8690cdw/inf(/.*)?'
semanage fcontext -a -t bin_t '/opt/brother/Printers/mfcl8690cdw/lpd(/.*)?'
semanage fcontext -a -t bin_t '/opt/brother/Printers/mfcl8690cdw/cupswrapper(/.*)?'
if command -v restorecon > /dev/null 2>&1; then
restorecon -R /opt/brother/Printers/mfcl8690cdw
fi
fi
Thank you for your time!
Last edited by binom (2025-01-25 15:19:22)
Offline
Yes, that's right. Bashisms are fine in PKGBUILDs though, if you prefer to use them.
Para todos todo, para nosotros nada
Offline