compress.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * compress routines:
  3. * zmagic() - returns 0 if not recognized, uncompresses and prints
  4. * information if recognized
  5. * uncompress(method, old, n, newch) - uncompress old into new,
  6. * using method, return sizeof new
  7. */
  8. #include "file.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #ifdef HAVE_UNISTD_H
  12. #include <unistd.h>
  13. #endif
  14. #include <string.h>
  15. #ifdef HAVE_SYS_WAIT_H
  16. #include <sys/wait.h>
  17. #endif
  18. #ifndef lint
  19. FILE_RCSID("@(#)$Id: compress.c,v 1.20 2001/07/22 21:04:15 christos Exp $")
  20. #endif
  21. static struct {
  22. const char *magic;
  23. int maglen;
  24. const char *const argv[3];
  25. int silent;
  26. } compr[] = {
  27. { "\037\235", 2, { "gzip", "-cdq", NULL }, 1 }, /* compressed */
  28. /* Uncompress can get stuck; so use gzip first if we have it
  29. * Idea from Damien Clark, thanks! */
  30. { "\037\235", 2, { "uncompress", "-c", NULL }, 1 }, /* compressed */
  31. { "\037\213", 2, { "gzip", "-cdq", NULL }, 1 }, /* gzipped */
  32. { "\037\236", 2, { "gzip", "-cdq", NULL }, 1 }, /* frozen */
  33. { "\037\240", 2, { "gzip", "-cdq", NULL }, 1 }, /* SCO LZH */
  34. /* the standard pack utilities do not accept standard input */
  35. { "\037\036", 2, { "gzip", "-cdq", NULL }, 0 }, /* packed */
  36. { "BZh", 3, { "bzip2", "-cd", NULL }, 1 }, /* bzip2-ed */
  37. };
  38. static int ncompr = sizeof(compr) / sizeof(compr[0]);
  39. static int uncompress __P((int, const unsigned char *, unsigned char **, int));
  40. static int swrite __P((int, const void *, size_t));
  41. static int sread __P((int, void *, size_t));
  42. int
  43. zmagic(buf, nbytes)
  44. unsigned char *buf;
  45. int nbytes;
  46. {
  47. unsigned char *newbuf;
  48. int newsize;
  49. int i;
  50. for (i = 0; i < ncompr; i++) {
  51. if (nbytes < compr[i].maglen)
  52. continue;
  53. if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 &&
  54. (newsize = uncompress(i, buf, &newbuf, nbytes)) != 0) {
  55. tryit(newbuf, newsize, 1);
  56. free(newbuf);
  57. printf(" (");
  58. tryit(buf, nbytes, 0);
  59. printf(")");
  60. return 1;
  61. }
  62. }
  63. if (i == ncompr)
  64. return 0;
  65. return 1;
  66. }
  67. /*
  68. * `safe' write for sockets and pipes.
  69. */
  70. static int
  71. swrite(fd, buf, n)
  72. int fd;
  73. const void *buf;
  74. size_t n;
  75. {
  76. int rv;
  77. size_t rn = n;
  78. do
  79. switch (rv = write(fd, buf, n)) {
  80. case -1:
  81. if (errno == EINTR)
  82. continue;
  83. return -1;
  84. default:
  85. n -= rv;
  86. buf = ((char *)buf) + rv;
  87. break;
  88. }
  89. while (n > 0);
  90. return rn;
  91. }
  92. /*
  93. * `safe' read for sockets and pipes.
  94. */
  95. static int
  96. sread(fd, buf, n)
  97. int fd;
  98. void *buf;
  99. size_t n;
  100. {
  101. int rv;
  102. size_t rn = n;
  103. do
  104. switch (rv = read(fd, buf, n)) {
  105. case -1:
  106. if (errno == EINTR)
  107. continue;
  108. return -1;
  109. default:
  110. n -= rv;
  111. buf = ((char *)buf) + rv;
  112. break;
  113. }
  114. while (n > 0);
  115. return rn;
  116. }
  117. static int
  118. uncompress(method, old, newch, n)
  119. int method;
  120. const unsigned char *old;
  121. unsigned char **newch;
  122. int n;
  123. {
  124. int fdin[2], fdout[2];
  125. if (pipe(fdin) == -1 || pipe(fdout) == -1) {
  126. error("cannot create pipe (%s).\n", strerror(errno));
  127. /*NOTREACHED*/
  128. }
  129. switch (fork()) {
  130. case 0: /* child */
  131. (void) close(0);
  132. (void) dup(fdin[0]);
  133. (void) close(fdin[0]);
  134. (void) close(fdin[1]);
  135. (void) close(1);
  136. (void) dup(fdout[1]);
  137. (void) close(fdout[0]);
  138. (void) close(fdout[1]);
  139. if (compr[method].silent)
  140. (void) close(2);
  141. execvp(compr[method].argv[0],
  142. (char *const *)compr[method].argv);
  143. exit(1);
  144. /*NOTREACHED*/
  145. case -1:
  146. error("could not fork (%s).\n", strerror(errno));
  147. /*NOTREACHED*/
  148. default: /* parent */
  149. (void) close(fdin[0]);
  150. (void) close(fdout[1]);
  151. if (swrite(fdin[1], old, n) != n) {
  152. n = 0;
  153. goto err;
  154. }
  155. (void) close(fdin[1]);
  156. fdin[1] = -1;
  157. if ((*newch = (unsigned char *) malloc(n)) == NULL) {
  158. n = 0;
  159. goto err;
  160. }
  161. if ((n = sread(fdout[0], *newch, n)) <= 0) {
  162. free(*newch);
  163. n = 0;
  164. goto err;
  165. }
  166. err:
  167. if (fdin[1] != -1)
  168. (void) close(fdin[1]);
  169. (void) close(fdout[0]);
  170. (void) wait(NULL);
  171. return n;
  172. }
  173. }