zlib.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <sys/stat.h>
  6. #include <sys/mman.h>
  7. #include <zlib.h>
  8. #include <linux/compiler.h>
  9. #include <unistd.h>
  10. #include "util/compress.h"
  11. #include "util/util.h"
  12. #include "util/debug.h"
  13. #define CHUNK_SIZE 16384
  14. int gzip_decompress_to_file(const char *input, int output_fd)
  15. {
  16. int ret = Z_STREAM_ERROR;
  17. int input_fd;
  18. void *ptr;
  19. int len;
  20. struct stat stbuf;
  21. unsigned char buf[CHUNK_SIZE];
  22. z_stream zs = {
  23. .zalloc = Z_NULL,
  24. .zfree = Z_NULL,
  25. .opaque = Z_NULL,
  26. .avail_in = 0,
  27. .next_in = Z_NULL,
  28. };
  29. input_fd = open(input, O_RDONLY);
  30. if (input_fd < 0)
  31. return -1;
  32. if (fstat(input_fd, &stbuf) < 0)
  33. goto out_close;
  34. ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
  35. if (ptr == MAP_FAILED)
  36. goto out_close;
  37. if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
  38. goto out_unmap;
  39. zs.next_in = ptr;
  40. zs.avail_in = stbuf.st_size;
  41. do {
  42. zs.next_out = buf;
  43. zs.avail_out = CHUNK_SIZE;
  44. ret = inflate(&zs, Z_NO_FLUSH);
  45. switch (ret) {
  46. case Z_NEED_DICT:
  47. ret = Z_DATA_ERROR;
  48. /* fall through */
  49. case Z_DATA_ERROR:
  50. case Z_MEM_ERROR:
  51. goto out;
  52. default:
  53. break;
  54. }
  55. len = CHUNK_SIZE - zs.avail_out;
  56. if (writen(output_fd, buf, len) != len) {
  57. ret = Z_DATA_ERROR;
  58. goto out;
  59. }
  60. } while (ret != Z_STREAM_END);
  61. out:
  62. inflateEnd(&zs);
  63. out_unmap:
  64. munmap(ptr, stbuf.st_size);
  65. out_close:
  66. close(input_fd);
  67. return ret == Z_STREAM_END ? 0 : -1;
  68. }
  69. bool gzip_is_compressed(const char *input)
  70. {
  71. int fd = open(input, O_RDONLY);
  72. const uint8_t magic[2] = { 0x1f, 0x8b };
  73. char buf[2] = { 0 };
  74. ssize_t rc;
  75. if (fd < 0)
  76. return -1;
  77. rc = read(fd, buf, sizeof(buf));
  78. close(fd);
  79. return rc == sizeof(buf) ?
  80. memcmp(buf, magic, sizeof(buf)) == 0 : false;
  81. }