ar.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 <stdint.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28. #include <dpkg/i18n.h>
  29. #include <dpkg/dpkg.h>
  30. #include <dpkg/fdio.h>
  31. #include <dpkg/buffer.h>
  32. #include <dpkg/ar.h>
  33. static void
  34. dpkg_ar_member_init(struct dpkg_ar_member *member, const char *name, off_t size)
  35. {
  36. member->name = name;
  37. member->size = size;
  38. member->time = time(NULL);
  39. member->mode = 0100644;
  40. member->uid = 0;
  41. member->gid = 0;
  42. }
  43. void
  44. dpkg_ar_normalize_name(struct ar_hdr *arh)
  45. {
  46. char *name = arh->ar_name;
  47. int i;
  48. /* Remove trailing spaces from the member name. */
  49. for (i = sizeof(arh->ar_name) - 1; i >= 0 && name[i] == ' '; i--)
  50. name[i] = '\0';
  51. /* Remove optional slash terminator (on GNU-style archives). */
  52. if (name[i] == '/')
  53. name[i] = '\0';
  54. }
  55. off_t
  56. dpkg_ar_member_get_size(const char *ar_name, struct ar_hdr *arh)
  57. {
  58. const char *str = arh->ar_size;
  59. int len = sizeof(arh->ar_size);
  60. off_t size = 0;
  61. while (len && *str == ' ')
  62. str++, len--;
  63. while (len--) {
  64. if (*str == ' ')
  65. break;
  66. if (*str < '0' || *str > '9')
  67. ohshit(_("invalid character '%c' in archive '%.250s' "
  68. "member '%.16s' size"),
  69. *str, ar_name, arh->ar_name);
  70. size *= 10;
  71. size += *str++ - '0';
  72. }
  73. return size;
  74. }
  75. bool
  76. dpkg_ar_member_is_illegal(struct ar_hdr *arh)
  77. {
  78. return memcmp(arh->ar_fmag, ARFMAG, sizeof(arh->ar_fmag)) != 0;
  79. }
  80. void
  81. dpkg_ar_put_magic(const char *ar_name, int ar_fd)
  82. {
  83. if (fd_write(ar_fd, DPKG_AR_MAGIC, strlen(DPKG_AR_MAGIC)) < 0)
  84. ohshite(_("unable to write file '%s'"), ar_name);
  85. }
  86. void
  87. dpkg_ar_member_put_header(const char *ar_name, int ar_fd,
  88. struct dpkg_ar_member *member)
  89. {
  90. char header[sizeof(struct ar_hdr) + 1];
  91. int n;
  92. if (strlen(member->name) > 15)
  93. ohshit(_("ar member name '%s' length too long"), member->name);
  94. if (member->size > 9999999999L)
  95. ohshit(_("ar member size %jd too large"), member->size);
  96. n = sprintf(header, "%-16s%-12lu%-6lu%-6lu%-8lo%-10jd`\n",
  97. member->name, (unsigned long)member->time,
  98. (unsigned long)member->uid, (unsigned long)member->gid,
  99. (unsigned long)member->mode, (intmax_t)member->size);
  100. if (n != sizeof(struct ar_hdr))
  101. ohshit(_("generated corrupt ar header for '%s'"), ar_name);
  102. if (fd_write(ar_fd, header, n) < 0)
  103. ohshite(_("unable to write file '%s'"), ar_name);
  104. }
  105. void
  106. dpkg_ar_member_put_mem(const char *ar_name, int ar_fd,
  107. const char *name, const void *data, size_t size)
  108. {
  109. struct dpkg_ar_member member;
  110. dpkg_ar_member_init(&member, name, size);
  111. dpkg_ar_member_put_header(ar_name, ar_fd, &member);
  112. /* Copy data contents. */
  113. if (fd_write(ar_fd, data, size) < 0)
  114. ohshite(_("unable to write file '%s'"), ar_name);
  115. if (size & 1)
  116. if (fd_write(ar_fd, "\n", 1) < 0)
  117. ohshite(_("unable to write file '%s'"), ar_name);
  118. }
  119. void
  120. dpkg_ar_member_put_file(const char *ar_name, int ar_fd,
  121. const char *name, int fd, off_t size)
  122. {
  123. struct dpkg_error err;
  124. struct dpkg_ar_member member;
  125. if (size <= 0) {
  126. struct stat st;
  127. if (fstat(fd, &st))
  128. ohshite(_("failed to fstat ar member file (%s)"), name);
  129. size = st.st_size;
  130. }
  131. dpkg_ar_member_init(&member, name, size);
  132. dpkg_ar_member_put_header(ar_name, ar_fd, &member);
  133. /* Copy data contents. */
  134. if (fd_fd_copy(fd, ar_fd, size, &err) < 0)
  135. ohshit(_("cannot append ar member file (%s) to '%s': %s"),
  136. name, ar_name, err.str);
  137. if (size & 1)
  138. if (fd_write(ar_fd, "\n", 1) < 0)
  139. ohshite(_("unable to write file '%s'"), ar_name);
  140. }