Blame libarchive/test/test_pax_filename_encoding.c

Packit 08bd4c
/*-
Packit 08bd4c
 * Copyright (c) 2003-2007 Tim Kientzle
Packit 08bd4c
 * All rights reserved.
Packit 08bd4c
 *
Packit 08bd4c
 * Redistribution and use in source and binary forms, with or without
Packit 08bd4c
 * modification, are permitted provided that the following conditions
Packit 08bd4c
 * are met:
Packit 08bd4c
 * 1. Redistributions of source code must retain the above copyright
Packit 08bd4c
 *    notice, this list of conditions and the following disclaimer.
Packit 08bd4c
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 08bd4c
 *    notice, this list of conditions and the following disclaimer in the
Packit 08bd4c
 *    documentation and/or other materials provided with the distribution.
Packit 08bd4c
 *
Packit 08bd4c
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
Packit 08bd4c
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit 08bd4c
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit 08bd4c
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit 08bd4c
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit 08bd4c
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 08bd4c
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 08bd4c
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 08bd4c
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit 08bd4c
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 08bd4c
 */
Packit 08bd4c
#include "test.h"
Packit 08bd4c
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_pax_filename_encoding.c 201247 2009-12-30 05:59:21Z kientzle $");
Packit 08bd4c
Packit 08bd4c
#include <locale.h>
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Pax interchange is supposed to encode filenames into
Packit 08bd4c
 * UTF-8.  Of course, that's not always possible.  This
Packit 08bd4c
 * test is intended to verify that filenames always get
Packit 08bd4c
 * stored and restored correctly, regardless of the encodings.
Packit 08bd4c
 */
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Read a manually-created archive that has filenames that are
Packit 08bd4c
 * stored in binary instead of UTF-8 and verify that we get
Packit 08bd4c
 * the right filename returned and that we get a warning only
Packit 08bd4c
 * if the header isn't marked as binary.
Packit 08bd4c
 */
Packit 08bd4c
static void
Packit 08bd4c
test_pax_filename_encoding_1(void)
Packit 08bd4c
{
Packit 08bd4c
	static const char testname[] = "test_pax_filename_encoding.tar";
Packit 08bd4c
	/*
Packit 08bd4c
	 * \314\214 is a valid 2-byte UTF-8 sequence.
Packit 08bd4c
	 * \374 is invalid in UTF-8.
Packit 08bd4c
	 */
Packit 08bd4c
	char filename[] = "abc\314\214mno\374xyz";
Packit 08bd4c
	struct archive *a;
Packit 08bd4c
	struct archive_entry *entry;
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Read an archive that has non-UTF8 pax filenames in it.
Packit 08bd4c
	 */
Packit 08bd4c
	extract_reference_file(testname);
Packit 08bd4c
	a = archive_read_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_read_support_format_tar(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_read_open_filename(a, testname, 10240));
Packit 08bd4c
	/*
Packit 08bd4c
	 * First entry in this test archive has an invalid UTF-8 sequence
Packit 08bd4c
	 * in it, but the header is not marked as hdrcharset=BINARY, so that
Packit 08bd4c
	 * requires a warning.
Packit 08bd4c
	 */
Packit 08bd4c
	failure("Invalid UTF8 in a pax archive pathname should cause a warning");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_pathname(entry));
Packit 08bd4c
	/*
Packit 08bd4c
	 * Second entry is identical except that it does have
Packit 08bd4c
	 * hdrcharset=BINARY, so no warning should be generated.
Packit 08bd4c
	 */
Packit 08bd4c
	failure("A pathname with hdrcharset=BINARY can have invalid UTF8\n"
Packit 08bd4c
	    " characters in it without generating a warning");
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_pathname(entry));
Packit 08bd4c
	archive_read_free(a);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Set the locale and write a pathname containing invalid characters.
Packit 08bd4c
 * This should work; the underlying implementation should automatically
Packit 08bd4c
 * fall back to storing the pathname in binary.
Packit 08bd4c
 */
Packit 08bd4c
static void
Packit 08bd4c
test_pax_filename_encoding_2(void)
Packit 08bd4c
{
Packit 08bd4c
	char filename[] = "abc\314\214mno\374xyz";
Packit 08bd4c
	struct archive *a;
Packit 08bd4c
	struct archive_entry *entry;
Packit 08bd4c
	char buff[65536];
Packit 08bd4c
	char longname[] = "abc\314\214mno\374xyz"
Packit 08bd4c
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
Packit 08bd4c
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
Packit 08bd4c
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
Packit 08bd4c
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
Packit 08bd4c
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
Packit 08bd4c
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
Packit 08bd4c
	    ;
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * We need a starting locale which has invalid sequences.
Packit 08bd4c
	 * en_US.UTF-8 seems to be commonly supported.
Packit 08bd4c
	 */
Packit 08bd4c
	/* If it doesn't exist, just warn and return. */
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
Packit 08bd4c
		skipping("invalid encoding tests require a suitable locale;"
Packit 08bd4c
		    " en_US.UTF-8 not available on this system");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	assert((a = archive_write_new()) != NULL);
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_set_format_pax(a));
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_add_filter_none(a));
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0));
Packit 08bd4c
	assertEqualInt(0,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	/* Set pathname, gname, uname, hardlink to nonconvertible values. */
Packit 08bd4c
	archive_entry_copy_pathname(entry, filename);
Packit 08bd4c
	archive_entry_copy_gname(entry, filename);
Packit 08bd4c
	archive_entry_copy_uname(entry, filename);
Packit 08bd4c
	archive_entry_copy_hardlink(entry, filename);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	failure("This should generate a warning for nonconvertible names.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	/* Set path, gname, uname, and symlink to nonconvertible values. */
Packit 08bd4c
	archive_entry_copy_pathname(entry, filename);
Packit 08bd4c
	archive_entry_copy_gname(entry, filename);
Packit 08bd4c
	archive_entry_copy_uname(entry, filename);
Packit 08bd4c
	archive_entry_copy_symlink(entry, filename);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFLNK);
Packit 08bd4c
	failure("This should generate a warning for nonconvertible names.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	/* Set pathname to a very long nonconvertible value. */
Packit 08bd4c
	archive_entry_copy_pathname(entry, longname);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	failure("This should generate a warning for nonconvertible names.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Now read the entries back.
Packit 08bd4c
	 */
Packit 08bd4c
Packit 08bd4c
	assert((a = archive_read_new()) != NULL);
Packit 08bd4c
	assertEqualInt(0, archive_read_support_format_tar(a));
Packit 08bd4c
	assertEqualInt(0, archive_read_open_memory(a, buff, used));
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_pathname(entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_gname(entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_uname(entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_hardlink(entry));
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_pathname(entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_gname(entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_uname(entry));
Packit 08bd4c
	assertEqualString(filename, archive_entry_symlink(entry));
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualString(longname, archive_entry_pathname(entry));
Packit 08bd4c
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
#if 0 /* Disable this until Tim check out it. */
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Create an entry starting from a wide-character Unicode pathname,
Packit 08bd4c
 * read it back into "C" locale, which doesn't support the name.
Packit 08bd4c
 * TODO: Figure out the "right" behavior here.
Packit 08bd4c
 */
Packit 08bd4c
static void
Packit 08bd4c
test_pax_filename_encoding_3(void)
Packit 08bd4c
{
Packit 08bd4c
	wchar_t badname[] = L"xxxAyyyBzzz";
Packit 08bd4c
	const char badname_utf8[] = "xxx\xE1\x88\xB4yyy\xE5\x99\xB8zzz";
Packit 08bd4c
	struct archive *a;
Packit 08bd4c
	struct archive_entry *entry;
Packit 08bd4c
	char buff[65536];
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	badname[3] = 0x1234;
Packit 08bd4c
	badname[7] = 0x5678;
Packit 08bd4c
Packit 08bd4c
	/* If it doesn't exist, just warn and return. */
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "C")) {
Packit 08bd4c
		skipping("Can't set \"C\" locale, so can't exercise "
Packit 08bd4c
		    "certain character-conversion failures");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* If wctomb is broken, warn and return. */
Packit 08bd4c
	if (wctomb(buff, 0x1234) > 0) {
Packit 08bd4c
		skipping("Cannot test conversion failures because \"C\" "
Packit 08bd4c
		    "locale on this system has no invalid characters.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* If wctomb is broken, warn and return. */
Packit 08bd4c
	if (wctomb(buff, 0x1234) > 0) {
Packit 08bd4c
		skipping("Cannot test conversion failures because \"C\" "
Packit 08bd4c
		    "locale on this system has no invalid characters.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Skip test if archive_entry_update_pathname_utf8() is broken. */
Packit 08bd4c
	/* In particular, this is currently broken on Win32 because
Packit 08bd4c
	 * setlocale() does not set the default encoding for CP_ACP. */
Packit 08bd4c
	entry = archive_entry_new();
Packit 08bd4c
	if (archive_entry_update_pathname_utf8(entry, badname_utf8)) {
Packit 08bd4c
		archive_entry_free(entry);
Packit 08bd4c
		skipping("Cannot test conversion failures.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((a = archive_write_new()) != NULL);
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_set_format_pax(a));
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_add_filter_none(a));
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0));
Packit 08bd4c
	assertEqualInt(0,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	/* Set pathname to non-convertible wide value. */
Packit 08bd4c
	archive_entry_copy_pathname_w(entry, badname);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname_w(entry, L"abc");
Packit 08bd4c
	/* Set gname to non-convertible wide value. */
Packit 08bd4c
	archive_entry_copy_gname_w(entry, badname);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname_w(entry, L"abc");
Packit 08bd4c
	/* Set uname to non-convertible wide value. */
Packit 08bd4c
	archive_entry_copy_uname_w(entry, badname);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname_w(entry, L"abc");
Packit 08bd4c
	/* Set hardlink to non-convertible wide value. */
Packit 08bd4c
	archive_entry_copy_hardlink_w(entry, badname);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assert((entry = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname_w(entry, L"abc");
Packit 08bd4c
	/* Set symlink to non-convertible wide value. */
Packit 08bd4c
	archive_entry_copy_symlink_w(entry, badname);
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFLNK);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Now read the entries back.
Packit 08bd4c
	 */
Packit 08bd4c
Packit 08bd4c
	assert((a = archive_read_new()) != NULL);
Packit 08bd4c
	assertEqualInt(0, archive_read_support_format_tar(a));
Packit 08bd4c
	assertEqualInt(0, archive_read_open_memory(a, buff, used));
Packit 08bd4c
Packit 08bd4c
	failure("A non-convertible pathname should cause a warning.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualWString(badname, archive_entry_pathname_w(entry));
Packit 08bd4c
	failure("If native locale can't convert, we should get UTF-8 back.");
Packit 08bd4c
	assertEqualString(badname_utf8, archive_entry_pathname(entry));
Packit 08bd4c
Packit 08bd4c
	failure("A non-convertible gname should cause a warning.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualWString(badname, archive_entry_gname_w(entry));
Packit 08bd4c
	failure("If native locale can't convert, we should get UTF-8 back.");
Packit 08bd4c
	assertEqualString(badname_utf8, archive_entry_gname(entry));
Packit 08bd4c
Packit 08bd4c
	failure("A non-convertible uname should cause a warning.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualWString(badname, archive_entry_uname_w(entry));
Packit 08bd4c
	failure("If native locale can't convert, we should get UTF-8 back.");
Packit 08bd4c
	assertEqualString(badname_utf8, archive_entry_uname(entry));
Packit 08bd4c
Packit 08bd4c
	failure("A non-convertible hardlink should cause a warning.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualWString(badname, archive_entry_hardlink_w(entry));
Packit 08bd4c
	failure("If native locale can't convert, we should get UTF-8 back.");
Packit 08bd4c
	assertEqualString(badname_utf8, archive_entry_hardlink(entry));
Packit 08bd4c
Packit 08bd4c
	failure("A non-convertible symlink should cause a warning.");
Packit 08bd4c
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
Packit 08bd4c
	assertEqualWString(badname, archive_entry_symlink_w(entry));
Packit 08bd4c
	assertEqualWString(NULL, archive_entry_hardlink_w(entry));
Packit 08bd4c
	failure("If native locale can't convert, we should get UTF-8 back.");
Packit 08bd4c
	assertEqualString(badname_utf8, archive_entry_symlink(entry));
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &entry));
Packit 08bd4c
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
Packit 08bd4c
}
Packit 08bd4c
#else
Packit 08bd4c
static void
Packit 08bd4c
test_pax_filename_encoding_3(void)
Packit 08bd4c
{
Packit 08bd4c
}
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Verify that KOI8-R filenames are correctly translated to Unicode and UTF-8.
Packit 08bd4c
 */
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding_KOI8R)
Packit 08bd4c
{
Packit 08bd4c
  	struct archive *a;
Packit 08bd4c
  	struct archive_entry *entry;
Packit 08bd4c
	char buff[4096];
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) {
Packit 08bd4c
		skipping("KOI8-R locale not available on this system.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Check if the platform completely supports the string conversion. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
Packit 08bd4c
		skipping("This system cannot convert character-set"
Packit 08bd4c
		    " from KOI8-R to UTF-8.");
Packit 08bd4c
		archive_write_free(a);
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
	archive_write_free(a);
Packit 08bd4c
Packit 08bd4c
	/* Re-create a write archive object since filenames should be written
Packit 08bd4c
	 * in UTF-8 by default. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	entry = archive_entry_new2(a);
Packit 08bd4c
	archive_entry_set_pathname(entry, "\xD0\xD2\xC9");
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	archive_entry_set_size(entry, 0);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/* Above three characters in KOI8-R should translate to the following
Packit 08bd4c
	 * three characters (two bytes each) in UTF-8. */
Packit 08bd4c
	assertEqualMem(buff + 512, "15 path=\xD0\xBF\xD1\x80\xD0\xB8\x0A", 15);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Verify that CP1251 filenames are correctly translated to Unicode and UTF-8.
Packit 08bd4c
 */
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding_CP1251)
Packit 08bd4c
{
Packit 08bd4c
  	struct archive *a;
Packit 08bd4c
  	struct archive_entry *entry;
Packit 08bd4c
	char buff[4096];
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "Russian_Russia") &&
Packit 08bd4c
	    NULL == setlocale(LC_ALL, "ru_RU.CP1251")) {
Packit 08bd4c
		skipping("KOI8-R locale not available on this system.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Check if the platform completely supports the string conversion. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
Packit 08bd4c
		skipping("This system cannot convert character-set"
Packit 08bd4c
		    " from KOI8-R to UTF-8.");
Packit 08bd4c
		archive_write_free(a);
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
	archive_write_free(a);
Packit 08bd4c
Packit 08bd4c
	/* Re-create a write archive object since filenames should be written
Packit 08bd4c
	 * in UTF-8 by default. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	entry = archive_entry_new2(a);
Packit 08bd4c
	archive_entry_set_pathname(entry, "\xef\xf0\xe8");
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	archive_entry_set_size(entry, 0);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/* Above three characters in KOI8-R should translate to the following
Packit 08bd4c
	 * three characters (two bytes each) in UTF-8. */
Packit 08bd4c
	assertEqualMem(buff + 512, "15 path=\xD0\xBF\xD1\x80\xD0\xB8\x0A", 15);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Verify that EUC-JP filenames are correctly translated to Unicode and UTF-8.
Packit 08bd4c
 */
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding_EUCJP)
Packit 08bd4c
{
Packit 08bd4c
  	struct archive *a;
Packit 08bd4c
  	struct archive_entry *entry;
Packit 08bd4c
	char buff[4096];
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) {
Packit 08bd4c
		skipping("eucJP locale not available on this system.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Check if the platform completely supports the string conversion. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
Packit 08bd4c
		skipping("This system cannot convert character-set"
Packit 08bd4c
		    " from eucJP to UTF-8.");
Packit 08bd4c
		archive_write_free(a);
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
	archive_write_free(a);
Packit 08bd4c
Packit 08bd4c
	/* Re-create a write archive object since filenames should be written
Packit 08bd4c
	 * in UTF-8 by default. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	entry = archive_entry_new2(a);
Packit 08bd4c
	archive_entry_set_pathname(entry, "\xC9\xBD.txt");
Packit 08bd4c
	/* Check the Unicode version. */
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	archive_entry_set_size(entry, 0);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/* Check UTF-8 version. */
Packit 08bd4c
	assertEqualMem(buff + 512, "16 path=\xE8\xA1\xA8.txt\x0A", 16);
Packit 08bd4c
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Verify that CP932/SJIS filenames are correctly translated to Unicode and UTF-8.
Packit 08bd4c
 */
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding_CP932)
Packit 08bd4c
{
Packit 08bd4c
  	struct archive *a;
Packit 08bd4c
  	struct archive_entry *entry;
Packit 08bd4c
	char buff[4096];
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "Japanese_Japan") &&
Packit 08bd4c
	    NULL == setlocale(LC_ALL, "ja_JP.SJIS")) {
Packit 08bd4c
		skipping("eucJP locale not available on this system.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Check if the platform completely supports the string conversion. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
Packit 08bd4c
		skipping("This system cannot convert character-set"
Packit 08bd4c
		    " from CP932/SJIS to UTF-8.");
Packit 08bd4c
		archive_write_free(a);
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
	archive_write_free(a);
Packit 08bd4c
Packit 08bd4c
	/* Re-create a write archive object since filenames should be written
Packit 08bd4c
	 * in UTF-8 by default. */
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	entry = archive_entry_new2(a);
Packit 08bd4c
	archive_entry_set_pathname(entry, "\x95\x5C.txt");
Packit 08bd4c
	/* Check the Unicode version. */
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	archive_entry_set_size(entry, 0);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/* Check UTF-8 version. */
Packit 08bd4c
	assertEqualMem(buff + 512, "16 path=\xE8\xA1\xA8.txt\x0A", 16);
Packit 08bd4c
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Verify that KOI8-R filenames are not translated to Unicode and UTF-8
Packit 08bd4c
 * when using hdrcharset=BINARY option.
Packit 08bd4c
 */
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding_KOI8R_BINARY)
Packit 08bd4c
{
Packit 08bd4c
  	struct archive *a;
Packit 08bd4c
  	struct archive_entry *entry;
Packit 08bd4c
	char buff[4096];
Packit 08bd4c
	size_t used;
Packit 08bd4c
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) {
Packit 08bd4c
		skipping("KOI8-R locale not available on this system.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	/* BINARY mode should be accepted. */
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_write_set_options(a, "hdrcharset=BINARY"));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK,
Packit 08bd4c
	    archive_write_open_memory(a, buff, sizeof(buff), &used));
Packit 08bd4c
Packit 08bd4c
	entry = archive_entry_new2(a);
Packit 08bd4c
	archive_entry_set_pathname(entry, "\xD0\xD2\xC9");
Packit 08bd4c
	archive_entry_set_filetype(entry, AE_IFREG);
Packit 08bd4c
	archive_entry_set_size(entry, 0);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
Packit 08bd4c
	archive_entry_free(entry);
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
Packit 08bd4c
	/* "hdrcharset=BINARY" pax attribute should be written. */
Packit 08bd4c
	assertEqualMem(buff + 512, "21 hdrcharset=BINARY\x0A", 21);
Packit 08bd4c
	/* Above three characters in KOI8-R should not translate to any
Packit 08bd4c
	 * character-set. */
Packit 08bd4c
	assertEqualMem(buff + 512+21, "12 path=\xD0\xD2\xC9\x0A", 12);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Pax format writer only accepts both BINARY and UTF-8.
Packit 08bd4c
 * If other character-set name is specified, you will get ARCHIVE_FAILED.
Packit 08bd4c
 */
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding_KOI8R_CP1251)
Packit 08bd4c
{
Packit 08bd4c
  	struct archive *a;
Packit 08bd4c
Packit 08bd4c
	if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) {
Packit 08bd4c
		skipping("KOI8-R locale not available on this system.");
Packit 08bd4c
		return;
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	a = archive_write_new();
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a));
Packit 08bd4c
	/* pax format writer only accepts both BINARY and UTF-8. */
Packit 08bd4c
	assertEqualInt(ARCHIVE_FAILED,
Packit 08bd4c
	    archive_write_set_options(a, "hdrcharset=CP1251"));
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
DEFINE_TEST(test_pax_filename_encoding)
Packit 08bd4c
{
Packit 08bd4c
	test_pax_filename_encoding_1();
Packit 08bd4c
	test_pax_filename_encoding_2();
Packit 08bd4c
	test_pax_filename_encoding_3();
Packit 08bd4c
}