| OLD | NEW | 
| (Empty) |  | 
 |    1 #!/bin/bash | 
 |    2 # | 
 |    3 ############################################################################# | 
 |    4 # | 
 |    5 # 7z2lzma.bash is very primitive .7z to .lzma converter. The input file must | 
 |    6 # have exactly one LZMA compressed stream, which has been created with the | 
 |    7 # default lc, lp, and pb values. The CRC32 in the .7z archive is not checked, | 
 |    8 # and the script may seem to succeed while it actually created a corrupt .lzma | 
 |    9 # file. You should always try uncompressing both the original .7z and the | 
 |   10 # created .lzma and compare that the output is identical. | 
 |   11 # | 
 |   12 # This script requires basic GNU tools and 7z or 7za tool from p7zip. | 
 |   13 # | 
 |   14 # Last modified: 2009-01-15 14:25+0200 | 
 |   15 # | 
 |   16 ############################################################################# | 
 |   17 # | 
 |   18 # Author: Lasse Collin <lasse.collin@tukaani.org> | 
 |   19 # | 
 |   20 # This file has been put into the public domain. | 
 |   21 # You can do whatever you want with this file. | 
 |   22 # | 
 |   23 ############################################################################# | 
 |   24  | 
 |   25 # You can use 7z or 7za, both will work. | 
 |   26 SEVENZIP=7za | 
 |   27  | 
 |   28 if [ $# != 2 -o -z "$1" -o -z "$2" ]; then | 
 |   29         echo "Usage: $0 input.7z output.lzma" | 
 |   30         exit 1 | 
 |   31 fi | 
 |   32  | 
 |   33 # Converts an integer variable to little endian binary integer. | 
 |   34 int2bin() | 
 |   35 { | 
 |   36         local LEN=$1 | 
 |   37         local NUM=$2 | 
 |   38         local HEX=(0 1 2 3 4 5 6 7 8 9 A B C D E F) | 
 |   39         local I | 
 |   40         for ((I=0; I < "$LEN"; ++I)); do | 
 |   41                 printf "\\x${HEX[(NUM >> 4) & 0x0F]}${HEX[NUM & 0x0F]}" | 
 |   42                 NUM=$((NUM >> 8)) | 
 |   43         done | 
 |   44 } | 
 |   45  | 
 |   46 # Make sure we get possible errors from pipes. | 
 |   47 set -o pipefail | 
 |   48  | 
 |   49 # Get information about the input file. At least older 7z and 7za versions | 
 |   50 # may return with zero exit status even when an error occurred, so check | 
 |   51 # if the output has any lines beginning with "Error". | 
 |   52 INFO=$("$SEVENZIP" l -slt "$1") | 
 |   53 if [ $? != 0 ] || printf '%s\n' "$INFO" | grep -q ^Error; then | 
 |   54         printf '%s\n' "$INFO" | 
 |   55         exit 1 | 
 |   56 fi | 
 |   57  | 
 |   58 # Check if the input file has more than one compressed block. | 
 |   59 if printf '%s\n' "$INFO" | grep -q '^Block = 1'; then | 
 |   60         echo "Cannot convert, because the input file has more than" | 
 |   61         echo "one compressed block." | 
 |   62         exit 1 | 
 |   63 fi | 
 |   64  | 
 |   65 # Get compressed, uncompressed, and dictionary size. | 
 |   66 CSIZE=$(printf '%s\n' "$INFO" | sed -rn 's|^Packed Size = ([0-9]+$)|\1|p') | 
 |   67 USIZE=$(printf '%s\n' "$INFO" | sed -rn 's|^Size = ([0-9]+$)|\1|p') | 
 |   68 DICT=$(printf '%s\n' "$INFO" | sed -rn 's|^Method = LZMA:([0-9]+[bkm]?)$|\1|p') | 
 |   69  | 
 |   70 if [ -z "$CSIZE" -o -z "$USIZE" -o -z "$DICT" ]; then | 
 |   71         echo "Parsing output of $SEVENZIP failed. Maybe the file uses some" | 
 |   72         echo "other compression method than plain LZMA." | 
 |   73         exit 1 | 
 |   74 fi | 
 |   75  | 
 |   76 # The following assumes that the default lc, lp, and pb settings were used. | 
 |   77 # Otherwise the output will be corrupt. | 
 |   78 printf '\x5D' > "$2" | 
 |   79  | 
 |   80 # Dictionary size can be either was power of two, bytes, kibibytes, or | 
 |   81 # mebibytes. We need to convert it to bytes. | 
 |   82 case $DICT in | 
 |   83         *b) | 
 |   84                 DICT=${DICT%b} | 
 |   85                 ;; | 
 |   86         *k) | 
 |   87                 DICT=${DICT%k} | 
 |   88                 DICT=$((DICT << 10)) | 
 |   89                 ;; | 
 |   90         *m) | 
 |   91                 DICT=${DICT%m} | 
 |   92                 DICT=$((DICT << 20)) | 
 |   93                 ;; | 
 |   94         *) | 
 |   95                 DICT=$((1 << DICT)) | 
 |   96                 ;; | 
 |   97 esac | 
 |   98 int2bin 4 "$DICT" >> "$2" | 
 |   99  | 
 |  100 # Uncompressed size | 
 |  101 int2bin 8 "$USIZE" >> "$2" | 
 |  102  | 
 |  103 # Copy the actual compressed data. Using multiple dd commands to avoid | 
 |  104 # copying large amount of data with one-byte block size, which would be | 
 |  105 # annoyingly slow. | 
 |  106 BS=8192 | 
 |  107 BIGSIZE=$((CSIZE / BS)) | 
 |  108 CSIZE=$((CSIZE % BS)) | 
 |  109 { | 
 |  110         dd of=/dev/null bs=32 count=1 \ | 
 |  111                 && dd bs="$BS" count="$BIGSIZE" \ | 
 |  112                 && dd bs=1 count="$CSIZE" | 
 |  113 } < "$1" >> "$2" | 
 |  114  | 
 |  115 exit $? | 
| OLD | NEW |