zlib.c 1.8 KB

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