unbflz.c 1.7 KB

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