xref: /netbsd-src/external/bsd/liblzf/dist/lzf.c (revision e6ea0ca4b63c68aa4d6153608fa0eb4fc2f96f72)
105206c06Stls /*
205206c06Stls  * Copyright (c) 2006      Stefan Traby <stefan@hello-penguin.com>
305206c06Stls  *
405206c06Stls  * Redistribution and use in source and binary forms, with or without modifica-
505206c06Stls  * tion, are permitted provided that the following conditions are met:
605206c06Stls  *
705206c06Stls  *   1.  Redistributions of source code must retain the above copyright notice,
805206c06Stls  *       this list of conditions and the following disclaimer.
905206c06Stls  *
1005206c06Stls  *   2.  Redistributions in binary form must reproduce the above copyright
1105206c06Stls  *       notice, this list of conditions and the following disclaimer in the
1205206c06Stls  *       documentation and/or other materials provided with the distribution.
1305206c06Stls  *
1405206c06Stls  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
1505206c06Stls  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
1605206c06Stls  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
1705206c06Stls  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
1805206c06Stls  * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1905206c06Stls  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2005206c06Stls  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2105206c06Stls  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
2205206c06Stls  * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2305206c06Stls  * OF THE POSSIBILITY OF SUCH DAMAGE.
2405206c06Stls  *
2505206c06Stls  * Alternatively, the contents of this file may be used under the terms of
2605206c06Stls  * the GNU General Public License ("GPL") version 2 or any later version,
2705206c06Stls  * in which case the provisions of the GPL are applicable instead of
2805206c06Stls  * the above. If you wish to allow the use of your version of this file
2905206c06Stls  * only under the terms of the GPL and not to allow others to use your
3005206c06Stls  * version of this file under the BSD license, indicate your decision
3105206c06Stls  * by deleting the provisions above and replace them with the notice
3205206c06Stls  * and other provisions required by the GPL. If you do not delete the
3305206c06Stls  * provisions above, a recipient may use your version of this file under
3405206c06Stls  * either the BSD or the GPL.
3505206c06Stls  */
3605206c06Stls 
3705206c06Stls #include <stdio.h>
3805206c06Stls #include <string.h>
3905206c06Stls #include <stdlib.h>
4005206c06Stls #include <unistd.h>
4105206c06Stls #include <sys/types.h>
4205206c06Stls #include <sys/stat.h>
4305206c06Stls #include <fcntl.h>
4405206c06Stls #include <errno.h>
4505206c06Stls #include <limits.h>
4605206c06Stls #include "lzf.h"
4705206c06Stls 
4805206c06Stls #ifdef HAVE_GETOPT_H
4905206c06Stls # include <getopt.h>
5005206c06Stls #endif
5105206c06Stls 
5205206c06Stls #define BLOCKSIZE (1024 * 64 - 1)
5305206c06Stls #define MAX_BLOCKSIZE BLOCKSIZE
5405206c06Stls 
5505206c06Stls static off_t nr_read, nr_written;
5605206c06Stls 
5705206c06Stls static const char *imagename;
58*e6ea0ca4Stls static enum { compress, uncompress, lzfcat } mode = compress;
5905206c06Stls static int verbose = 0;
6005206c06Stls static int force = 0;
6105206c06Stls static long blocksize = BLOCKSIZE;
6205206c06Stls 
6305206c06Stls #ifdef HAVE_GETOPT_LONG
6405206c06Stls 
6505206c06Stls   struct option longopts[] = {
6605206c06Stls     {"compress", 0, 0, 'c'},
6705206c06Stls     {"decompress", 0, 0, 'd'},
6805206c06Stls     {"uncompress", 0, 0, 'd'},
6905206c06Stls     {"force", 0, 0, 'f'},
7005206c06Stls     {"help", 0, 0, 'h'},
7105206c06Stls     {"verbose", 0, 0, 'v'},
7205206c06Stls     {"blocksize", 1, 0, 'b'},
7305206c06Stls     {0, 0, 0, 0}
7405206c06Stls   };
7505206c06Stls 
7605206c06Stls   static const char *opt =
7705206c06Stls     "-c --compress    compress\n"
7805206c06Stls     "-d --decompress  decompress\n"
7905206c06Stls     "-f --force       force overwrite of output file\n"
8005206c06Stls     "-h --help        give this help\n" "-v --verbose     verbose mode\n" "-b # --blocksize # set blocksize\n" "\n";
8105206c06Stls 
8205206c06Stls #else
8305206c06Stls 
8405206c06Stls   static const char *opt =
8505206c06Stls     "-c   compress\n"
8605206c06Stls     "-d   decompress\n"
8705206c06Stls     "-f   force overwrite of output file\n"
8805206c06Stls     "-h   give this help\n"
8905206c06Stls     "-v   verbose mode\n"
9005206c06Stls     "-b # set blocksize\n"
9105206c06Stls     "\n";
9205206c06Stls 
9305206c06Stls #endif
9405206c06Stls 
9505206c06Stls static void
usage(int rc)9605206c06Stls usage (int rc)
9705206c06Stls {
9805206c06Stls   fprintf (stderr, "\n"
9905206c06Stls            "lzf, a very lightweight compression/decompression utility written by Stefan Traby.\n"
10005206c06Stls            "uses liblzf written by Marc Lehmann <schmorp@schmorp.de> You can find more info at\n"
10105206c06Stls            "http://liblzf.plan9.de/\n"
10205206c06Stls            "\n"
10305206c06Stls            "usage: lzf [-dufhvb] [file ...]\n"
10405206c06Stls            "       unlzf [file ...]\n"
105*e6ea0ca4Stls            "       lzfcat [file ...]\n"
10605206c06Stls            "\n%s",
10705206c06Stls            opt);
10805206c06Stls 
10905206c06Stls   exit (rc);
11005206c06Stls }
11105206c06Stls 
11205206c06Stls static inline ssize_t
rread(int fd,void * buf,size_t len)11305206c06Stls rread (int fd, void *buf, size_t len)
11405206c06Stls {
11505206c06Stls   ssize_t rc = 0, offset = 0;
11605206c06Stls   char *p = buf;
11705206c06Stls 
11805206c06Stls   while (len && (rc = read (fd, &p[offset], len)) > 0)
11905206c06Stls     {
12005206c06Stls       offset += rc;
12105206c06Stls       len -= rc;
12205206c06Stls     }
12305206c06Stls 
12405206c06Stls   nr_read += offset;
12505206c06Stls 
12605206c06Stls   if (rc < 0)
12705206c06Stls     return rc;
12805206c06Stls 
12905206c06Stls   return offset;
13005206c06Stls }
13105206c06Stls 
13205206c06Stls /* returns 0 if all written else -1 */
13305206c06Stls static inline ssize_t
wwrite(int fd,void * buf,size_t len)13405206c06Stls wwrite (int fd, void *buf, size_t len)
13505206c06Stls {
13605206c06Stls   ssize_t rc;
13705206c06Stls   char *b = buf;
13805206c06Stls   size_t l = len;
13905206c06Stls 
14005206c06Stls   while (l)
14105206c06Stls     {
14205206c06Stls       rc = write (fd, b, l);
14305206c06Stls       if (rc < 0)
14405206c06Stls         {
14505206c06Stls           fprintf (stderr, "%s: write error: ", imagename);
14605206c06Stls           perror ("");
14705206c06Stls           return -1;
14805206c06Stls         }
14905206c06Stls 
15005206c06Stls       l -= rc;
15105206c06Stls       b += rc;
15205206c06Stls     }
15305206c06Stls 
15405206c06Stls   nr_written += len;
15505206c06Stls   return 0;
15605206c06Stls }
15705206c06Stls 
15805206c06Stls /*
15905206c06Stls  * Anatomy: an lzf file consists of any number of blocks in the following format:
16005206c06Stls  *
16105206c06Stls  * \x00   EOF (optional)
16205206c06Stls  * "ZV\0" 2-byte-usize <uncompressed data>
16305206c06Stls  * "ZV\1" 2-byte-csize 2-byte-usize <compressed data>
16405206c06Stls  * "ZV\2" 4-byte-crc32-0xdebb20e3 (NYI)
16505206c06Stls  */
16605206c06Stls 
16705206c06Stls 
16805206c06Stls #define TYPE0_HDR_SIZE 5
16905206c06Stls #define TYPE1_HDR_SIZE 7
17005206c06Stls #define MAX_HDR_SIZE 7
17105206c06Stls #define MIN_HDR_SIZE 5
17205206c06Stls 
17305206c06Stls static int
compress_fd(int from,int to)17405206c06Stls compress_fd (int from, int to)
17505206c06Stls {
17605206c06Stls   ssize_t us, cs, len;
17705206c06Stls   u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
17805206c06Stls   u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
17905206c06Stls   u8 *header;
18005206c06Stls 
18105206c06Stls   nr_read = nr_written = 0;
18205206c06Stls   while ((us = rread (from, &buf1[MAX_HDR_SIZE], blocksize)) > 0)
18305206c06Stls     {
18405206c06Stls       cs = lzf_compress (&buf1[MAX_HDR_SIZE], us, &buf2[MAX_HDR_SIZE], us > 4 ? us - 4 : us);
18505206c06Stls       if (cs)
18605206c06Stls         {
18705206c06Stls           header = &buf2[MAX_HDR_SIZE - TYPE1_HDR_SIZE];
18805206c06Stls           header[0] = 'Z';
18905206c06Stls           header[1] = 'V';
19005206c06Stls           header[2] = 1;
19105206c06Stls           header[3] = cs >> 8;
19205206c06Stls           header[4] = cs & 0xff;
19305206c06Stls           header[5] = us >> 8;
19405206c06Stls           header[6] = us & 0xff;
19505206c06Stls           len = cs + TYPE1_HDR_SIZE;
19605206c06Stls         }
19705206c06Stls       else
19805206c06Stls         {                       // write uncompressed
19905206c06Stls           header = &buf1[MAX_HDR_SIZE - TYPE0_HDR_SIZE];
20005206c06Stls           header[0] = 'Z';
20105206c06Stls           header[1] = 'V';
20205206c06Stls           header[2] = 0;
20305206c06Stls           header[3] = us >> 8;
20405206c06Stls           header[4] = us & 0xff;
20505206c06Stls           len = us + TYPE0_HDR_SIZE;
20605206c06Stls         }
20705206c06Stls 
20805206c06Stls       if (wwrite (to, header, len) == -1)
20905206c06Stls         return -1;
21005206c06Stls     }
21105206c06Stls 
21205206c06Stls   return 0;
21305206c06Stls }
21405206c06Stls 
21505206c06Stls static int
uncompress_fd(int from,int to)21605206c06Stls uncompress_fd (int from, int to)
21705206c06Stls {
21805206c06Stls   u8 header[MAX_HDR_SIZE];
21905206c06Stls   u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
22005206c06Stls   u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
22105206c06Stls   u8 *p;
22205206c06Stls   int l, rd;
22305206c06Stls   ssize_t rc, cs, us, bytes, over = 0;
22405206c06Stls 
22505206c06Stls   nr_read = nr_written = 0;
22605206c06Stls   while (1)
22705206c06Stls     {
22805206c06Stls       rc = rread (from, header + over, MAX_HDR_SIZE - over);
22905206c06Stls       if (rc < 0)
23005206c06Stls         {
23105206c06Stls           fprintf (stderr, "%s: read error: ", imagename);
23205206c06Stls           perror ("");
23305206c06Stls           return -1;
23405206c06Stls         }
23505206c06Stls 
23605206c06Stls       rc += over;
23705206c06Stls       over = 0;
23805206c06Stls       if (!rc || header[0] == 0)
23905206c06Stls         return 0;
24005206c06Stls 
24105206c06Stls       if (rc < MIN_HDR_SIZE || header[0] != 'Z' || header[1] != 'V')
24205206c06Stls         {
24305206c06Stls           fprintf (stderr, "%s: invalid data stream - magic not found or short header\n", imagename);
24405206c06Stls           return -1;
24505206c06Stls         }
24605206c06Stls 
24705206c06Stls       switch (header[2])
24805206c06Stls         {
24905206c06Stls           case 0:
25005206c06Stls             cs = -1;
25105206c06Stls             us = (header[3] << 8) | header[4];
25205206c06Stls             p = &header[TYPE0_HDR_SIZE];
25305206c06Stls             break;
25405206c06Stls           case 1:
25505206c06Stls             if (rc < TYPE1_HDR_SIZE)
25605206c06Stls               {
25705206c06Stls                 goto short_read;
25805206c06Stls               }
25905206c06Stls             cs = (header[3] << 8) | header[4];
26005206c06Stls             us = (header[5] << 8) | header[6];
26105206c06Stls             p = &header[TYPE1_HDR_SIZE];
26205206c06Stls             break;
26305206c06Stls           default:
26405206c06Stls             fprintf (stderr, "%s: unknown blocktype\n", imagename);
26505206c06Stls             return -1;
26605206c06Stls         }
26705206c06Stls 
26805206c06Stls       bytes = cs == -1 ? us : cs;
26905206c06Stls       l = &header[rc] - p;
27005206c06Stls 
27105206c06Stls       if (l > 0)
27205206c06Stls         memcpy (buf1, p, l);
27305206c06Stls 
27405206c06Stls       if (l > bytes)
27505206c06Stls         {
27605206c06Stls           over = l - bytes;
27705206c06Stls           memmove (header, &p[bytes], over);
27805206c06Stls         }
27905206c06Stls 
28005206c06Stls       p = &buf1[l];
28105206c06Stls       rd = bytes - l;
28205206c06Stls       if (rd > 0)
28305206c06Stls         if ((rc = rread (from, p, rd)) != rd)
28405206c06Stls           goto short_read;
28505206c06Stls 
28605206c06Stls       if (cs == -1)
28705206c06Stls         {
28805206c06Stls           if (wwrite (to, buf1, us))
28905206c06Stls             return -1;
29005206c06Stls         }
29105206c06Stls       else
29205206c06Stls         {
29305206c06Stls           if (lzf_decompress (buf1, cs, buf2, us) != us)
29405206c06Stls             {
29505206c06Stls               fprintf (stderr, "%s: decompress: invalid stream - data corrupted\n", imagename);
29605206c06Stls               return -1;
29705206c06Stls             }
29805206c06Stls 
29905206c06Stls           if (wwrite (to, buf2, us))
30005206c06Stls             return -1;
30105206c06Stls         }
30205206c06Stls     }
30305206c06Stls 
30405206c06Stls   return 0;
30505206c06Stls 
30605206c06Stls short_read:
30705206c06Stls   fprintf (stderr, "%s: short data\n", imagename);
30805206c06Stls   return -1;
30905206c06Stls }
31005206c06Stls 
31105206c06Stls static int
open_out(const char * name)31205206c06Stls open_out (const char *name)
31305206c06Stls {
31405206c06Stls   int fd;
31505206c06Stls   int m = O_EXCL;
31605206c06Stls 
31705206c06Stls   if (force)
31805206c06Stls     m = 0;
31905206c06Stls 
32005206c06Stls   fd = open (name, O_CREAT | O_WRONLY | O_TRUNC | m, 600);
32105206c06Stls #if defined(__MINGW32__)
32205206c06Stls   _setmode(fd, _O_BINARY);
32305206c06Stls #endif
32405206c06Stls   return fd;
32505206c06Stls }
32605206c06Stls 
32705206c06Stls static int
compose_name(const char * fname,char * oname)32805206c06Stls compose_name (const char *fname, char *oname)
32905206c06Stls {
33005206c06Stls   char *p;
33105206c06Stls 
33205206c06Stls   if (mode == compress)
33305206c06Stls     {
33405206c06Stls       if (strlen (fname) > PATH_MAX - 4)
33505206c06Stls         {
33605206c06Stls           fprintf (stderr, "%s: %s.lzf: name too long", imagename, fname);
33705206c06Stls           return -1;
33805206c06Stls         }
33905206c06Stls 
34005206c06Stls       strcpy (oname, fname);
34105206c06Stls       strcat (oname, ".lzf");
34205206c06Stls     }
34305206c06Stls   else
34405206c06Stls     {
34505206c06Stls       if (strlen (fname) > PATH_MAX)
34605206c06Stls         {
34705206c06Stls           fprintf (stderr, "%s: %s: name too long\n", imagename, fname);
34805206c06Stls           return -1;
34905206c06Stls         }
35005206c06Stls 
35105206c06Stls       strcpy (oname, fname);
35205206c06Stls       p = &oname[strlen (oname)] - 4;
35305206c06Stls       if (p < oname || strcmp (p, ".lzf"))
35405206c06Stls         {
35505206c06Stls           fprintf (stderr, "%s: %s: unknown suffix\n", imagename, fname);
35605206c06Stls           return -1;
35705206c06Stls         }
35805206c06Stls 
35905206c06Stls       *p = 0;
36005206c06Stls     }
36105206c06Stls 
36205206c06Stls   return 0;
36305206c06Stls }
36405206c06Stls 
36505206c06Stls static int
run_file(const char * fname)36605206c06Stls run_file (const char *fname)
36705206c06Stls {
36805206c06Stls   int fd, fd2;
36905206c06Stls   int rc;
37005206c06Stls   struct stat mystat;
37105206c06Stls   char oname[PATH_MAX + 1];
37205206c06Stls 
373*e6ea0ca4Stls   if (mode != lzfcat)
37405206c06Stls     if (compose_name (fname, oname))
37505206c06Stls       return -1;
37605206c06Stls 
37705206c06Stls #if !defined(__MINGW32__)
37805206c06Stls   rc = lstat (fname, &mystat);
37905206c06Stls #else
38005206c06Stls   rc = stat (fname, &mystat);
38105206c06Stls #endif
38205206c06Stls   fd = open (fname, O_RDONLY);
38305206c06Stls #if defined(__MINGW32__)
38405206c06Stls   _setmode(fd, _O_BINARY);
38505206c06Stls #endif
38605206c06Stls   if (rc || fd == -1)
38705206c06Stls     {
38805206c06Stls       fprintf (stderr, "%s: %s: ", imagename, fname);
38905206c06Stls       perror ("");
39005206c06Stls       return -1;
39105206c06Stls     }
39205206c06Stls 
39305206c06Stls   if (!S_ISREG (mystat.st_mode))
39405206c06Stls     {
39505206c06Stls       fprintf (stderr, "%s: %s: not a regular file.\n", imagename, fname);
39605206c06Stls       close (fd);
39705206c06Stls       return -1;
39805206c06Stls     }
39905206c06Stls 
400*e6ea0ca4Stls   if (mode == lzfcat)
40105206c06Stls     {
40205206c06Stls       rc = uncompress_fd (fd, 1);
40305206c06Stls       close (fd);
40405206c06Stls       return rc;
40505206c06Stls     }
40605206c06Stls 
40705206c06Stls   fd2 = open_out (oname);
40805206c06Stls   if (fd2 == -1)
40905206c06Stls     {
41005206c06Stls       fprintf (stderr, "%s: %s: ", imagename, oname);
41105206c06Stls       perror ("");
41205206c06Stls       close (fd);
41305206c06Stls       return -1;
41405206c06Stls     }
41505206c06Stls 
41605206c06Stls   if (mode == compress)
41705206c06Stls     {
41805206c06Stls       rc = compress_fd (fd, fd2);
41905206c06Stls       if (!rc && verbose)
42005206c06Stls         fprintf (stderr, "%s:  %5.1f%% -- replaced with %s\n",
42105206c06Stls                  fname, nr_read == 0 ? 0 : 100.0 - nr_written / ((double) nr_read / 100.0), oname);
42205206c06Stls     }
42305206c06Stls   else
42405206c06Stls     {
42505206c06Stls       rc = uncompress_fd (fd, fd2);
42605206c06Stls       if (!rc && verbose)
42705206c06Stls         fprintf (stderr, "%s:  %5.1f%% -- replaced with %s\n",
42805206c06Stls                  fname, nr_written == 0 ? 0 : 100.0 - nr_read / ((double) nr_written / 100.0), oname);
42905206c06Stls     }
43005206c06Stls 
43105206c06Stls #if !defined(__MINGW32__)
43205206c06Stls   fchmod (fd2, mystat.st_mode);
43305206c06Stls #else
43405206c06Stls   chmod (oname, mystat.st_mode);
43505206c06Stls #endif
43605206c06Stls   close (fd);
43705206c06Stls   close (fd2);
43805206c06Stls 
43905206c06Stls   if (!rc)
44005206c06Stls     unlink (fname);
44105206c06Stls 
44205206c06Stls   return rc;
44305206c06Stls }
44405206c06Stls 
44505206c06Stls int
main(int argc,char * argv[])44605206c06Stls main (int argc, char *argv[])
44705206c06Stls {
44805206c06Stls   char *p = argv[0];
44905206c06Stls   int optc;
45005206c06Stls   int rc = 0;
45105206c06Stls 
45205206c06Stls   errno = 0;
45305206c06Stls   p = getenv ("LZF_BLOCKSIZE");
45405206c06Stls   if (p)
45505206c06Stls     {
45605206c06Stls       blocksize = strtoul (p, 0, 0);
45705206c06Stls       if (errno || !blocksize || blocksize > MAX_BLOCKSIZE)
45805206c06Stls         blocksize = BLOCKSIZE;
45905206c06Stls     }
46005206c06Stls 
46105206c06Stls   p = strrchr (argv[0], '/');
46205206c06Stls   imagename = p ? ++p : argv[0];
46305206c06Stls 
46405206c06Stls   if (!strncmp (imagename, "un", 2) || !strncmp (imagename, "de", 2))
46505206c06Stls     mode = uncompress;
46605206c06Stls 
46705206c06Stls   if (strstr (imagename, "cat"))
468*e6ea0ca4Stls     mode = lzfcat;
46905206c06Stls 
47005206c06Stls #ifdef HAVE_GETOPT_LONG
47105206c06Stls   while ((optc = getopt_long (argc, argv, "cdfhvb:", longopts, 0)) != -1)
47205206c06Stls #else
47305206c06Stls   while ((optc = getopt (argc, argv, "cdfhvb:")) != -1)
47405206c06Stls #endif
47505206c06Stls     {
47605206c06Stls       switch (optc)
47705206c06Stls         {
47805206c06Stls           case 'c':
47905206c06Stls             mode = compress;
48005206c06Stls             break;
48105206c06Stls           case 'd':
48205206c06Stls             mode = uncompress;
48305206c06Stls             break;
48405206c06Stls           case 'f':
48505206c06Stls             force = 1;
48605206c06Stls             break;
48705206c06Stls           case 'h':
48805206c06Stls             usage (0);
48905206c06Stls             break;
49005206c06Stls           case 'v':
49105206c06Stls             verbose = 1;
49205206c06Stls             break;
49305206c06Stls           case 'b':
49405206c06Stls             errno = 0;
49505206c06Stls             blocksize = strtoul (optarg, 0, 0);
49605206c06Stls             if (errno || !blocksize || blocksize > MAX_BLOCKSIZE)
49705206c06Stls               blocksize = BLOCKSIZE;
49805206c06Stls             break;
49905206c06Stls           default:
50005206c06Stls             usage (1);
50105206c06Stls             break;
50205206c06Stls         }
50305206c06Stls     }
50405206c06Stls 
50505206c06Stls   if (optind == argc)
50605206c06Stls     {                           // stdin stdout
50705206c06Stls       if (!force)
50805206c06Stls         {
509*e6ea0ca4Stls           if ((mode == uncompress || mode == lzfcat) && isatty (0))
51005206c06Stls             {
51105206c06Stls               fprintf (stderr, "%s: compressed data not read from a terminal. Use -f to force decompression.\n", imagename);
51205206c06Stls               exit (1);
51305206c06Stls             }
51405206c06Stls           if (mode == compress && isatty (1))
51505206c06Stls             {
51605206c06Stls               fprintf (stderr, "%s: compressed data not written to a terminal. Use -f to force compression.\n", imagename);
51705206c06Stls               exit (1);
51805206c06Stls             }
51905206c06Stls         }
52005206c06Stls 
52105206c06Stls       if (mode == compress)
52205206c06Stls         rc = compress_fd (0, 1);
52305206c06Stls       else
52405206c06Stls         rc = uncompress_fd (0, 1);
52505206c06Stls 
52605206c06Stls       exit (rc ? 1 : 0);
52705206c06Stls     }
52805206c06Stls 
52905206c06Stls   while (optind < argc)
53005206c06Stls     rc |= run_file (argv[optind++]);
53105206c06Stls 
53205206c06Stls   exit (rc ? 1 : 0);
53305206c06Stls }
53405206c06Stls 
535