GNU patch for CF

/df

Well-Known Member
Some time ago
Unified Diff Format

This is a standard representation, and commonly used on this forum for discussing code changes. If you are going to get into hand-modifying the CF files, you need to become familiar it.
...
Create a file containing the Unified Diff Format description of the changes required (or obtain a ready-made one). Apply the changes on the command line (Telnet, or WebIF >> Diagnostics >> Command Line):

patch -b < <changes file>

The "-b" switch creates a backup of the original file. The file to be edited does not need to be specified, as this is already defined in the changes file.

I will also verify whether the changes file can contain all the diffs in one, or if they need a separate patch operation for each file to be modified.

Yes, it is possible to concatenate all the diffs into one file, but (1) the Busybox version of patch (as installed in the CF) doesn't seem to accept the -b flag, and (2) won't act on its own output!
I fixed a long-standing bug in the full GNU patch program and here it is, built for the Humax HD/R Fox platform. Anyone who is unhappy with the Busybox patch should have a better experience with this one.
Code:
humaxhdr# patch --help
Usage: patch [OPTION]... [ORIGFILE [PATCHFILE]]

Input options:

  -p NUM  --strip=NUM  Strip NUM leading components from file names.
  -F LINES  --fuzz LINES  Set the fuzz factor to LINES for inexact matching.
  -l  --ignore-whitespace  Ignore white space changes between patch and input.

  -c  --context  Interpret the patch as a context difference.
  -e  --ed  Interpret the patch as an ed script.
  -n  --normal  Interpret the patch as a normal difference.
  -u  --unified  Interpret the patch as a unified difference.

  -N  --forward  Ignore patches that appear to be reversed or already applied.
  -R  --reverse  Assume patches were created with old and new files swapped.

  -i PATCHFILE  --input=PATCHFILE  Read patch from PATCHFILE instead of stdin.

Output options:

  -o FILE  --output=FILE  Output patched files to FILE.
  -r FILE  --reject-file=FILE  Output rejects to FILE.

  -D NAME  --ifdef=NAME  Make merged if-then-else output using NAME.
  --merge  Merge using conflict markers instead of creating reject files.
  -E  --remove-empty-files  Remove output files that are empty after patching.

  -Z  --set-utc  Set times of patched files, assuming diff uses UTC (GMT).
  -T  --set-time  Likewise, assuming local time.

  --quoting-style=WORD   output file names using quoting style WORD.
    Valid WORDs are: literal, shell, shell-always, c, escape.
    Default is taken from QUOTING_STYLE env variable, or 'shell' if unset.

Backup and version control options:

  -b  --backup  Back up the original contents of each file.
  --backup-if-mismatch  Back up if the patch does not match exactly.
  --no-backup-if-mismatch  Back up mismatches only if otherwise requested.

  -V STYLE  --version-control=STYLE  Use STYLE version control.
        STYLE is either 'simple', 'numbered', or 'existing'.
  -B PREFIX  --prefix=PREFIX  Prepend PREFIX to backup file names.
  -Y PREFIX  --basename-prefix=PREFIX  Prepend PREFIX to backup file basenames.
  -z SUFFIX  --suffix=SUFFIX  Append SUFFIX to backup file names.

  -g NUM  --get=NUM  Get files from RCS etc. if positive; ask if negative.

Miscellaneous options:

  -t  --batch  Ask no questions; skip bad-Prereq patches; assume reversed.
  -f  --force  Like -t, but ignore bad-Prereq patches, and assume unreversed.
  -s  --quiet  --silent  Work silently unless an error occurs.
  --verbose  Output extra information about the work being done.
  --dry-run  Do not actually change any files; just print what would happen.
  --posix  Conform to the POSIX standard.

  -d DIR  --directory=DIR  Change the working directory to DIR first.
  --reject-format=FORMAT  Create 'context' or 'unified' rejects.
  --binary  Read and write data in binary mode.
  --read-only=BEHAVIOR  How to handle read-only input files: 'ignore' that they
                        are read-only, 'warn' (default), or 'fail'.

  -v  --version  Output version info.
  --help  Output this help.

Report bugs to <bug-patch@gnu.org>.
Strangely this (non-static) build is almost 3 times bigger than version 2.7.1 for x86 on Ubuntu. Is that just a question of relative instruction set terseness, or should I be setting some other build options (on box)?

As usual, the on-box build crashes (bus error) unless you override the broken implementation of sigemptyset() and sigfillset() in /lib/libuClibc-0.9.29.so. Why don't /bin/abduco and /bin/opkg, which appear to call sigemptyset(), crash in the same way?
 

Attachments

  • patch-2.7.6df.zip
    100.9 KB · Views: 10
Last edited:
Excellent. Does that mean the diff output can now be used directly as patch's input?

For information: that's what's wrong with the current implementation - feeding a diff output into patch did not result in the relevant file being patched as described. If it does now, that means code mods can be shared around and interested parties can try them out with only a modicum of terminal commands, ahead of the tweaks being propagated through a beta release.
 
I have not had a problem with the busybox implementation of diff and patch when using unified diffs. There is the undocumented '-u' option to busybox diff for creating unified diffs. When the unified diffs are concatenated or generated using recursion between two directories the resulting patch can be fed into patch without any issues.
Code:
# patch -p0  < /mod/dbg/webif-epg1.patch 
patching file mod/webif/lib/epg.class
patching file mod/webif/html/epg/list.jim
patching file mod/webif/html/xepg/index.jim
# patch -p0 -R < /mod/dbg/webif-epg1.patch 
patching file mod/webif/lib/epg.class
patching file mod/webif/html/epg/list.jim
patching file mod/webif/html/xepg/index.jim
#
 
The main problem I have seen with patches posted here, is when they have been cut and pasted from a terminal window. Tabs can get expanded into spaces which breaks the patches.
 
Excellent. Does that mean the diff output can now be used directly as patch's input?
...
Please try it. This patch passes the package's test suite. Obvs it could eventually be made into a CF package; for the moment extract it into /mod/bin.

I have not had a problem with the busybox implementation of diff and patch when using unified diffs. ...
It's good to know that unified diffs are reliable, in case people need to rely on /mod/bin/busybox/patch (though that's a package anyway). Support for -u is a POSIX requirement since 2008.
... and ...
The main problem I have seen with patches posted here, is when they have been cut and pasted from a terminal window. Tabs can get expanded into spaces which breaks the patches.
As long as the patches aren't for Python source (whose tabs are syntactically significant) the (POSIX mandatory, not supported by BB-1.20 patch) -l option should deal with that, making a syntactically equivalent, if not character-identical, patched file.

Non-support of the (POSIX mandatory) -b option was one complaint about the BB-1.20 patch utlity. Another was silent rejection of patch input: I haven't checked whether a non-zero return code was set, which would have allowed a work-around by adding || echo "Failed ($?)") to the command line.

I've read some of Larry Wall's code for Perl; the GNU patch code, based on his original versions, was disturbingly similar in style (but then I'm not offering any code I might have written in 1988 for review!). Nonetheless, it has the benefit of Darwinian improvement over 30 years (73 bugs fixed since 2009) so that it can handle all types of diff output. After all, someone creating a patch cannot generally be aware that the recipient will be using a limited patch program, especially not one that fails POSIX.
 
Hence my question "should I be setting some other build options (on box)"! Eventually I'll excavate the build HDR and check the options.

I doubt that the small patch (4 lines or so) applied to 2.7.6 makes that much difference, nor whatever changes were made between 2.7.1 and 2.7.6.
 
Back
Top