4

I'm using BusyBox 1.24.1 on my Embedded Linux machine (with kernel v3.10.31) and I get behavior I can't understand when unzipping files.  The gunzip command (often, but not always) fails, with no output (not even an error message), even when given a “known good” .gz file (i.e., one that I just created, using a gzip command, on the same system).  It's very hard to find a file that can actually be unzipped.  Does anyone get an "Eureka!" when looking at this?

It seems like something in the text file make the gunzip command fail, but I can't figure out what.  See below:

# ls -l
-rw-------    1 root     root            65 Sep 13 10:02 cantunzip
-rw-------    1 root     root            64 Sep 13 10:01 canunzip
more cantunzip 
fsdgafjklsdfasdsdjfhjafasdohfkl asdfas a fsd a

2132313 12 51515
# more canunzip 
fsdgafjklsdfasdsdjfhjafasdohfkl asdfas a fsd a
2132313 12 51515
# hexdump cantunzip 
0000000 7366 6764 6661 6b6a 736c 6664 7361 7364
0000010 6a64 6866 616a 6166 6473 686f 6b66 206c
0000020 7361 6664 7361 6120 6620 6473 6120 0a0a
0000030 3132 3233 3133 2033 3231 3520 3531 3531
0000040 000a                                   
0000041
# hexdump canunzip 
0000000 7366 6764 6661 6b6a 736c 6664 7361 7364
0000010 6a64 6866 616a 6166 6473 686f 6b66 206c
0000020 7361 6664 7361 6120 6620 6473 6120 320a
0000030 3331 3332 3331 3120 2032 3135 3135 0a35
0000040
# gzip canunzip 
# gzip cantunzip 
# ls -l
-rw-------    1 root     root            77 Sep 13 10:04 cantunzip.gz
-rw-------    1 root     root            77 Sep 13 10:03 canunzip.gz
# gunzip canunzip.gz 
# echo $?
0
# gunzip cantunzip.gz
# echo $?
1
# ls -l
-rw-------    1 root     root            77 Sep 13 10:04 cantunzip.gz
-rw-------    1 root     root            64 Sep 13 10:04 canunzip

2 Answers2

0

You can check the error code for the gunzip command which fails to unzip.

echo $?

That could give you a clue for the failure.

Taking the hexdump of the two files and comparing them might also help.

0

For what it's worth, the BusyBox News page lists updates to its gzip applet in every minor release between 1.24.0 and 1.32.0 except 1.28.0, so I'm not surprised that I can't reproduce this on my Debian system using busybox 1.35.0. The current stable is 1.34.1. Your best bet is to upgrade.

If upgrading isn't an option, this shell wrapper function should at least get that command some sanity:

gzip() {
  local target
  for target in "$@"; do true; done
  cp -p "$target" "$target.temp" || return $?
  busybox gzip "[email protected]"

  gunzip < "$target.temp.gz" > "$target.temp"
  if [ $? = 0 ] && diff -q "$target" "$target.temp" >/dev/null 2>&1; then
    rm -f "$target" "$target.temp"
    mv "$target.temp.gz" "$target.gz"
    return 0
  fi
  echo "gzip: failure" >&2
  rm -f "$target.temp.gz" "$target.temp"
  return 1
}

Put that in a file (like ~/.bashrc) and source it (like source ~/.bashrc) and then you should be able to use gzip normally. This function assumes your final argument is the target file to compress, looping through your command arguments solely to save the last one as $target. Because your version of BusyBox is older than 1.27.0 (when it added gzip -k support), we copy the file first, then run busybox's gzip applet with all of your arguments on the copy. The rest is vetting and housekeeping.

To verify the file, we simply decompress it using pipes to preserve the .gz version, then we ensure that succeeded ($? is the exit code of the previous command, which is zero when it worked) and that it does not differ form the original target file. In this case, remove the test file and the original since the .gz is verified, then return a success value of 0. Otherwise, announce the failure on standard error and remove the test file and the faulty .gz file (if it even exists) and return an error value of 1.

You can alternatively make this a script. Just remove the first two lines and the final line and add a new first line that says #!/bin/sh, then make the file executable and put it in your $PATH ahead of gzip.

Adam Katz
  • 3,800
  • 1
  • 24
  • 33