Gzcompat

From Computer History Wiki
Revision as of 22:56, 6 February 2009 by Neozeed (talk | contribs) (New page: gzcompat is a utility to convert from Sokolov compression into gzip. The primary use is to convert the Quasijarus install files into gzip, so that they can easily be decompressed. == sou...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

gzcompat is a utility to convert from Sokolov compression into gzip. The primary use is to convert the Quasijarus install files into gzip, so that they can easily be decompressed.

source code

#ifndef lint
static char sccsid[] = "@(#)gzcompat.c  5.1 (Berkeley) 1/21/99";
#endif

/* gzcompat converts between compress -s and gzip formats. */

#include <stdio.h>

char magic_strong[2] = {037, 0241};
char magic_gzip[2]   = {037, 0213};

struct gzheader {
        unsigned char cm;
        unsigned char flg;
        unsigned char mtime[4];
        unsigned char xfl;
        unsigned char os;
} gzheader;

#define CM_DEFLATE 0x08

#define FTEXT    0x01
#define FHCRC    0x02
#define FEXTRA   0x04
#define FNAME    0x08
#define FCOMMENT 0x10
#define FRSVD    0xE0

#define OS_UNIX 0x03

int main()
{
        char buf[4096];
        int len;
        int mkgzip;

        /* First read the input magic number. */
        len = fread(buf, 1, 2, stdin);
        if (len < 0) {
                perror("stdin");
                return 1;
        }
        if (len != 2) {
                fprintf(stderr, "stdin: not in compress -s or gzip format\n");
                return 1;
        }
        if (buf[0] == magic_strong[0] && buf[1] == magic_strong[1])
                mkgzip = 1;
        else if (buf[0] == magic_gzip[0] && buf[1] == magic_gzip[1])
                mkgzip = 0;
        else {
                fprintf(stderr, "stdin: not in compress -s or gzip format\n");
                return 1;
        }

        /* Now read and check the gzip header if necessary. */
        if (!mkgzip) {
                len = fread(&gzheader, sizeof(struct gzheader), 1, stdin);
                if (len < 0) {
                        perror("stdin");
                        return 1;
                }
                if (len != 1) {
                        fprintf(stderr, "stdin: invalid gzip header\n");
                        return 1;
                }
                if (gzheader.cm != CM_DEFLATE || gzheader.flg & FRSVD) {
                        fprintf(stderr, "stdin: invalid gzip header\n");
                        return 1;
                }
                if (gzheader.flg & FEXTRA) {
                        int count;

                        count = getchar();
                        if (ferror(stdin)) {
                                perror("stdin");
                                return 1;
                        }
                        if (feof(stdin)) {
                                fprintf(stderr, "stdin: invalid gzip header\n");

                                return 1;
                        }
                        while (count) {
                                getchar();
                                if (ferror(stdin)) {
                                        perror("stdin");
                                        return 1;
                                }
                                if (feof(stdin)) {
                                        fprintf(stderr, "stdin: invalid gzip header\n");
                                        return 1;
                                }
                                count--;
                        }
                }
                if (gzheader.flg & FNAME) {
                        int ch;

                        do {
                                ch = getchar();
                                if (ferror(stdin)) {
                                        perror("stdin");
                                        return 1;
                                }
                                if (feof(stdin)) {
                                        fprintf(stderr, "stdin: invalid gzip header\n");
                                        return 1;
                                }
                        }
                        while (ch);
                }
                if (gzheader.flg & FCOMMENT) {
                        int ch;

                        do {
                                ch = getchar();
                                if (ferror(stdin)) {
                                        perror("stdin");
                                        return 1;
                                }
                                if (feof(stdin)) {
                                        fprintf(stderr, "stdin: invalid gzip header\n");
                                        return 1;
                                }
                        }
                        while (ch);
                }
                if (gzheader.flg & FHCRC) {
                        len = fread(buf, 1, 2, stdin);
                        if (len < 0) {
                                perror("stdin");
                                return 1;
                        }
                        if (len != 2) {
                                fprintf(stderr, "stdin: invalid gzip header\n");

                                return 1;
                        }
                }
        }

        /* Now write the output magic number. */
        if (mkgzip) {
                if (fwrite(magic_gzip, 1, 2, stdout) != 2) {
                        perror("stdout");
                        return 1;
                }
        }
        else {
                if (fwrite(magic_strong, 1, 2, stdout) != 2) {
                        perror("stdout");
                        return 1;
                }
        }

        /* Now write the gzip header if necessary. */
        if (mkgzip) {
                gzheader.cm = CM_DEFLATE;
                gzheader.flg = 0;
                gzheader.mtime[0] = 0;
                gzheader.mtime[1] = 0;
                gzheader.mtime[2] = 0;
                gzheader.mtime[3] = 0;
                gzheader.xfl = 0;
                gzheader.os = OS_UNIX;
                if (fwrite(&gzheader, sizeof(struct gzheader), 1, stdout) != 1)
{
                        perror("stdout");
                        return 1;
                }
        }

        /* Now actually copy the data! */
        for (;;) {
                len = fread(buf, 1, sizeof(buf), stdin);
                if (len < 0) {
                        perror("stdin");
                        return 1;
                }
                if (len == 0)
                        break;
                if (fwrite(buf, 1, len, stdout) != len) {
                        perror("stdout");
                        return 1;
                }
        }

        /* I can't believe we're done! */
        return 0;
}