[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[debian-knoppix] Better(?) create_compressed_fs and small guide.



Hi!

I re-wrote create_compressed_fs so it doesn't need to read the entire cd into 
memory anymore.  That way you don't need a gig of ram/swap to make the 
image:)  It works slightly different now, but the end result is the same.  It 
seems the image it makes is slightly different, but extracting it creates an 
identical iso to the old version, and mounting it shows the files inside to 
be identical.  I really don't know how it works...It just does :)

I also wrote up the method I use to remaster the cd, with the new way to use 
create_compressed_fs.

so...here you go:)

you can get newer versions of these files and a deb for cloop-utils here:

http://s.bouncybouncy.net/~justin/code/

-- 
-Justin
/* Creates a compressed image, given a file as an argument.
 * (c)1999 Paul `Rusty' Russell.  GPL.
 *
 * CHANGELOG:
 * * Sat Sep 29 2001 Klaus Knopper <knopper@knopper.net>
 * - changed compression to Z_BEST_COMPRESSION,
 * * Sat Jun 17 2000 Klaus Knopper <knopper@knopper.net>
 * - Support for reading file from stdin,
 * - Changed Preamble.
 * * Sat Jul 28 2001 Klaus Knopper <knopper@knopper.net>
 * - cleanup and gcc 2.96 / glibc checking
 */

#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "compressed_loop.h"
#include "zlib-1.1.4/zlib.h"




#define MAX_KMALLOC_SIZE 2L<<17

#define CLOOP_PREAMBLE "#!/bin/sh\n" "insmod cloop.o file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"

/* Now using the goto style because it is quicker to read */
int write_compressed_blocks(int in,int out, unsigned long
                          blocksize, unsigned long expblocks, unsigned long *numblocks)
{
  unsigned long i=0,last;
  
  unsigned long long total_uncompressed=0,total_compressed=0;
  unsigned long maxlen = blocksize + blocksize/1000 + 12;
  char *compressed, *uncompressed;
  
  off_t data_offset;

  u_int32_t tmp;
  int ret;


  data_offset=lseek(out,0,1)+(expblocks+1)*sizeof(u_int32_t);

  printf("%lu\n", data_offset);
  if((uncompressed=malloc(blocksize))==NULL)
    {
      fprintf(stderr, "*** Can't malloc(%ld).\n",blocksize);
      return -1;
    }

  if((compressed=malloc(maxlen))==NULL)
    {
      fprintf(stderr, "*** Can't malloc(%ld).\n",blocksize);
      goto free_uncompressed;
    }
  
  for(i=0,last=0; !last; i++)
    {
      int z_error;
      unsigned long total=0, len = maxlen;
      memset(compressed,0,len); memset(uncompressed,0,blocksize);
      while(total<blocksize) /* Read a complete block */
	{
	  ssize_t r=read(in, uncompressed+total, blocksize-total);
	  if(r<=0) { last=1; break; }
	  total+=r;
	}
      total_uncompressed += total;
      if (total != blocksize)
	{
	  last=1;
	  fprintf(stderr, "Partial read (%lu bytes of %lu), padding with zeros.\n",
		  total, blocksize);
	}
      /* BEST_COMPRESSION does not seem to improve compression at a blocksize */
      /* of 64k or less, but is significantly slower. KK.                     */
      if((z_error=compress2(compressed, &len, uncompressed, blocksize, Z_DEFAULT_COMPRESSION)) != Z_OK)
	{
	  fprintf(stderr, "*** Error %d compressing block %lu! (compressed=%p, len=%lu, uncompressed=%p, blocksize=%lu)\n", z_error, i, compressed,len,uncompressed,blocksize);
	  return -1;
	    }
      
      total_compressed+=len;
      /* Print status */
      fprintf(stderr, "Block# %5lu / %lu size %6lu -> %6lu [compression ratio %3lu%%, overall: %3Lu%%] %d%% done\n", i, expblocks-1, total, len, total>0?((len*100)/total):100,total_uncompressed>0?((total_compressed*100)/total_uncompressed):100, (int)(100*i/expblocks));
      
      tmp = htonl(data_offset);
      write(out, &tmp, sizeof(tmp));

	if((ret=pwrite(out, compressed, len,data_offset)) != len)
	{
	  perror("writing block");
	  return -1;
	}
	else
	  data_offset+=ret;

    } /* for */

  tmp = htonl(data_offset);
  write(out, &tmp, sizeof(tmp));
      

  goto free_compressed;
  
 free_compressed:
  free(compressed);
 free_uncompressed:
  free(uncompressed);
  
  *numblocks=i;
  return 0;
}

int main(int argc, char **argv)
{

 int in, out;
 unsigned long blocksize;
 struct cloop_head head;
 unsigned long numblocks, expblocks;
 unsigned long bytes_so_far;
 int retval;

 struct stat st;

 if (argc != 4 && argc !=5)
  {
   fprintf(stderr, "Usage: %s input output blocksize(bytes) [size].\n",argv[0]);
   fprintf(stderr, "Use '-' as filename for stdin.\n");
   fprintf(stderr, "When input is stdin you must specify the filesize, try:\n\
echo $(($(mkisofs -R -l  -print-size -quiet /path/name)*2048))\n");
   return 1;
  }

 blocksize = atoi(argv[3]);
 if (blocksize == 0 || blocksize % 512 != 0)
  {
   fprintf(stderr, "*** Blocksize must be a multiple of 512.\n");
   return 1;
  }

 if (blocksize > MAX_KMALLOC_SIZE)
  {
   fprintf(stderr, "WARNING: Blocksize %lu may be too big for a kmalloc() (%lu max).\n",blocksize,MAX_KMALLOC_SIZE);
   sleep(2);
  }

 if (sizeof(CLOOP_PREAMBLE) > CLOOP_HEADROOM)
  {
   fprintf(stderr, "*** Preamble (%u chars) > headroom (%u)\n",
			sizeof(CLOOP_PREAMBLE), CLOOP_HEADROOM);
   return 1;
  }
 
 if(strcmp(argv[1],"-")==0){
   in=dup(fileno(stdin));
   if(argc!=5){
     fprintf(stderr, "Usage: %s input output blocksize(bytes) [size].\n",argv[0]);
     fprintf(stderr, "When input is stdin you must specify the filesize, try:\n\
echo $(($(mkisofs -R -l  -print-size -quiet /path/name)*2048))\n");
     return 1;
   }
   expblocks=1+atol(argv[4])/blocksize;
 }
 else {
     in=open(argv[1], O_RDONLY);
     fstat(in, &st);
     expblocks=1+st.st_size/blocksize;
 }
 if (in < 0)
  {
   perror("Opening input");
   return 1;
  }

 
 out=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC, 0644);
 
 if(out < 0)
   {
     perror("Opening output data");
     return 1;
   }



 memcpy(head.preamble, CLOOP_PREAMBLE, sizeof(CLOOP_PREAMBLE));
 head.block_size = htonl(blocksize);
 head.num_blocks = htonl(expblocks);

 fprintf(stderr, "Block size %lu, number of blocks %lu.\n",
         blocksize, expblocks);

 //fprintf(stderr,"%lu and %lu\n",numblocks,expblocks);

 bytes_so_far = sizeof(head) + sizeof(u_int32_t) * (expblocks + 1);
 if(bytes_so_far > MAX_KMALLOC_SIZE)
  {
   fprintf(stderr, "\nWARNING: cloop block index may not fit into a kmalloc()\n*** (%lu bytes max, current %lu)\n\n", MAX_KMALLOC_SIZE, bytes_so_far);
   sleep(2);
  }

 /* Write out head... */
 write(out, &head, sizeof(head));
 fprintf(stderr, "offset is %lu\n",lseek(out,0,1));

 retval = write_compressed_blocks(in, out, blocksize, expblocks, &numblocks);
 if(retval<0)
   fprintf(stderr,"Something went wrong....\n");

 close(in);
 close(out); 

 //fprintf(stderr, "offset is %lu\n",lseek(out,0,1));
 //fprintf(stderr, "would have guessed it to be %lu\n",sizeof(head)+(expblocks+1)*sizeof(u_int32_t));


 fprintf(stderr,"Done.\n");


 return 0;
}
get knoppix iso

extract it completely 
# mkdir temp
# mount -o loop whatever.iso temp
# cp -a temp KNOPPIX_cd
# umount temp

If you have cloop if your kernel you can do these next steps differently,
otherwise you have to use extract_compressed_fs like so:

# extract_compressed_fs KNOPPIX_cd/KNOPPIX/KNOPPIX >temp.iso
# mv OR rm KNOPPIX_cd/KNOPPIX/KNOPPIX
# mount -o loop temp.iso temp
# cp -a temp KNOPPIX_filesystem
# umount temp
# rm temp.iso
# rmdir temp

modify
# chroot KNOPPIX_filesystem
# have fun :)
# exit( from the chroot )

make cd 
NOTE!!!!!
get http://s.bouncybouncy.net/~justin/code/cloop-utils_0.66-1_i386.deb
or http://s.bouncybouncy.net/~justin/code/create_compressed_fs.c if you know
what to do with it

# DIR=KNOPPIX_filesystem

# filesize=$(($(mkisofs -R -l  -print-size -quiet $DIR)*2048))

# mkisofs -R -l -V "KNOPPIX iso9660 filesystem" -hide-rr-moved -v $DIR | \
  create_compressed_fs - KNOPPIX_cd/KNOPPIX/KNOPPIX 65536 $filesize

# mkisofs -l -r -J -V "KNOPPIX-yourname" -hide-rr-moved -v -b\
  KNOPPIX/boot-en.img  -c KNOPPIX/boot.cat -o knoppix_yourname.iso KNOPPIX_cd

# cdrecord -v knoppix_yourname.iso

Reply to: