unbflz.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. void
  5. usage(void)
  6. {
  7. fprint(2, "usage: unbflz [file]\n");
  8. exits("usage");
  9. }
  10. int
  11. Bgetint(Biobuf *b)
  12. {
  13. uchar p[4];
  14. if(Bread(b, p, 4) != 4)
  15. sysfatal("short read");
  16. return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
  17. }
  18. /*
  19. * memmove but make sure overlap works properly.
  20. */
  21. void
  22. copy(uchar *dst, uchar *src, int n)
  23. {
  24. while(n-- > 0)
  25. *dst++ = *src++;
  26. }
  27. void
  28. main(int argc, char **argv)
  29. {
  30. Biobuf *b, bin;
  31. char buf[5];
  32. uchar *data;
  33. ulong *blk, l;
  34. int nblk, mblk;
  35. int sum;
  36. int i, j, length, m, n, o;
  37. ARGBEGIN{
  38. default:
  39. usage();
  40. }ARGEND
  41. switch(argc){
  42. default:
  43. usage();
  44. case 0:
  45. Binit(&bin, 0, OREAD);
  46. b = &bin;
  47. break;
  48. case 1:
  49. if((b = Bopen(argv[0], OREAD)) == nil)
  50. sysfatal("open %s: %r", argv[0]);
  51. break;
  52. }
  53. if(Bread(b, buf, 4) != 4)
  54. sysfatal("short read");
  55. if(memcmp(buf, "BLZ\n", 4) != 0)
  56. sysfatal("bad header");
  57. length = Bgetint(b);
  58. data = malloc(length);
  59. if(data == nil)
  60. sysfatal("out of memory");
  61. sum = 0;
  62. nblk = 0;
  63. mblk = 0;
  64. blk = nil;
  65. while(sum < length){
  66. if(nblk>=mblk){
  67. mblk += 16384;
  68. blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
  69. if(blk == nil)
  70. sysfatal("out of memory");
  71. }
  72. l = Bgetint(b);
  73. blk[nblk++] = l;
  74. if(l&(1<<31))
  75. l &= ~(1<<31);
  76. else
  77. blk[nblk++] = Bgetint(b);
  78. sum += l;
  79. }
  80. if(sum != length)
  81. sysfatal("bad compressed data %d %d", sum, length);
  82. i = 0;
  83. j = 0;
  84. while(i < length){
  85. assert(j < nblk);
  86. n = blk[j++];
  87. if(n&(1<<31)){
  88. n &= ~(1<<31);
  89. if((m=Bread(b, data+i, n)) != n)
  90. sysfatal("short read %d %d", n, m);
  91. }else{
  92. o = blk[j++];
  93. copy(data+i, data+o, n);
  94. }
  95. i += n;
  96. }
  97. write(1, data, length);
  98. exits(nil);
  99. }