--- cloop-2.01/create_compressed_fs.c.orig	2003-10-26 01:15:22.000000000 +0200
+++ cloop-2.01/create_compressed_fs.c	2005-03-17 12:53:08.000000000 +0100
@@ -34,6 +34,11 @@ struct cb_list
 	char data[0];
 };
 
+/* memory optimization when files are seekable */
+#include <sys/stat.h>
+struct stat st;
+char in_mem = 1;
+
 void free_cb_list(struct cb_list *cbl)
 {
  if(cbl->next) free_cb_list(cbl->next);
@@ -83,7 +88,7 @@ static struct cb_list *create_compressed
      fprintf(stderr, "*** Error %d compressing block %lu! (compressed=%p, len=%lu, uncompressed=%p, blocksize=%lu)\n", z_error, i, compressed,len,uncompressed,blocksize);
      goto error_free_cb_list;
     }
-   if((*cbp = malloc(sizeof(struct cb_list)+len))==NULL) /* get another block */
+   if((*cbp = malloc(sizeof(struct cb_list)+len*in_mem))==NULL) /* get another block */
     {
      fprintf(stderr, "*** Out of memory allocating block ptrs (virtual memory exhausted).\n");
      goto error_free_cb_list;
@@ -92,7 +97,12 @@ static struct cb_list *create_compressed
    /* Print status */
    fprintf(stderr, "Block# %5lu size %6lu -> %6lu [compression ratio %3lu%%, overall: %3Lu%%]\n", i, total, len, total>0?((len*100)/total):100,total_uncompressed>0?((total_compressed*100)/total_uncompressed):100);
    (*cbp)->size = len;
+   if (in_mem)
    memcpy((*cbp)->data, compressed, len);
+   else
+     {
+       write(1, compressed, len);
+     }
    (*cbp)->next=NULL;
    cbp=&((*cbp)->next);
   } /* for */
@@ -155,9 +165,31 @@ int main(int argc, char **argv)
    return 1;
   }
 
+ /* If we can stat the input and seek the output, there's no need
+  * to keep everything im memory
+  */
+ if (fstat(in, &st) == 0)
+   if (S_ISREG(st.st_mode) && st.st_size > 0 &&
+       lseek(STDOUT_FILENO, (off_t)0x1234, SEEK_SET) == (off_t)0x1234)
+     {
+       lseek(STDOUT_FILENO, CLOOP_HEADROOM +
+	     /* round upwards to blocksize, add 1 for the last block's
+	      * "end" mark and another for C arrays' [0..n-1] notion.
+	      */
+	     ((st.st_size+blocksize-1)/blocksize+2)*sizeof(loff_t),
+	     SEEK_SET);
+       in_mem = 0;
+     }
+
  compressed_blocks = create_compressed_blocks(in, blocksize, &numblocks);
 
  close(in);
+ if (!in_mem)
+   if (lseek(STDOUT_FILENO, 0, SEEK_SET) != 0)
+     {
+       perror("output rewind");
+       return 1;
+     }
 
  memset(head.preamble, 0, sizeof(head.preamble));
  memcpy(head.preamble, CLOOP_PREAMBLE, sizeof(CLOOP_PREAMBLE));
@@ -183,6 +215,9 @@ int main(int argc, char **argv)
    if(cbp) { bytes_so_far += cbp->size; cbp=cbp->next; }
   }
 
+ if (!in_mem)
+   return 0;
+
  /* Now write blocks and free them. */
  for (i = 0, cbp=compressed_blocks; cbp && i < numblocks; i++)
   {
