archive_write_set_format_cpio_newc.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*-
  2. * Copyright (c) 2003-2007 Tim Kientzle
  3. * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "archive_platform.h"
  27. __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_cpio_newc.c,v 1.4 2008/03/15 11:04:45 kientzle Exp $");
  28. #ifdef HAVE_ERRNO_H
  29. #include <errno.h>
  30. #endif
  31. #include <stdio.h>
  32. #ifdef HAVE_STDLIB_H
  33. #include <stdlib.h>
  34. #endif
  35. #ifdef HAVE_STRING_H
  36. #include <string.h>
  37. #endif
  38. #include "archive.h"
  39. #include "archive_entry.h"
  40. #include "archive_private.h"
  41. #include "archive_write_private.h"
  42. static ssize_t archive_write_newc_data(struct archive_write *,
  43. const void *buff, size_t s);
  44. static int archive_write_newc_finish(struct archive_write *);
  45. static int archive_write_newc_destroy(struct archive_write *);
  46. static int archive_write_newc_finish_entry(struct archive_write *);
  47. static int archive_write_newc_header(struct archive_write *,
  48. struct archive_entry *);
  49. static int format_hex(int64_t, void *, int);
  50. static int64_t format_hex_recursive(int64_t, char *, int);
  51. struct cpio {
  52. uint64_t entry_bytes_remaining;
  53. int padding;
  54. };
  55. struct cpio_header_newc {
  56. char c_magic[6];
  57. char c_ino[8];
  58. char c_mode[8];
  59. char c_uid[8];
  60. char c_gid[8];
  61. char c_nlink[8];
  62. char c_mtime[8];
  63. char c_filesize[8];
  64. char c_devmajor[8];
  65. char c_devminor[8];
  66. char c_rdevmajor[8];
  67. char c_rdevminor[8];
  68. char c_namesize[8];
  69. char c_checksum[8];
  70. };
  71. /* Logic trick: difference between 'n' and next multiple of 4 */
  72. #define PAD4(n) (3 & (1 + ~(n)))
  73. /*
  74. * Set output format to 'cpio' format.
  75. */
  76. int
  77. archive_write_set_format_cpio_newc(struct archive *_a)
  78. {
  79. struct archive_write *a = (struct archive_write *)_a;
  80. struct cpio *cpio;
  81. /* If someone else was already registered, unregister them. */
  82. if (a->format_destroy != NULL)
  83. (a->format_destroy)(a);
  84. cpio = (struct cpio *)malloc(sizeof(*cpio));
  85. if (cpio == NULL) {
  86. archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
  87. return (ARCHIVE_FATAL);
  88. }
  89. memset(cpio, 0, sizeof(*cpio));
  90. a->format_data = cpio;
  91. a->pad_uncompressed = 1;
  92. a->format_name = "cpio";
  93. a->format_write_header = archive_write_newc_header;
  94. a->format_write_data = archive_write_newc_data;
  95. a->format_finish_entry = archive_write_newc_finish_entry;
  96. a->format_finish = archive_write_newc_finish;
  97. a->format_destroy = archive_write_newc_destroy;
  98. a->archive.archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
  99. a->archive.archive_format_name = "SVR4 cpio nocrc";
  100. return (ARCHIVE_OK);
  101. }
  102. static int
  103. archive_write_newc_header(struct archive_write *a, struct archive_entry *entry)
  104. {
  105. struct cpio *cpio;
  106. const char *p, *path;
  107. int pathlength, ret;
  108. struct cpio_header_newc h;
  109. int pad;
  110. cpio = (struct cpio *)a->format_data;
  111. ret = 0;
  112. path = archive_entry_pathname(entry);
  113. pathlength = strlen(path) + 1; /* Include trailing null. */
  114. memset(&h, 0, sizeof(h));
  115. format_hex(0x070701, &h.c_magic, sizeof(h.c_magic));
  116. format_hex(archive_entry_devmajor(entry), &h.c_devmajor, sizeof(h.c_devmajor));
  117. format_hex(archive_entry_devminor(entry), &h.c_devminor, sizeof(h.c_devminor));
  118. if (archive_entry_ino64(entry) > 0xffffffff) {
  119. archive_set_error(&a->archive, ERANGE, "large inode number truncated");
  120. ret = ARCHIVE_WARN;
  121. }
  122. format_hex(archive_entry_ino64(entry) & 0xffffffff, &h.c_ino, sizeof(h.c_ino));
  123. format_hex(archive_entry_mode(entry), &h.c_mode, sizeof(h.c_mode));
  124. format_hex(archive_entry_uid(entry), &h.c_uid, sizeof(h.c_uid));
  125. format_hex(archive_entry_gid(entry), &h.c_gid, sizeof(h.c_gid));
  126. format_hex(archive_entry_nlink(entry), &h.c_nlink, sizeof(h.c_nlink));
  127. if (archive_entry_filetype(entry) == AE_IFBLK
  128. || archive_entry_filetype(entry) == AE_IFCHR) {
  129. format_hex(archive_entry_rdevmajor(entry), &h.c_rdevmajor, sizeof(h.c_rdevmajor));
  130. format_hex(archive_entry_rdevminor(entry), &h.c_rdevminor, sizeof(h.c_rdevminor));
  131. } else {
  132. format_hex(0, &h.c_rdevmajor, sizeof(h.c_rdevmajor));
  133. format_hex(0, &h.c_rdevminor, sizeof(h.c_rdevminor));
  134. }
  135. format_hex(archive_entry_mtime(entry), &h.c_mtime, sizeof(h.c_mtime));
  136. format_hex(pathlength, &h.c_namesize, sizeof(h.c_namesize));
  137. format_hex(0, &h.c_checksum, sizeof(h.c_checksum));
  138. /* Non-regular files don't store bodies. */
  139. if (archive_entry_filetype(entry) != AE_IFREG)
  140. archive_entry_set_size(entry, 0);
  141. /* Symlinks get the link written as the body of the entry. */
  142. p = archive_entry_symlink(entry);
  143. if (p != NULL && *p != '\0')
  144. format_hex(strlen(p), &h.c_filesize, sizeof(h.c_filesize));
  145. else
  146. format_hex(archive_entry_size(entry),
  147. &h.c_filesize, sizeof(h.c_filesize));
  148. ret = (a->compressor.write)(a, &h, sizeof(h));
  149. if (ret != ARCHIVE_OK)
  150. return (ARCHIVE_FATAL);
  151. /* Pad pathname to even length. */
  152. ret = (a->compressor.write)(a, path, pathlength);
  153. if (ret != ARCHIVE_OK)
  154. return (ARCHIVE_FATAL);
  155. pad = PAD4(pathlength + sizeof(struct cpio_header_newc));
  156. if (pad)
  157. ret = (a->compressor.write)(a, "\0\0\0", pad);
  158. if (ret != ARCHIVE_OK)
  159. return (ARCHIVE_FATAL);
  160. cpio->entry_bytes_remaining = archive_entry_size(entry);
  161. cpio->padding = PAD4(cpio->entry_bytes_remaining);
  162. /* Write the symlink now. */
  163. if (p != NULL && *p != '\0') {
  164. ret = (a->compressor.write)(a, p, strlen(p));
  165. if (ret != ARCHIVE_OK)
  166. return (ARCHIVE_FATAL);
  167. pad = PAD4(strlen(p));
  168. ret = (a->compressor.write)(a, "\0\0\0", pad);
  169. }
  170. return (ret);
  171. }
  172. static ssize_t
  173. archive_write_newc_data(struct archive_write *a, const void *buff, size_t s)
  174. {
  175. struct cpio *cpio;
  176. int ret;
  177. cpio = (struct cpio *)a->format_data;
  178. if (s > cpio->entry_bytes_remaining)
  179. s = cpio->entry_bytes_remaining;
  180. ret = (a->compressor.write)(a, buff, s);
  181. cpio->entry_bytes_remaining -= s;
  182. if (ret >= 0)
  183. return (s);
  184. else
  185. return (ret);
  186. }
  187. /*
  188. * Format a number into the specified field.
  189. */
  190. static int
  191. format_hex(int64_t v, void *p, int digits)
  192. {
  193. int64_t max;
  194. int ret;
  195. max = (((int64_t)1) << (digits * 4)) - 1;
  196. if (v >= 0 && v <= max) {
  197. format_hex_recursive(v, (char *)p, digits);
  198. ret = 0;
  199. } else {
  200. format_hex_recursive(max, (char *)p, digits);
  201. ret = -1;
  202. }
  203. return (ret);
  204. }
  205. static int64_t
  206. format_hex_recursive(int64_t v, char *p, int s)
  207. {
  208. if (s == 0)
  209. return (v);
  210. v = format_hex_recursive(v, p+1, s-1);
  211. *p = "0123456789abcdef"[v & 0xf];
  212. return (v >>= 4);
  213. }
  214. static int
  215. archive_write_newc_finish(struct archive_write *a)
  216. {
  217. struct cpio *cpio;
  218. int er;
  219. struct archive_entry *trailer;
  220. cpio = (struct cpio *)a->format_data;
  221. trailer = archive_entry_new();
  222. archive_entry_set_nlink(trailer, 1);
  223. archive_entry_set_pathname(trailer, "TRAILER!!!");
  224. er = archive_write_newc_header(a, trailer);
  225. archive_entry_free(trailer);
  226. return (er);
  227. }
  228. static int
  229. archive_write_newc_destroy(struct archive_write *a)
  230. {
  231. struct cpio *cpio;
  232. cpio = (struct cpio *)a->format_data;
  233. free(cpio);
  234. a->format_data = NULL;
  235. return (ARCHIVE_OK);
  236. }
  237. static int
  238. archive_write_newc_finish_entry(struct archive_write *a)
  239. {
  240. struct cpio *cpio;
  241. int to_write, ret;
  242. cpio = (struct cpio *)a->format_data;
  243. ret = ARCHIVE_OK;
  244. while (cpio->entry_bytes_remaining > 0) {
  245. to_write = cpio->entry_bytes_remaining < a->null_length ?
  246. cpio->entry_bytes_remaining : a->null_length;
  247. ret = (a->compressor.write)(a, a->nulls, to_write);
  248. if (ret != ARCHIVE_OK)
  249. return (ret);
  250. cpio->entry_bytes_remaining -= to_write;
  251. }
  252. ret = (a->compressor.write)(a, a->nulls, cpio->padding);
  253. return (ret);
  254. }