1e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li/*
2e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * Copyright (c) 2006      Stefan Traby <stefan@hello-penguin.com>
3e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *
4e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * Redistribution and use in source and binary forms, with or without modifica-
5e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * tion, are permitted provided that the following conditions are met:
6e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *
7e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *   1.  Redistributions of source code must retain the above copyright notice,
8e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *       this list of conditions and the following disclaimer.
9e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *
10e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *   2.  Redistributions in binary form must reproduce the above copyright
11e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *       notice, this list of conditions and the following disclaimer in the
12e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *       documentation and/or other materials provided with the distribution.
13e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *
14e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
16e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
17e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
18e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
22e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
23e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * OF THE POSSIBILITY OF SUCH DAMAGE.
24e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *
25e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * Alternatively, the contents of this file may be used under the terms of
26e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * the GNU General Public License ("GPL") version 2 or any later version,
27e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * in which case the provisions of the GPL are applicable instead of
28e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * the above. If you wish to allow the use of your version of this file
29e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * only under the terms of the GPL and not to allow others to use your
30e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * version of this file under the BSD license, indicate your decision
31e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * by deleting the provisions above and replace them with the notice
32e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * and other provisions required by the GPL. If you do not delete the
33e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * provisions above, a recipient may use your version of this file under
34e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * either the BSD or the GPL.
35e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li */
36e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
37e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include "config.h"
38e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <stdio.h>
39e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <string.h>
40e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <stdlib.h>
41e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <unistd.h>
42e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <sys/types.h>
43e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <sys/stat.h>
44e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <fcntl.h>
45e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <errno.h>
46e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include <limits.h>
47e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#include "lzf.h"
48e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
49e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#ifdef HAVE_GETOPT_H
50e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li# include <getopt.h>
51e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
52e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
53e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#define BLOCKSIZE (1024 * 64 - 1)
54e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#define MAX_BLOCKSIZE BLOCKSIZE
55e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
56e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Litypedef unsigned char u8;
57e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
58e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic off_t nr_read, nr_written;
59e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
60e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic const char *imagename;
61e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic enum { compress, uncompress, lzcat } mode = compress;
62e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int verbose = 0;
63e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int force = 0;
64e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic long blocksize = BLOCKSIZE;
65e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
66e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#ifdef HAVE_GETOPT_LONG
67e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
68e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  struct option longopts[] = {
69e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"compress", 0, 0, 'c'},
70e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"decompress", 0, 0, 'd'},
71e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"uncompress", 0, 0, 'd'},
72e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"force", 0, 0, 'f'},
73e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"help", 0, 0, 'h'},
74e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"verbose", 0, 0, 'v'},
75e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {"blocksize", 1, 0, 'b'},
76e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {0, 0, 0, 0}
77e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  };
78e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
79e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  static const char *opt =
80e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-c --compress    compress\n"
81e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-d --decompress  decompress\n"
82e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-f --force       force overwrite of output file\n"
83e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-h --help        give this help\n" "-v --verbose     verbose mode\n" "-b # --blocksize # set blocksize\n" "\n";
84e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
85e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#else
86e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
87e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  static const char *opt =
88e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-c   compress\n"
89e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-d   decompress\n"
90e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-f   force overwrite of output file\n"
91e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-h   give this help\n"
92e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-v   verbose mode\n"
93e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "-b # set blocksize\n"
94e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    "\n";
95e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
96e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
97e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
98e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic void
99e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Liusage (int rc)
100e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
101e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  fprintf (stderr, "\n"
102e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "lzf, a very lightweight compression/decompression utility written by Stefan Traby.\n"
103e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "uses liblzf written by Marc Lehmann <schmorp@schmorp.de> You can find more info at\n"
104e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "http://liblzf.plan9.de/\n"
105e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "\n"
106e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "usage: lzf [-dufhvb] [file ...]\n"
107e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "       unlzf [file ...]\n"
108e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "       lzcat [file ...]\n"
109e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           "\n%s",
110e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li           opt);
111e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
112e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  exit (rc);
113e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
114e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
115e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic inline ssize_t
116e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Lirread (int fd, void *buf, size_t len)
117e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
118e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  ssize_t rc = 0, offset = 0;
119e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  char *p = buf;
120e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
121e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while (len && (rc = read (fd, &p[offset], len)) > 0)
122e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
123e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      offset += rc;
124e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      len -= rc;
125e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
126e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
127e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  nr_read += offset;
128e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
129e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (rc < 0)
130e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    return rc;
131e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
132e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return offset;
133e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
134e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
135e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li/* returns 0 if all written else -1 */
136e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic inline ssize_t
137e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Liwwrite (int fd, void *buf, size_t len)
138e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
139e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  ssize_t rc;
140e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  char *b = buf;
141e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  size_t l = len;
142e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
143e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while (l)
144e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
145e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rc = write (fd, b, l);
146e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (rc < 0)
147e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
148e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          fprintf (stderr, "%s: write error: ", imagename);
149e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          perror ("");
150e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          return -1;
151e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
152e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
153e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      l -= rc;
154e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      b += rc;
155e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
156e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
157e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  nr_written += len;
158e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return 0;
159e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
160e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
161e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li/*
162e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * Anatomy: an lzf file consists of any number of blocks in the following format:
163e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li *
164e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * \x00   EOF (optional)
165e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * "ZV\0" 2-byte-usize <uncompressed data>
166e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * "ZV\1" 2-byte-csize 2-byte-usize <compressed data>
167e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li * "ZV\2" 4-byte-crc32-0xdebb20e3 (NYI)
168e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li */
169e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
170e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
171e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#define TYPE0_HDR_SIZE 5
172e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#define TYPE1_HDR_SIZE 7
173e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#define MAX_HDR_SIZE 7
174e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#define MIN_HDR_SIZE 5
175e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
176e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int
177e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Licompress_fd (int from, int to)
178e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
179e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  ssize_t us, cs, len;
180e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
181e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
182e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 *header;
183e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
184e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  nr_read = nr_written = 0;
185e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while ((us = rread (from, &buf1[MAX_HDR_SIZE], blocksize)) > 0)
186e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
187e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      cs = lzf_compress (&buf1[MAX_HDR_SIZE], us, &buf2[MAX_HDR_SIZE], us > 4 ? us - 4 : us);
188e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (cs)
189e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
190e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header = &buf2[MAX_HDR_SIZE - TYPE1_HDR_SIZE];
191e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[0] = 'Z';
192e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[1] = 'V';
193e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[2] = 1;
194e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[3] = cs >> 8;
195e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[4] = cs & 0xff;
196e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[5] = us >> 8;
197e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[6] = us & 0xff;
198e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          len = cs + TYPE1_HDR_SIZE;
199e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
200e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      else
201e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {                       // write uncompressed
202e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header = &buf1[MAX_HDR_SIZE - TYPE0_HDR_SIZE];
203e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[0] = 'Z';
204e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[1] = 'V';
205e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[2] = 0;
206e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[3] = us >> 8;
207e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          header[4] = us & 0xff;
208e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          len = us + TYPE0_HDR_SIZE;
209e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
210e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
211e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (wwrite (to, header, len) == -1)
212e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        return -1;
213e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
214e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
215e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return 0;
216e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
217e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
218e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int
219e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Liuncompress_fd (int from, int to)
220e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
221e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 header[MAX_HDR_SIZE];
222e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
223e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
224e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  u8 *p;
225e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int l, rd;
226e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  ssize_t rc, cs, us, bytes, over = 0;
227e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
228e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  nr_read = nr_written = 0;
229e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while (1)
230e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
231e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rc = rread (from, header + over, MAX_HDR_SIZE - over);
232e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (rc < 0)
233e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
234e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          fprintf (stderr, "%s: read error: ", imagename);
235e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          perror ("");
236e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          return -1;
237e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
238e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
239e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rc += over;
240e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      over = 0;
241e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (!rc || header[0] == 0)
242e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        return 0;
243e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
244e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (rc < MIN_HDR_SIZE || header[0] != 'Z' || header[1] != 'V')
245e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
246e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          fprintf (stderr, "%s: invalid data stream - magic not found or short header\n", imagename);
247e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          return -1;
248e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
249e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
250e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      switch (header[2])
251e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
252e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 0:
253e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            cs = -1;
254e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            us = (header[3] << 8) | header[4];
255e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            p = &header[TYPE0_HDR_SIZE];
256e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
257e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 1:
258e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            if (rc < TYPE1_HDR_SIZE)
259e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              {
260e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li                goto short_read;
261e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              }
262e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            cs = (header[3] << 8) | header[4];
263e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            us = (header[5] << 8) | header[6];
264e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            p = &header[TYPE1_HDR_SIZE];
265e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
266e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          default:
267e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            fprintf (stderr, "%s: unknown blocktype\n", imagename);
268e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            return -1;
269e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
270e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
271e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      bytes = cs == -1 ? us : cs;
272e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      l = &header[rc] - p;
273e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
274e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (l > 0)
275e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        memcpy (buf1, p, l);
276e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
277e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (l > bytes)
278e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
279e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          over = l - bytes;
280e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          memmove (header, &p[bytes], over);
281e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
282e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
283e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      p = &buf1[l];
284e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rd = bytes - l;
285e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (rd > 0)
286e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        if ((rc = rread (from, p, rd)) != rd)
287e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          goto short_read;
288e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
289e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (cs == -1)
290e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
291e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          if (wwrite (to, buf1, us))
292e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            return -1;
293e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
294e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      else
295e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
296e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          if (lzf_decompress (buf1, cs, buf2, us) != us)
297e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            {
298e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              fprintf (stderr, "%s: decompress: invalid stream - data corrupted\n", imagename);
299e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              return -1;
300e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            }
301e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
302e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          if (wwrite (to, buf2, us))
303e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            return -1;
304e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
305e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
306e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
307e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return 0;
308e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
309e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Lishort_read:
310e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  fprintf (stderr, "%s: short data\n", imagename);
311e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return -1;
312e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
313e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
314e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int
315e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Liopen_out (const char *name)
316e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
317e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int fd;
318e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int m = O_EXCL;
319e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
320e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (force)
321e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    m = 0;
322e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
323e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  fd = open (name, O_CREAT | O_WRONLY | O_TRUNC | m, 600);
324e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#if defined(__MINGW32__)
325e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  _setmode(fd, _O_BINARY);
326e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
327e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return fd;
328e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
329e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
330e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int
331e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Licompose_name (const char *fname, char *oname)
332e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
333e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  char *p;
334e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
335e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (mode == compress)
336e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
337e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (strlen (fname) > PATH_MAX - 4)
338e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
339e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          fprintf (stderr, "%s: %s.lzf: name too long", imagename, fname);
340e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          return -1;
341e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
342e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
343e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      strcpy (oname, fname);
344e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      strcat (oname, ".lzf");
345e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
346e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  else
347e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
348e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (strlen (fname) > PATH_MAX)
349e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
350e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          fprintf (stderr, "%s: %s: name too long\n", imagename, fname);
351e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          return -1;
352e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
353e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
354e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      strcpy (oname, fname);
355e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      p = &oname[strlen (oname)] - 4;
356e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (p < oname || strcmp (p, ".lzf"))
357e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
358e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          fprintf (stderr, "%s: %s: unknown suffix\n", imagename, fname);
359e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          return -1;
360e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
361e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
362e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      *p = 0;
363e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
364e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
365e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return 0;
366e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
367e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
368e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Listatic int
369e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Lirun_file (const char *fname)
370e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
371e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int fd, fd2;
372e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int rc;
373e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  struct stat mystat;
374e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  char oname[PATH_MAX + 1];
375e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
376e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (mode != lzcat)
377e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    if (compose_name (fname, oname))
378e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      return -1;
379e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
380e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#if !defined(__MINGW32__)
381e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  rc = lstat (fname, &mystat);
382e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#else
383e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  rc = stat (fname, &mystat);
384e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
385e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  fd = open (fname, O_RDONLY);
386e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#if defined(__MINGW32__)
387e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  _setmode(fd, _O_BINARY);
388e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
389e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (rc || fd == -1)
390e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
391e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      fprintf (stderr, "%s: %s: ", imagename, fname);
392e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      perror ("");
393e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      return -1;
394e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
395e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
396e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (!S_ISREG (mystat.st_mode))
397e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
398e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      fprintf (stderr, "%s: %s: not a regular file.\n", imagename, fname);
399e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      close (fd);
400e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      return -1;
401e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
402e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
403e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (mode == lzcat)
404e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
405e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rc = uncompress_fd (fd, 1);
406e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      close (fd);
407e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      return rc;
408e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
409e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
410e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  fd2 = open_out (oname);
411e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (fd2 == -1)
412e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
413e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      fprintf (stderr, "%s: %s: ", imagename, oname);
414e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      perror ("");
415e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      close (fd);
416e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      return -1;
417e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
418e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
419e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (mode == compress)
420e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
421e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rc = compress_fd (fd, fd2);
422e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (!rc && verbose)
423e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        fprintf (stderr, "%s:  %5.1f%% -- replaced with %s\n",
424e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li                 fname, nr_read == 0 ? 0 : 100.0 - nr_written / ((double) nr_read / 100.0), oname);
425e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
426e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  else
427e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
428e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      rc = uncompress_fd (fd, fd2);
429e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (!rc && verbose)
430e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        fprintf (stderr, "%s:  %5.1f%% -- replaced with %s\n",
431e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li                 fname, nr_written == 0 ? 0 : 100.0 - nr_read / ((double) nr_written / 100.0), oname);
432e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
433e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
434e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#if !defined(__MINGW32__)
435e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  fchmod (fd2, mystat.st_mode);
436e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#else
437e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  chmod (oname, mystat.st_mode);
438e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
439e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  close (fd);
440e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  close (fd2);
441e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
442e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (!rc)
443e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    unlink (fname);
444e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
445e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  return rc;
446e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
447e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
448e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Liint
449e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Limain (int argc, char *argv[])
450e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li{
451e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  char *p = argv[0];
452e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int optc;
453e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  int rc = 0;
454e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
455e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  errno = 0;
456e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  p = getenv ("LZF_BLOCKSIZE");
457e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (p)
458e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
459e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      blocksize = strtoul (p, 0, 0);
460e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (errno || !blocksize || blocksize > MAX_BLOCKSIZE)
461e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        blocksize = BLOCKSIZE;
462e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
463e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
464e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  p = strrchr (argv[0], '/');
465e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  imagename = p ? ++p : argv[0];
466e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
467e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (!strncmp (imagename, "un", 2) || !strncmp (imagename, "de", 2))
468e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    mode = uncompress;
469e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
470e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (strstr (imagename, "cat"))
471e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    mode = lzcat;
472e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
473e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#ifdef HAVE_GETOPT_LONG
474e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while ((optc = getopt_long (argc, argv, "cdfhvb:", longopts, 0)) != -1)
475e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#else
476e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while ((optc = getopt (argc, argv, "cdfhvb:")) != -1)
477e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li#endif
478e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {
479e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      switch (optc)
480e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
481e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 'c':
482e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            mode = compress;
483e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
484e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 'd':
485e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            mode = uncompress;
486e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
487e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 'f':
488e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            force = 1;
489e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
490e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 'h':
491e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            usage (0);
492e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
493e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 'v':
494e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            verbose = 1;
495e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
496e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          case 'b':
497e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            errno = 0;
498e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            blocksize = strtoul (optarg, 0, 0);
499e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            if (errno || !blocksize || blocksize > MAX_BLOCKSIZE)
500e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              blocksize = BLOCKSIZE;
501e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
502e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          default:
503e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            usage (1);
504e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            break;
505e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
506e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
507e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
508e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  if (optind == argc)
509e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    {                           // stdin stdout
510e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (!force)
511e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        {
512e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          if ((mode == uncompress || mode == lzcat) && isatty (0))
513e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            {
514e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              fprintf (stderr, "%s: compressed data not read from a terminal. Use -f to force decompression.\n", imagename);
515e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              exit (1);
516e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            }
517e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li          if (mode == compress && isatty (1))
518e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            {
519e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              fprintf (stderr, "%s: compressed data not written to a terminal. Use -f to force compression.\n", imagename);
520e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li              exit (1);
521e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li            }
522e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        }
523e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
524e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      if (mode == compress)
525e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        rc = compress_fd (0, 1);
526e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      else
527e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li        rc = uncompress_fd (0, 1);
528e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
529e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li      exit (rc ? 1 : 0);
530e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    }
531e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
532e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  while (optind < argc)
533e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li    rc |= run_file (argv[optind++]);
534e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
535e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li  exit (rc ? 1 : 0);
536e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li}
537e54acca48ba1ab84ac7c693de45ed31ac3f311c2David Li
538