diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
index b731b8b72a3d..02cb2dd9ccd1 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
@@ -643,6 +643,15 @@
maintainer to update the package.
+
+
+ ppd files in pkgs.cups-drv-rastertosag-gdi
+ are now gzipped. If you refer to such a ppd file with its path
+ (e.g. via
+ hardware.printers.ensurePrinters)
+ you will need to append .gz to the path.
+
+
xow package removed along with the
diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md
index 0f0e3c7a2e55..43abb40b8a04 100644
--- a/nixos/doc/manual/release-notes/rl-2211.section.md
+++ b/nixos/doc/manual/release-notes/rl-2211.section.md
@@ -210,6 +210,8 @@ Available as [services.patroni](options.html#opt-services.patroni.enable).
- riak package removed along with `services.riak` module, due to lack of maintainer to update the package.
+- ppd files in `pkgs.cups-drv-rastertosag-gdi` are now gzipped. If you refer to such a ppd file with its path (e.g. via [hardware.printers.ensurePrinters](options.html#opt-hardware.printers.ensurePrinters)) you will need to append `.gz` to the path.
+
- xow package removed along with the `hardware.xow` module, due to the project being deprecated in favor of `xone`, which is available via the `hardware.xone` module.
- dd-agent package removed along with the `services.dd-agent` module, due to the project being deprecated in favor of `datadog-agent`, which is available via the `services.datadog-agent` module.
diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/default.nix b/pkgs/build-support/setup-hooks/patch-ppd-files/default.nix
new file mode 100644
index 000000000000..b3c7b19f3732
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/patch-ppd-files/default.nix
@@ -0,0 +1,25 @@
+{ lib
+, makeSetupHook
+, which
+, callPackage
+}:
+
+let
+ patchPpdFilesHook = makeSetupHook
+ {
+ name = "patch-ppd-files";
+ substitutions.which = lib.attrsets.getBin which;
+ substitutions.awkscript = ./patch-ppd-lines.awk;
+ }
+ ./patch-ppd-hook.sh;
+in
+
+patchPpdFilesHook.overrideAttrs (
+ lib.trivial.flip
+ lib.attrsets.recursiveUpdate
+ {
+ passthru.tests.test = callPackage ./test.nix {};
+ meta.description = "setup hook to patch executable paths in ppd files";
+ meta.maintainers = [ lib.maintainers.yarny ];
+ }
+)
diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh
new file mode 100644
index 000000000000..a450ecd7f963
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-hook.sh
@@ -0,0 +1,183 @@
+fixupOutputHooks+=(_patchPpdFileCommands4fixupOutputHooks)
+
+
+
+# Install a hook for the `fixupPhase`:
+# If the variable `ppdFileCommands` contains a list of
+# executable names, the hook calls `patchPpdFileCommands`
+# on each output's `/share/cups/model` and `/share/ppds`
+# directories in order to replace calls to those executables.
+
+_patchPpdFileCommands4fixupOutputHooks () {
+ [[ -n $ppdFileCommands ]] || return 0
+ if [[ -d $prefix/share/cups/model ]]; then
+ patchPpdFileCommands "$prefix/share/cups/model" $ppdFileCommands
+ fi
+ if [[ -d $prefix/share/ppds ]]; then
+ patchPpdFileCommands "$prefix/share/ppds" $ppdFileCommands
+ fi
+}
+
+
+
+# patchPpdFileCommands PPD-ROOT PROGNAME...
+#
+# Look for ppd files in the directory PPD-ROOT.
+# Descend into subdirectories, even if they are symlinks.
+# However, ignore ppd files that don't belong to the same
+# prefix ($NIX_STORE/$package_name) as PPD-ROOT-DIR does,
+# to avoid stepping into other package's directories.
+# ppd files may be gzipped; if the are,
+# uncompress them, later recompress them.
+# Skip symlinks to ppd files.
+# PPD-ROOT may also be a single ppd file.
+#
+# Look for the PROGNAME executable in outputs and `buildInputs`,
+# then look for PROGNAME invocations in the ppd files,
+# without path or with common paths like `/usr/bin/$PROGNAME`.
+# Replace those invocations with an absolute path to the
+# corresponding executable from the outputs or `buildInputs`.
+# Executables are searched where CUPS would search them,
+# i.e., in `/bin` and `/lib/cups/filter`.
+#
+# As soon as an executable's path is replaced as
+# described above, the package containing the binary
+# is added to the list of propagated build inputs.
+# This ensures the executable's package is still
+# recognized as runtime dependency of the ppd file
+# even if the ppd file is compressed lateron.
+#
+# PROGNAME may not contain spaces or tabs.
+# The function will also likely fail or produce
+# broken results if PROGNAME contains characters that
+# require shell or regex escaping (e.g. a backslash).
+
+patchPpdFileCommands () {
+
+ local bin binnew binold binoldgrep cupspath path ppdroot ppdrootprefix
+
+ # we will store some temporary data here
+ pushd "$(mktemp -d --tmpdir patch-ppd-file-commands.XXXX)"
+
+ # remember the ppd root path
+ [[ "$1" == $NIX_STORE/* ]] # ensure it's a store directory
+ ppdroot=$1
+ shift # now "$@" is the list of binaries
+ ppdrootprefix=${ppdroot%"/${ppdroot#"$NIX_STORE"/*/}"}
+
+ # create `cupspath` (where we should look for binaries),
+ # with these priorities
+ # * outputs of current build before buildInputs
+ # * `/lib/cups/filter' before `/bin`
+ # * add HOST_PATH at end, so we don't miss anything
+ for path in $outputs; do
+ addToSearchPath cupspath "${!path}/lib/cups/filter"
+ addToSearchPath cupspath "${!path}/bin"
+ done
+ for path in ${pkgsHostTarget+"${pkgsHostTarget[@]}"}; do
+ addToSearchPath cupspath "$path/lib/cups/filter"
+ addToSearchPath cupspath "$path/bin"
+ done
+ while read -r -d : path; do
+ addToSearchPath cupspath "$path"
+ done <<< "${HOST_PATH:+"${HOST_PATH}:"}"
+
+ # create list of compressed ppd files
+ # so we can recompress them later
+ find -L "$ppdroot" -type f -iname '*.ppd.gz' '!' -xtype l -print0 > gzipped
+
+ # decompress gzipped ppd files
+ echo "patchPpdFileCommands: decompressing $(grep -cz '^' < gzipped) gzipped ppd file(s) in $ppdroot"
+ xargs -0r -n 64 -P "$NIX_BUILD_CORES" gunzip < gzipped
+
+ # create list of all ppd files to be checked
+ find -L "$ppdroot" -type f -iname '*.ppd' '!' -xtype l -print0 > ppds
+
+ for bin in "$@"; do
+
+ # discover new path
+ binnew=$(PATH=$cupspath '@which@/bin/which' "$bin")
+ echo "patchPpdFileCommands: located binary $binnew"
+
+ # for each binary, we look for the name itself, but
+ # also for a couple of common paths that might be used
+ for binold in {/usr,}/{lib/cups/filter,sbin,bin}/"$bin" "$bin"; do
+
+ # escape regex characters in the old command string
+ binoldgrep=$(sed 's,[]$.*[\^],\\&,g' <<< "$binold")
+ # ...and surround old command with some regex
+ # that singles out shell command invocations
+ # to avoid replacing other strings that might contain the
+ # command name by accident (like "perl" in "perl-script")
+ binoldgrep='\(^\|[;&| '$'\t''"`(]\)'"$binoldgrep"'\($\|[);&| '$'\t''"`<>]\)'
+ # this string is used to *quickly* filter out
+ # unaffected files before the (slower) awk script runs;
+ # note that a similar regex is build in the awk script;
+ # if `binoldgrep` is changed, the awk script should also be checked
+
+ # create list of likely affected files
+ # (might yield exit status != 0 if there are no matches)
+ xargs -0r grep -lZ "$binoldgrep" < ppds > ppds-to-patch || true
+
+ echo "patchPpdFileCommands: $(grep -cz '^' < ppds-to-patch) ppd file(s) contain $binold"
+
+ # actually patch affected ppd files with awk;
+ # this takes some time but can be parallelized;
+ # speed up with LC_ALL=C, https://stackoverflow.com/a/33850386
+ LC_ALL=C xargs -0r -n 64 -P "$NIX_BUILD_CORES" \
+ awk -i inplace -v old="${binold//\\/\\\\}" -v new="${binnew//\\/\\\\}" -f "@awkscript@" \
+ < ppds-to-patch
+
+ done
+
+ # create list of affected files
+ xargs -0r grep -lZF "$binnew" < ppds > patched-ppds || true
+
+ echo "patchPpdFileCommands: $(grep -cz '^' < patched-ppds) ppd file(s) patched with $binnew"
+
+ # if the new command is contained in a file,
+ # remember the new path so we can add it to
+ # the list of propagated dependencies later
+ if [[ -s patched-ppds ]]; then
+ printf '%s\0' "${binnew%"/${binnew#"${NIX_STORE}"/*/}"}" >> dependencies
+ fi
+
+ done
+
+ # recompress ppd files that have been decompressed before
+ echo "patchPpdFileCommands: recompressing $(grep -cz '^' < gzipped) gzipped ppd file(s)"
+ # we can't just hand over the paths of the uncompressed files
+ # to gzip as it would add the lower-cased extension ".gz"
+ # even for files where the original was named ".GZ"
+ xargs -0r -n 1 -P "$NIX_BUILD_CORES" \
+ "$SHELL" -c 'gzip -9nS ".${0##*.}" "${0%.*}"' \
+ < gzipped
+
+ # enlist dependencies for propagation;
+ # this is needed in case ppd files are compressed later
+ # (Nix won't find dependency paths in compressed files)
+ if [[ -s dependencies ]]; then
+
+ # weed out duplicates from the dependency list first
+ sort -zu dependencies > sorted-dependencies
+
+ mkdir -p "$ppdrootprefix/nix-support"
+ while IFS= read -r -d '' path; do
+ printWords "$path" >> "$ppdrootprefix/nix-support/propagated-build-inputs"
+ # stdenv writes it's own `propagated-build-inputs`,
+ # based on the variable `propagatedBuildInputs`,
+ # but only to one output (`outputDev`).
+ # So we also add our dependencies to that variable.
+ # If our file survives as written above, great!
+ # If stdenv overwrits it,
+ # our dependencies will still be added to the file.
+ # The end result might contain too many
+ # propagated dependencies for multi-output packages,
+ # but never a broken package.
+ propagatedBuildInputs+=("$path")
+ done < sorted-dependencies
+ fi
+
+ popd
+
+}
diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk
new file mode 100644
index 000000000000..ddb9171fff32
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/patch-ppd-files/patch-ppd-lines.awk
@@ -0,0 +1,50 @@
+BEGIN {
+
+ # ppd file keys are separated from their values by a colon,
+ # but "options" may reside between the key name and the colon;
+ # options are separated from the key by spaces
+ # (we also permit tabs to be on the safe side)
+ FS = "[: \t]";
+
+ # escape regex characters in the old and new command strings
+ gsub(/[]\\.^$(){}|*+?[]/, "\\\\&", old);
+ gsub(/\\/, "\\\\&", new);
+ # ...and surround old command with some regex
+ # that singles out shell command invocations
+ # to avoid replacing other strings that might contain the
+ # command name by accident (like "perl" in "perl-script")
+ new = "\\1" new "\\2";
+ old = "(^|[;&| \\t\"`(])" old "($|[);&| \\t\"`<>])";
+ # note that a similar regex is build in the shell script to
+ # filter out unaffected files before this awk script is called;
+ # if the regex here is changed, the shell script should also be checked
+
+ # list of PPD keys that contain executable names or scripts, see
+ # https://refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Printing/LSB-Printing/ppdext.html
+ # https://www.cups.org/doc/spec-ppd.html
+ cmds["*APAutoSetupTool"] = "";
+ cmds["*APPrinterLowInkTool"] = "";
+ cmds["*FoomaticRIPCommandLine"] = "";
+ cmds["*FoomaticRIPPostPipe"] = "";
+ cmds["*cupsFilter"] = "";
+ cmds["*cupsFilter2"] = "";
+ cmds["*cupsPreFilter"] = "";
+
+}
+
+# since comments always start with "*%",
+# this mechanism also properly recognizes (and ignores) them
+
+{
+
+ # if the current line starts a new key,
+ # check if it is a command-containing key;
+ # also reset the `isCmd` flag if a new file begins
+ if ($0 ~ /^\*/ || FNR == 1) { isCmd = ($1 in cmds) }
+
+ # replace commands if the current keys might contain commands
+ if (isCmd) { $0 = gensub(old, new, "g") }
+
+ print
+
+}
diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/test.nix b/pkgs/build-support/setup-hooks/patch-ppd-files/test.nix
new file mode 100644
index 000000000000..4f2996b23510
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/patch-ppd-files/test.nix
@@ -0,0 +1,40 @@
+{ substituteAll
+, diffutils
+, stdenv
+, patchPpdFilesHook
+}:
+
+let
+ input = substituteAll {
+ src = ./test.ppd;
+ keep = "cmp";
+ patch = "cmp";
+ pathkeep = "/bin/cmp";
+ pathpatch = "/bin/cmp";
+ };
+
+ output = substituteAll {
+ src = ./test.ppd;
+ keep = "cmp";
+ patch = "${diffutils}/bin/cmp";
+ pathkeep = "/bin/cmp";
+ pathpatch = "${diffutils}/bin/cmp";
+ };
+in
+
+stdenv.mkDerivation {
+ name = "${patchPpdFilesHook.name}-test";
+ buildInputs = [ diffutils ];
+ nativeBuildInputs = [ diffutils patchPpdFilesHook ];
+ dontUnpack = true;
+ dontInstall = true;
+ ppdFileCommands = [ "cmp" ];
+ preFixup = ''
+ install -D "${input}" "${placeholder "out"}/share/cups/model/test.ppd"
+ install -D "${input}" "${placeholder "out"}/share/ppds/test.ppd"
+ '';
+ postFixup = ''
+ diff --color --report-identical-files "${output}" "${placeholder "out"}/share/cups/model/test.ppd"
+ diff --color --report-identical-files "${output}" "${placeholder "out"}/share/ppds/test.ppd"
+ '';
+}
diff --git a/pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd b/pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd
new file mode 100644
index 000000000000..d0ca11ccfe6d
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/patch-ppd-files/test.ppd
@@ -0,0 +1,22 @@
+*% This comment: might look like a command @keep@
+*% but it should be left untouched
+*SomeKey: do not replace this @keep@
+*APAutoSetupTool: do replace this @patch@
+*FoomaticRIPCommandLine: "patch also @patch@
+in a multi-line command @patch@
+and another line @patch@
+*SomeKey: "stop patching on new non-command key @keep@
+and remember the key in the next line @keep@"
+*cupsFilter option: recognize keys with options @patch@
+*cupsFilter : handle strange spacing;@patch@
+*cupsFilter : handle tabulator @patch@
+*cupsFilter: patch common paths @pathpatch@
+*cupsFilter: patch quoted commands "@patch@"
+*cupsFilter: patch commands in subshell (@patch@)
+*cupsFilter: patch commands in subshell `@pathpatch@`
+*cupsFilter: keep uncommon paths /fancy/@pathkeep@
+*cupsFilter: keep entangled commands-@keep@
+*cupsFilter: keep entangled commands\@keep@
+*cupsFilter: keep entangled commands @keep@()
+*cupsFilter: keep entangled commands @pathkeep@-cmd
+*%cupsFilter: This comment should also be left as is @pathkeep@
diff --git a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix
index d49143655459..4f1ad6c9911e 100644
--- a/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix
+++ b/pkgs/misc/cups/drivers/cups-drv-rastertosag-gdi/default.nix
@@ -3,6 +3,7 @@
, fetchpatch
, cups
, python3Packages
+, patchPpdFilesHook
}:
python3Packages.buildPythonApplication rec {
@@ -20,9 +21,9 @@ python3Packages.buildPythonApplication rec {
})
];
format = "other";
- nativeBuildInputs = [ (lib.getBin cups) ];
+ nativeBuildInputs = [ (lib.getBin cups) patchPpdFilesHook ];
# The source image also brings pre-built ppd files,
- # be we prefer to generate from source where possible, so
+ # but we prefer to generate from source where possible, so
# the following line generates ppd files from the drv file.
postBuild = ''
ppdc -v -d . -I "${cups}/share/cups/ppdc" rastertosag-gdi.drv
@@ -35,6 +36,10 @@ python3Packages.buildPythonApplication rec {
ln -vst "${placeholder "out"}/lib/cups/filter/" "${placeholder "out"}/bin/rastertosag-gdi"
runHook postInstall
'';
+ ppdFileCommands = [ "rastertosag-gdi" ];
+ postFixup = ''
+ gzip -9nv "${placeholder "out"}/share/cups/model/rastertosag-gdi"/*.ppd
+ '';
meta = {
description = "CUPS driver for Ricoh Aficio SP 1000S and SP 1100S printers";
downloadPage = "https://www.openprinting.org/download/printing/rastertosag-gdi/";
diff --git a/pkgs/misc/cups/drivers/foomatic-db-engine/default.nix b/pkgs/misc/cups/drivers/foomatic-db-engine/default.nix
new file mode 100644
index 000000000000..b5e107ebf37f
--- /dev/null
+++ b/pkgs/misc/cups/drivers/foomatic-db-engine/default.nix
@@ -0,0 +1,94 @@
+{ lib
+, perlPackages
+, fetchFromGitHub
+, withCupsAccess ? false # needed to access local cups server
+, cups
+, cups-filters
+, curl
+, withSocketAccess ? false # needed to access network printers
+, netcat-gnu
+, withSMBAccess ? false # needed to access SMB-connected printers
+, samba
+, autoconf
+, automake
+, file
+, makeWrapper
+}:
+
+perlPackages.buildPerlPackage {
+ pname = "foomatic-db-engine";
+ version = "unstable-2022-05-03";
+
+ src = fetchFromGitHub {
+ # there is also a daily snapshot at the `downloadPage`,
+ # but it gets deleted quickly and would provoke 404 errors
+ owner = "OpenPrinting";
+ repo = "foomatic-db-engine";
+ rev = "2e6f14b54748fa121a4d2e3d480010e10b070c5a";
+ hash = "sha256-m7FQTxWmawbtm24h8UqznGKXgX41JhOtyyFMRwEhm5k=";
+ };
+
+ outputs = [ "out" ];
+
+ propagatedBuildInputs = [
+ perlPackages.Clone
+ perlPackages.DBI
+ perlPackages.XMLLibXML
+ ];
+
+ buildInputs =
+ # provide some "cups-*" commands to `foomatic-{configure,printjob}`
+ # so that they can manage a local cups server (add queues, add jobs...)
+ lib.optionals withCupsAccess [ cups cups-filters curl ]
+ # the commands `foomatic-{configure,getpjloptions}` need
+ # netcat if they are used to query or alter a network
+ # printer via AppSocket/HP JetDirect protocol
+ ++ lib.optional withSocketAccess netcat-gnu
+ # `foomatic-configure` can be used to access printers that are
+ # shared via the SMB protocol, but it needs the `smbclient` binary
+ ++ lib.optional withSMBAccess samba
+ ;
+
+ nativeBuildInputs = [ autoconf automake file makeWrapper ];
+
+ # sed-substitute indirection is more robust against
+ # characters in paths that might need escaping
+ prePatch = ''
+ sed -Ei 's|^(S?BINSEARCHPATH=).+$|\1"@PATH@"|g' configure.ac
+ substituteInPlace configure.ac --subst-var PATH
+ touch Makefile.PL # `buildPerlPackage` fails unless this exists
+ '';
+
+ preConfigure = ''
+ ./make_configure
+ '';
+
+ configureFlags = [
+ "--sysconfdir=${placeholder "out"}/etc"
+ "LIBDIR=${placeholder "out"}/share/foomatic"
+ "PERLPREFIX=${placeholder "out"}"
+ ];
+
+ postFixup = ''
+ for bin in "${placeholder "out"}/bin"/*; do
+ test '!' -L "$bin" || continue # skip symlink
+ wrapProgram "$bin" --set PERL5LIB "$PERL5LIB"
+ done
+ '';
+
+ doCheck = false; # no tests, would fail
+
+ meta = {
+ description = "OpenPrinting printer support database engine";
+ downloadPage = "https://www.openprinting.org/download/foomatic/";
+ homepage = "https://openprinting.github.io/projects/02-foomatic/";
+ license = lib.licenses.gpl2Only;
+ maintainers = [ lib.maintainers.yarny ];
+ longDescription = ''
+ Foomatic's database engine generates PPD files
+ from the data in Foomatic's XML database.
+ It also contains scripts to directly
+ generate print queues and handle jobs.
+ '';
+ };
+}
diff --git a/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix b/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix
new file mode 100644
index 000000000000..1c38ae38b98a
--- /dev/null
+++ b/pkgs/misc/cups/drivers/foomatic-db-nonfree/default.nix
@@ -0,0 +1,86 @@
+{ lib
+, stdenv
+, fetchFromGitHub
+, autoconf
+, automake
+, perl
+}:
+
+stdenv.mkDerivation {
+ pname = "foomatic-db-nonfree";
+ version = "unstable-2015-06-05";
+
+ src = fetchFromGitHub {
+ # there is also a daily snapshot at the `downloadPage`,
+ # but it gets deleted quickly and would provoke 404 errors
+ owner = "OpenPrinting";
+ repo = "foomatic-db-nonfree";
+ rev = "6ddae02ac89240c019f8b5026cfe70e30fd2b3db";
+ hash = "sha256-cRZH0CXg03FEqUJdxaNnPVXjf8+ct86PjhL59WQbw60=";
+ };
+
+ nativeBuildInputs = [ autoconf automake perl ];
+
+ # sed-substitute indirection is more robust against
+ # characters in paths that might need escaping
+ postPatch = ''
+ sed -Ei -e 's|^(S?BINSEARCHPATH=).+$|\1"@PATH@"|g' \
+ -e 's|^(DATASEARCHPATH=).+$|\1"@DATA@"|g' configure.ac
+ substituteInPlace configure.ac \
+ --subst-var PATH \
+ --subst-var-by DATA "${placeholder "out"}/share"
+ '';
+
+ preConfigure = ''
+ mkdir -p "${placeholder "out"}/share/foomatic/db/source"
+ ./make_configure
+ '';
+
+ # make ppd files available to cups,
+ # use a package-specific subdirectory to avoid
+ # conflicts with other ppd-containing packages
+ postInstall = ''
+ if ! [[ -d "${placeholder "out"}/share/foomatic/db/source/PPD" ]]; then
+ echo "failed to create share/foomatic/db/source/PPD"
+ exit 1
+ fi
+ mkdir -p "${placeholder "out"}/share/cups/model"
+ ln -s "${placeholder "out"}/share/foomatic/db/source/PPD" \
+ "${placeholder "out"}/share/cups/model/foomatic-db-nonfree"
+ '';
+
+ # we might patch ppd file commands with `patchPpdFilesHook`,
+ # but the only command "rastertophaser6100" isn't packaged yet
+
+ # compress ppd files
+ postFixup = ''
+ echo 'compressing ppd files'
+ find -H "${placeholder "out"}/share/cups/model/foomatic-db-nonfree" -type f -iname '*.ppd' -print0 \
+ | xargs -0r -n 64 -P "$NIX_BUILD_CORES" gzip -9n
+ '';
+
+ meta = {
+ description = "OpenPrinting printer support database (unfree content)";
+ downloadPage = "https://www.openprinting.org/download/foomatic/";
+ homepage = "https://openprinting.github.io/projects/02-foomatic/";
+ license = lib.licenses.unfree;
+ maintainers = [ lib.maintainers.yarny ];
+ # list printer manufacturers here so people
+ # searching for ppd files can find this package
+ longDescription = ''
+ The collected knowledge about printers,
+ drivers, and driver options in XML files,
+ used by `foomatic-db-engine` to generate PPD files.
+ This is a package of PPD and Foomatic XML files
+ that may have restrictions that keep them
+ from being used on a variety of machines
+ for licensing and other non-technical reasons.
+ The XML files in this package enable `foomatic-db-ppds`
+ to create about 120 additional PPD files, for printer from
+ Dell, Genicom, Lexmark, Oce, Tektronix and Xerox.
+ Besides the XML files, this package contains
+ about 130 PPD files, for printers from
+ Dell, Genicom, Lexmark, Oce and Xerox.
+ '';
+ };
+}
diff --git a/pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix b/pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix
new file mode 100644
index 000000000000..bdc1e0a9b5fe
--- /dev/null
+++ b/pkgs/misc/cups/drivers/foomatic-db-ppds/default.nix
@@ -0,0 +1,122 @@
+{ lib
+, foomatic-db
+, foomatic-db-nonfree
+, buildEnv
+, foomatic-db-engine
+, stdenv
+, cups-filters
+, ghostscript
+, netpbm
+, perl
+, psutils
+, patchPpdFilesHook
+, withNonfreeDb ? false # include foomatic-db-nonfree ppd files
+}:
+
+let
+ foomatic-db-packages = [ foomatic-db ] ++
+ lib.lists.optional withNonfreeDb foomatic-db-nonfree;
+
+ foomatic-db-combined = buildEnv {
+ name = "foomatic-db-combined";
+ paths = foomatic-db-packages;
+ pathsToLink = [ "/share/foomatic" ];
+ # `foomatic-db-combined` is a nativeBuildInput of `foomatic-db-ppds`.
+ # The setup hook defined here helps scripts in
+ # `foomatic-db-engine` to find the database.
+ postBuild = ''
+ mkdir -p "${placeholder "out"}"/{etc/cups,nix-support}
+ cat >> "${placeholder "out"}/nix-support/setup-hook" << eof
+ export FOOMATICDB="${placeholder "out"}/share/foomatic"
+ eof
+ '';
+ };
+
+ # the effective license is `free` if all database
+ # packages have free licenses, `unfree` otherwise
+ isFree = lib.trivial.pipe foomatic-db-packages [
+ (lib.lists.map (lib.attrsets.attrByPath [ "meta" "license" ] lib.licenses.unfree))
+ (lib.lists.all (lib.attrsets.attrByPath [ "free" ] true))
+ ];
+in
+
+stdenv.mkDerivation {
+ pname = "foomatic-db-ppds";
+ # the effective version is simply the
+ # highest version of all database packages
+ version = lib.trivial.pipe foomatic-db-packages [
+ (lib.lists.map (lib.attrsets.getAttr "version"))
+ (lib.lists.sort lib.strings.versionOlder)
+ lib.lists.reverseList
+ lib.lists.head
+ ];
+
+ buildInputs = [
+ cups-filters
+ ghostscript
+ netpbm
+ perl
+ psutils
+ ];
+
+ nativeBuildInputs = [
+ foomatic-db-combined
+ foomatic-db-engine
+ patchPpdFilesHook
+ ];
+
+ dontUnpack = true;
+
+ installPhase = ''
+ runHook preInstall
+ mkdir -p "${placeholder "out"}/share/cups/model"
+ foomatic-compiledb -j "$NIX_BUILD_CORES" -d "${placeholder "out"}/share/cups/model/foomatic-db-ppds"
+ runHook postInstall
+ '';
+
+ # Comments indicate the respective
+ # package the command is contained in.
+ ppdFileCommands = [
+ "cat" "echo" # coreutils
+ "foomatic-rip" # cups-filters or foomatic-filters
+ "gs" # ghostscript
+ "pnmflip" "pnmgamma" "pnmnoraw" # netpbm
+ "perl" # perl
+ "psresize" # psutils
+ # These commands aren't packaged yet.
+ # ppd files using these likely won't work.
+ #"c2050" "c2070" "cjet" "lm1100"
+ #"pbm2l2030" "pbm2lwxl" "rastertophaser6100"
+ ];
+
+ # compress ppd files
+ postFixup = ''
+ echo 'compressing ppd files'
+ find -H "${placeholder "out"}/share/cups/model/foomatic-db-ppds" -type f -iname '*.ppd' -print0 \
+ | xargs -0r -n 64 -P "$NIX_BUILD_CORES" gzip -9n
+ '';
+
+ meta = {
+ description = "OpenPrinting ppd files";
+ homepage = "https://openprinting.github.io/projects/02-foomatic/";
+ license = if isFree then lib.licenses.free else lib.licenses.unfree;
+ maintainers = [ lib.maintainers.yarny ];
+ # list printer manufacturers here so people
+ # searching for ppd files can find this package
+ longDescription = ''
+ All PPD files available in
+ OpenPrinting's Foomatic database.
+ This package contains about 8,800 PPD files,
+ for printers from
+ Alps, Anitech, Apollo, Apple, Avery, Brother, Canon,
+ Citizen, CItoh, Compaq, DEC, Dell, Dymo-CoStar, Epson,
+ Fujitsu, FujiXerox, Generic, Genicom, Gestetner,
+ Heidelberg, Hitachi, HP, IBM, Imagen, Imagistics,
+ InfoPrint, Infotec, Kodak, KONICAMINOLTA, Kyocera, Lanier,
+ Lexmark, Minolta, MinoltaQMS, Mitsubishi, NEC, NRG, Oce,
+ Oki, Olivetti, Panasonic, PCPI, Pentax, QMS, Raven, Ricoh,
+ Samsung, Savin, Seiko, Sharp, SiPix, Sony, Star, Tally,
+ Tektronix, TexasInstruments, Toshiba, Xante and Xerox.
+ '';
+ };
+}
diff --git a/pkgs/misc/cups/drivers/foomatic-db/default.nix b/pkgs/misc/cups/drivers/foomatic-db/default.nix
new file mode 100644
index 000000000000..dd76fb1ee05b
--- /dev/null
+++ b/pkgs/misc/cups/drivers/foomatic-db/default.nix
@@ -0,0 +1,102 @@
+{ lib
+, stdenv
+, fetchFromGitHub
+, cups
+, cups-filters
+, ghostscript
+, gnused
+, perl
+, autoconf
+, automake
+, patchPpdFilesHook
+}:
+
+stdenv.mkDerivation {
+ pname = "foomatic-db";
+ version = "unstable-2022-10-03";
+
+ src = fetchFromGitHub {
+ # there is also a daily snapshot at the `downloadPage`,
+ # but it gets deleted quickly and would provoke 404 errors
+ owner = "OpenPrinting";
+ repo = "foomatic-db";
+ rev = "2a3c4d1bf7eadc42f936ce8989c1dd2973ea9669";
+ hash = "sha256-in0/j1nAQvM0NowBIBx3jj5WVMPIfZAeAk1SkuA3tjA=";
+ };
+
+ buildInputs = [ cups cups-filters ghostscript gnused perl ];
+
+ nativeBuildInputs = [ autoconf automake patchPpdFilesHook perl ];
+
+ # sed-substitute indirection is more robust
+ # against characters in paths that might need escaping
+ postPatch = ''
+ sed -Ei -e 's|^(S?BINSEARCHPATH=).+$|\1"@PATH@"|g' \
+ -e 's|^(DATASEARCHPATH=).+$|\1"@DATA@"|g' configure.ac
+ substituteInPlace configure.ac \
+ --subst-var PATH \
+ --subst-var-by DATA "${placeholder "out"}/share"
+ '';
+
+ preConfigure = ''
+ mkdir -p "${placeholder "out"}/share/foomatic/db/source"
+ ./make_configure
+ '';
+
+ # don't let the intaller gzip ppd files as we would
+ # have to unzip them later in order to patch them
+ configureFlags = [ "--disable-gzip-ppds" ];
+
+ # make ppd files available to cups,
+ # use a package-specific subdirectory to avoid
+ # conflicts with other ppd-containing packages
+ postInstall = ''
+ if ! [[ -d "${placeholder "out"}/share/foomatic/db/source/PPD" ]]; then
+ echo "failed to create share/foomatic/db/source/PPD"
+ exit 1
+ fi
+ mkdir -p "${placeholder "out"}/share/cups/model"
+ ln -s "${placeholder "out"}/share/foomatic/db/source/PPD" \
+ "${placeholder "out"}/share/cups/model/foomatic-db"
+ '';
+
+ # Comments indicate the respective
+ # package the command is contained in.
+ ppdFileCommands = [
+ "cat" "date" "printf" # coreutils
+ "rastertohp" # cups
+ "foomatic-rip" # cups-filters or foomatic-filters
+ "gs" # ghostscript
+ "sed" # gnused
+ "perl" # perl
+ ];
+
+ # compress ppd files
+ postFixup = ''
+ echo 'compressing ppd files'
+ find -H "${placeholder "out"}/share/cups/model/foomatic-db" -type f -iname '*.ppd' -print0 \
+ | xargs -0r -n 64 -P "$NIX_BUILD_CORES" gzip -9n
+ '';
+
+ meta = {
+ description = "OpenPrinting printer support database (free content)";
+ downloadPage = "https://www.openprinting.org/download/foomatic/";
+ homepage = "https://openprinting.github.io/projects/02-foomatic/";
+ license = lib.licenses.free; # mostly GPL and MIT, see README in source dir
+ maintainers = [ lib.maintainers.yarny ];
+ # list printer manufacturers here so people
+ # searching for ppd files can find this package
+ longDescription = ''
+ The collected knowledge about printers,
+ drivers, and driver options in XML files,
+ used by `foomatic-db-engine` to generate PPD files.
+ PPD files generated from the XML files in this package
+ are contained in the package 'foomatic-db-ppds'.
+ Besides the XML files, this package contains
+ about 6,600 PPD files, for printers from
+ Brother, Canon, Epson, Gestetner, HP, InfoPrint,
+ Infotec, KONICA_MINOLTA, Kyocera, Lanier, Lexmark, NRG,
+ Oce, Oki, Ricoh, Samsung, Savin, Sharp, Toshiba and Utax.
+ '';
+ };
+}
diff --git a/pkgs/misc/cups/drivers/kyocera/default.nix b/pkgs/misc/cups/drivers/kyocera/default.nix
index 28b2a1281761..0a560e3188f6 100644
--- a/pkgs/misc/cups/drivers/kyocera/default.nix
+++ b/pkgs/misc/cups/drivers/kyocera/default.nix
@@ -1,4 +1,9 @@
-{ stdenv, lib, fetchzip, cups }:
+{ lib
+, stdenv
+, cups
+, fetchzip
+, patchPpdFilesHook
+}:
let
platform =
@@ -23,7 +28,11 @@ stdenv.mkDerivation {
sha256 = "0z1pbgidkibv4j21z0ys8cq1lafc6687syqa07qij2qd8zp15wiz";
};
+ nativeBuildInputs = [ patchPpdFilesHook ];
+
installPhase = ''
+ runHook preInstall
+
tar -xvf ${platform}/Global/English.tar.gz
install -Dm755 English/rastertokpsl $out/lib/cups/filter/rastertokpsl
patchelf \
@@ -33,13 +42,13 @@ stdenv.mkDerivation {
mkdir -p $out/share/cups/model/Kyocera
cd English
- for i in *.ppd; do
- sed -i $i -e \
- "s,/usr/lib/cups/filter/rastertokpsl,$out/lib/cups/filter/rastertokpsl,g"
- cp $i $out/share/cups/model/Kyocera
- done;
+ cp *.ppd $out/share/cups/model/Kyocera
+
+ runHook postInstall
'';
+ ppdFileCommands = [ "rastertokpsl" ];
+
meta = with lib; {
description = "CUPS drivers for several Kyocera FS-{1020,1025,1040,1060,1120,1125} printers";
homepage = "https://www.kyoceradocumentsolutions.ru/index/service_support/download_center.false.driver.FS1040._.EN.html#";
diff --git a/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix b/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix
index fac3dfccba62..47700265231f 100644
--- a/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix
+++ b/pkgs/misc/cups/drivers/samsung/1.00.36/default.nix
@@ -23,6 +23,7 @@ in stdenv.mkDerivation rec {
];
installPhase = ''
+ runHook preInstall
mkdir -p $out/bin
cp -R ${arch}/{gettext,pstosecps,rastertospl,smfpnetdiscovery,usbresetter} $out/bin
@@ -82,6 +83,8 @@ in stdenv.mkDerivation rec {
cd $out/share/cups
ln -s ../ppd .
ln -s ppd model
+
+ runHook postInstall
'';
preFixup = ''
diff --git a/pkgs/misc/cups/drivers/samsung/1.00.37.nix b/pkgs/misc/cups/drivers/samsung/1.00.37.nix
index 0aab52eac5da..59a210e6f534 100644
--- a/pkgs/misc/cups/drivers/samsung/1.00.37.nix
+++ b/pkgs/misc/cups/drivers/samsung/1.00.37.nix
@@ -22,6 +22,7 @@ in stdenv.mkDerivation rec {
];
installPhase = ''
+ runHook preInstall
mkdir -p $out/bin
cp -R ${arch}/{gettext,pstosecps,rastertospl,smfpnetdiscovery,usbresetter} $out/bin
@@ -65,6 +66,8 @@ in stdenv.mkDerivation rec {
cd $out/share/cups
ln -s ../ppd .
ln -s ppd model
+
+ runHook postInstall
'';
preFixup = ''
diff --git a/pkgs/misc/cups/drivers/samsung/4.01.17.nix b/pkgs/misc/cups/drivers/samsung/4.01.17.nix
index 12cfcde82f76..334703017478 100644
--- a/pkgs/misc/cups/drivers/samsung/4.01.17.nix
+++ b/pkgs/misc/cups/drivers/samsung/4.01.17.nix
@@ -11,7 +11,13 @@
# }
# (This advice was tested on the 1st November 2016.)
-{ lib, stdenv, fetchurl, cups, libusb-compat-0_1 }:
+{ lib
+, stdenv
+, cups
+, libusb-compat-0_1
+, fetchurl
+, patchPpdFilesHook
+}:
# Do not bump lightly! Visit
# to see what will break when upgrading. Consider a new versioned attribute.
@@ -28,10 +34,14 @@ in stdenv.mkDerivation rec {
sha256 = "1vv3pzvqpg1dq3xjr8161x2yp3v7ca75vil56ranhw5pkjwq66x0";
};
+ nativeBuildInputs = [ patchPpdFilesHook ];
+
dontPatchELF = true;
dontStrip = true;
installPhase = ''
+ runHook preInstall
+
cd Linux/${installationPath}
mkdir -p $out/lib/cups/{backend,filter}
install -Dm755 mfp $out/lib/cups/backend/
@@ -63,15 +73,18 @@ in stdenv.mkDerivation rec {
mkdir -p $out/share/cups/model/samsung
cd -
cd ../noarch/at_opt/share/ppd
- for i in *.ppd; do
- sed -i $i -e \
- "s,pstosecps,$out/lib/cups/filter/pstosecps,g; \
- s,pstospl,$out/lib/cups/filter/pstospl,g; \
- s,rastertospl,$out/lib/cups/filter/rastertospl,g"
- done;
cp -r ./* $out/share/cups/model/samsung
+
+ runHook postInstall
'';
+ ppdFileCommands = [
+ "pstosecps"
+ "pstospl"
+ "pstosplc"
+ "rastertospl"
+ ];
+
meta = with lib; {
description = "Samsung's Linux printing drivers; includes binaries without source code";
homepage = "http://www.samsung.com/";
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 9708553e8e71..1965a7216afa 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -1076,6 +1076,8 @@ with pkgs;
{ name = "validate-pkg-config"; deps = [ findutils pkg-config ]; }
../build-support/setup-hooks/validate-pkg-config.sh;
+ patchPpdFilesHook = callPackage ../build-support/setup-hooks/patch-ppd-files {};
+
#package writers
writers = callPackage ../build-support/writers {};
@@ -36360,6 +36362,12 @@ with pkgs;
epson-workforce-635-nx625-series = callPackage ../misc/drivers/epson-workforce-635-nx625-series { };
+ foomatic-db = callPackage ../misc/cups/drivers/foomatic-db {};
+ foomatic-db-engine = callPackage ../misc/cups/drivers/foomatic-db-engine {};
+ foomatic-db-nonfree = callPackage ../misc/cups/drivers/foomatic-db-nonfree {};
+ foomatic-db-ppds = callPackage ../misc/cups/drivers/foomatic-db-ppds {};
+ foomatic-db-ppds-withNonfreeDb = callPackage ../misc/cups/drivers/foomatic-db-ppds { withNonfreeDb = true; };
+
gutenprint = callPackage ../misc/drivers/gutenprint { };
gutenprintBin = callPackage ../misc/drivers/gutenprint/bin.nix { };