コード例 #1
0
/*
 * Format a number into a field, with some intelligence.
 */
static int
format_number(int64_t v, char *p, int s, int maxsize, int strict)
{
	int64_t limit;

	limit = ((int64_t)1 << (s*3));

	/* "Strict" only permits octal values with proper termination. */
	if (strict)
		return (format_octal(v, p, s));

	/*
	 * In non-strict mode, we allow the number to overwrite one or
	 * more bytes of the field termination.  Even old tar
	 * implementations should be able to handle this with no
	 * problem.
	 */
	if (v >= 0) {
		while (s <= maxsize) {
			if (v < limit)
				return (format_octal(v, p, s));
			s++;
			limit <<= 3;
		}
	}

	/* Base-256 can handle any number, positive or negative. */
	return (format_256(v, p, maxsize));
}
コード例 #2
0
/*
 * Format a number into a field, falling back to base-256 if necessary.
 */
static int
format_number(int64_t v, char *p, int s, int maxsize)
{
	int64_t limit = ((int64_t)1 << (s*3));

	if (v < limit)
		return (format_octal(v, p, s));
	return (format_256(v, p, maxsize));
}
コード例 #3
0
static int
archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
{
	struct cpio *cpio;
	const char *p, *path;
	int pathlength, ret;
	struct cpio_header	 h;

	cpio = (struct cpio *)a->format_data;
	ret = 0;

	path = archive_entry_pathname(entry);
	pathlength = strlen(path) + 1; /* Include trailing null. */

	memset(&h, 0, sizeof(h));
	format_octal(070707, &h.c_magic, sizeof(h.c_magic));
	format_octal(archive_entry_dev(entry), &h.c_dev, sizeof(h.c_dev));
	/*
	 * TODO: Generate artificial inode numbers rather than just
	 * re-using the ones off the disk.  That way, the 18-bit c_ino
	 * field only limits the number of files in the archive.
	 */
	if (archive_entry_ino(entry) > 0777777) {
		archive_set_error(&a->archive, ERANGE, "large inode number truncated");
		ret = ARCHIVE_WARN;
	}

	format_octal(archive_entry_ino(entry) & 0777777, &h.c_ino, sizeof(h.c_ino));
	format_octal(archive_entry_mode(entry), &h.c_mode, sizeof(h.c_mode));
	format_octal(archive_entry_uid(entry), &h.c_uid, sizeof(h.c_uid));
	format_octal(archive_entry_gid(entry), &h.c_gid, sizeof(h.c_gid));
	format_octal(archive_entry_nlink(entry), &h.c_nlink, sizeof(h.c_nlink));
	if (archive_entry_filetype(entry) == AE_IFBLK
	    || archive_entry_filetype(entry) == AE_IFCHR)
	    format_octal(archive_entry_dev(entry), &h.c_rdev, sizeof(h.c_rdev));
	else
	    format_octal(0, &h.c_rdev, sizeof(h.c_rdev));
	format_octal(archive_entry_mtime(entry), &h.c_mtime, sizeof(h.c_mtime));
	format_octal(pathlength, &h.c_namesize, sizeof(h.c_namesize));

	/* Non-regular files don't store bodies. */
	if (archive_entry_filetype(entry) != AE_IFREG)
		archive_entry_set_size(entry, 0);

	/* Symlinks get the link written as the body of the entry. */
	p = archive_entry_symlink(entry);
	if (p != NULL  &&  *p != '\0')
		format_octal(strlen(p), &h.c_filesize, sizeof(h.c_filesize));
	else
		format_octal(archive_entry_size(entry),
		    &h.c_filesize, sizeof(h.c_filesize));

	ret = (a->compressor.write)(a, &h, sizeof(h));
	if (ret != ARCHIVE_OK)
		return (ARCHIVE_FATAL);

	ret = (a->compressor.write)(a, path, pathlength);
	if (ret != ARCHIVE_OK)
		return (ARCHIVE_FATAL);

	cpio->entry_bytes_remaining = archive_entry_size(entry);

	/* Write the symlink now. */
	if (p != NULL  &&  *p != '\0')
		ret = (a->compressor.write)(a, p, strlen(p));

	return (ret);
}
コード例 #4
0
static int
archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
{
	int ret, append_fn;
	char buff[60];
	char *ss, *se;
	struct ar_w *ar;
	const char *pathname;
	const char *filename;
	int64_t size;

	append_fn = 0;
	ar = (struct ar_w *)a->format_data;
	ar->is_strtab = 0;
	filename = NULL;
	size = archive_entry_size(entry);


	/*
	 * Reject files with empty name.
	 */
	pathname = archive_entry_pathname(entry);
	if (pathname == NULL || *pathname == '\0') {
		archive_set_error(&a->archive, EINVAL,
		    "Invalid filename");
		return (ARCHIVE_WARN);
	}

	/*
	 * If we are now at the beginning of the archive,
	 * we need first write the ar global header.
	 */
	if (!ar->wrote_global_header) {
		__archive_write_output(a, "!<arch>\n", 8);
		ar->wrote_global_header = 1;
	}

	memset(buff, ' ', 60);
	strncpy(&buff[AR_fmag_offset], "`\n", 2);

	if (strcmp(pathname, "/") == 0 ) {
		/* Entry is archive symbol table in GNU format */
		buff[AR_name_offset] = '/';
		goto stat;
	}
	if (strcmp(pathname, "__.SYMDEF") == 0) {
		/* Entry is archive symbol table in BSD format */
		strncpy(buff + AR_name_offset, "__.SYMDEF", 9);
		goto stat;
	}
	if (strcmp(pathname, "//") == 0) {
		/*
		 * Entry is archive filename table, inform that we should
		 * collect strtab in next _data call.
		 */
		ar->is_strtab = 1;
		buff[AR_name_offset] = buff[AR_name_offset + 1] = '/';
		/*
		 * For archive string table, only ar_size field should
		 * be set.
		 */
		goto size;
	}

	/*
	 * Otherwise, entry is a normal archive member.
	 * Strip leading paths from filenames, if any.
	 */
	if ((filename = ar_basename(pathname)) == NULL) {
		/* Reject filenames with trailing "/" */
		archive_set_error(&a->archive, EINVAL,
		    "Invalid filename");
		return (ARCHIVE_WARN);
	}

	if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) {
		/*
		 * SVR4/GNU variant use a "/" to mark then end of the filename,
		 * make it possible to have embedded spaces in the filename.
		 * So, the longest filename here (without extension) is
		 * actually 15 bytes.
		 */
		if (strlen(filename) <= 15) {
			strncpy(&buff[AR_name_offset], 
			    filename, strlen(filename));
			buff[AR_name_offset + strlen(filename)] = '/';
		} else {
			/*
			 * For filename longer than 15 bytes, GNU variant
			 * makes use of a string table and instead stores the
			 * offset of the real filename to in the ar_name field.
			 * The string table should have been written before.
			 */
			if (ar->has_strtab <= 0) {
				archive_set_error(&a->archive, EINVAL,
				    "Can't find string table");
				return (ARCHIVE_WARN);
			}

			se = (char *)malloc(strlen(filename) + 3);
			if (se == NULL) {
				archive_set_error(&a->archive, ENOMEM,
				    "Can't allocate filename buffer");
				return (ARCHIVE_FATAL);
			}

			strncpy(se, filename, strlen(filename));
			strcpy(se + strlen(filename), "/\n");

			ss = strstr(ar->strtab, se);
			free(se);

			if (ss == NULL) {
				archive_set_error(&a->archive, EINVAL,
				    "Invalid string table");
				return (ARCHIVE_WARN);
			}

			/*
			 * GNU variant puts "/" followed by digits into
			 * ar_name field. These digits indicates the real
			 * filename string's offset to the string table.
			 */
			buff[AR_name_offset] = '/';
			if (format_decimal(ss - ar->strtab,
			    buff + AR_name_offset + 1,
			    AR_name_size - 1)) {
				archive_set_error(&a->archive, ERANGE,
				    "string table offset too large");
				return (ARCHIVE_WARN);
			}
		}
	} else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) {
		/*
		 * BSD variant: for any file name which is more than
		 * 16 chars or contains one or more embedded space(s), the
		 * string "#1/" followed by the ASCII length of the name is
		 * put into the ar_name field. The file size (stored in the
		 * ar_size field) is incremented by the length of the name.
		 * The name is then written immediately following the
		 * archive header.
		 */
		if (strlen(filename) <= 16 && strchr(filename, ' ') == NULL) {
			strncpy(&buff[AR_name_offset], filename, strlen(filename));
			buff[AR_name_offset + strlen(filename)] = ' ';
		}
		else {
			strncpy(buff + AR_name_offset, "#1/", 3);
			if (format_decimal(strlen(filename),
			    buff + AR_name_offset + 3,
			    AR_name_size - 3)) {
				archive_set_error(&a->archive, ERANGE,
				    "File name too long");
				return (ARCHIVE_WARN);
			}
			append_fn = 1;
			size += strlen(filename);
		}
	}

stat:
	if (format_decimal(archive_entry_mtime(entry), buff + AR_date_offset, AR_date_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "File modification time too large");
		return (ARCHIVE_WARN);
	}
	if (format_decimal(archive_entry_uid(entry), buff + AR_uid_offset, AR_uid_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric user ID too large");
		return (ARCHIVE_WARN);
	}
	if (format_decimal(archive_entry_gid(entry), buff + AR_gid_offset, AR_gid_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric group ID too large");
		return (ARCHIVE_WARN);
	}
	if (format_octal(archive_entry_mode(entry), buff + AR_mode_offset, AR_mode_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric mode too large");
		return (ARCHIVE_WARN);
	}
	/*
	 * Sanity Check: A non-pseudo archive member should always be
	 * a regular file.
	 */
	if (filename != NULL && archive_entry_filetype(entry) != AE_IFREG) {
		archive_set_error(&a->archive, EINVAL,
		    "Regular file required for non-pseudo member");
		return (ARCHIVE_WARN);
	}

size:
	if (format_decimal(size, buff + AR_size_offset, AR_size_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "File size out of range");
		return (ARCHIVE_WARN);
	}

	ret = __archive_write_output(a, buff, 60);
	if (ret != ARCHIVE_OK)
		return (ret);

	ar->entry_bytes_remaining = size;
	ar->entry_padding = ar->entry_bytes_remaining % 2;

	if (append_fn > 0) {
		ret = __archive_write_output(a, filename, strlen(filename));
		if (ret != ARCHIVE_OK)
			return (ret);
		ar->entry_bytes_remaining -= strlen(filename);
	}

	return (ARCHIVE_OK);
}
コード例 #5
0
/*
 * Format a basic 512-byte "ustar" header.
 *
 * Returns -1 if format failed (due to field overflow).
 * Note that this always formats as much of the header as possible.
 * If "strict" is set to zero, it will extend numeric fields as
 * necessary (overwriting terminators or using base-256 extensions).
 *
 * This is exported so that other 'tar' formats can use it.
 */
int
__archive_write_format_header_ustar(struct archive_write *a, char h[512],
    struct archive_entry *entry, int tartype, int strict)
{
	unsigned int checksum;
	int i, ret;
	size_t copy_length;
	const char *p, *pp;
	int mytartype;

	ret = 0;
	mytartype = -1;
	/*
	 * The "template header" already includes the "ustar"
	 * signature, various end-of-field markers and other required
	 * elements.
	 */
	memcpy(h, &template_header, 512);

	/*
	 * Because the block is already null-filled, and strings
	 * are allowed to exactly fill their destination (without null),
	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
	 */

	pp = tk_archive_entry_pathname(entry);
	if (strlen(pp) <= USTAR_name_size)
		memcpy(h + USTAR_name_offset, pp, strlen(pp));
	else {
		/* Store in two pieces, splitting at a '/'. */
		p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/');
		/*
		 * Look for the next '/' if we chose the first character
		 * as the separator.  (ustar format doesn't permit
		 * an empty prefix.)
		 */
		if (p == pp)
			p = strchr(p + 1, '/');
		/* Fail if the name won't fit. */
		if (!p) {
			/* No separator. */
			tk_archive_set_error(&a->archive, ENAMETOOLONG,
			    "Pathname too long");
			ret = ARCHIVE_FAILED;
		} else if (p[1] == '\0') {
			/*
			 * The only feasible separator is a final '/';
			 * this would result in a non-empty prefix and
			 * an empty name, which POSIX doesn't
			 * explicity forbid, but it just feels wrong.
			 */
			tk_archive_set_error(&a->archive, ENAMETOOLONG,
			    "Pathname too long");
			ret = ARCHIVE_FAILED;
		} else if (p  > pp + USTAR_prefix_size) {
			/* Prefix is too long. */
			tk_archive_set_error(&a->archive, ENAMETOOLONG,
			    "Pathname too long");
			ret = ARCHIVE_FAILED;
		} else {
			/* Copy prefix and remainder to appropriate places */
			memcpy(h + USTAR_prefix_offset, pp, p - pp);
			memcpy(h + USTAR_name_offset, p + 1, pp + strlen(pp) - p - 1);
		}
	}

	p = tk_archive_entry_hardlink(entry);
	if (p != NULL)
		mytartype = '1';
	else
		p = tk_archive_entry_symlink(entry);
	if (p != NULL && p[0] != '\0') {
		copy_length = strlen(p);
		if (copy_length > USTAR_linkname_size) {
			tk_archive_set_error(&a->archive, ENAMETOOLONG,
			    "Link contents too long");
			ret = ARCHIVE_FAILED;
			copy_length = USTAR_linkname_size;
		}
		memcpy(h + USTAR_linkname_offset, p, copy_length);
	}

	p = tk_archive_entry_uname(entry);
	if (p != NULL && p[0] != '\0') {
		copy_length = strlen(p);
		if (copy_length > USTAR_uname_size) {
			tk_archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
			    "Username too long");
			ret = ARCHIVE_FAILED;
			copy_length = USTAR_uname_size;
		}
		memcpy(h + USTAR_uname_offset, p, copy_length);
	}

	p = tk_archive_entry_gname(entry);
	if (p != NULL && p[0] != '\0') {
		copy_length = strlen(p);
		if (strlen(p) > USTAR_gname_size) {
			tk_archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
			    "Group name too long");
			ret = ARCHIVE_FAILED;
			copy_length = USTAR_gname_size;
		}
		memcpy(h + USTAR_gname_offset, p, copy_length);
	}

	if (format_number(tk_archive_entry_mode(entry) & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
		tk_archive_set_error(&a->archive, ERANGE, "Numeric mode too large");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(tk_archive_entry_uid(entry), h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
		tk_archive_set_error(&a->archive, ERANGE, "Numeric user ID too large");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(tk_archive_entry_gid(entry), h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
		tk_archive_set_error(&a->archive, ERANGE, "Numeric group ID too large");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(tk_archive_entry_size(entry), h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
		tk_archive_set_error(&a->archive, ERANGE, "File size out of range");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(tk_archive_entry_mtime(entry), h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
		tk_archive_set_error(&a->archive, ERANGE,
		    "File modification time too large");
		ret = ARCHIVE_FAILED;
	}

	if (tk_archive_entry_filetype(entry) == AE_IFBLK
	    || tk_archive_entry_filetype(entry) == AE_IFCHR) {
		if (format_number(tk_archive_entry_rdevmajor(entry), h + USTAR_rdevmajor_offset,
			USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) {
			tk_archive_set_error(&a->archive, ERANGE,
			    "Major device number too large");
			ret = ARCHIVE_FAILED;
		}

		if (format_number(tk_archive_entry_rdevminor(entry), h + USTAR_rdevminor_offset,
			USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) {
			tk_archive_set_error(&a->archive, ERANGE,
			    "Minor device number too large");
			ret = ARCHIVE_FAILED;
		}
	}

	if (tartype >= 0) {
		h[USTAR_typeflag_offset] = tartype;
	} else if (mytartype >= 0) {
		h[USTAR_typeflag_offset] = mytartype;
	} else {
		switch (tk_archive_entry_filetype(entry)) {
		case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break;
		case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break;
		case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break;
		case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
		case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
		case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
		case AE_IFSOCK:
			tk_archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive socket");
			return (ARCHIVE_FAILED);
		default:
			tk_archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive this (mode=0%lo)",
			    (unsigned long)tk_archive_entry_mode(entry));
			ret = ARCHIVE_FAILED;
		}
	}

	checksum = 0;
	for (i = 0; i < 512; i++)
		checksum += 255 & (unsigned int)h[i];
	h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
	/* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
	format_octal(checksum, h + USTAR_checksum_offset, 6);
	return (ret);
}
コード例 #6
0
static int
archive_format_gnutar_header(struct archive_write *a, char h[512],
    struct archive_entry *entry, int tartype)
{
	unsigned int checksum;
	int i, ret;
	size_t copy_length;
	const char *p;
	struct gnutar *gnutar;

	gnutar = (struct gnutar *)a->format_data;

	ret = 0;

	/*
	 * The "template header" already includes the signature,
	 * various end-of-field markers, and other required elements.
	 */
	memcpy(h, &template_header, 512);

	/*
	 * Because the block is already null-filled, and strings
	 * are allowed to exactly fill their destination (without null),
	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
	 */

	if (tartype == 'K' || tartype == 'L') {
		p = archive_entry_pathname(entry);
		copy_length = strlen(p);
	} else {
		p = gnutar->pathname;
		copy_length = gnutar->pathname_length;
	}
	if (copy_length > GNUTAR_name_size)
		copy_length = GNUTAR_name_size;
	memcpy(h + GNUTAR_name_offset, p, copy_length);

	if ((copy_length = gnutar->linkname_length) > 0) {
		if (copy_length > GNUTAR_linkname_size)
			copy_length = GNUTAR_linkname_size;
		memcpy(h + GNUTAR_linkname_offset, gnutar->linkname,
		    copy_length);
	}

	/* TODO: How does GNU tar handle unames longer than GNUTAR_uname_size? */
	if (tartype == 'K' || tartype == 'L') {
		p = archive_entry_uname(entry);
		copy_length = strlen(p);
	} else {
		p = gnutar->uname;
		copy_length = gnutar->uname_length;
	}
	if (copy_length > 0) {
		if (copy_length > GNUTAR_uname_size)
			copy_length = GNUTAR_uname_size;
		memcpy(h + GNUTAR_uname_offset, p, copy_length);
	}

	/* TODO: How does GNU tar handle gnames longer than GNUTAR_gname_size? */
	if (tartype == 'K' || tartype == 'L') {
		p = archive_entry_gname(entry);
		copy_length = strlen(p);
	} else {
		p = gnutar->gname;
		copy_length = gnutar->gname_length;
	}
	if (copy_length > 0) {
		if (strlen(p) > GNUTAR_gname_size)
			copy_length = GNUTAR_gname_size;
		memcpy(h + GNUTAR_gname_offset, p, copy_length);
	}

	/* By truncating the mode here, we ensure it always fits. */
	format_octal(archive_entry_mode(entry) & 07777,
	    h + GNUTAR_mode_offset, GNUTAR_mode_size);

	/* GNU tar supports base-256 here, so should never overflow. */
	if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset,
		GNUTAR_uid_size, GNUTAR_uid_max_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric user ID %jd too large",
		    (intmax_t)archive_entry_uid(entry));
		ret = ARCHIVE_FAILED;
	}

	/* GNU tar supports base-256 here, so should never overflow. */
	if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset,
		GNUTAR_gid_size, GNUTAR_gid_max_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric group ID %jd too large",
		    (intmax_t)archive_entry_gid(entry));
		ret = ARCHIVE_FAILED;
	}

	/* GNU tar supports base-256 here, so should never overflow. */
	if (format_number(archive_entry_size(entry), h + GNUTAR_size_offset,
		GNUTAR_size_size, GNUTAR_size_max_size)) {
		archive_set_error(&a->archive, ERANGE,
		    "File size out of range");
		ret = ARCHIVE_FAILED;
	}

	/* Shouldn't overflow before 2106, since mtime field is 33 bits. */
	format_octal(archive_entry_mtime(entry),
	    h + GNUTAR_mtime_offset, GNUTAR_mtime_size);

	if (archive_entry_filetype(entry) == AE_IFBLK
	    || archive_entry_filetype(entry) == AE_IFCHR) {
		if (format_octal(archive_entry_rdevmajor(entry),
		    h + GNUTAR_rdevmajor_offset,
			GNUTAR_rdevmajor_size)) {
			archive_set_error(&a->archive, ERANGE,
			    "Major device number too large");
			ret = ARCHIVE_FAILED;
		}

		if (format_octal(archive_entry_rdevminor(entry),
		    h + GNUTAR_rdevminor_offset,
			GNUTAR_rdevminor_size)) {
			archive_set_error(&a->archive, ERANGE,
			    "Minor device number too large");
			ret = ARCHIVE_FAILED;
		}
	}

	h[GNUTAR_typeflag_offset] = tartype;

	checksum = 0;
	for (i = 0; i < 512; i++)
		checksum += 255 & (unsigned int)h[i];
	h[GNUTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
	/* h[GNUTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
	format_octal(checksum, h + GNUTAR_checksum_offset, 6);
	return (ret);
}
コード例 #7
0
/*
 * Format a basic 512-byte "v7tar" header.
 *
 * Returns -1 if format failed (due to field overflow).
 * Note that this always formats as much of the header as possible.
 * If "strict" is set to zero, it will extend numeric fields as
 * necessary (overwriting terminators or using base-256 extensions).
 *
 */
static int
format_header_v7tar(struct archive_write *a, char h[512],
    struct archive_entry *entry, int strict,
    struct archive_string_conv *sconv)
{
	unsigned int checksum;
	int i, r, ret;
	size_t copy_length;
	const char *p, *pp;
	int mytartype;

	ret = 0;
	mytartype = -1;
	/*
	 * The "template header" already includes the "v7tar"
	 * signature, various end-of-field markers and other required
	 * elements.
	 */
	memcpy(h, &template_header, 512);

	/*
	 * Because the block is already null-filled, and strings
	 * are allowed to exactly fill their destination (without null),
	 * I use memcpy(dest, src, strlen()) here a lot to copy strings.
	 */
	r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
	if (r != 0) {
		if (errno == ENOMEM) {
			archive_set_error(&a->archive, ENOMEM,
			    "Can't allocate memory for Pathname");
			return (ARCHIVE_FATAL);
		}
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Can't translate pathname '%s' to %s",
		    pp, archive_string_conversion_charset_name(sconv));
		ret = ARCHIVE_WARN;
	}
	if (strict && copy_length < V7TAR_name_size)
		memcpy(h + V7TAR_name_offset, pp, copy_length);
	else if (!strict && copy_length <= V7TAR_name_size)
		memcpy(h + V7TAR_name_offset, pp, copy_length);
	else {
		/* Prefix is too long. */
		archive_set_error(&a->archive, ENAMETOOLONG,
		    "Pathname too long");
		ret = ARCHIVE_FAILED;
	}

	r = archive_entry_hardlink_l(entry, &p, &copy_length, sconv);
	if (r != 0) {
		if (errno == ENOMEM) {
			archive_set_error(&a->archive, ENOMEM,
			    "Can't allocate memory for Linkname");
			return (ARCHIVE_FATAL);
		}
		archive_set_error(&a->archive,
		    ARCHIVE_ERRNO_FILE_FORMAT,
		    "Can't translate linkname '%s' to %s",
		    p, archive_string_conversion_charset_name(sconv));
		ret = ARCHIVE_WARN;
	}
	if (copy_length > 0)
		mytartype = '1';
	else {
		r = archive_entry_symlink_l(entry, &p, &copy_length, sconv);
		if (r != 0) {
			if (errno == ENOMEM) {
				archive_set_error(&a->archive, ENOMEM,
				    "Can't allocate memory for Linkname");
				return (ARCHIVE_FATAL);
			}
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "Can't translate linkname '%s' to %s",
			    p, archive_string_conversion_charset_name(sconv));
			ret = ARCHIVE_WARN;
		}
	}
	if (copy_length > 0) {
		if (copy_length >= V7TAR_linkname_size) {
			archive_set_error(&a->archive, ENAMETOOLONG,
			    "Link contents too long");
			ret = ARCHIVE_FAILED;
			copy_length = V7TAR_linkname_size;
		}
		memcpy(h + V7TAR_linkname_offset, p, copy_length);
	}

	if (format_number(archive_entry_mode(entry) & 07777,
	    h + V7TAR_mode_offset, V7TAR_mode_size,
	    V7TAR_mode_max_size, strict)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric mode too large");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(archive_entry_uid(entry),
	    h + V7TAR_uid_offset, V7TAR_uid_size, V7TAR_uid_max_size, strict)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric user ID too large");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(archive_entry_gid(entry),
	    h + V7TAR_gid_offset, V7TAR_gid_size, V7TAR_gid_max_size, strict)) {
		archive_set_error(&a->archive, ERANGE,
		    "Numeric group ID too large");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(archive_entry_size(entry),
	    h + V7TAR_size_offset, V7TAR_size_size,
	    V7TAR_size_max_size, strict)) {
		archive_set_error(&a->archive, ERANGE,
		    "File size out of range");
		ret = ARCHIVE_FAILED;
	}

	if (format_number(archive_entry_mtime(entry),
	    h + V7TAR_mtime_offset, V7TAR_mtime_size,
	    V7TAR_mtime_max_size, strict)) {
		archive_set_error(&a->archive, ERANGE,
		    "File modification time too large");
		ret = ARCHIVE_FAILED;
	}

	if (mytartype >= 0) {
		h[V7TAR_typeflag_offset] = mytartype;
	} else {
		switch (archive_entry_filetype(entry)) {
		case AE_IFREG: case AE_IFDIR:
			break;
		case AE_IFLNK:
			h[V7TAR_typeflag_offset] = '2';
			break;
		case AE_IFCHR:
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive character device");
			return (ARCHIVE_FAILED);
		case AE_IFBLK:
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive block device");
			return (ARCHIVE_FAILED);
		case AE_IFIFO:
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive fifo");
			return (ARCHIVE_FAILED);
		case AE_IFSOCK:
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive socket");
			return (ARCHIVE_FAILED);
		default:
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive this (mode=0%lo)",
			    (unsigned long)archive_entry_mode(entry));
			ret = ARCHIVE_FAILED;
		}
	}

	checksum = 0;
	for (i = 0; i < 512; i++)
		checksum += 255 & (unsigned int)h[i];
	format_octal(checksum, h + V7TAR_checksum_offset, 6);
	/* Can't be pre-set in the template. */
	h[V7TAR_checksum_offset + 6] = '\0';
	return (ret);
}