the code in gzip uses a function pointer abstraction but tries to shove too
much code into the same functions. this is impeding work to refactor the code
to fork + pledge helper processes.
in many cases, the duplication results absurd code like this:
error = (decomp ? dodecompress : docompress)
(infile, outfile, method, bits, entry->fts_statp);
what? why are we passing bits to a decompressor? because somebody was a little
too enamored with ?: operations.
this diff doesn't change any behavior, but creates separate read and write
open functions (which currently share quite a bit of code) that only take the
necessary arguments.
it also deletes a never used zopen function. and removes completely unncessary
mode checking, because these functions were only ever called with fixed
strings.
Index: compress.h
===================================================================
RCS file: /cvs/src/usr.bin/compress/compress.h,v
retrieving revision 1.12
diff -u -p -r1.12 compress.h
--- compress.h 22 Sep 2011 10:41:04 -0000 1.12
+++ compress.h 2 Sep 2016 15:53:55 -0000
@@ -58,26 +58,23 @@ enum program_mode {
extern char null_magic[];
-extern void *z_open(int, const char *, char *, int, u_int32_t, int);
+extern void *z_ropen(int, char *, int);
+extern void *z_wopen(int, char *, int, u_int32_t);
extern FILE *zopen(const char *, const char *,int);
extern int zread(void *, char *, int);
extern int zwrite(void *, const char *, int);
extern int z_close(void *, struct z_info *, const char *, struct stat *);
-extern void *gz_open(int, const char *, char *, int, u_int32_t, int);
+extern void *gz_ropen(int, char *, int);
+extern void *gz_wopen(int, char *, int, u_int32_t);
extern int gz_read(void *, char *, int);
extern int gz_write(void *, const char *, int);
extern int gz_close(void *, struct z_info *, const char *, struct stat *);
extern int gz_flush(void *, int);
-extern void *lzh_open(int, const char *, char *, int, u_int32_t, int);
-extern int lzh_read(void *, char *, int);
-extern int lzh_write(void *, const char *, int);
-extern int lzh_close(void *, struct z_info *);
-extern int lzh_flush(void *, int);
-
-extern void *null_open(int, const char *, char *, int, u_int32_t, int);
+extern void *null_ropen(int, char *, int);
+extern void *null_wopen(int, char *, int, u_int32_t);
extern int null_read(void *, char *, int);
extern int null_write(void *, const char *, int);
extern int null_close(void *, struct z_info *, const char *, struct stat *);
Index: gzopen.c
===================================================================
RCS file: /cvs/src/usr.bin/compress/gzopen.c,v
retrieving revision 1.32
diff -u -p -r1.32 gzopen.c
--- gzopen.c 17 Aug 2016 12:02:38 -0000 1.32
+++ gzopen.c 2 Sep 2016 15:57:39 -0000
@@ -103,16 +103,14 @@ static int put_header(gz_stream *, char
static int get_byte(gz_stream *);
void *
-gz_open(int fd, const char *mode, char *name, int bits,
- u_int32_t mtime, int gotmagic)
+gz_wopen(int fd, char *name, int bits, u_int32_t mtime)
{
gz_stream *s;
- if (fd < 0 || !mode)
+ if (fd < 0)
return NULL;
- if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||
- bits < 0 || bits > Z_BEST_COMPRESSION) {
+ if (bits < 0 || bits > Z_BEST_COMPRESSION) {
errno = EINVAL;
return NULL;
}
@@ -132,45 +130,74 @@ gz_open(int fd, const char *mode, char *
s->z_total_in = 0;
s->z_total_out = 0;
s->z_crc = crc32(0L, Z_NULL, 0);
- s->z_mode = mode[0];
+ s->z_mode = 'w';
- if (s->z_mode == 'w') {
#ifndef SMALL
- /* windowBits is passed < 0 to suppress zlib header */
- if (deflateInit2(&(s->z_stream), bits, Z_DEFLATED,
- -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK) {
- free (s);
- return NULL;
- }
- s->z_stream.next_out = s->z_buf;
+ /* windowBits is passed < 0 to suppress zlib header */
+ if (deflateInit2(&(s->z_stream), bits, Z_DEFLATED,
+ -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK) {
+ free (s);
+ return NULL;
+ }
+ s->z_stream.next_out = s->z_buf;
#else
- free(s);
- return (NULL);
+ free(s);
+ return (NULL);
#endif
- } else {
- if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
- free (s);
- return NULL;
- }
- s->z_stream.next_in = s->z_buf;
+ s->z_stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+ s->z_fd = fd;
+
+ /* write the .gz header */
+ if (put_header(s, name, mtime, bits) != 0) {
+ gz_close(s, NULL, NULL, NULL);
+ s = NULL;
+ }
+
+ return s;
+}
+
+void *
+gz_ropen(int fd, char *name, int gotmagic)
+{
+ gz_stream *s;
+
+ if (fd < 0)
+ return NULL;
+
+ if ((s = calloc(1, sizeof(gz_stream))) == NULL)
+ return NULL;
+
+ s->z_stream.zalloc = (alloc_func)0;
+ s->z_stream.zfree = (free_func)0;
+ s->z_stream.opaque = (voidpf)0;
+ s->z_stream.next_in = Z_NULL;
+ s->z_stream.next_out = Z_NULL;
+ s->z_stream.avail_in = s->z_stream.avail_out = 0;
+ s->z_fd = 0;
+ s->z_eof = 0;
+ s->z_time = 0;
+ s->z_hlen = 0;
+ s->z_total_in = 0;
+ s->z_total_out = 0;
+ s->z_crc = crc32(0L, Z_NULL, 0);
+ s->z_mode = 'r';
+
+ if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
+ free (s);
+ return NULL;
}
+ s->z_stream.next_in = s->z_buf;
s->z_stream.avail_out = Z_BUFSIZE;
errno = 0;
s->z_fd = fd;
- if (s->z_mode == 'w') {
- /* write the .gz header */
- if (put_header(s, name, mtime, bits) != 0) {
- gz_close(s, NULL, NULL, NULL);
- s = NULL;
- }
- } else {
- /* read the .gz header */
- if (get_header(s, name, gotmagic) != 0) {
- gz_close(s, NULL, NULL, NULL);
- s = NULL;
- }
+ /* read the .gz header */
+ if (get_header(s, name, gotmagic) != 0) {
+ gz_close(s, NULL, NULL, NULL);
+ s = NULL;
}
return s;
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/compress/main.c,v
retrieving revision 1.91
diff -u -p -r1.91 main.c
--- main.c 14 Jul 2016 08:31:18 -0000 1.91
+++ main.c 2 Sep 2016 15:54:32 -0000
@@ -60,7 +60,8 @@ const struct compressor {
const char *comp_opts;
const char *decomp_opts;
const char *cat_opts;
- void *(*open)(int, const char *, char *, int, u_int32_t, int);
+ void *(*ropen)(int, char *, int);
+ void *(*wopen)(int, char *, int, u_int32_t);
int (*read)(void *, char *, int);
int (*write)(void *, const char *, int);
int (*close)(void *, struct z_info *, const char *, struct stat *);
@@ -73,7 +74,8 @@ const struct compressor {
"123456789ab:cdfhLlNnOo:qrS:tVv",
"cfhLlNno:qrtVv",
"fhqr",
- gz_open,
+ gz_ropen,
+ gz_wopen,
gz_read,
gz_write,
gz_close
@@ -87,20 +89,13 @@ const struct compressor {
"123456789ab:cdfghlNnOo:qrS:tv",
"cfhlNno:qrtv",
"fghqr",
- z_open,
+ z_ropen,
+ z_wopen,
zread,
zwrite,
z_close
},
#endif /* SMALL */
-#if 0
-#define M_LZH (&c_table[2])
- { "lzh", ".lzh", "\037\240", lzh_open, lzh_read, lzh_write, lzh_close },
-#define M_ZIP (&c_table[3])
- { "zip", ".zip", "PK", zip_open, zip_read, zip_write, zip_close },
-#define M_PACK (&c_table[4])
- { "pack", ".pak", "\037\036", pak_open, pak_read, pak_write, pak_close },
-#endif
{ NULL }
};
@@ -112,7 +107,8 @@ const struct compressor null_method = {
"123456789ab:cdfghlNnOo:qrS:tv",
"cfhlNno:qrtv",
"fghqr",
- null_open,
+ null_ropen,
+ null_wopen,
null_read,
null_write,
null_close
@@ -123,8 +119,7 @@ int permission(const char *);
__dead void usage(int);
int docompress(const char *, char *, const struct compressor *,
int, struct stat *);
-int dodecompress(const char *, char *, const struct compressor *,
- int, struct stat *);
+int dodecompress(const char *, char *, struct stat *);
const struct compressor *check_method(int);
const char *check_suffix(const char *);
char *set_outfile(const char *, char *, size_t);
@@ -450,8 +445,10 @@ main(int argc, char *argv[])
if (verbose > 0 && !pipin && !list)
fprintf(stderr, "%s:\t", infile);
- error = (decomp ? dodecompress : docompress)
- (infile, outfile, method, bits, entry->fts_statp);
+ if (decomp)
+ error = dodecompress(infile, outfile, entry->fts_statp);
+ else
+ error = docompress(infile, outfile, method, bits,
entry->fts_statp);
switch (error) {
case SUCCESS:
@@ -481,7 +478,7 @@ docompress(const char *in, char *out, co
#ifndef SMALL
u_char buf[Z_BUFSIZE];
char *name;
- int error, ifd, ofd, flags, oreg;
+ int error, ifd, ofd, oreg;
void *cookie;
ssize_t nr;
u_int32_t mtime;
@@ -489,7 +486,7 @@ docompress(const char *in, char *out, co
struct stat osb;
mtime = 0;
- flags = oreg = 0;
+ oreg = 0;
error = SUCCESS;
name = NULL;
cookie = NULL;
@@ -536,7 +533,7 @@ docompress(const char *in, char *out, co
name = basename(in);
mtime = (u_int32_t)sb->st_mtime;
}
- if ((cookie = (*method->open)(ofd, "w", name, bits, mtime, flags)) ==
NULL) {
+ if ((cookie = method->wopen(ofd, name, bits, mtime)) == NULL) {
if (verbose >= 0)
warn("%s", out);
if (oreg)
@@ -616,9 +613,9 @@ check_method(int fd)
}
int
-dodecompress(const char *in, char *out, const struct compressor *method,
- int bits, struct stat *sb)
+dodecompress(const char *in, char *out, struct stat *sb)
{
+ const struct compressor *method;
u_char buf[Z_BUFSIZE];
char oldname[PATH_MAX];
int error, oreg, ifd, ofd;
@@ -658,7 +655,7 @@ dodecompress(const char *in, char *out,
/* XXX - open constrains outfile to MAXPATHLEN so this is safe */
oldname[0] = '\0';
- if ((cookie = (*method->open)(ifd, "r", oldname, bits, 0, 1)) == NULL) {
+ if ((cookie = method->ropen(ifd, oldname, 1)) == NULL) {
if (verbose >= 0)
warn("%s", in);
close (ifd);
Index: nullopen.c
===================================================================
RCS file: /cvs/src/usr.bin/compress/nullopen.c,v
retrieving revision 1.5
diff -u -p -r1.5 nullopen.c
--- nullopen.c 20 Aug 2015 22:32:41 -0000 1.5
+++ nullopen.c 2 Sep 2016 15:50:12 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: nullopen.c,v 1.5 2015/08/20 22:32:41 deraadt Exp $ */
+/* $OpenBSD: nullopen.c,v 1.4 2011/09/22 10:41:04 deraadt Exp $ */
/*
* Copyright (c) 2003 Can Erkin Acar
@@ -47,26 +47,39 @@ char null_magic[2];
void *
-null_open(int fd, const char *mode, char *name, int bits,
- u_int32_t mtime, int gotmagic)
+null_ropen(int fd, char *name, int gotmagic)
{
null_stream *s;
- if (fd < 0 || !mode)
+ if (fd < 0)
return NULL;
- if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0') {
- errno = EINVAL;
+ if ((s = calloc(1, sizeof(null_stream))) == NULL)
+ return NULL;
+
+ s->fd = fd;
+ s->gotmagic = gotmagic;
+ s->total_in = s->total_out = 0;
+ s->mode = 'r';
+
+ return s;
+}
+
+void *
+null_wopen(int fd, char *name, int bits, u_int32_t mtime)
+{
+ null_stream *s;
+
+ if (fd < 0)
return NULL;
- }
if ((s = calloc(1, sizeof(null_stream))) == NULL)
return NULL;
s->fd = fd;
- s->gotmagic = gotmagic;
+ s->gotmagic = 0;
s->total_in = s->total_out = 0;
- s->mode = mode[0];
+ s->mode = 'w';
return s;
}
Index: zopen.c
===================================================================
RCS file: /cvs/src/usr.bin/compress/zopen.c,v
retrieving revision 1.20
diff -u -p -r1.20 zopen.c
--- zopen.c 1 Feb 2015 11:50:23 -0000 1.20
+++ zopen.c 2 Sep 2016 15:56:57 -0000
@@ -735,36 +735,12 @@ cl_hash(struct s_zstate *zs, count_int c
*--htab_p = m1;
}
-FILE *
-zopen(const char *name, const char *mode, int bits)
-{
- FILE *fp;
- int fd;
- void *cookie;
- if ((fd = open(name, (*mode=='r'? O_RDONLY:O_WRONLY|O_CREAT),
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
- return NULL;
- if ((cookie = z_open(fd, mode, NULL, bits, 0, 0)) == NULL) {
- close(fd);
- return NULL;
- }
- if ((fp = funopen(cookie, (*mode == 'r'?zread:NULL),
- (*mode == 'w'?zwrite:NULL), NULL, zclose)) == NULL) {
- close(fd);
- free(cookie);
- return NULL;
- }
- return fp;
-}
-
void *
-z_open(int fd, const char *mode, char *name, int bits,
- u_int32_t mtime, int gotmagic)
+z_wopen(int fd, char *name, int bits, u_int32_t mtime)
{
struct s_zstate *zs;
- if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||
- bits < 0 || bits > BITS) {
+ if (bits < 0 || bits > BITS) {
errno = EINVAL;
return (NULL);
}
@@ -784,10 +760,40 @@ z_open(int fd, const char *mode, char *n
zs->zs_checkpoint = CHECK_GAP;
zs->zs_in_count = 0; /* Length of input. */
zs->zs_out_count = 0; /* # of codes output (for debugging).*/
+ zs->zs_state = S_START;
+ zs->zs_offset = 0;
+ zs->zs_size = 0;
+ zs->zs_mode = 'w';
+ zs->zs_bp = zs->zs_ebp = zs->zs_buf;
+
+ zs->zs_fd = fd;
+ return zs;
+}
+
+void *
+z_ropen(int fd, char *name, int gotmagic)
+{
+ struct s_zstate *zs;
+
+ if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)
+ return (NULL);
+
+ /* User settable max # bits/code. */
+ zs->zs_maxbits = BITS;
+ /* Should NEVER generate this code. */
+ zs->zs_maxmaxcode = 1 << zs->zs_maxbits;
+ zs->zs_hsize = HSIZE; /* For dynamic table sizing. */
+ zs->zs_free_ent = 0; /* First unused entry. */
+ zs->zs_block_compress = BLOCK_MASK;
+ zs->zs_clear_flg = 0;
+ zs->zs_ratio = 0;
+ zs->zs_checkpoint = CHECK_GAP;
+ zs->zs_in_count = 0; /* Length of input. */
+ zs->zs_out_count = 0; /* # of codes output (for debugging).*/
zs->zs_state = gotmagic ? S_MAGIC : S_START;
zs->zs_offset = 0;
zs->zs_size = 0;
- zs->zs_mode = mode[0];
+ zs->zs_mode = 'r';
zs->zs_bp = zs->zs_ebp = zs->zs_buf;
zs->zs_fd = fd;