nixpkgs/pkgs/misc/cups/drivers/mfcj6510dwlpr/default.nix
Jörg Thalheim dadc7eb329
treewide: use runtimeShell instead of stdenv.shell whenever possible
Whenever we create scripts that are installed to $out, we must use runtimeShell
in order to get the shell that can be executed on the machine we create the
package for. This is relevant for cross-compiling. The only use case for
stdenv.shell are scripts that are executed as part of the build system.
Usages in checkPhase are borderline however to decrease the likelyhood
of people copying the wrong examples, I decided to use runtimeShell as well.
2019-02-26 14:10:49 +00:00

90 lines
5.2 KiB
Nix

{ stdenv, fetchurl, pkgsi686Linux, dpkg, makeWrapper, coreutils, gnused, gawk, file, cups, utillinux, xxd, runtimeShell
, ghostscript, a2ps }:
# Why:
# The executable "brprintconf_mfcj6510dw" binary is looking for "/opt/brother/Printers/%s/inf/br%sfunc" and "/opt/brother/Printers/%s/inf/br%src".
# Whereby, %s is printf(3) string substitution for stdin's arg0 (the command's own filename) from the 10th char forwards, as a runtime dependency.
# e.g. Say the filename is "0123456789ABCDE", the runtime will be looking for /opt/brother/Printers/ABCDE/inf/brABCDEfunc.
# Presumably, the binary was designed to be deployed under the filename "printconf_mfcj6510dw", whereby it will search for "/opt/brother/Printers/mfcj6510dw/inf/brmfcj6510dwfunc".
# For NixOS, we want to change the string to the store path of brmfcj6510dwfunc and brmfcj6510dwrc but we're faced with two complications:
# 1. Too little room to specify the nix store path. We can't even take advantage of %s by renaming the file to the store path hash since the variable is too short and can't contain the whole hash.
# 2. The binary needs the directory it's running from to be r/w.
# What:
# As such, we strip the path and substitution altogether, leaving only "brmfcj6510dwfunc" and "brmfcj6510dwrc", while filling the leftovers with nulls.
# Fully null terminating the cstrings is necessary to keep the array the same size and preventing overflows.
# We then use a shell script to link and execute the binary, func and rc files in a temporary directory.
# How:
# In the package, we dump the raw binary as a string of search-able hex values using hexdump. We execute the substitution with sed. We then convert the hex values back to binary form using xxd.
# We also write a shell script that invoked "mktemp -d" to produce a r/w temporary directory and link what we need in the temporary directory.
# Result:
# The user can run brprintconf_mfcj6510dw in the shell.
stdenv.mkDerivation rec {
name = "mfcj6510dwlpr-${version}";
version = "3.0.0-1";
src = fetchurl {
url = "https://download.brother.com/welcome/dlf006614/mfcj6510dwlpr-${version}.i386.deb";
sha256 = "1ccvx393pqavsgzd8igrzlin5jrsf01d3acyvwqd1d0yz5jgqy6d";
};
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ cups ghostscript dpkg a2ps ];
unpackPhase = "true";
brprintconf_mfcj6510dw_script = ''
#!${runtimeShell}
cd $(mktemp -d)
ln -s @out@/usr/bin/brprintconf_mfcj6510dw_patched brprintconf_mfcj6510dw_patched
ln -s @out@/opt/brother/Printers/mfcj6510dw/inf/brmfcj6510dwfunc brmfcj6510dwfunc
ln -s @out@/opt/brother/Printers/mfcj6510dw/inf/brmfcj6510dwrc brmfcj6510dwrc
./brprintconf_mfcj6510dw_patched "$@"
'';
installPhase = ''
dpkg-deb -x $src $out
substituteInPlace $out/opt/brother/Printers/mfcj6510dw/lpd/filtermfcj6510dw \
--replace /opt "$out/opt"
substituteInPlace $out/opt/brother/Printers/mfcj6510dw/lpd/psconvertij2 \
--replace "GHOST_SCRIPT=`which gs`" "GHOST_SCRIPT=${ghostscript}/bin/gs"
substituteInPlace $out/opt/brother/Printers/mfcj6510dw/inf/setupPrintcapij \
--replace "/opt/brother/Printers" "$out/opt/brother/Printers" \
--replace "printcap.local" "printcap"
patchelf --set-interpreter ${pkgsi686Linux.stdenv.cc.libc.out}/lib/ld-linux.so.2 \
--set-rpath $out/opt/brother/Printers/mfcj6510dw/inf:$out/opt/brother/Printers/mfcj6510dw/lpd \
$out/opt/brother/Printers/mfcj6510dw/lpd/brmfcj6510dwfilter
patchelf --set-interpreter ${pkgsi686Linux.stdenv.cc.libc.out}/lib/ld-linux.so.2 $out/usr/bin/brprintconf_mfcj6510dw
#stripping the hardcoded path.
${utillinux}/bin/hexdump -ve '1/1 "%.2X"' $out/usr/bin/brprintconf_mfcj6510dw | \
sed 's.2F6F70742F62726F746865722F5072696E746572732F25732F696E662F6272257366756E63.62726d66636a36353130647766756e63000000000000000000000000000000000000000000.' | \
sed 's.2F6F70742F62726F746865722F5072696E746572732F25732F696E662F627225737263.62726D66636A3635313064777263000000000000000000000000000000000000000000.' | \
${xxd}/bin/xxd -r -p > $out/usr/bin/brprintconf_mfcj6510dw_patched
chmod +x $out/usr/bin/brprintconf_mfcj6510dw_patched
#executing from current dir. segfaults if it's not r\w.
mkdir -p $out/bin
echo -n "$brprintconf_mfcj6510dw_script" > $out/bin/brprintconf_mfcj6510dw
chmod +x $out/bin/brprintconf_mfcj6510dw
substituteInPlace $out/bin/brprintconf_mfcj6510dw --replace @out@ $out
mkdir -p $out/lib/cups/filter/
ln -s $out/opt/brother/Printers/mfcj6510dw/lpd/filtermfcj6510dw $out/lib/cups/filter/brother_lpdwrapper_mfcj6510dw
wrapProgram $out/opt/brother/Printers/mfcj6510dw/lpd/psconvertij2 \
--prefix PATH ":" ${ stdenv.lib.makeBinPath [ coreutils gnused gawk ] }
wrapProgram $out/opt/brother/Printers/mfcj6510dw/lpd/filtermfcj6510dw \
--prefix PATH ":" ${ stdenv.lib.makeBinPath [ coreutils gnused file ghostscript a2ps ] }
'';
meta = with stdenv.lib; {
description = "Brother MFC-J6510DW LPR driver";
downloadPage = http://support.brother.com/g/b/downloadlist.aspx?c=us&lang=en&prod=mfcj6510dw_all&os=128;
homepage = http://www.brother.com/;
license = with licenses; unfree;
maintainers = with maintainers; [ ramkromberg ];
platforms = with platforms; linux;
};
}