ar.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * ar.c - primitives for ar handling
  4. *
  5. * Copyright © 2010 Guillem Jover <guillem@debian.org>
  6. *
  7. * This is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <compat.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <time.h>
  25. #include <fcntl.h>
  26. #include <stdint.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <unistd.h>
  30. #include <dpkg/i18n.h>
  31. #include <dpkg/dpkg.h>
  32. #include <dpkg/fdio.h>
  33. #include <dpkg/buffer.h>
  34. #include <dpkg/ar.h>
  35. struct dpkg_ar *
  36. dpkg_ar_fdopen(const char *filename, int fd)
  37. {
  38. struct dpkg_ar *ar;
  39. struct stat st;
  40. if (fstat(fd, &st) != 0)
  41. ohshite(_("failed to fstat archive"));
  42. ar = m_malloc(sizeof(*ar));
  43. ar->name = filename;
  44. ar->mode = st.st_mode;
  45. ar->size = st.st_size;
  46. ar->time = st.st_mtime;
  47. ar->fd = fd;
  48. return ar;
  49. }
  50. struct dpkg_ar *
  51. dpkg_ar_open(const char *filename)
  52. {
  53. int fd;
  54. if (strcmp(filename, "-") == 0)
  55. fd = STDIN_FILENO;
  56. else
  57. fd = open(filename, O_RDONLY);
  58. if (fd < 0)
  59. ohshite(_("failed to read archive '%.255s'"), filename);
  60. return dpkg_ar_fdopen(filename, fd);
  61. }
  62. struct dpkg_ar *
  63. dpkg_ar_create(const char *filename, mode_t mode)
  64. {
  65. int fd;
  66. fd = creat(filename, mode);
  67. if (fd < 0)
  68. ohshite(_("unable to create '%.255s'"), filename);
  69. return dpkg_ar_fdopen(filename, fd);
  70. }
  71. void
  72. dpkg_ar_set_mtime(struct dpkg_ar *ar, time_t mtime)
  73. {
  74. ar->time = mtime;
  75. }
  76. void
  77. dpkg_ar_close(struct dpkg_ar *ar)
  78. {
  79. if (close(ar->fd))
  80. ohshite(_("unable to close file '%s'"), ar->name);
  81. free(ar);
  82. }
  83. static void
  84. dpkg_ar_member_init(struct dpkg_ar *ar, struct dpkg_ar_member *member,
  85. const char *name, off_t size)
  86. {
  87. member->name = name;
  88. member->size = size;
  89. member->time = ar->time;
  90. member->mode = 0100644;
  91. member->uid = 0;
  92. member->gid = 0;
  93. }
  94. void
  95. dpkg_ar_normalize_name(struct ar_hdr *arh)
  96. {
  97. char *name = arh->ar_name;
  98. int i;
  99. /* Remove trailing spaces from the member name. */
  100. for (i = sizeof(arh->ar_name) - 1; i >= 0 && name[i] == ' '; i--)
  101. name[i] = '\0';
  102. /* Remove optional slash terminator (on GNU-style archives). */
  103. if (i >= 0 && name[i] == '/')
  104. name[i] = '\0';
  105. }
  106. off_t
  107. dpkg_ar_member_get_size(struct dpkg_ar *ar, struct ar_hdr *arh)
  108. {
  109. const char *str = arh->ar_size;
  110. int len = sizeof(arh->ar_size);
  111. off_t size = 0;
  112. while (len && *str == ' ')
  113. str++, len--;
  114. while (len--) {
  115. if (*str == ' ')
  116. break;
  117. if (*str < '0' || *str > '9')
  118. ohshit(_("invalid character '%c' in archive '%.250s' "
  119. "member '%.16s' size"),
  120. *str, ar->name, arh->ar_name);
  121. size *= 10;
  122. size += *str++ - '0';
  123. }
  124. return size;
  125. }
  126. bool
  127. dpkg_ar_member_is_illegal(struct ar_hdr *arh)
  128. {
  129. return memcmp(arh->ar_fmag, ARFMAG, sizeof(arh->ar_fmag)) != 0;
  130. }
  131. void
  132. dpkg_ar_put_magic(struct dpkg_ar *ar)
  133. {
  134. if (fd_write(ar->fd, DPKG_AR_MAGIC, strlen(DPKG_AR_MAGIC)) < 0)
  135. ohshite(_("unable to write file '%s'"), ar->name);
  136. }
  137. void
  138. dpkg_ar_member_put_header(struct dpkg_ar *ar, struct dpkg_ar_member *member)
  139. {
  140. char header[sizeof(struct ar_hdr) + 1];
  141. int n;
  142. if (strlen(member->name) > 15)
  143. ohshit(_("ar member name '%s' length too long"), member->name);
  144. if (member->size > 9999999999L)
  145. ohshit(_("ar member size %jd too large"), member->size);
  146. n = sprintf(header, "%-16s%-12lu%-6lu%-6lu%-8lo%-10jd`\n",
  147. member->name, (unsigned long)member->time,
  148. (unsigned long)member->uid, (unsigned long)member->gid,
  149. (unsigned long)member->mode, (intmax_t)member->size);
  150. if (n != sizeof(struct ar_hdr))
  151. ohshit(_("generated corrupt ar header for '%s'"), ar->name);
  152. if (fd_write(ar->fd, header, n) < 0)
  153. ohshite(_("unable to write file '%s'"), ar->name);
  154. }
  155. void
  156. dpkg_ar_member_put_mem(struct dpkg_ar *ar,
  157. const char *name, const void *data, size_t size)
  158. {
  159. struct dpkg_ar_member member;
  160. dpkg_ar_member_init(ar, &member, name, size);
  161. dpkg_ar_member_put_header(ar, &member);
  162. /* Copy data contents. */
  163. if (fd_write(ar->fd, data, size) < 0)
  164. ohshite(_("unable to write file '%s'"), ar->name);
  165. if (size & 1)
  166. if (fd_write(ar->fd, "\n", 1) < 0)
  167. ohshite(_("unable to write file '%s'"), ar->name);
  168. }
  169. void
  170. dpkg_ar_member_put_file(struct dpkg_ar *ar,
  171. const char *name, int fd, off_t size)
  172. {
  173. struct dpkg_error err;
  174. struct dpkg_ar_member member;
  175. if (size <= 0) {
  176. struct stat st;
  177. if (fstat(fd, &st))
  178. ohshite(_("failed to fstat ar member file (%s)"), name);
  179. size = st.st_size;
  180. }
  181. dpkg_ar_member_init(ar, &member, name, size);
  182. dpkg_ar_member_put_header(ar, &member);
  183. /* Copy data contents. */
  184. if (fd_fd_copy(fd, ar->fd, size, &err) < 0)
  185. ohshit(_("cannot append ar member file (%s) to '%s': %s"),
  186. name, ar->name, err.str);
  187. if (size & 1)
  188. if (fd_write(ar->fd, "\n", 1) < 0)
  189. ohshite(_("unable to write file '%s'"), ar->name);
  190. }