archive_write_set_format_v7tar.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /*-
  2. * Copyright (c) 2003-2007 Tim Kientzle
  3. * Copyright (c) 2011-2012 Michihiro NAKAJIMA
  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$");
  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_entry_locale.h"
  41. #include "archive_private.h"
  42. #include "archive_write_private.h"
  43. struct v7tar {
  44. uint64_t entry_bytes_remaining;
  45. uint64_t entry_padding;
  46. struct archive_string_conv *opt_sconv;
  47. struct archive_string_conv *sconv_default;
  48. int init_default_conversion;
  49. };
  50. /*
  51. * Define structure of POSIX 'v7tar' tar header.
  52. */
  53. #define V7TAR_name_offset 0
  54. #define V7TAR_name_size 100
  55. #define V7TAR_mode_offset 100
  56. #define V7TAR_mode_size 6
  57. #define V7TAR_mode_max_size 8
  58. #define V7TAR_uid_offset 108
  59. #define V7TAR_uid_size 6
  60. #define V7TAR_uid_max_size 8
  61. #define V7TAR_gid_offset 116
  62. #define V7TAR_gid_size 6
  63. #define V7TAR_gid_max_size 8
  64. #define V7TAR_size_offset 124
  65. #define V7TAR_size_size 11
  66. #define V7TAR_size_max_size 12
  67. #define V7TAR_mtime_offset 136
  68. #define V7TAR_mtime_size 11
  69. #define V7TAR_mtime_max_size 12
  70. #define V7TAR_checksum_offset 148
  71. #define V7TAR_checksum_size 8
  72. #define V7TAR_typeflag_offset 156
  73. #define V7TAR_typeflag_size 1
  74. #define V7TAR_linkname_offset 157
  75. #define V7TAR_linkname_size 100
  76. #define V7TAR_padding_offset 257
  77. #define V7TAR_padding_size 255
  78. /*
  79. * A filled-in copy of the header for initialization.
  80. */
  81. static const char template_header[] = {
  82. /* name: 100 bytes */
  83. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  84. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  85. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  86. 0,0,0,0,
  87. /* Mode, space-null termination: 8 bytes */
  88. '0','0','0','0','0','0', ' ','\0',
  89. /* uid, space-null termination: 8 bytes */
  90. '0','0','0','0','0','0', ' ','\0',
  91. /* gid, space-null termination: 8 bytes */
  92. '0','0','0','0','0','0', ' ','\0',
  93. /* size, space termination: 12 bytes */
  94. '0','0','0','0','0','0','0','0','0','0','0', ' ',
  95. /* mtime, space termination: 12 bytes */
  96. '0','0','0','0','0','0','0','0','0','0','0', ' ',
  97. /* Initial checksum value: 8 spaces */
  98. ' ',' ',' ',' ',' ',' ',' ',' ',
  99. /* Typeflag: 1 byte */
  100. 0,
  101. /* Linkname: 100 bytes */
  102. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  103. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  104. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  105. 0,0,0,0,
  106. /* Padding: 255 bytes */
  107. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  108. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  109. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  110. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  111. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  112. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  113. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  114. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0
  115. };
  116. static ssize_t archive_write_v7tar_data(struct archive_write *a, const void *buff,
  117. size_t s);
  118. static int archive_write_v7tar_free(struct archive_write *);
  119. static int archive_write_v7tar_close(struct archive_write *);
  120. static int archive_write_v7tar_finish_entry(struct archive_write *);
  121. static int archive_write_v7tar_header(struct archive_write *,
  122. struct archive_entry *entry);
  123. static int archive_write_v7tar_options(struct archive_write *,
  124. const char *, const char *);
  125. static int format_256(int64_t, char *, int);
  126. static int format_number(int64_t, char *, int size, int max, int strict);
  127. static int format_octal(int64_t, char *, int);
  128. static int format_header_v7tar(struct archive_write *, char h[512],
  129. struct archive_entry *, int, struct archive_string_conv *);
  130. /*
  131. * Set output format to 'v7tar' format.
  132. */
  133. int
  134. archive_write_set_format_v7tar(struct archive *_a)
  135. {
  136. struct archive_write *a = (struct archive_write *)_a;
  137. struct v7tar *v7tar;
  138. archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
  139. ARCHIVE_STATE_NEW, "archive_write_set_format_v7tar");
  140. /* If someone else was already registered, unregister them. */
  141. if (a->format_free != NULL)
  142. (a->format_free)(a);
  143. /* Basic internal sanity test. */
  144. if (sizeof(template_header) != 512) {
  145. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  146. "Internal: template_header wrong size: %zu should be 512",
  147. sizeof(template_header));
  148. return (ARCHIVE_FATAL);
  149. }
  150. v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar));
  151. if (v7tar == NULL) {
  152. archive_set_error(&a->archive, ENOMEM,
  153. "Can't allocate v7tar data");
  154. return (ARCHIVE_FATAL);
  155. }
  156. a->format_data = v7tar;
  157. a->format_name = "tar (non-POSIX)";
  158. a->format_options = archive_write_v7tar_options;
  159. a->format_write_header = archive_write_v7tar_header;
  160. a->format_write_data = archive_write_v7tar_data;
  161. a->format_close = archive_write_v7tar_close;
  162. a->format_free = archive_write_v7tar_free;
  163. a->format_finish_entry = archive_write_v7tar_finish_entry;
  164. a->archive.archive_format = ARCHIVE_FORMAT_TAR;
  165. a->archive.archive_format_name = "tar (non-POSIX)";
  166. return (ARCHIVE_OK);
  167. }
  168. static int
  169. archive_write_v7tar_options(struct archive_write *a, const char *key,
  170. const char *val)
  171. {
  172. struct v7tar *v7tar = (struct v7tar *)a->format_data;
  173. int ret = ARCHIVE_FAILED;
  174. if (strcmp(key, "hdrcharset") == 0) {
  175. if (val == NULL || val[0] == 0)
  176. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  177. "%s: hdrcharset option needs a character-set name",
  178. a->format_name);
  179. else {
  180. v7tar->opt_sconv = archive_string_conversion_to_charset(
  181. &a->archive, val, 0);
  182. if (v7tar->opt_sconv != NULL)
  183. ret = ARCHIVE_OK;
  184. else
  185. ret = ARCHIVE_FATAL;
  186. }
  187. return (ret);
  188. }
  189. /* Note: The "warn" return is just to inform the options
  190. * supervisor that we didn't handle it. It will generate
  191. * a suitable error if no one used this option. */
  192. return (ARCHIVE_WARN);
  193. }
  194. static int
  195. archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
  196. {
  197. char buff[512];
  198. int ret, ret2;
  199. struct v7tar *v7tar;
  200. struct archive_entry *entry_main;
  201. struct archive_string_conv *sconv;
  202. v7tar = (struct v7tar *)a->format_data;
  203. /* Setup default string conversion. */
  204. if (v7tar->opt_sconv == NULL) {
  205. if (!v7tar->init_default_conversion) {
  206. v7tar->sconv_default =
  207. archive_string_default_conversion_for_write(
  208. &(a->archive));
  209. v7tar->init_default_conversion = 1;
  210. }
  211. sconv = v7tar->sconv_default;
  212. } else
  213. sconv = v7tar->opt_sconv;
  214. /* Sanity check. */
  215. if (archive_entry_pathname(entry) == NULL) {
  216. archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
  217. "Can't record entry in tar file without pathname");
  218. return (ARCHIVE_FAILED);
  219. }
  220. /* Only regular files (not hardlinks) have data. */
  221. if (archive_entry_hardlink(entry) != NULL ||
  222. archive_entry_symlink(entry) != NULL ||
  223. !(archive_entry_filetype(entry) == AE_IFREG))
  224. archive_entry_set_size(entry, 0);
  225. if (AE_IFDIR == archive_entry_filetype(entry)) {
  226. const char *p;
  227. size_t path_length;
  228. /*
  229. * Ensure a trailing '/'. Modify the entry so
  230. * the client sees the change.
  231. */
  232. #if defined(_WIN32) && !defined(__CYGWIN__)
  233. const wchar_t *wp;
  234. wp = archive_entry_pathname_w(entry);
  235. if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
  236. struct archive_wstring ws;
  237. archive_string_init(&ws);
  238. path_length = wcslen(wp);
  239. if (archive_wstring_ensure(&ws,
  240. path_length + 2) == NULL) {
  241. archive_set_error(&a->archive, ENOMEM,
  242. "Can't allocate v7tar data");
  243. archive_wstring_free(&ws);
  244. return(ARCHIVE_FATAL);
  245. }
  246. /* Should we keep '\' ? */
  247. if (wp[path_length -1] == L'\\')
  248. path_length--;
  249. archive_wstrncpy(&ws, wp, path_length);
  250. archive_wstrappend_wchar(&ws, L'/');
  251. archive_entry_copy_pathname_w(entry, ws.s);
  252. archive_wstring_free(&ws);
  253. p = NULL;
  254. } else
  255. #endif
  256. p = archive_entry_pathname(entry);
  257. /*
  258. * On Windows, this is a backup operation just in
  259. * case getting WCS failed. On POSIX, this is a
  260. * normal operation.
  261. */
  262. if (p != NULL && p[strlen(p) - 1] != '/') {
  263. struct archive_string as;
  264. archive_string_init(&as);
  265. path_length = strlen(p);
  266. if (archive_string_ensure(&as,
  267. path_length + 2) == NULL) {
  268. archive_set_error(&a->archive, ENOMEM,
  269. "Can't allocate v7tar data");
  270. archive_string_free(&as);
  271. return(ARCHIVE_FATAL);
  272. }
  273. #if defined(_WIN32) && !defined(__CYGWIN__)
  274. /* NOTE: This might break the pathname
  275. * if the current code page is CP932 and
  276. * the pathname includes a character '\'
  277. * as a part of its multibyte pathname. */
  278. if (p[strlen(p) -1] == '\\')
  279. path_length--;
  280. else
  281. #endif
  282. archive_strncpy(&as, p, path_length);
  283. archive_strappend_char(&as, '/');
  284. archive_entry_copy_pathname(entry, as.s);
  285. archive_string_free(&as);
  286. }
  287. }
  288. #if defined(_WIN32) && !defined(__CYGWIN__)
  289. /* Make sure the path separators in pathname, hardlink and symlink
  290. * are all slash '/', not the Windows path separator '\'. */
  291. entry_main = __la_win_entry_in_posix_pathseparator(entry);
  292. if (entry_main == NULL) {
  293. archive_set_error(&a->archive, ENOMEM,
  294. "Can't allocate v7tar data");
  295. return(ARCHIVE_FATAL);
  296. }
  297. if (entry != entry_main)
  298. entry = entry_main;
  299. else
  300. entry_main = NULL;
  301. #else
  302. entry_main = NULL;
  303. #endif
  304. ret = format_header_v7tar(a, buff, entry, 1, sconv);
  305. if (ret < ARCHIVE_WARN) {
  306. if (entry_main)
  307. archive_entry_free(entry_main);
  308. return (ret);
  309. }
  310. ret2 = __archive_write_output(a, buff, 512);
  311. if (ret2 < ARCHIVE_WARN) {
  312. if (entry_main)
  313. archive_entry_free(entry_main);
  314. return (ret2);
  315. }
  316. if (ret2 < ret)
  317. ret = ret2;
  318. v7tar->entry_bytes_remaining = archive_entry_size(entry);
  319. v7tar->entry_padding = 0x1ff & (-(int64_t)v7tar->entry_bytes_remaining);
  320. if (entry_main)
  321. archive_entry_free(entry_main);
  322. return (ret);
  323. }
  324. /*
  325. * Format a basic 512-byte "v7tar" header.
  326. *
  327. * Returns -1 if format failed (due to field overflow).
  328. * Note that this always formats as much of the header as possible.
  329. * If "strict" is set to zero, it will extend numeric fields as
  330. * necessary (overwriting terminators or using base-256 extensions).
  331. *
  332. */
  333. static int
  334. format_header_v7tar(struct archive_write *a, char h[512],
  335. struct archive_entry *entry, int strict,
  336. struct archive_string_conv *sconv)
  337. {
  338. unsigned int checksum;
  339. int i, r, ret;
  340. size_t copy_length;
  341. const char *p, *pp;
  342. int mytartype;
  343. ret = 0;
  344. mytartype = -1;
  345. /*
  346. * The "template header" already includes the "v7tar"
  347. * signature, various end-of-field markers and other required
  348. * elements.
  349. */
  350. memcpy(h, &template_header, 512);
  351. /*
  352. * Because the block is already null-filled, and strings
  353. * are allowed to exactly fill their destination (without null),
  354. * I use memcpy(dest, src, strlen()) here a lot to copy strings.
  355. */
  356. r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
  357. if (r != 0) {
  358. if (errno == ENOMEM) {
  359. archive_set_error(&a->archive, ENOMEM,
  360. "Can't allocate memory for Pathname");
  361. return (ARCHIVE_FATAL);
  362. }
  363. archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
  364. "Can't translate pathname '%s' to %s",
  365. pp, archive_string_conversion_charset_name(sconv));
  366. ret = ARCHIVE_WARN;
  367. }
  368. if (strict && copy_length < V7TAR_name_size)
  369. memcpy(h + V7TAR_name_offset, pp, copy_length);
  370. else if (!strict && copy_length <= V7TAR_name_size)
  371. memcpy(h + V7TAR_name_offset, pp, copy_length);
  372. else {
  373. /* Prefix is too long. */
  374. archive_set_error(&a->archive, ENAMETOOLONG,
  375. "Pathname too long");
  376. ret = ARCHIVE_FAILED;
  377. }
  378. r = archive_entry_hardlink_l(entry, &p, &copy_length, sconv);
  379. if (r != 0) {
  380. if (errno == ENOMEM) {
  381. archive_set_error(&a->archive, ENOMEM,
  382. "Can't allocate memory for Linkname");
  383. return (ARCHIVE_FATAL);
  384. }
  385. archive_set_error(&a->archive,
  386. ARCHIVE_ERRNO_FILE_FORMAT,
  387. "Can't translate linkname '%s' to %s",
  388. p, archive_string_conversion_charset_name(sconv));
  389. ret = ARCHIVE_WARN;
  390. }
  391. if (copy_length > 0)
  392. mytartype = '1';
  393. else {
  394. r = archive_entry_symlink_l(entry, &p, &copy_length, sconv);
  395. if (r != 0) {
  396. if (errno == ENOMEM) {
  397. archive_set_error(&a->archive, ENOMEM,
  398. "Can't allocate memory for Linkname");
  399. return (ARCHIVE_FATAL);
  400. }
  401. archive_set_error(&a->archive,
  402. ARCHIVE_ERRNO_FILE_FORMAT,
  403. "Can't translate linkname '%s' to %s",
  404. p, archive_string_conversion_charset_name(sconv));
  405. ret = ARCHIVE_WARN;
  406. }
  407. }
  408. if (copy_length > 0) {
  409. if (copy_length >= V7TAR_linkname_size) {
  410. archive_set_error(&a->archive, ENAMETOOLONG,
  411. "Link contents too long");
  412. ret = ARCHIVE_FAILED;
  413. copy_length = V7TAR_linkname_size;
  414. }
  415. memcpy(h + V7TAR_linkname_offset, p, copy_length);
  416. }
  417. if (format_number(archive_entry_mode(entry) & 07777,
  418. h + V7TAR_mode_offset, V7TAR_mode_size,
  419. V7TAR_mode_max_size, strict)) {
  420. archive_set_error(&a->archive, ERANGE,
  421. "Numeric mode too large");
  422. ret = ARCHIVE_FAILED;
  423. }
  424. if (format_number(archive_entry_uid(entry),
  425. h + V7TAR_uid_offset, V7TAR_uid_size, V7TAR_uid_max_size, strict)) {
  426. archive_set_error(&a->archive, ERANGE,
  427. "Numeric user ID too large");
  428. ret = ARCHIVE_FAILED;
  429. }
  430. if (format_number(archive_entry_gid(entry),
  431. h + V7TAR_gid_offset, V7TAR_gid_size, V7TAR_gid_max_size, strict)) {
  432. archive_set_error(&a->archive, ERANGE,
  433. "Numeric group ID too large");
  434. ret = ARCHIVE_FAILED;
  435. }
  436. if (format_number(archive_entry_size(entry),
  437. h + V7TAR_size_offset, V7TAR_size_size,
  438. V7TAR_size_max_size, strict)) {
  439. archive_set_error(&a->archive, ERANGE,
  440. "File size out of range");
  441. ret = ARCHIVE_FAILED;
  442. }
  443. if (format_number(archive_entry_mtime(entry),
  444. h + V7TAR_mtime_offset, V7TAR_mtime_size,
  445. V7TAR_mtime_max_size, strict)) {
  446. archive_set_error(&a->archive, ERANGE,
  447. "File modification time too large");
  448. ret = ARCHIVE_FAILED;
  449. }
  450. if (mytartype >= 0) {
  451. h[V7TAR_typeflag_offset] = mytartype;
  452. } else {
  453. switch (archive_entry_filetype(entry)) {
  454. case AE_IFREG: case AE_IFDIR:
  455. break;
  456. case AE_IFLNK:
  457. h[V7TAR_typeflag_offset] = '2';
  458. break;
  459. case AE_IFCHR:
  460. archive_set_error(&a->archive,
  461. ARCHIVE_ERRNO_FILE_FORMAT,
  462. "tar format cannot archive character device");
  463. return (ARCHIVE_FAILED);
  464. case AE_IFBLK:
  465. archive_set_error(&a->archive,
  466. ARCHIVE_ERRNO_FILE_FORMAT,
  467. "tar format cannot archive block device");
  468. return (ARCHIVE_FAILED);
  469. case AE_IFIFO:
  470. archive_set_error(&a->archive,
  471. ARCHIVE_ERRNO_FILE_FORMAT,
  472. "tar format cannot archive fifo");
  473. return (ARCHIVE_FAILED);
  474. case AE_IFSOCK:
  475. archive_set_error(&a->archive,
  476. ARCHIVE_ERRNO_FILE_FORMAT,
  477. "tar format cannot archive socket");
  478. return (ARCHIVE_FAILED);
  479. default:
  480. archive_set_error(&a->archive,
  481. ARCHIVE_ERRNO_FILE_FORMAT,
  482. "tar format cannot archive this (mode=0%lo)",
  483. (unsigned long)archive_entry_mode(entry));
  484. ret = ARCHIVE_FAILED;
  485. }
  486. }
  487. checksum = 0;
  488. for (i = 0; i < 512; i++)
  489. checksum += 255 & (unsigned int)h[i];
  490. format_octal(checksum, h + V7TAR_checksum_offset, 6);
  491. /* Can't be pre-set in the template. */
  492. h[V7TAR_checksum_offset + 6] = '\0';
  493. return (ret);
  494. }
  495. /*
  496. * Format a number into a field, with some intelligence.
  497. */
  498. static int
  499. format_number(int64_t v, char *p, int s, int maxsize, int strict)
  500. {
  501. int64_t limit;
  502. limit = ((int64_t)1 << (s*3));
  503. /* "Strict" only permits octal values with proper termination. */
  504. if (strict)
  505. return (format_octal(v, p, s));
  506. /*
  507. * In non-strict mode, we allow the number to overwrite one or
  508. * more bytes of the field termination. Even old tar
  509. * implementations should be able to handle this with no
  510. * problem.
  511. */
  512. if (v >= 0) {
  513. while (s <= maxsize) {
  514. if (v < limit)
  515. return (format_octal(v, p, s));
  516. s++;
  517. limit <<= 3;
  518. }
  519. }
  520. /* Base-256 can handle any number, positive or negative. */
  521. return (format_256(v, p, maxsize));
  522. }
  523. /*
  524. * Format a number into the specified field using base-256.
  525. */
  526. static int
  527. format_256(int64_t v, char *p, int s)
  528. {
  529. p += s;
  530. while (s-- > 0) {
  531. *--p = (char)(v & 0xff);
  532. v >>= 8;
  533. }
  534. *p |= 0x80; /* Set the base-256 marker bit. */
  535. return (0);
  536. }
  537. /*
  538. * Format a number into the specified field.
  539. */
  540. static int
  541. format_octal(int64_t v, char *p, int s)
  542. {
  543. int len;
  544. len = s;
  545. /* Octal values can't be negative, so use 0. */
  546. if (v < 0) {
  547. while (len-- > 0)
  548. *p++ = '0';
  549. return (-1);
  550. }
  551. p += s; /* Start at the end and work backwards. */
  552. while (s-- > 0) {
  553. *--p = (char)('0' + (v & 7));
  554. v >>= 3;
  555. }
  556. if (v == 0)
  557. return (0);
  558. /* If it overflowed, fill field with max value. */
  559. while (len-- > 0)
  560. *p++ = '7';
  561. return (-1);
  562. }
  563. static int
  564. archive_write_v7tar_close(struct archive_write *a)
  565. {
  566. return (__archive_write_nulls(a, 512*2));
  567. }
  568. static int
  569. archive_write_v7tar_free(struct archive_write *a)
  570. {
  571. struct v7tar *v7tar;
  572. v7tar = (struct v7tar *)a->format_data;
  573. free(v7tar);
  574. a->format_data = NULL;
  575. return (ARCHIVE_OK);
  576. }
  577. static int
  578. archive_write_v7tar_finish_entry(struct archive_write *a)
  579. {
  580. struct v7tar *v7tar;
  581. int ret;
  582. v7tar = (struct v7tar *)a->format_data;
  583. ret = __archive_write_nulls(a,
  584. (size_t)(v7tar->entry_bytes_remaining + v7tar->entry_padding));
  585. v7tar->entry_bytes_remaining = v7tar->entry_padding = 0;
  586. return (ret);
  587. }
  588. static ssize_t
  589. archive_write_v7tar_data(struct archive_write *a, const void *buff, size_t s)
  590. {
  591. struct v7tar *v7tar;
  592. int ret;
  593. v7tar = (struct v7tar *)a->format_data;
  594. if (s > v7tar->entry_bytes_remaining)
  595. s = (size_t)v7tar->entry_bytes_remaining;
  596. ret = __archive_write_output(a, buff, s);
  597. v7tar->entry_bytes_remaining -= s;
  598. if (ret != ARCHIVE_OK)
  599. return (ret);
  600. return (s);
  601. }