diff -r -u rzip-2.1.orig/main.c rzip-2.1/main.c
--- rzip-2.1.orig/main.c	2009-10-12 14:02:23.000000000 +0200
+++ rzip-2.1/main.c	2009-10-12 14:02:23.000000000 +0200
@@ -23,6 +23,7 @@
 {
 	printf("rzip %d.%d\n", RZIP_MAJOR_VERSION, RZIP_MINOR_VERSION);
 	printf("Copright (C) Andrew Tridgell 1998-2003\n\n");
+	printf("stdin/stdout patch by Nicolas Rachinsky\n\n");
 	printf("usage: rzip [options] <file...>\n");
 	printf(" Options:\n");
 	printf("     -0            fastest (worst) compression\n");
@@ -36,11 +37,17 @@
 	printf("     -P            show compression progress\n");
 	printf("     -L level      set compression level\n");
 	printf("     -V            show version\n");
+	printf("     -q file       temporary file for input\n");
+	printf("     -Q file       temporary file for output\n");
 #if 0
 	/* damn, this will be quite hard to do */
 	printf("     -t          test compressed file integrity\n");
 #endif
-	printf("\nnote that rzip cannot operate on stdin/stdout\n"); 
+	printf("\n"); 
+	printf("to read from stdin -q is necessary\n"); 
+	printf("to write to stdout -Q is necessary\n"); 
+	printf("reading from stdin and writing to stdout while compressing results in files\n"); 
+	printf("that cannot be decompressed with plain rzip\n"); 
 }
 
 
@@ -55,9 +62,12 @@
 	magic[4] = RZIP_MAJOR_VERSION;
 	magic[5] = RZIP_MINOR_VERSION;
 
-	if (fstat(fd_in, &st) != 0) {
+	if (fd_in && fstat(fd_in, &st) != 0) {
 		fatal("bad magic file descriptor!?\n");
+	} else if(!fd_in) {
+		st.st_size=0;
 	}
+	
 
 #if HAVE_LARGE_FILES
 	v = htonl(st.st_size & 0xFFFFFFFF);
@@ -74,6 +84,35 @@
 	}
 }
 
+static void update_magic(off_t l, int fd_out)
+{
+	char magic[24];
+	uint32_t v;
+
+	memset(magic, 0, sizeof(magic));
+	strcpy(magic, "RZIP");
+	magic[4] = RZIP_MAJOR_VERSION;
+	magic[5] = RZIP_MINOR_VERSION;
+
+
+#if HAVE_LARGE_FILES
+	v = htonl(l & 0xFFFFFFFF);
+	memcpy(&magic[6], &v, 4);
+	v = htonl(l >> 32);
+	memcpy(&magic[10], &v, 4);
+#else
+	v = htonl(l
+	memcpy(&magic[6], &v, 4);
+#endif
+
+	if(lseek(fd_out,0,SEEK_SET)==-1)
+		fatal("Failed to seek\n");
+
+	if (write(fd_out, magic, sizeof(magic)) != sizeof(magic)) {
+		fatal("Failed to write magic header\n");
+	}
+}
+
 static void read_magic(int fd_in, int fd_out, off_t *expected_size)
 {
 	uint32_t v;
@@ -129,28 +168,41 @@
 	int fd_in, fd_out = -1, fd_hist = -1;
 	off_t expected_size;
 
-	if (control->outname) {
-		control->outfile = strdup(control->outname);
+	if(control->out_tmp) {
+		control->outfile = strdup("-");
 	} else {
-		if (strlen(control->suffix) >= strlen(control->infile) ||
-		    strcmp(control->suffix, 
-			   control->infile + 
-			   strlen(control->infile) - strlen(control->suffix)) != 0) {
-			fatal("%s: unknown suffix\n", control->infile);
+		if (control->outname) {
+			control->outfile = strdup(control->outname);
+		} else {
+			if (strlen(control->suffix) >= strlen(control->infile) ||
+			    strcmp(control->suffix, 
+				   control->infile + 
+				   strlen(control->infile) - strlen(control->suffix)) != 0) {
+				fatal("%s: unknown suffix\n", control->infile);
+			}
+			
+			control->outfile = strdup(control->infile);
+			control->outfile[strlen(control->infile) - strlen(control->suffix)] = 0;
 		}
-		
-		control->outfile = strdup(control->infile);
-		control->outfile[strlen(control->infile) - strlen(control->suffix)] = 0;
 	}
 
-	fd_in = open(control->infile,O_RDONLY);
-	if (fd_in == -1) {
-		fatal("Failed to open %s: %s\n", 
-		      control->infile, 
-		      strerror(errno));
+	if(control->in_tmp) {
+		fd_in = open(control->in_tmp,O_RDWR|O_CREAT|O_EXCL,0600);
+		if (fd_in == -1) {
+			fatal("Failed to open %s: %s\n", 
+			      control->in_tmp, 
+			      strerror(errno));
+		}
+	} else {
+		fd_in = open(control->infile,O_RDONLY);
+		if (fd_in == -1) {
+			fatal("Failed to open %s: %s\n", 
+			      control->infile, 
+			      strerror(errno));
+		}
 	}
 
-	if ((control->flags & FLAG_TEST_ONLY) == 0) {
+	if ((control->flags & FLAG_TEST_ONLY) == 0 && ! control->out_tmp) {
 		if (control->flags & FLAG_FORCE_REPLACE) {
 			fd_out = open(control->outfile,O_WRONLY|O_CREAT|O_TRUNC,0666);
 		} else {
@@ -161,18 +213,32 @@
 			      control->outfile, strerror(errno));
 		}
 
-		preserve_perms(control, fd_in, fd_out);
+		if(!control->in_tmp)
+			preserve_perms(control, fd_in, fd_out);
 		
 		fd_hist = open(control->outfile,O_RDONLY);
 		if (fd_hist == -1) {
 			fatal("Failed to open history file %s\n", 
 			      control->outfile);
 		}
+	} else if(control->out_tmp) {
+		fd_out = open(control->out_tmp,O_RDWR|O_CREAT|O_EXCL,0600);
+		if (fd_out == -1) {
+			fatal("Failed to create %s: %s\n", 
+			      control->out_tmp, strerror(errno));
+		}
+
+		fd_hist = open(control->out_tmp,O_RDONLY);
+		if (fd_hist == -1) {
+			fatal("Failed to open history file %s\n", 
+			      control->out_tmp);
+		}
 	}
 
+
 	
-	read_magic(fd_in, fd_out, &expected_size);
-	runzip_fd(fd_in, fd_out, fd_hist, expected_size);	
+	read_magic(control->in_tmp?STDIN_FILENO:fd_in, fd_out, &expected_size);
+	runzip_fd(fd_in, fd_out, fd_hist, expected_size,control->out_tmp?1:0,control->in_tmp?1:0);
 	
 	if ((control->flags & FLAG_TEST_ONLY) == 0) {
 		if (close(fd_hist) != 0 ||
@@ -183,7 +249,13 @@
 
 	close(fd_in);
 
-	if ((control->flags & (FLAG_KEEP_FILES | FLAG_TEST_ONLY)) == 0) {
+
+	if(control->out_tmp)
+		unlink(control->out_tmp);
+
+	if(control->in_tmp)
+		unlink(control->in_tmp);
+	else if ((control->flags & (FLAG_KEEP_FILES | FLAG_TEST_ONLY)) == 0) {
 		if (unlink(control->infile) != 0) {
 			fatal("Failed to unlink %s: %s\n", 
 			      control->infile, strerror(errno));
@@ -199,6 +271,7 @@
 static void compress_file(struct rzip_control *control)
 {
 	int fd_in, fd_out;
+	off_t l;
 
 	if (strlen(control->suffix) <= strlen(control->infile) &&
 	    strcmp(control->suffix, control->infile + strlen(control->infile) - strlen(control->suffix)) == 0) {
@@ -218,36 +291,67 @@
 		strcat(control->outfile, control->suffix);
 	}
 
-	fd_in = open(control->infile,O_RDONLY);
-	if (fd_in == -1) {
-		fatal("Failed to open %s: %s\n", control->infile, strerror(errno));
+	if(control->in_tmp) {
+		fd_in = open(control->in_tmp,O_RDWR|O_CREAT|O_EXCL,0600);
+		if (fd_in == -1) {
+			fatal("Failed to open %s: %s\n", control->in_tmp, strerror(errno));
+		}
+
+	} else {
+		fd_in = open(control->infile,O_RDONLY);
+		if (fd_in == -1) {
+			fatal("Failed to open %s: %s\n", control->infile, strerror(errno));
+		}
 	}
 	
-	if (control->flags & FLAG_FORCE_REPLACE) {
-		fd_out = open(control->outfile,O_WRONLY|O_CREAT|O_TRUNC,0666);
+	if(control->out_tmp) {
+		fd_out = open(control->out_tmp,O_RDWR|O_CREAT|O_EXCL,0600);
+		if (fd_out == -1) {
+			fatal("Failed to open %s: %s\n", control->out_tmp, strerror(errno));
+		}
 	} else {
-		fd_out = open(control->outfile,O_WRONLY|O_CREAT|O_EXCL,0666);
+		if (control->flags & FLAG_FORCE_REPLACE) {
+			fd_out = open(control->outfile,O_WRONLY|O_CREAT|O_TRUNC,0666);
+		} else {
+			fd_out = open(control->outfile,O_WRONLY|O_CREAT|O_EXCL,0666);
+		}
+		if (fd_out == -1) {
+			fatal("Failed to create %s: %s\n", control->outfile, strerror(errno));
+		}
 	}
-	if (fd_out == -1) {
-		fatal("Failed to create %s: %s\n", control->outfile, strerror(errno));
+
+	if(!control->in_tmp && !control->out_tmp)
+		preserve_perms(control, fd_in, fd_out);
+
+	if(!control->in_tmp) {
+		write_magic(fd_in, fd_out);
+	} else {
+		write_magic(0, fd_out);
 	}
 
-	preserve_perms(control, fd_in, fd_out);
+	l = rzip_fd(control, fd_in, fd_out);
 
-	write_magic(fd_in, fd_out);
-	rzip_fd(control, fd_in, fd_out);
+	if(control->in_tmp && !control->out_tmp) {
+		update_magic(l, fd_out);
+	}
 
 	if (close(fd_in) != 0 ||
 	    close(fd_out) != 0) {
 		fatal("Failed to close files\n");
 	}
 
-	if ((control->flags & FLAG_KEEP_FILES) == 0) {
+	if(control->out_tmp)
+		unlink (control->out_tmp);
+
+	if(control->in_tmp) {
+		unlink (control->in_tmp);
+	} else if ((control->flags & FLAG_KEEP_FILES) == 0) {
 		if (unlink(control->infile) != 0) {
 			fatal("Failed to unlink %s: %s\n", control->infile, strerror(errno));
 		}
 	}
 
+
 	free(control->outfile);
 }
 
@@ -267,7 +371,7 @@
 		control.flags |= FLAG_DECOMPRESS;
 	}
 
-	while ((c = getopt(argc, argv, "h0123456789dS:tVvkfPo:L:")) != -1) {
+	while ((c = getopt(argc, argv, "h0123456789dS:tVvkfPo:L:q:Q:")) != -1) {
 		if (isdigit(c)) {
 			control.compression_level = c - '0';
 			continue;
@@ -285,6 +389,13 @@
 		case 'o':
 			control.outname = optarg;
 			break;
+		case 'q':
+			control.in_tmp = optarg;
+			break;
+		case 'Q':
+			control.out_tmp = optarg;
+			control.flags |= FLAG_KEEP_FILES;
+			break;
 		case 't':
 			fatal("integrity checking currently not implemented\n");
 			control.flags |= FLAG_TEST_ONLY;
@@ -321,13 +432,35 @@
 		fatal("Cannot specify output filename with more than 1 file\n");
 	}
 	
+	if (!control.outname && control.in_tmp && ! control.out_tmp) {
+		fatal("Must specify output filename when reading from stdin\n");
+	}
+	
+	if (control.outname && control.out_tmp) {
+		fatal("Must not specify output filename when writing to stdout\n");
+	}
+	
+	if (control.in_tmp && argc > 0) {
+		fatal("Cannot specify -q with input files\n");
+	}
+
+	if (!(control.flags & FLAG_DECOMPRESS) && control.out_tmp && control.in_tmp) {
+		fprintf(stderr,"WARNING: file produced is not usable with plain rzip\n");
+	}
+
+	if (control.in_tmp)
+		argc=1;
+
 	if (argc < 1) {
 		usage();
 		exit(1);
 	}
 
 	for (i=0;i<argc;i++) {
-		control.infile = argv[i];
+		if (control.in_tmp)
+			control.infile = "-";
+		else
+			control.infile = argv[i];
 
 		if (control.flags & (FLAG_DECOMPRESS | FLAG_TEST_ONLY)) {
 			decompress_file(&control);
diff -r -u rzip-2.1.orig/runzip.c rzip-2.1/runzip.c
--- rzip-2.1.orig/runzip.c	2009-10-12 14:02:23.000000000 +0200
+++ rzip-2.1/runzip.c	2009-10-12 14:02:23.000000000 +0200
@@ -63,9 +63,10 @@
 }
 
 
-static int unzip_literal(void *ss, int len, int fd_out, uint32 *cksum)
+static int unzip_literal(void *ss, int len, int fd_out, uint32 *cksum, int out_is_pipe)
 {
 	uchar *buf;
+	ssize_t w,r;
 
 	buf = malloc(len);
 	if (!buf) {
@@ -76,6 +77,13 @@
 	if (write(fd_out, buf, len) != len) {
 		fatal("Failed to write literal buffer of size %d\n", len);
 	}
+	if (out_is_pipe) {
+		w=0;
+		while(w<len && (r=write(STDOUT_FILENO, buf+w, len-w))>0)
+			w+=r;
+		if(r<0)
+			fatal("Failed to write literal buffer of size %d\n", len);
+	}
 
 	*cksum = crc32_buffer(buf, len, *cksum);
 
@@ -83,12 +91,13 @@
 	return len;
 }
 
-static int unzip_match(void *ss, int len, int fd_out, int fd_hist, uint32 *cksum)
+static int unzip_match(void *ss, int len, int fd_out, int fd_hist, uint32 *cksum, int out_is_pipe)
 {
 	unsigned offset;
 	int n, total=0;
 	off_t cur_pos = lseek(fd_out, 0, SEEK_CUR);
 	offset = read_u32(ss, 0);
+	ssize_t w,r;
 
 	if (lseek(fd_hist, cur_pos-offset, SEEK_SET) == (off_t)-1) {
 		fatal("Seek failed by %d from %d on history file in unzip_match - %s\n", 
@@ -112,6 +121,13 @@
 			fatal("Failed to write %d bytes in unzip_match\n", n);
 		}
 
+		if (out_is_pipe) {
+			w=0;
+			while(w<n && (r=write(STDOUT_FILENO, buf+w, n-w))>0)
+				w+=r;
+			if(r<0)
+				fatal("Failed to write literal buffer of size %d\n", len);
+		}
 		*cksum = crc32_buffer(buf, n, *cksum);
 
 		len -= n;
@@ -126,7 +142,7 @@
 /* decompress a section of an open file. Call fatal() on error
    return the number of bytes that have been retrieved
  */
-static int runzip_chunk(int fd_in, int fd_out, int fd_hist)
+static int runzip_chunk(int fd_in, int fd_out, int fd_hist, int out_is_pipe, int in_is_pipe)
 {
 	uchar head;
 	int len;
@@ -135,29 +151,34 @@
 	off_t ofs;
 	int total = 0;
 	uint32 good_cksum, cksum = 0;
+	int eof;
 	
-	ofs = lseek(fd_in, 0, SEEK_CUR);
-	if (ofs == (off_t)-1) {
-		fatal("Failed to seek input file in runzip_fd\n");
-	}
+	if(!in_is_pipe) {
+		ofs = lseek(fd_in, 0, SEEK_CUR);
+		if (ofs == (off_t)-1) {
+			fatal("Failed to seek input file in runzip_fd\n");
+		}
 
-	if (fstat(fd_in, &st) != 0 || st.st_size-ofs == 0) {
-		return 0;
+		if (fstat(fd_in, &st) != 0 || st.st_size-ofs == 0) {
+			return 0;
+		}
 	}
 
-	ss = open_stream_in(fd_in, NUM_STREAMS);
+	ss = open_stream_in(fd_in, NUM_STREAMS, in_is_pipe, &eof);
 	if (!ss) {
+		if(eof)
+			return 0;
 		fatal(NULL);
 	}
 
 	while ((len = read_header(ss, &head)) || head) {
 		switch (head) {
 		case 0:
-			total += unzip_literal(ss, len, fd_out, &cksum);
+			total += unzip_literal(ss, len, fd_out, &cksum, out_is_pipe);
 			break;
 
 		default:
-			total += unzip_match(ss, len, fd_out, fd_hist, &cksum);
+			total += unzip_match(ss, len, fd_out, fd_hist, &cksum, out_is_pipe);
 			break;
 		}
 	}
@@ -171,17 +192,27 @@
 		fatal("Failed to close stream!\n");
 	}
 
+	if(out_is_pipe) {
+		if(lseek(fd_out,0,SEEK_SET)==-1 ||
+		   lseek(fd_hist,0,SEEK_SET)==-1 ||
+		   ftruncate(fd_out,0)==-1)
+			fatal("cannot truncate temporary file\n");
+	}
+
 	return total;
 }
 
 /* decompress a open file. Call fatal() on error
    return the number of bytes that have been retrieved
  */
-off_t runzip_fd(int fd_in, int fd_out, int fd_hist, off_t expected_size)
+off_t runzip_fd(int fd_in, int fd_out, int fd_hist, off_t expected_size, int out_is_pipe, int in_is_pipe)
 {
-	off_t total = 0;
-	while (total < expected_size) {
-		total += runzip_chunk(fd_in, fd_out, fd_hist);
+	off_t total = 0, l;
+	while (total < expected_size || expected_size==0) {
+		l = runzip_chunk(fd_in, fd_out, fd_hist, out_is_pipe, in_is_pipe);
+		total += l;
+		if( l == 0)
+			break;
 	}
 	return total;
 }
diff -r -u rzip-2.1.orig/rzip.c rzip-2.1/rzip.c
--- rzip-2.1.orig/rzip.c	2009-10-12 14:02:23.000000000 +0200
+++ rzip-2.1/rzip.c	2009-10-12 14:02:23.000000000 +0200
@@ -108,6 +108,27 @@
 	put_u8(ss, stream, (s>>24) & 0xFF);
 }
 
+static int tmp_in_chunk(int fd_in,int chunk)
+{
+	ssize_t r,w;
+	size_t l=0;
+	static char buf[64*1024];
+
+	while(chunk-l>0 && (r=read(STDIN_FILENO,buf,MIN(sizeof(buf),chunk-l)))>0) {
+		l+=r;
+		w=write(fd_in,buf,r);
+		if(w<0) 
+			fatal("cannot write to temporary file: %s\n",strerror(errno));
+		if(w!=r) 
+			fatal("partial write?!\n");
+	}
+	if(r<0) {
+		fatal("cannot read from stdin: %s\n",strerror(errno));
+	}
+	if(lseek(fd_in,0,SEEK_SET)==-1)
+		fatal("failed to seek");
+	return l;
+}
 
 static void put_header(void *ss, uchar head, int len)
 {
@@ -528,7 +549,7 @@
 /* compress a chunk of an open file. Assumes that the file is able to
    be mmap'd and is seekable */
 static void rzip_chunk(struct rzip_state *st, int fd_in, int fd_out, off_t offset, 
-		       double pct_base, double pct_multiple)
+		       double pct_base, double pct_multiple, int outpiped)
 {
 	uchar *buf;
 
@@ -537,7 +558,7 @@
 		fatal("Failed to map buffer in rzip_fd\n");
 	}
 
-	st->ss = open_stream_out(fd_out, NUM_STREAMS, st->level->bzip_level);
+	st->ss = open_stream_out(fd_out, NUM_STREAMS, st->level->bzip_level, outpiped);
 	if (!st->ss) {
 		fatal("Failed to open streams in rzip_fd\n");
 	}
@@ -550,11 +571,13 @@
 
 
 /* compress a whole file chunks at a time */
-void rzip_fd(struct rzip_control *control, int fd_in, int fd_out)
+off_t rzip_fd(struct rzip_control *control, int fd_in, int fd_out)
 {
 	struct stat s, s2;
-	off_t len;
+	int progress= control->flags & FLAG_SHOW_PROGRESS;
+	off_t len, total_len=0;
 	struct rzip_state *st;
+	int outpiped=control->out_tmp?1:0;
 
 	st = calloc(sizeof(*st), 1);
 	if (!st) {
@@ -568,10 +591,19 @@
 
 	init_hash_indexes(st);
 
-	if (fstat(fd_in, &s)) {
-		fatal("Failed to stat fd_in in rzip_fd - %s\n", strerror(errno));
+	if(!control->in_tmp) {
+		if (fstat(fd_in, &s)) {
+			fatal("Failed to stat fd_in in rzip_fd - %s\n", strerror(errno));
+		}
+		len = s.st_size;
+	} else {
+		len = 1;
+		control->flags &= ~FLAG_SHOW_PROGRESS;
+	}
+
+	if(!control->out_tmp) {
+		control->flags &= ~FLAG_SHOW_PROGRESS;
 	}
-	len = s.st_size;
 
 	while (len) {
 		int chunk;
@@ -582,19 +614,31 @@
 		} else {
 			chunk = control->compression_level * CHUNK_MULTIPLE;
 		}
-		
-		if (chunk > len) chunk = len;
 
-		pct_base = (100.0 * (s.st_size - len)) / s.st_size;
-		pct_multiple = ((double)chunk) / s.st_size;
+		if(control->in_tmp) {
+			len=chunk;
+			chunk=tmp_in_chunk(fd_in,chunk);
+			if(chunk<len)
+				len=0;
 
-		st->chunk_size = chunk;
+			st->chunk_size = chunk;
+
+			rzip_chunk(st, fd_in, fd_out, 0, pct_base, pct_multiple, outpiped);
+		} else {
+			if (chunk > len) chunk = len;
 
-		rzip_chunk(st, fd_in, fd_out, s.st_size - len, pct_base, pct_multiple);
-		len -= chunk;
+			pct_base = (100.0 * (s.st_size - len)) / s.st_size;
+			pct_multiple = ((double)chunk) / s.st_size;
+
+			st->chunk_size = chunk;
+
+			rzip_chunk(st, fd_in, fd_out, s.st_size - len, pct_base, pct_multiple, outpiped);
+			len -= chunk;
+		}
+
+		total_len+=chunk;
 	}
 
-	fstat(fd_out, &s2);
 
 	if (st->control->verbosity > 1) {
 		printf("matches=%d match_bytes=%d\n", 
@@ -608,14 +652,20 @@
 		       (1.0 + st->stats.match_bytes) / st->stats.literal_bytes);
 	}
 
-	if ((st->control->flags & FLAG_SHOW_PROGRESS) ||
-	    st->control->verbosity > 0) {
-		printf("%s - compression ratio %.3f\n", 
-		       st->control->infile, 1.0 * s.st_size / s2.st_size);
+	if(!control->out_tmp) {
+		fstat(fd_out, &s2);
+
+		if (progress ||
+		    st->control->verbosity > 0) {
+			printf("%s - compression ratio %.3f\n", 
+			       st->control->infile, 1.0 * total_len / s2.st_size);
+		}
 	}
 
 	if (st->hash_table) {
 		free(st->hash_table);
 	}
 	free(st);
+
+	return total_len;
 }
diff -r -u rzip-2.1.orig/rzip.h rzip-2.1/rzip.h
--- rzip-2.1.orig/rzip.h	2009-10-12 14:02:23.000000000 +0200
+++ rzip-2.1/rzip.h	2009-10-12 14:02:23.000000000 +0200
@@ -108,6 +108,7 @@
 
 struct rzip_control {
 	const char *infile, *outname;
+	const char *in_tmp, *out_tmp;
 	char *outfile;
 	const char *suffix;
 	unsigned compression_level;
@@ -117,10 +118,10 @@
 
 void fatal(const char *format, ...);
 void err_msg(const char *format, ...);
-off_t runzip_fd(int fd_in, int fd_out, int fd_hist, off_t expected_size);
-void rzip_fd(struct rzip_control *control, int fd_in, int fd_out);
-void *open_stream_out(int f, int n, int bzip_level);
-void *open_stream_in(int f, int n);
+off_t runzip_fd(int fd_in, int fd_out, int fd_hist, off_t expected_size, int out_is_pipe, int in_is_pipe);
+off_t rzip_fd(struct rzip_control *control, int fd_in, int fd_out);
+void *open_stream_out(int f, int n, int bzip_level, int piped);
+void *open_stream_in(int f, int n, int piped, int *eof);
 int write_stream(void *ss, int stream, uchar *p, int len);
 int read_stream(void *ss, int stream, uchar *p, int len);
 int close_stream_out(void *ss);
diff -r -u rzip-2.1.orig/stream.c rzip-2.1/stream.c
--- rzip-2.1.orig/stream.c	2009-10-12 14:02:23.000000000 +0200
+++ rzip-2.1/stream.c	2009-10-12 14:04:43.000000000 +0200
@@ -39,10 +39,12 @@
 	struct stream *s;
 	int num_streams;
 	int fd;
+	int piped;
 	u32 bufsize;
 	u32 cur_pos;
 	off_t initial_pos;
 	u32 total_read;
+	off_t piped_in;
 };
 
 /*
@@ -106,6 +108,74 @@
 	return 0;
 }
 
+#define GD_LEN 1
+#define GD_OFF 2
+#define GD_REL 3
+#define GD_LEN_EOF 4
+static int get_data(struct stream_info *ss, int len, off_t offset, int what)
+{
+	off_t currpos, endpos;
+	size_t toread;
+	ssize_t r,w;
+	static char buf[64*1024];
+	int eof_ok=0;
+
+	if(!ss->piped)
+		return 1;
+
+	currpos=lseek(ss->fd,0,SEEK_CUR);
+	if(currpos==-1)
+		fatal("cannot seek in temporary file\n");
+
+	switch(what) {
+		case GD_LEN_EOF:
+			eof_ok=1;
+			/* FALLTHROUGH */
+		case GD_LEN:
+			toread=len;
+			break;
+		case GD_OFF:
+			endpos=offset+len;
+			toread=(endpos>ss->piped_in)?endpos-ss->piped_in:0;
+			break;
+		case GD_REL:
+			endpos=currpos+len;
+			toread=(endpos>ss->piped_in)?endpos-ss->piped_in:0;
+			break;
+		default:
+			fatal("internal error\n");
+		
+	}
+
+	if(toread==0)
+		return;
+	
+	if(lseek(ss->fd,0,SEEK_END)==-1)
+		fatal("cannot seek in temporary file\n");
+
+	ss->piped_in+=toread;
+
+	while(toread>0 && (r=read(STDIN_FILENO,buf,MIN(sizeof(buf),toread)))>0) {
+		toread-=r;
+		w=write(ss->fd,buf,r);
+		if(w<0) 
+			fatal("cannot write to temporary file: %s\n",strerror(errno));
+		if(w!=r) 
+			fatal("partial write?!\n");
+	}
+	if(r==0) {
+		if(eof_ok && len==toread)
+			return 0;
+		fatal("premature EOF\n");
+	}
+	if(r<0) {
+		fatal("cannot read from stdin: %s\n",strerror(errno));
+	}
+	if(lseek(ss->fd,currpos,SEEK_SET)==-1)
+		fatal("failed to seek");
+	return 1;
+}
+
 /* write to a file, return 0 on success and -1 on failure */
 static int write_buf(int f, uchar *p, int len)
 {
@@ -206,7 +276,7 @@
 
 /* open a set of output streams, compressing with the given
    bzip level */
-void *open_stream_out(int f, int n, int bzip_level)
+void *open_stream_out(int f, int n, int bzip_level, int piped)
 {
 	int i;
 	struct stream_info *sinfo;
@@ -219,6 +289,7 @@
 	sinfo->num_streams = n;
 	sinfo->cur_pos = 0;
 	sinfo->fd = f;
+	sinfo->piped = piped;
 	if (bzip_level == 0) {
 		sinfo->bufsize = 100*1024;
 	} else {
@@ -258,11 +329,13 @@
 }
 
 /* prepare a set of n streams for reading on file descriptor f */
-void *open_stream_in(int f, int n)
+void *open_stream_in(int f, int n, int piped, int *eof)
 {
 	int i;
 	struct stream_info *sinfo;
 
+	*eof=0;
+
 	sinfo = calloc(sizeof(*sinfo), 1);
 	if (!sinfo) {
 		return NULL;
@@ -270,6 +343,8 @@
 
 	sinfo->num_streams = n;
 	sinfo->fd = f;
+	sinfo->piped = piped;
+	sinfo->piped_in = 0;
 	sinfo->initial_pos = lseek(f, 0, SEEK_CUR);
 
 	sinfo->s = (struct stream *)calloc(sizeof(sinfo->s[0]), n);
@@ -278,6 +353,12 @@
 		return NULL;
 	}
 
+	if(get_data(sinfo,n*13,0,GD_LEN_EOF)==0) {
+		free(sinfo);
+		*eof=1;
+		return NULL;
+	}
+
 	for (i=0;i<n;i++) {
 		uchar c;
 		u32 v1, v2;
@@ -300,6 +381,7 @@
 		    i == 0) {
 			err_msg("Enabling stream close workaround\n");
 			sinfo->initial_pos += 13;
+			get_data(sinfo,13,0,GD_LEN);
 			goto again;
 		}
 
@@ -377,6 +459,8 @@
 	uchar c_type;
 	u32 u_len, c_len;
 
+	get_data(sinfo, 13, sinfo->s[stream].last_head, GD_OFF);
+
 	if (seekto(sinfo, sinfo->s[stream].last_head) != 0) {
 		return -1;
 	}
@@ -396,6 +480,7 @@
 
 	sinfo->total_read += 13;
 
+	get_data(sinfo, c_len, 0, GD_REL);
 	if (sinfo->s[stream].buf) {
 		free(sinfo->s[stream].buf);
 	}
@@ -474,6 +559,8 @@
 /* flush and close down a stream. return -1 on failure */
 int close_stream_out(void *ss)
 {
+	ssize_t r,w,l;
+	static char buf[64*1024];
 	struct stream_info *sinfo = ss;
 	int i;
 	for (i=0;i<sinfo->num_streams;i++) {
@@ -483,6 +570,30 @@
 		}
 		if (sinfo->s[i].buf) free(sinfo->s[i].buf);
 	}
+
+	if(sinfo->piped) {
+		if(lseek(sinfo->fd,0,SEEK_SET)==-1)
+			fatal("cannot seek in temporary file\n");
+
+		while((r=read(sinfo->fd,buf,sizeof(buf)))>0) {
+			w=l=0;
+			while(r>0 && (w=write(STDOUT_FILENO,buf+l,r))>0) {
+				l+=w;
+				r-=w;
+			}
+			if(w<0) {
+				fatal("cannot write to stdout: %s\n",strerror(errno));
+			}
+		}
+		if(r<0) {
+			fatal("cannot read from temporary file: %s\n",strerror(errno));
+		}
+
+		if(lseek(sinfo->fd,0,SEEK_SET)==-1 ||
+		   ftruncate(sinfo->fd,0)==-1)
+			fatal("cannot truncate temporary file\n");
+	}
+
 	free(sinfo->s);
 	free(sinfo);
 	return 0;
@@ -502,6 +613,11 @@
 		if (sinfo->s[i].buf) free(sinfo->s[i].buf);
 	}
 
+	if(sinfo->piped) {
+		if(lseek(sinfo->fd,0,SEEK_SET)==-1 ||
+		   ftruncate(sinfo->fd,0)==-1)
+			fatal("cannot truncate temporary file\n");
+	}
 	free(sinfo->s);
 	free(sinfo);
 	return 0;
