Makefile | 37 ++++++++++++++++++++----------- testw.c | 41 ++++++++++++++++++++++++++++++++++ testx.c | 2 +- zio.c | 76 +++++++++++++++++++++++++++++++++++++++++----------------------- zioP.h | 25 ++++++++++++--------- 5 files changed, 130 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index f8f8c43..4c88104 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,15 @@ # LARGE = $(shell getconf LFS_CFLAGS) -CFLAGS = $(RPM_OPT_FLAGS) -pipe -Wall -D_GNU_SOURCE -D_REENTRANT -D_DEFAULT_SOURCE $(LARGE) +CFLAGS_for_configure = \ + $(INCLUDES) -D_GNU_SOURCE -D_REENTRANT -D_DEFAULT_SOURCE $(LARGE) \ + $(RPM_OPT_FLAGS) -pipe -Wall +CFLAGS = $(CFLAGS_for_configure) CC = gcc MAJOR = 1 MINOR = 06 VERSION = $(MAJOR).$(MINOR) -SONAME = libzio.so.$(MAJOR) +SONAME = libzio.so.0 LDMAP = -Wl,--version-script=zio.map prefix = /usr @@ -38,10 +41,12 @@ FILES = README \ cc-include = $(shell $(CC) $(INCLUDES) -include $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 && echo "-D$(2)") cc-library = $(shell echo 'int main () { return 0; }' |$(CC) -l$(1:lib%=%) -o /dev/null -xc - > /dev/null 2>&1 && echo yes) cc-function = $(shell echo 'extern void $(1)(void); int main () { $(1)(); return 0; }' |$(CC) -o /dev/null -xc - > /dev/null 2>&1 && echo "-D$(2)") +cc-type = $(shell echo 'int main(){return (int)sizeof($(1));}' |$(CC) $(CFLAGS_for_configure) -include $(2) -S -o /dev/null -xc - > /dev/null 2>&1 && echo "-D$(3)") CFLAGS += $(call cc-include,libio.h,HAVE_LIBIO_H) CFLAGS += $(call cc-function,fopencookie,HAVE_FOPENCOOKIE) CFLAGS += $(call cc-function,funopen,HAVE_FUNOPEN) +CFLAGS += $(call cc-type,cookie_io_functions_t,stdio.h,HAVE_COOKIE_IO_FUNCTIONS_T) CFLAGS += $(call cc-include,zlib.h,HAS_ZLIB_H) CFLAGS += $(call cc-include,bzlib.h,HAS_BZLIB_H) @@ -63,8 +68,8 @@ endif all: shared static noweak: CFLAGS += -DNO_WEAK noweak: LINK += $(LIBS) -noweak: all -shared: libzio.so.$(VERSION) zio.map +noweak: shared +shared: libzio.so zio.map static: libzio.a obj/zio.o: zio.c zioP.h zio.h @@ -90,6 +95,12 @@ libzio.a: obj/zio.o obj/unlzw.o libzio.so.$(VERSION): obs/zio.o obs/unlzw.o gcc -shared -Wl,-soname,$(SONAME),-stats $(LDMAP) -o $@ $^ $(LINK) +$(SONAME): libzio.so.$(VERSION) + ln -sf libzio.so.$(VERSION) $(SONAME) + +libzio.so: $(SONAME) + ln -sf $(SONAME) libzio.so + zioP.h: /usr/include/bzlib.h /usr/include/zlib.h zio.h: zio.h.in /usr/include/stdio.h sed 's/@@VERSION@@/$(VERSION)/' < $< > $@ @@ -103,8 +114,8 @@ install: install-shared install-static install-data install-shared: libzio.so.$(VERSION) mkdir -p $(DESTDIR)$(libdir) install -m 0755 libzio.so.$(VERSION) $(DESTDIR)$(libdir)/ - ln -sf libzio.so.$(VERSION) $(DESTDIR)$(libdir)/libzio.so.$(MAJOR) - ln -sf libzio.so.$(MAJOR) $(DESTDIR)$(libdir)/libzio.so + ln -sf libzio.so.$(VERSION) $(DESTDIR)$(libdir)/$(SONAME) + ln -sf $(SONAME) $(DESTDIR)$(libdir)/libzio.so install-static: libzio.a mkdir -p $(DESTDIR)$(libdir) @@ -117,7 +128,7 @@ install-data: zio.h fzopen.3 install -m 0644 fzopen.3 $(DESTDIR)$(mandir)/man3/ clean: - rm -f *.a *.so* testt tests zio.h + rm -f *.a *.so* testt tests testx zio.h rm -rf obj/ obs/ rm -f libzio-$(VERSION).tar.gz @@ -127,11 +138,11 @@ dest: clean tar czf libzio-$(VERSION).tar.gz libzio-$(VERSION)/ rm -rf libzio-$(VERSION)/ -testt: testt.c libzio.a - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +testt: testt.c libzio.so + $(CC) $(CFLAGS) -o $@ $^ -L. -lzio -tests: tests.c libzio.a - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +tests: tests.c libzio.so + $(CC) $(CFLAGS) -o $@ $^ -L. -lzio -testx: testx.c libzio.a - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +testx: testx.c libzio.so + $(CC) $(CFLAGS) -o $@ $^ -L. -lzio diff --git a/testw.c b/testw.c new file mode 100644 index 0000000..ea3fbf4 --- /dev/null +++ b/testw.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include "zio.h" + +int main(int argc, char *argv[]) +{ + int rc = 0; + + while (argc > 1) { + FILE *file; + char line[1024]; + size_t len; + + argv++; + argc--; + + if (!(file = fzopen(*argv, "w6"))) { + fprintf(stderr, "fzopen: %s: %s\n", *argv, strerror(errno)); + continue; + } + + while ((len = fread(line, sizeof(char), sizeof (line), stdin))) { + size_t ret = fwrite(line, sizeof(char), len, file); + if ((ret != len)) { + rc = 1; + fprintf(stderr, "fwrite: %s: %zu < %zu: %s\n", + *argv, ret, len, strerror(errno)); + break; + } + } + + if (fclose(file)) { + rc = 1; + fprintf(stderr, "fclose: %s: %s\n", *argv, strerror(errno)); + } + } + + return rc; +} diff --git a/testx.c b/testx.c index d705e4c..21af73f 100644 --- a/testx.c +++ b/testx.c @@ -10,7 +10,7 @@ int main(int argc, char *argv[]) char line[1<<13]; size_t len; - if (!(file = fdzopen(fileno(stdout), "w", argc > 1 ? argv[1] : "g"))) { + if (!(file = fdzopen(fileno(stdout), "w6", argc > 1 ? argv[1] : "g"))) { fprintf(stderr, "%s\n", strerror(errno)); return 1; } diff --git a/zio.c b/zio.c index be27da5..7495daa 100644 --- a/zio.c +++ b/zio.c @@ -301,6 +301,7 @@ static ssize_t lzmaread(void *cookie, char *buf, size_t count) strm->avail_in = fread(lzma->buf, 1, sizeof(lzma->buf), lzma->file); if (strm->avail_in == 0) eof = 1; + strm->next_in = lzma->buf; } lret = lzma_code(strm, LZMA_RUN); if (lret == LZMA_STREAM_END) { @@ -664,12 +665,54 @@ static cookie_io_functions_t iolzw = { .close = (cookie_close_function_t*)lzwclose, }; +static char +guess_by_magic(const char *path) +{ + char what = 'n'; + int olderr = errno; + int fd = open(path, O_RDONLY|O_NOCTTY); + char m[5]; + + if (fd < 0) { + errno = olderr; + return what; + } + + if (read(fd, m, sizeof(m)) == sizeof(m)) { + if (m[0] == '\037' && m[1] == '\213') + what = 'g'; + else if (m[0] == '\037' && m[1] == '\235') + what = 'Z'; + else if (m[0] == '\037' && m[1] == '\236') + what = 'z'; + else if (m[0] == 'B' && m[1] == 'Z' && m[2] == 'h') + what = 'b'; + else if (m[0] == ']' && m[1] == '\0' && m[2] == '\0' && m[3] == '\200') /* weak!! */ + what = 'l'; + else if (m[0] == '\377' && m[1] == 'L' && m[2] == 'Z' && m[3] == 'M' && m[4] == 'A') + what = 'l'; + else if (m[0] == '\375' && m[1] == '7' && m[2] == 'z' && m[3] == 'X' && m[4] == 'Z') + what = 'x'; + } + + close(fd); + errno = olderr; + return what; +} + static inline char autodetect(char **__restrict path, const char *__restrict check) { + char what = 'n'; + + if (*check == 'r') { + what = guess_by_magic(*path); + if (what != 'n') + return what; + } + const size_t len = strlen(*path); char *suff = strrchr(*path, '.'); char *ext = *path; - char what = 'n'; if (suff) { suff++; @@ -688,9 +731,8 @@ static inline char autodetect(char **__restrict path, const char *__restrict che } if (what == 'n' && *check == 'r') { - int olderr, fd; + int olderr; struct stat st; - char m[5]; ext = malloc(sizeof(char)*(len + 5 + 1)); if (!ext) goto out; @@ -728,26 +770,6 @@ static inline char autodetect(char **__restrict path, const char *__restrict che goto skip; } *suff = '\0'; - - if ((fd = open(ext, O_RDONLY|O_NOCTTY)) < 0) - goto skip; - if (read(fd, m, sizeof(m)) == sizeof(m)) { - if (m[0] == '\037' && m[1] == '\213') - what = 'g'; - if (m[0] == '\037' && m[1] == '\235') - what = 'Z'; - if (m[0] == '\037' && m[1] == '\236') - what = 'z'; - else if (m[0] == 'B' && m[1] == 'Z' && m[2] == 'h') - what = 'b'; - else if (m[0] == ']' && m[1] == '\0' && m[2] == '\0' && m[3] == '\200') /* weak!! */ - what = 'l'; - else if (m[0] == '\377' && m[1] == 'L' && m[2] == 'Z' && m[3] == 'M' && m[4] == 'A') - what = 'l'; - else if (m[0] == '\375' && m[1] == '7' && m[2] == 'z' && m[3] == 'X' && m[4] == 'Z') - what = 'x'; - } - close(fd); skip: errno = olderr; } @@ -888,7 +910,7 @@ FILE * fzopen(const char * path, const char * mode) n = strlen(mode); for (i = 1; i < n; i++) { if (mode[i] >= '0' && mode[i] <= '9') { - level = (int)mode[i]; + level = mode[i] - '0'; break; } } @@ -947,7 +969,7 @@ FILE * fzopen(const char * path, const char * mode) for (i = 1; i < n; i++) { if (mode[i] >= '0' && mode[i] <= '9') { - level = (int)mode[i]; + level = mode[i] - '0'; break; } } @@ -1155,7 +1177,7 @@ FILE * fdzopen(int fildes, const char * mode, const char *what) n = strlen(mode); for (i = 1; i < n; i++) { if (mode[i] >= '0' && mode[i] <= '9') { - level = (int)mode[i]; + level = mode[i] - '0'; break; } } @@ -1216,7 +1238,7 @@ FILE * fdzopen(int fildes, const char * mode, const char *what) for (i = 1; i < n; i++) { if (mode[i] >= '0' && mode[i] <= '9') { - level = (int)mode[i]; + level = mode[i] - '0'; break; } } diff --git a/zioP.h b/zioP.h index 4348676..d76e1df 100644 --- a/zioP.h +++ b/zioP.h @@ -35,9 +35,6 @@ #include #include #include -#ifdef HAVE_LIBIO_H -# include -#endif #include #include #include @@ -58,14 +55,22 @@ # error Requires fopencookie(3GNU) or funopen(3BSD) #endif -#if defined(HAVE_LIBIO_H) || defined(HAVE_FOPENCOOKIE) -# if defined __GLIBC__ && __GLIBC__ > 1 -# undef LIBIO_IS_FIXED -# if __GLIBC__ > 2 || (__GLIBC__ >= 2 && __GLIBC_MINOR__ > 0) -# define LIBIO_IS_FIXED +#undef LIBIO_IS_FIXED +#if defined(HAVE_FOPENCOOKIE) && defined(HAVE_COOKIE_IO_FUNCTIONS_T) +# define LIBIO_IS_FIXED 1 +#endif +#ifndef LIBIO_IS_FIXED +# if defined(HAVE_LIBIO_H) +# include +# endif +# if defined(HAVE_LIBIO_H) || defined(HAVE_FOPENCOOKIE) +# if defined __GLIBC__ && __GLIBC__ > 1 +# if __GLIBC__ > 2 || (__GLIBC__ >= 2 && __GLIBC_MINOR__ > 0) +# define LIBIO_IS_FIXED +# endif +# else +# error The libzio requires the GLIBC # endif -# else -# error The libzio requires the GLIBC # endif #endif