From dc7f8ab10c15b08b8b91069b01048e2c0f91ffc3 Mon Sep 17 00:00:00 2001 From: castrojo Date: Wed, 16 Sep 2026 09:49:44 -0400 Subject: [PATCH 1/3] docs: plan stateful FSDK drivers Assisted-by: github-copilot/gpt-5.6-sol via pi --- ...026-09-16-fsdk-stateful-profile-drivers.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md diff --git a/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md b/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md new file mode 100644 index 0000000..3ed4e12 --- /dev/null +++ b/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md @@ -0,0 +1,35 @@ +# FSDK Stateful Profile Drivers Implementation Plan + +**Goal:** Restore HPIJS, foo2zjs, and m2300w with immutable builds, valid OCI paths, discoverable driver data, and persistent user-editable configuration/profile state. + +**Architecture:** Add one pinned BuildStream element per upstream source. Build HPLIP in its minimal HPIJS-only configuration and keep its mutable `hplip.conf` under `/var/lib/ghostscript-printer-app/hplip`, reached through `/etc/hp/hplip.conf`. Build foo2zjs and m2300w against the existing FSDK CUPS/Ghostscript graph and the single repository-owned JBIG artifact. Their wrappers use `/usr` for executables and `/var/lib/ghostscript-printer-app/{foo2zjs,m2300w}` for profile data. Immutable defaults live under `/usr/share/ghostscript-printer-app/defaults`; the entrypoint copies only missing files into persistent state before starting the application. + +## Task 1: Build immutable driver artifacts + +- [ ] Add HPLIP from `debian/3.26.4+dfsg0-3-0-gf27f786d5f1060cce7c92e42488bd5e5d00ba135`, configured for HPIJS only, and install only `hpijs`, its required libraries, and a valid default `hplip.conf` seed. +- [ ] Add foo2zjs from `debian/20200505dfsg0-5-0-g816bcd01d5fa0b3171fe6d09c093a9290ccf7c25`, sharing the existing JBIG owner and installing only runtime encoders, wrappers, command filter, immutable profile defaults, and a pyppd archive. +- [ ] Exclude foo2zjs models that require per-boot firmware loading, preserving the existing container contract. +- [ ] Add m2300w from `debian/0.51-15-0-gf4ebe31fe93e8f2f56ecce2f927e59bb41432d53`, installing its encoder, wrapper, PostScript resources, and four generated PPDs in a pyppd archive. +- [ ] Install all CUPS filters at `/usr/lib/cups/filter`; use `/usr/bin` for wrapper helpers and real `/usr`, `/etc`, and `/var/lib/ghostscript-printer-app` paths only. + +## Task 2: Initialize persistent state + +- [ ] Store immutable HPLIP, foo2zjs, and m2300w defaults under `/usr/share/ghostscript-printer-app/defaults`. +- [ ] Point `/etc/hp/hplip.conf` at `/var/lib/ghostscript-printer-app/hplip/hplip.conf` while keeping HPIJS compiled for `/etc/hp`. +- [ ] Extend `container-entrypoint.sh` to create the three state directories and copy default files only when their destination is absent. +- [ ] Preserve existing user files byte-for-byte across container restarts while allowing newly added defaults to seed later images. + +## Task 3: Compose and verify + +- [ ] Add the three artifacts to `core-stack.bst` without adding a second CUPS, Ghostscript, JBIG, or Foomatic owner. +- [ ] Add `just verify-stateful-drivers` and `tests/stateful-drivers.sh`. +- [ ] Assert executable, shebang, and ELF closure for HPIJS, foo2zjs, and m2300w plus every wrapper helper they invoke. +- [ ] Require representative HPIJS/IJS, foo2zjs, and m2300w conversions to emit non-empty, repeatable printer-language output with stable protocol signatures. +- [ ] Start the real appliance with persistent state, modify one seeded HPLIP configuration/profile file per state family, restart, and prove the modifications survive. +- [ ] Require representative HPIJS, foo2zjs, and m2300w entries in the live Printer Application driver catalog. + +## Task 4: Verify and publish + +- [ ] Run `just validate`, all prior slice gates, `just verify-stateful-drivers`, workflow lint, shell syntax checks, and `git diff --check`. +- [ ] Review the full diff from `feat/fsdk-packaged-drivers` and resolve all blocking findings. +- [ ] Resolve issue 06, commit and push `feat/fsdk-stateful-drivers`, and open a stacked PR based on `feat/fsdk-packaged-drivers`. From c8fc83d9168b91b18742eb11a25f20677bb9195d Mon Sep 17 00:00:00 2001 From: castrojo Date: Wed, 16 Sep 2026 10:47:29 -0400 Subject: [PATCH 2/3] feat: restore stateful printer drivers Assisted-by: GitHub Copilot GPT-5.6 via pi --- Justfile | 3 + ...026-09-16-fsdk-stateful-profile-drivers.md | 34 ++-- elements/printer-app/core-stack.bst | 3 + elements/printer-app/foo2zjs.bst | 85 ++++++++ elements/printer-app/hpijs.bst | 64 ++++++ elements/printer-app/ijs.bst | 7 +- elements/printer-app/jbigkit.bst | 16 +- elements/printer-app/m2300w.bst | 56 ++++++ elements/printer-app/psutils.bst | 18 ++ files/container-entrypoint.sh | 7 +- tests/stateful-drivers.sh | 188 ++++++++++++++++++ 11 files changed, 456 insertions(+), 25 deletions(-) create mode 100644 elements/printer-app/foo2zjs.bst create mode 100644 elements/printer-app/hpijs.bst create mode 100644 elements/printer-app/m2300w.bst create mode 100644 elements/printer-app/psutils.bst create mode 100755 tests/stateful-drivers.sh diff --git a/Justfile b/Justfile index 36cd830..b0156a3 100644 --- a/Justfile +++ b/Justfile @@ -73,5 +73,8 @@ verify-raster-drivers: verify-packaged-drivers: tests/packaged-drivers.sh +verify-stateful-drivers: + tests/stateful-drivers.sh + verify-cups-patch-chain: tests/cups-patch-chain.sh diff --git a/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md b/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md index 3ed4e12..72f72b8 100644 --- a/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md +++ b/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md @@ -6,30 +6,30 @@ ## Task 1: Build immutable driver artifacts -- [ ] Add HPLIP from `debian/3.26.4+dfsg0-3-0-gf27f786d5f1060cce7c92e42488bd5e5d00ba135`, configured for HPIJS only, and install only `hpijs`, its required libraries, and a valid default `hplip.conf` seed. -- [ ] Add foo2zjs from `debian/20200505dfsg0-5-0-g816bcd01d5fa0b3171fe6d09c093a9290ccf7c25`, sharing the existing JBIG owner and installing only runtime encoders, wrappers, command filter, immutable profile defaults, and a pyppd archive. -- [ ] Exclude foo2zjs models that require per-boot firmware loading, preserving the existing container contract. -- [ ] Add m2300w from `debian/0.51-15-0-gf4ebe31fe93e8f2f56ecce2f927e59bb41432d53`, installing its encoder, wrapper, PostScript resources, and four generated PPDs in a pyppd archive. -- [ ] Install all CUPS filters at `/usr/lib/cups/filter`; use `/usr/bin` for wrapper helpers and real `/usr`, `/etc`, and `/var/lib/ghostscript-printer-app` paths only. +- [x] Add HPLIP from `debian/3.26.4+dfsg0-3-0-gf27f786d5f1060cce7c92e42488bd5e5d00ba135`, configured for HPIJS only, and install only `hpijs`, its required libraries, and a valid default `hplip.conf` seed. +- [x] Add foo2zjs from `debian/20200505dfsg0-5-0-g816bcd01d5fa0b3171fe6d09c093a9290ccf7c25`, sharing the existing JBIG owner and installing only runtime encoders, wrappers, command filter, immutable profile defaults, and a pyppd archive. +- [x] Exclude foo2zjs models that require per-boot firmware loading, preserving the existing container contract. +- [x] Add m2300w from `debian/0.51-15-0-gf4ebe31fe93e8f2f56ecce2f927e59bb41432d53`, installing its encoder, wrapper, PostScript resources, and four generated PPDs in a pyppd archive. +- [x] Install all CUPS filters at `/usr/lib/cups/filter`; use `/usr/bin` for wrapper helpers and real `/usr`, `/etc`, and `/var/lib/ghostscript-printer-app` paths only. ## Task 2: Initialize persistent state -- [ ] Store immutable HPLIP, foo2zjs, and m2300w defaults under `/usr/share/ghostscript-printer-app/defaults`. -- [ ] Point `/etc/hp/hplip.conf` at `/var/lib/ghostscript-printer-app/hplip/hplip.conf` while keeping HPIJS compiled for `/etc/hp`. -- [ ] Extend `container-entrypoint.sh` to create the three state directories and copy default files only when their destination is absent. -- [ ] Preserve existing user files byte-for-byte across container restarts while allowing newly added defaults to seed later images. +- [x] Store immutable HPLIP, foo2zjs, and m2300w defaults under `/usr/share/ghostscript-printer-app/defaults`. +- [x] Point `/etc/hp/hplip.conf` at `/var/lib/ghostscript-printer-app/hplip/hplip.conf` while keeping HPIJS compiled for `/etc/hp`. +- [x] Extend `container-entrypoint.sh` to create the three state directories and copy default files only when their destination is absent. +- [x] Preserve existing user files byte-for-byte across container restarts while allowing newly added defaults to seed later images. ## Task 3: Compose and verify -- [ ] Add the three artifacts to `core-stack.bst` without adding a second CUPS, Ghostscript, JBIG, or Foomatic owner. -- [ ] Add `just verify-stateful-drivers` and `tests/stateful-drivers.sh`. -- [ ] Assert executable, shebang, and ELF closure for HPIJS, foo2zjs, and m2300w plus every wrapper helper they invoke. -- [ ] Require representative HPIJS/IJS, foo2zjs, and m2300w conversions to emit non-empty, repeatable printer-language output with stable protocol signatures. -- [ ] Start the real appliance with persistent state, modify one seeded HPLIP configuration/profile file per state family, restart, and prove the modifications survive. -- [ ] Require representative HPIJS, foo2zjs, and m2300w entries in the live Printer Application driver catalog. +- [x] Add the three artifacts to `core-stack.bst` without adding a second CUPS, Ghostscript, JBIG, or Foomatic owner. +- [x] Add `just verify-stateful-drivers` and `tests/stateful-drivers.sh`. +- [x] Assert executable, shebang, and ELF closure for HPIJS, foo2zjs, and m2300w plus every wrapper helper they invoke. +- [x] Require representative HPIJS/IJS, foo2zjs, and m2300w conversions to emit non-empty, repeatable printer-language output with stable protocol signatures. +- [x] Start the real appliance with persistent state, modify one seeded HPLIP configuration/profile file per state family, restart, and prove the modifications survive. +- [x] Require representative HPIJS, foo2zjs, and m2300w entries in the live Printer Application driver catalog. ## Task 4: Verify and publish -- [ ] Run `just validate`, all prior slice gates, `just verify-stateful-drivers`, workflow lint, shell syntax checks, and `git diff --check`. -- [ ] Review the full diff from `feat/fsdk-packaged-drivers` and resolve all blocking findings. +- [x] Run `just validate`, all prior slice gates, `just verify-stateful-drivers`, workflow lint, shell syntax checks, and `git diff --check`. +- [x] Review the full diff from `feat/fsdk-packaged-drivers` and resolve all blocking findings. - [ ] Resolve issue 06, commit and push `feat/fsdk-stateful-drivers`, and open a stacked PR based on `feat/fsdk-packaged-drivers`. diff --git a/elements/printer-app/core-stack.bst b/elements/printer-app/core-stack.bst index d44236c..f868d8f 100644 --- a/elements/printer-app/core-stack.bst +++ b/elements/printer-app/core-stack.bst @@ -18,6 +18,9 @@ depends: - printer-app/pxljr.bst - printer-app/rastertosag-gdi.bst - printer-app/splix.bst + - printer-app/foo2zjs.bst + - printer-app/hpijs.bst + - printer-app/m2300w.bst - freedesktop-sdk.bst:public-stacks/runtime-gnu.bst - freedesktop-sdk.bst:components/avahi.bst - freedesktop-sdk.bst:components/ca-certificates.bst diff --git a/elements/printer-app/foo2zjs.bst b/elements/printer-app/foo2zjs.bst new file mode 100644 index 0000000..a0b5b0f --- /dev/null +++ b/elements/printer-app/foo2zjs.bst @@ -0,0 +1,85 @@ +kind: manual +description: Build foo2zjs drivers with persistent color-profile paths. + +sources: + - kind: git_repo + url: salsa:printing-team/foo2zjs.git + track: debian/20200505dfsg0-5 + ref: debian/20200505dfsg0-5-0-g816bcd01d5fa0b3171fe6d09c093a9290ccf7c25 + +build-depends: + - printer-app/pyppd.bst + - freedesktop-sdk.bst:public-stacks/buildsystem-make.bst + +depends: + - printer-app/jbigkit.bst + - printer-app/psutils.bst + - freedesktop-sdk.bst:components/bc.bst + - freedesktop-sdk.bst:components/cups.bst + - freedesktop-sdk.bst:components/cups-filters.bst + - freedesktop-sdk.bst:components/ghostscript.bst + - freedesktop-sdk.bst:components/file.bst + - freedesktop-sdk.bst:components/grep.bst + - freedesktop-sdk.bst:components/lcms.bst + - freedesktop-sdk.bst:components/python3.bst + - freedesktop-sdk.bst:components/sed.bst + - freedesktop-sdk.bst:public-stacks/runtime-gnu.bst + +config: + build-commands: + - | + for wrapper in *-wrapper.in; do + sed -i \ + -e 's|$PREFIX/share/foo2|/var/lib/ghostscript-printer-app/foo2zjs/foo2|g' \ + -e 's|ICC2PS=$PREFIX/bin/foo2zjs-icc2ps|ICC2PS=/usr/bin/psicc|' \ + -e 's|/tmp|${TMPDIR:-/tmp}|g' \ + -e 's|dNOPAUSE|dNOPAUSE -dNOINTERPOLATE|g' \ + "$wrapper" + done + - >- + make -j2 + foo2zjs zjsdecode arm2hpdl + foo2hp foo2xqx xqxdecode + foo2lava lavadecode foo2qpdl qpdldecode opldecode + foo2oak oakdecode foo2slx slxdecode + foo2hiperc hipercdecode foo2hbpl2 hbpldecode + gipddecode foo2ddst ddstdecode usb_printerid + foo2zjs-wrapper foo2oak-wrapper foo2hp2600-wrapper + foo2xqx-wrapper foo2lava-wrapper foo2qpdl-wrapper + foo2slx-wrapper foo2hiperc-wrapper foo2hbpl2-wrapper + foo2ddst-wrapper foo2zjs-pstops + CUPS_SERVERBIN=/usr/lib/cups CUPS_DEVEL=1 CUPS_GOODAPI=1 + - make command2foo2lava-pjl CUPS_SERVERBIN=/usr/lib/cups CUPS_DEVEL=1 CUPS_GOODAPI=1 + - | + cp -a PPD ppd + for model in 1000 1005 1018 1020 P1005 P1006 P1007 P1008 P1505; do + rm -f "ppd/HP-LaserJet_${model}.ppd" + done + pyppd -v -o foo2zjs-ppds ppd + install-commands: + - | + install -d "%{install-root}/usr/bin" + for file in \ + foo2zjs zjsdecode arm2hpdl \ + foo2hp foo2xqx xqxdecode \ + foo2lava lavadecode foo2qpdl qpdldecode opldecode \ + foo2oak oakdecode foo2slx slxdecode \ + foo2hiperc hipercdecode foo2hbpl2 hbpldecode \ + gipddecode foo2ddst ddstdecode usb_printerid \ + foo2zjs-wrapper foo2oak-wrapper foo2hp2600-wrapper \ + foo2xqx-wrapper foo2lava-wrapper foo2qpdl-wrapper \ + foo2slx-wrapper foo2hiperc-wrapper foo2hbpl2-wrapper \ + foo2ddst-wrapper foo2zjs-pstops; do + install -m 0755 "$file" "%{install-root}/usr/bin/$file" + done + - install -D -m 0755 command2foo2lava-pjl "%{install-root}/usr/lib/cups/filter/command2foo2lava-pjl" + - install -D -m 0755 foo2zjs-ppds "%{install-root}/usr/share/ppd/foo2zjs-ppds" + - | + defaults="%{install-root}/usr/share/ghostscript-printer-app/defaults/foo2zjs" + for directory in foo2zjs foo2oak foo2hp foo2xqx foo2lava foo2qpdl foo2slx foo2hiperc foo2hbpl foo2ddst; do + install -d "$defaults/$directory/icm" + done + install -m 0644 gamma.ps gamma-lookup.ps "$defaults/foo2zjs/" + install -d "$defaults/foo2zjs/crd" "$defaults/foo2qpdl/crd" + cp -a crd/zjs/. "$defaults/foo2zjs/crd/" + cp -a crd/qpdl/. "$defaults/foo2qpdl/crd/" diff --git a/elements/printer-app/hpijs.bst b/elements/printer-app/hpijs.bst new file mode 100644 index 0000000..6a8b68b --- /dev/null +++ b/elements/printer-app/hpijs.bst @@ -0,0 +1,64 @@ +kind: manual +description: Build the HPLIP HPIJS driver with persistent appliance configuration. + +sources: + - kind: git_repo + url: salsa:printing-team/hplip.v2.git + track: debian/3.26.4+dfsg0-3 + ref: debian/3.26.4+dfsg0-3-0-gf27f786d5f1060cce7c92e42488bd5e5d00ba135 + +build-depends: + - freedesktop-sdk.bst:public-stacks/buildsystem-autotools.bst + - freedesktop-sdk.bst:components/python3.bst + - freedesktop-sdk.bst:components/sed.bst + +depends: + - freedesktop-sdk.bst:components/jpeg.bst + - freedesktop-sdk.bst:public-stacks/runtime-gnu.bst + +config: + build-commands: + - sed -i 's|"/var/lib/hp|"/var/lib/ghostscript-printer-app/hplip|g' common/utils.c common/utils.h + - sh debian/autogen.sh + - >- + ./configure + --build=%{gcc-triplet} + --prefix=/usr + --enable-hpijs-only-build + --enable-hpijs-install + --disable-foomatic-rip-hplip-install + --without-docdir + --without-htmldir + --without-hpppddir + --without-drvdir + --without-icondir + --disable-hpcups-install + --disable-cups-drv-install + --disable-cups-ppd-install + --disable-foomatic-drv-install + --disable-foomatic-ppd-install + --disable-network-build + --disable-pp-build + --disable-scan-build + --disable-gui-build + --disable-fax-build + --disable-dbus-build + --disable-qt3 + --disable-qt4 + --disable-qt5 + --disable-policykit + - make -j2 hpijs + - | + sed -i \ + -e 's|^home=.*|home=/usr/share/hplip|' \ + -e 's|^run=.*|run=/var/lib/ghostscript-printer-app/hplip/run|' \ + -e 's|^ppd=.*|ppd=/usr/share/ppd|' \ + -e 's|^ppdbase=.*|ppdbase=/usr/share/ppd|' \ + -e 's|^cupsbackend=.*|cupsbackend=/usr/lib/cups/backend|' \ + -e 's|^cupsfilter=.*|cupsfilter=/usr/lib/cups/filter|' \ + hplip.conf + install-commands: + - install -D -m 0755 hpijs "%{install-root}/usr/bin/hpijs" + - install -d "%{install-root}/usr/share/hplip" + - install -D -m 0644 hplip.conf "%{install-root}/usr/share/ghostscript-printer-app/defaults/hplip/hplip.conf" + - mkdir -p "%{install-root}/etc/hp" && ln -s /var/lib/ghostscript-printer-app/hplip/hplip.conf "%{install-root}/etc/hp/hplip.conf" diff --git a/elements/printer-app/ijs.bst b/elements/printer-app/ijs.bst index a06c28c..996bb50 100644 --- a/elements/printer-app/ijs.bst +++ b/elements/printer-app/ijs.bst @@ -14,9 +14,10 @@ public: bst: split-rules: devel: - - "%{includedir}" - - "%{includedir}/**" - - "%{libdir}/libijs.so" + (>): + - "%{includedir}" + - "%{includedir}/**" + - "%{libdir}/libijs.so" config: build-commands: diff --git a/elements/printer-app/jbigkit.bst b/elements/printer-app/jbigkit.bst index 690edd4..c2af54a 100644 --- a/elements/printer-app/jbigkit.bst +++ b/elements/printer-app/jbigkit.bst @@ -1,5 +1,5 @@ kind: manual -description: Build the minimal JBIG85 shared library required by SpliX. +description: Build the JBIG and JBIG85 shared libraries required by legacy drivers. sources: - kind: git_repo @@ -14,17 +14,25 @@ public: bst: split-rules: devel: - - "%{includedir}/jbig85.h" - - "%{includedir}/jbig_ar.h" - - "%{libdir}/libjbig85.so" + (>): + - "%{includedir}/jbig85.h" + - "%{includedir}/jbig.h" + - "%{includedir}/jbig_ar.h" + - "%{libdir}/libjbig85.so" + - "%{libdir}/libjbig.so" config: build-commands: - cc $CFLAGS -fPIC -Ilibjbig -c libjbig/jbig85.c -o jbig85.o + - cc $CFLAGS -fPIC -Ilibjbig -c libjbig/jbig.c -o jbig.o - cc $CFLAGS -fPIC -Ilibjbig -c libjbig/jbig_ar.c -o jbig_ar.o - cc $LDFLAGS -shared -Wl,-soname,libjbig85.so.0 -o libjbig85.so.0 jbig85.o jbig_ar.o + - cc $LDFLAGS -shared -Wl,-soname,libjbig.so.0 -o libjbig.so.0 jbig.o jbig_ar.o install-commands: - install -D -m 0644 libjbig85.so.0 "%{install-root}%{libdir}/libjbig85.so.0" - ln -s libjbig85.so.0 "%{install-root}%{libdir}/libjbig85.so" + - install -D -m 0644 libjbig.so.0 "%{install-root}%{libdir}/libjbig.so.0" + - ln -s libjbig.so.0 "%{install-root}%{libdir}/libjbig.so" - install -D -m 0644 libjbig/jbig85.h "%{install-root}/usr/include/jbig85.h" + - install -D -m 0644 libjbig/jbig.h "%{install-root}/usr/include/jbig.h" - install -D -m 0644 libjbig/jbig_ar.h "%{install-root}/usr/include/jbig_ar.h" diff --git a/elements/printer-app/m2300w.bst b/elements/printer-app/m2300w.bst new file mode 100644 index 0000000..7a7c3e6 --- /dev/null +++ b/elements/printer-app/m2300w.bst @@ -0,0 +1,56 @@ +kind: manual +description: Build the m2300w drivers with persistent color-profile paths. + +sources: + - kind: git_repo + url: salsa:printing-team/m2300w.git + track: debian/0.51-15 + ref: debian/0.51-15-0-gf4ebe31fe93e8f2f56ecce2f927e59bb41432d53 + +build-depends: + - printer-app/pyppd.bst + - freedesktop-sdk.bst:public-stacks/buildsystem-autotools.bst + - freedesktop-sdk.bst:components/cups.bst + - freedesktop-sdk.bst:components/ghostscript.bst + - freedesktop-sdk.bst:components/perl.bst + +depends: + - printer-app/psutils.bst + - freedesktop-sdk.bst:components/cups-filters.bst + - freedesktop-sdk.bst:components/ghostscript.bst + - freedesktop-sdk.bst:components/python3.bst + - freedesktop-sdk.bst:components/sed.bst + - freedesktop-sdk.bst:public-stacks/runtime-gnu.bst + +config: + build-commands: + - autoreconf --install + - ./configure --prefix=/usr + - make -j2 + - make INSTROOT="$PWD/stage" install + - | + for wrapper in stage/usr/bin/*-wrapper; do + sed -i \ + -e 's|^PREFIX=.*|PREFIX=/usr|' \ + -e 's|^SHARE=.*|SHARE=/var/lib/ghostscript-printer-app/m2300w/0.51|' \ + -e 's|/tmp|${TMPDIR:-/tmp}|g' \ + -e 's|^$((resX\*=$RESMUL));|resX=$((resX * RESMUL))|' \ + "$wrapper" + done + - rm -rf stage/usr/share/m2300w/0.51/foomatic + - | + mkdir packaged-ppd + for model in 2300 2400; do + source="stage/usr/share/cups/model/Minolta/magicolor_${model}W-m${model}w.ppd" + target="packaged-ppd/Minolta-magicolor_${model}W-m2300w.ppd" + cp "$source" "$target" + sed 's/Minolta/KONICA MINOLTA/g' "$target" > "packaged-ppd/KONICA_MINOLTA-magicolor_${model}W-m2300w.ppd" + sed -i 's/KONICA MINOLTA/Minolta/g' "$target" + done + pyppd -v -o m2300w-ppds packaged-ppd + install-commands: + - install -D -m 0755 stage/usr/bin/m2300w "%{install-root}/usr/bin/m2300w" + - install -D -m 0755 stage/usr/bin/m2400w "%{install-root}/usr/bin/m2400w" + - install -D -m 0755 stage/usr/bin/m2300w-wrapper "%{install-root}/usr/bin/m2300w-wrapper" + - install -D -m 0755 m2300w-ppds "%{install-root}/usr/share/ppd/m2300w-ppds" + - mkdir -p "%{install-root}/usr/share/ghostscript-printer-app/defaults/m2300w" && cp -a stage/usr/share/m2300w/. "%{install-root}/usr/share/ghostscript-printer-app/defaults/m2300w/" diff --git a/elements/printer-app/psutils.bst b/elements/printer-app/psutils.bst new file mode 100644 index 0000000..e62f92c --- /dev/null +++ b/elements/printer-app/psutils.bst @@ -0,0 +1,18 @@ +kind: manual +description: Build the legacy psnup helper required by stateful driver wrappers. + +sources: + - kind: git_repo + url: salsa:debian/psutils.git + track: debian/1.17.dfsg-5 + ref: debian/1.17.dfsg-5-0-gafa3fccb4b77165a22b783f21feac35a082d8137 + +build-depends: + - freedesktop-sdk.bst:public-stacks/buildsystem-make.bst + +config: + build-commands: + - sed -i 's/^CFLAGS = /CFLAGS = -std=gnu89 /' Makefile.unix + - make -f Makefile.unix -j2 psnup CC=cc PAPER=a4 + install-commands: + - install -D -m 0755 psnup "%{install-root}/usr/bin/psnup" diff --git a/files/container-entrypoint.sh b/files/container-entrypoint.sh index fd1a6a0..c30addc 100755 --- a/files/container-entrypoint.sh +++ b/files/container-entrypoint.sh @@ -7,13 +7,18 @@ if [[ -n "${PORT:-}" && ! "$PORT" =~ ^[0-9]+$ ]]; then fi state_dir=/var/lib/ghostscript-printer-app -mkdir -p "$state_dir/ppd" "$state_dir/spool" "$state_dir/usb" "$state_dir/cups/ssl" "$state_dir/pnm2ppa" /run/dbus /run/avahi-daemon /run/ghostscript-printer-app +mkdir -p "$state_dir/ppd" "$state_dir/spool" "$state_dir/usb" "$state_dir/cups/ssl" "$state_dir/pnm2ppa" "$state_dir/hplip/run" "$state_dir/foo2zjs" "$state_dir/m2300w" /run/dbus /run/avahi-daemon /run/ghostscript-printer-app if [[ ! -e "$state_dir/cups/snmp.conf" ]]; then cp /etc/cups/snmp.conf "$state_dir/cups/snmp.conf" fi if [[ ! -e "$state_dir/pnm2ppa/pnm2ppa.conf" ]]; then cp /usr/share/ghostscript-printer-app/pnm2ppa.conf "$state_dir/pnm2ppa/pnm2ppa.conf" fi +if [[ ! -e "$state_dir/hplip/hplip.conf" ]]; then + cp /usr/share/ghostscript-printer-app/defaults/hplip/hplip.conf "$state_dir/hplip/hplip.conf" +fi +cp -a --no-clobber /usr/share/ghostscript-printer-app/defaults/foo2zjs/. "$state_dir/foo2zjs/" +cp -a --no-clobber /usr/share/ghostscript-printer-app/defaults/m2300w/. "$state_dir/m2300w/" export BACKEND_DIR=/usr/lib/ghostscript-printer-app/backend export CUPS_SERVERBIN=/usr/lib/ghostscript-printer-app diff --git a/tests/stateful-drivers.sh b/tests/stateful-drivers.sh new file mode 100755 index 0000000..7c4aaaa --- /dev/null +++ b/tests/stateful-drivers.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env bash +set -euo pipefail + +image="ghcr.io/projectbluefin/ghostscript-printer-app:build" +name="ghostscript-printer-app-stateful-drivers" +port="${PORT:-18040}" +state_dir="$(mktemp -d)" + +cleanup() { + podman rm -f "$name" >/dev/null 2>&1 || true + podman unshare rm -rf "$state_dir" +} +trap cleanup EXIT + +wait_for_http() { + for _ in $(seq 1 60); do + curl --fail --silent "http://127.0.0.1:${port}/" >/dev/null 2>&1 && return 0 + sleep 1 + done + return 1 +} + +just build + +require_runtime_deps() { + local element="$1" graph dependency + shift + graph="$(just bst show --deps run --format '%{name}' "printer-app/$element.bst")" + for dependency in "$@"; do + [[ "$graph" == *"$dependency"* ]] + done +} + +require_runtime_deps hpijs \ + freedesktop-sdk.bst:components/jpeg.bst \ + freedesktop-sdk.bst:public-stacks/runtime-gnu.bst +require_runtime_deps foo2zjs \ + printer-app/jbigkit.bst \ + printer-app/psutils.bst \ + freedesktop-sdk.bst:components/bc.bst \ + freedesktop-sdk.bst:components/cups.bst \ + freedesktop-sdk.bst:components/cups-filters.bst \ + freedesktop-sdk.bst:components/file.bst \ + freedesktop-sdk.bst:components/ghostscript.bst \ + freedesktop-sdk.bst:components/grep.bst \ + freedesktop-sdk.bst:components/lcms.bst \ + freedesktop-sdk.bst:components/python3.bst \ + freedesktop-sdk.bst:components/sed.bst +require_runtime_deps m2300w \ + printer-app/psutils.bst \ + freedesktop-sdk.bst:components/cups-filters.bst \ + freedesktop-sdk.bst:components/ghostscript.bst \ + freedesktop-sdk.bst:components/python3.bst \ + freedesktop-sdk.bst:components/sed.bst +chmod 0777 "$state_dir" +podman run -d --name "$name" --network host -e PORT="$port" \ + -v "$state_dir:/var/lib/ghostscript-printer-app:Z" "$image" >/dev/null +wait_for_http + +podman exec "$name" /usr/bin/bash -c ' + set -euo pipefail + export PATH=/usr/lib/cups/filter:/usr/bin:/bin + export TMPDIR=/tmp + state=/var/lib/ghostscript-printer-app + work=/tmp/stateful-drivers + mkdir -p "$work" + + test -L /etc/hp/hplip.conf + [[ "$(readlink /etc/hp/hplip.conf)" == "$state/hplip/hplip.conf" ]] + test -f "$state/hplip/hplip.conf" + test -f "$state/foo2zjs/foo2zjs/gamma.ps" + test -f "$state/foo2zjs/foo2zjs/crd/screen1200.ps" + test -f "$state/m2300w/0.51/psfiles/prolog.ps" + ! grep -R "/ghostscript-printer-app/current" /etc/hp "$state/hplip" /usr/bin/*-wrapper + + binaries=( + hpijs psnup + foo2zjs zjsdecode arm2hpdl foo2hp foo2xqx xqxdecode + foo2lava lavadecode foo2qpdl qpdldecode opldecode + foo2oak oakdecode foo2slx slxdecode foo2hiperc hipercdecode + foo2hbpl2 hbpldecode gipddecode foo2ddst ddstdecode usb_printerid + m2300w m2400w + ) + for executable in "${binaries[@]}"; do + path="$(command -v "$executable")" + dependencies="$(ldd "$path")" + [[ "$dependencies" != *"not found"* ]] + done + command_dependencies="$(ldd /usr/lib/cups/filter/command2foo2lava-pjl)" + [[ "$command_dependencies" != *"not found"* ]] + wrappers=( + foo2zjs-wrapper foo2oak-wrapper foo2hp2600-wrapper + foo2xqx-wrapper foo2lava-wrapper foo2qpdl-wrapper + foo2slx-wrapper foo2hiperc-wrapper foo2hbpl2-wrapper + foo2ddst-wrapper foo2zjs-pstops m2300w-wrapper + ) + for wrapper in "${wrappers[@]}"; do + path="$(command -v "$wrapper")" + read -r shebang < "$path" + [[ "$shebang" == "#!/bin/sh" ]] + done + for helper in basename bc cat dc dd expr file foomatic-rip grep gs psicc psnup sed tee tr; do + command -v "$helper" >/dev/null + done + + foo_entries="$(/usr/share/ppd/foo2zjs-ppds list)" + [[ "$foo_entries" == *"Minolta magicolor 2300 DL"* ]] + m2300_entries="$(/usr/share/ppd/m2300w-ppds list)" + [[ "$m2300_entries" == *"KONICA MINOLTA magicolor 2300W"* ]] + + printf "%s\n" \ + "%!PS-Adobe-3.0" \ + "%%Pages: 1" \ + "%%Page: 1 1" \ + "newpath 10 10 moveto 60 60 lineto stroke" \ + "showpage" \ + "%%EOF" > "$work/page.ps" + + assert_repeatable() { + local first_hash second_hash + test -s "$1" + test -s "$2" + read -r first_hash _ < <(sha256sum "$1") + read -r second_hash _ < <(sha256sum "$2") + [[ "$first_hash" == "$second_hash" ]] + } + + /usr/share/ppd/foomatic-ppds cat \ + foomatic-ppds:0/Generic-PCL_5e_Printer-hpijs-pcl5e.ppd > "$work/hpijs.ppd" + for suffix in first second; do + PPD="$work/hpijs.ppd" foomatic-rip 1 test test 1 "" "$work/page.ps" \ + > "$work/hpijs-$suffix.prn" 2> "$work/hpijs-$suffix.log" + done + assert_repeatable "$work/hpijs-first.prn" "$work/hpijs-second.prn" + [[ "$(od -An -tx1 -N 16 "$work/hpijs-first.prn")" == " 1b 25 2d 31 32 33 34 35 58 40 50 4a 4c 20 53 45" ]] + (("$(stat -c %s "$work/hpijs-first.prn")" > 10000)) + printf "OK: full-page HPIJS conversion\n" + + for suffix in first second; do + foo2zjs-wrapper -z0 -c -C1 "$work/page.ps" \ + > "$work/foo2zjs-$suffix.prn" 2> "$work/foo2zjs-$suffix.log" + done + assert_repeatable "$work/foo2zjs-first.prn" "$work/foo2zjs-second.prn" + [[ "$(od -An -tx1 -N 4 "$work/foo2zjs-first.prn")" == " 4a 5a 4a 5a" ]] + (("$(stat -c %s "$work/foo2zjs-first.prn")" > 500)) + printf "OK: foo2zjs profile-backed conversion\n" + + for suffix in first second; do + m2300w-wrapper "$work/page.ps" \ + > "$work/m2300w-$suffix.prn" 2> "$work/m2300w-$suffix.log" + done + assert_repeatable "$work/m2300w-first.prn" "$work/m2300w-second.prn" + [[ "$(od -An -tx1 -N 4 "$work/m2300w-first.prn")" == " 1b 40 00 02" ]] + (("$(stat -c %s "$work/m2300w-first.prn")" > 1000)) + m2300w-wrapper -2 "$work/page.ps" > "$work/m2300w-nup.prn" 2> "$work/m2300w-nup.log" + test -s "$work/m2300w-nup.prn" + printf "OK: m2300w profile-backed and psnup conversions\n" + + printf "# persistence-probe\n" >> "$state/hplip/hplip.conf" + printf "%% persistence-probe\n" >> "$state/foo2zjs/foo2zjs/gamma.ps" + printf "%% persistence-probe\n" >> "$state/m2300w/0.51/psfiles/prolog.ps" +' + +drivers="$(podman exec "$name" ghostscript-printer-app -u "ipp://127.0.0.1:${port}/ipp/system" drivers)" +for marker in "hpijs-pcl5e" "foo2zjs" "m2300w"; do + [[ "$drivers" == *"$marker"* ]] +done + +podman stop --time 15 "$name" >/dev/null +podman rm "$name" >/dev/null +podman run -d --name "$name" --network host -e PORT="$port" \ + -v "$state_dir:/var/lib/ghostscript-printer-app:Z" "$image" >/dev/null +wait_for_http +podman exec "$name" /usr/bin/bash -c ' + set -euo pipefail + for file in \ + /var/lib/ghostscript-printer-app/hplip/hplip.conf \ + /var/lib/ghostscript-printer-app/foo2zjs/foo2zjs/gamma.ps \ + /var/lib/ghostscript-printer-app/m2300w/0.51/psfiles/prolog.ps; do + found=0 + while IFS= read -r line; do + [[ "$line" == "# persistence-probe" || "$line" == "% persistence-probe" ]] && found=1 + done < "$file" + [[ "$found" == 1 ]] + done +' + +printf 'OK: stateful drivers execute and preserve user configuration\n' From 50a668153e51630c5ee082e4a852a2689e9ff009 Mon Sep 17 00:00:00 2001 From: castrojo Date: Wed, 16 Sep 2026 10:48:11 -0400 Subject: [PATCH 3/3] docs: record stateful driver completion Assisted-by: GitHub Copilot GPT-5.6 via pi --- .../plans/2026-09-16-fsdk-stateful-profile-drivers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md b/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md index 72f72b8..79cdba8 100644 --- a/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md +++ b/docs/superpowers/plans/2026-09-16-fsdk-stateful-profile-drivers.md @@ -32,4 +32,4 @@ - [x] Run `just validate`, all prior slice gates, `just verify-stateful-drivers`, workflow lint, shell syntax checks, and `git diff --check`. - [x] Review the full diff from `feat/fsdk-packaged-drivers` and resolve all blocking findings. -- [ ] Resolve issue 06, commit and push `feat/fsdk-stateful-drivers`, and open a stacked PR based on `feat/fsdk-packaged-drivers`. +- [x] Resolve issue 06, commit and push `feat/fsdk-stateful-drivers`, and open a stacked PR based on `feat/fsdk-packaged-drivers`.