/* This file is part of Ciso. Ciso is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Ciso is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright 2005 BOOSTER */ #include #include #include #include /* /usr(/local)/include/zlib.h */ #include #include "ciso.h" const char *fname_in,*fname_out; FILE *fin,*fout; z_stream z; uint32_t *index_buf = NULL; uint32_t *crc_buf = NULL; uint8_t *block_buf1 = NULL; uint8_t *block_buf2 = NULL; /**************************************************************************** compress ISO to CSO ****************************************************************************/ CISO_H ciso; int ciso_total_block; uint64_t check_file_size(FILE *fp) { uint64_t pos; if( fseek(fp,0,SEEK_END) < 0) return -1; pos = ftell(fp); if(pos==-1) return pos; /* init ciso header */ memset(&ciso,0,sizeof(ciso)); ciso.magic[0] = 'C'; ciso.magic[1] = 'I'; ciso.magic[2] = 'S'; ciso.magic[3] = 'O'; ciso.ver = 0x01; ciso.block_size = 0x800; /* ISO9660 one of sector */ ciso.total_bytes = pos; #if 0 /* align >0 has bug */ for(ciso.align = 0 ; (ciso.total_bytes >> ciso.align) >0x80000000LL ; ciso.align++); #endif ciso_total_block = pos / ciso.block_size ; fseek(fp,0,SEEK_SET); return pos; } /**************************************************************************** decompress CSO to ISO ****************************************************************************/ int decomp_ciso(void) { uint64_t file_size; uint32_t index , index2; uint64_t read_pos , read_size; int total_sectors; int index_size; int block; unsigned char buf4[4]; int cmp_size; int status; int percent_period; int percent_cnt; int plain; /* read header */ if( fread(&ciso, 1, sizeof(ciso), fin) != sizeof(ciso) ) { printf("file read error\n"); return 1; } /* check header */ if( ciso.magic[0] != 'C' || ciso.magic[1] != 'I' || ciso.magic[2] != 'S' || ciso.magic[3] != 'O' || ciso.block_size ==0 || ciso.total_bytes == 0 ) { printf("ciso file format error\n"); return 1; } ciso_total_block = ciso.total_bytes / ciso.block_size; /* allocate index block */ index_size = (ciso_total_block + 1 ) * sizeof(uint32_t); index_buf = malloc(index_size); block_buf1 = malloc(ciso.block_size); block_buf2 = malloc(ciso.block_size*2); if( !index_buf || !block_buf1 || !block_buf2 ) { printf("Can't allocate memory\n"); return 1; } memset(index_buf,0,index_size); /* read index block */ if( fread(index_buf, 1, index_size, fin) != index_size ) { printf("file read error\n"); return 1; } /* show info */ printf("Decompress '%s' to '%s'\n",fname_in,fname_out); printf("Total File Size %lld bytes\n",ciso.total_bytes); printf("block size %d bytes\n",ciso.block_size); printf("total blocks %d blocks\n",ciso_total_block); printf("index align %d\n",1<>(ciso.align); /* read buffer */ z.next_out = block_buf2; z.avail_out = ciso.block_size*2; z.next_in = block_buf1; z.avail_in = fread(block_buf1, 1, ciso.block_size , fin); if(z.avail_in != ciso.block_size) { printf("block=%d : read error\n",block); return 1; } /* compress block status = deflate(&z, Z_FULL_FLUSH);*/ status = deflate(&z, Z_FINISH); if (status != Z_STREAM_END) /* if (status != Z_OK) */ { printf("block %d:deflate : %s[%d]\n", block,(z.msg) ? z.msg : "error",status); return 1; } cmp_size = ciso.block_size*2 - z.avail_out; /* choise plain / compress */ if(cmp_size >= ciso.block_size) { cmp_size = ciso.block_size; memcpy(block_buf2,block_buf1,cmp_size); /* plain block mark */ index_buf[block] |= 0x80000000; } /* write compressed block */ if(fwrite(block_buf2, 1,cmp_size , fout) != cmp_size) { printf("block %d : Write error\n",block); return 1; } /* mark next index */ write_pos += cmp_size; /* term zlib */ if (deflateEnd(&z) != Z_OK) { printf("deflateEnd : %s\n", (z.msg) ? z.msg : "error"); return 1; } } /* last position (total size)*/ index_buf[block] = write_pos>>(ciso.align); /* write header & index block */ fseek(fout,sizeof(ciso),SEEK_SET); fwrite(index_buf,1,index_size,fout); printf("ciso compress completed , total size = %8d bytes , rate %d%%\n" ,(int)write_pos,(int)(write_pos*100/ciso.total_bytes)); return 0; } /**************************************************************************** main ****************************************************************************/ int main(int argc, char *argv[]) { int level; int result; fprintf(stderr, "Compressed ISO9660 converter Ver.1.02 by BOOSTER\n"); if (argc != 4) { printf("Usage: ciso level infile outfile\n"); printf(" level: 1-9 compress ISO to CSO (1=fast/large - 9=small/slow\n"); printf(" 0 decompress CSO to ISO\n"); return 0; } level = argv[1][0] - '0'; if(level < 0 || level > 9) { printf("Unknown mode: %c\n", argv[1][0]); return 1; } fname_in = argv[2]; fname_out = argv[3]; if ((fin = fopen(fname_in, "rb")) == NULL) { printf("Can't open %s\n", fname_in); return 1; } if ((fout = fopen(fname_out, "wb")) == NULL) { printf("Can't create %s\n", fname_out); return 1; } if(level==0) result = decomp_ciso(); else result = comp_ciso(level); /* free memory */ if(index_buf) free(index_buf); if(crc_buf) free(crc_buf); if(block_buf1) free(block_buf1); if(block_buf2) free(block_buf2); /* close files */ fclose(fin); fclose(fout); return result; }