1248590Smm/*-
2248590Smm * Copyright (c) 2003-2007 Tim Kientzle
3248590Smm * Copyright (c) 2012 Michihiro NAKAJIMA
4248590Smm * All rights reserved.
5248590Smm *
6248590Smm * Redistribution and use in source and binary forms, with or without
7248590Smm * modification, are permitted provided that the following conditions
8248590Smm * are met:
9248590Smm * 1. Redistributions of source code must retain the above copyright
10248590Smm *    notice, this list of conditions and the following disclaimer.
11248590Smm * 2. Redistributions in binary form must reproduce the above copyright
12248590Smm *    notice, this list of conditions and the following disclaimer in the
13248590Smm *    documentation and/or other materials provided with the distribution.
14248590Smm *
15248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16248590Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17248590Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18248590Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19248590Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20248590Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21248590Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22248590Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23248590Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24248590Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25248590Smm */
26248590Smm#include "test.h"
27248590Smm__FBSDID("$FreeBSD$");
28248590Smm
29248590Smmstatic int
30248590Smmis_null(const char *p, size_t l)
31248590Smm{
32248590Smm	while (l > 0) {
33248590Smm		if (*p != '\0')
34248590Smm			return (0);
35248590Smm		--l;
36248590Smm		++p;
37248590Smm	}
38248590Smm	return (1);
39248590Smm}
40248590Smm
41248590Smm/* Verify the contents, then erase them to NUL bytes. */
42248590Smm/* Tar requires all "unused" bytes be set to NUL; this allows us
43248590Smm * to easily verify that by invoking is_null() over the entire header
44248590Smm * after verifying each field. */
45248590Smm#define myAssertEqualMem(a,b,s) assertEqualMem(a, b, s); memset(a, 0, s)
46248590Smm
47248590Smm/*
48248590Smm * Detailed verification that 'v7tar' archives are written with
49248590Smm * the correct format.
50248590Smm */
51248590SmmDEFINE_TEST(test_write_format_tar_v7tar)
52248590Smm{
53248590Smm	struct archive *a;
54248590Smm	struct archive_entry *entry;
55248590Smm	char *buff, *e;
56248590Smm	size_t buffsize = 100000;
57248590Smm	size_t used;
58248590Smm	int i;
59248590Smm	char f99[100];
60248590Smm	char f100[101];
61248590Smm
62248590Smm	for (i = 0; i < 99; ++i)
63248590Smm		f99[i] = 'a' + i % 26;
64248590Smm	f99[99] = '\0';
65248590Smm
66248590Smm	for (i = 0; i < 100; ++i)
67248590Smm		f100[i] = 'A' + i % 26;
68248590Smm	f100[100] = '\0';
69248590Smm
70248590Smm	buff = malloc(buffsize);
71248590Smm
72248590Smm	/* Create a new archive in memory. */
73248590Smm	assert((a = archive_write_new()) != NULL);
74248590Smm	assertEqualIntA(a, ARCHIVE_OK,
75248590Smm	    archive_write_set_format_v7tar(a));
76248590Smm	assertEqualIntA(a, ARCHIVE_OK,
77248590Smm	    archive_write_add_filter_none(a));
78248590Smm	assertEqualIntA(a, ARCHIVE_OK,
79248590Smm	    archive_write_open_memory(a, buff, buffsize, &used));
80248590Smm
81248590Smm	/*
82248590Smm	 * Add various files to it.
83248590Smm	 * TODO: Extend this to cover more filetypes.
84248590Smm	 */
85248590Smm
86248590Smm	/* "file" with 10 bytes of content */
87248590Smm	assert((entry = archive_entry_new()) != NULL);
88248590Smm	archive_entry_set_mtime(entry, 1, 10);
89248590Smm	archive_entry_set_pathname(entry, "file");
90248590Smm	archive_entry_set_mode(entry, S_IFREG | 0664);
91248590Smm	archive_entry_set_size(entry, 10);
92248590Smm	archive_entry_set_uid(entry, 80);
93248590Smm	archive_entry_set_gid(entry, 90);
94248590Smm	archive_entry_set_dev(entry, 12);
95248590Smm	archive_entry_set_ino(entry, 89);
96248590Smm	archive_entry_set_nlink(entry, 2);
97248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry));
98248590Smm	archive_entry_free(entry);
99248590Smm	assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));
100248590Smm
101248590Smm	/* Hardlink to "file" with 10 bytes of content */
102248590Smm	assert((entry = archive_entry_new()) != NULL);
103248590Smm	archive_entry_set_mtime(entry, 1, 10);
104248590Smm	archive_entry_set_pathname(entry, "linkfile");
105248590Smm	archive_entry_set_hardlink(entry, "file");
106248590Smm	archive_entry_set_mode(entry, S_IFREG | 0664);
107248590Smm	archive_entry_set_size(entry, 10);
108248590Smm	archive_entry_set_uid(entry, 80);
109248590Smm	archive_entry_set_gid(entry, 90);
110248590Smm	archive_entry_set_dev(entry, 12);
111248590Smm	archive_entry_set_ino(entry, 89);
112248590Smm	archive_entry_set_nlink(entry, 2);
113248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry));
114248590Smm	archive_entry_free(entry);
115248590Smm	/* Write of data to dir should fail == zero bytes get written. */
116248590Smm	assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
117248590Smm
118248590Smm	/* "dir" */
119248590Smm	assert((entry = archive_entry_new()) != NULL);
120248590Smm	archive_entry_set_mtime(entry, 2, 20);
121248590Smm	archive_entry_set_pathname(entry, "dir");
122248590Smm	archive_entry_set_mode(entry, S_IFDIR | 0775);
123248590Smm	archive_entry_set_size(entry, 10);
124248590Smm	archive_entry_set_nlink(entry, 2);
125248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry));
126248590Smm	archive_entry_free(entry);
127248590Smm	/* Write of data to dir should fail == zero bytes get written. */
128248590Smm	assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
129248590Smm
130248590Smm	/* "symlink" pointing to "file" */
131248590Smm	assert((entry = archive_entry_new()) != NULL);
132248590Smm	archive_entry_set_mtime(entry, 3, 30);
133248590Smm	archive_entry_set_pathname(entry, "symlink");
134248590Smm	archive_entry_set_mode(entry, 0664);
135248590Smm	archive_entry_set_filetype(entry, AE_IFLNK);
136248590Smm	archive_entry_set_symlink(entry,"file");
137248590Smm	archive_entry_set_size(entry, 0);
138248590Smm	archive_entry_set_uid(entry, 88);
139248590Smm	archive_entry_set_gid(entry, 98);
140248590Smm	archive_entry_set_dev(entry, 12);
141248590Smm	archive_entry_set_ino(entry, 90);
142248590Smm	archive_entry_set_nlink(entry, 1);
143248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry));
144248590Smm	archive_entry_free(entry);
145248590Smm
146248590Smm	/* file with 99-char filename. */
147248590Smm	assert((entry = archive_entry_new()) != NULL);
148248590Smm	archive_entry_set_mtime(entry, 1, 10);
149248590Smm	archive_entry_set_pathname(entry, f99);
150248590Smm	archive_entry_set_mode(entry, S_IFREG | 0664);
151248590Smm	archive_entry_set_size(entry, 0);
152248590Smm	archive_entry_set_uid(entry, 82);
153248590Smm	archive_entry_set_gid(entry, 93);
154248590Smm	archive_entry_set_dev(entry, 102);
155248590Smm	archive_entry_set_ino(entry, 7);
156248590Smm	archive_entry_set_nlink(entry, 1);
157248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry));
158248590Smm	archive_entry_free(entry);
159248590Smm
160248590Smm	/* file with 100-char filename. */
161248590Smm	assert((entry = archive_entry_new()) != NULL);
162248590Smm	archive_entry_set_mtime(entry, 1, 10);
163248590Smm	archive_entry_set_pathname(entry, f100);
164248590Smm	archive_entry_set_mode(entry, S_IFREG | 0664);
165248590Smm	archive_entry_set_size(entry, 0);
166248590Smm	archive_entry_set_uid(entry, 82);
167248590Smm	archive_entry_set_gid(entry, 93);
168248590Smm	archive_entry_set_dev(entry, 102);
169248590Smm	archive_entry_set_ino(entry, 7);
170248590Smm	archive_entry_set_nlink(entry, 1);
171248590Smm	failure("100-char filename should be rejected");
172248590Smm	assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, entry));
173248590Smm	archive_entry_free(entry);
174248590Smm
175248590Smm	/* Close out the archive. */
176248590Smm	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
177248590Smm
178248590Smm	/*
179248590Smm	 * Verify the archive format.
180248590Smm	 */
181248590Smm	e = buff;
182248590Smm
183248590Smm	/* "file" */
184248590Smm	myAssertEqualMem(e + 0, "file", 5); /* Filename */
185248590Smm	myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
186248590Smm	myAssertEqualMem(e + 108, "000120 ", 8); /* uid */
187248590Smm	myAssertEqualMem(e + 116, "000132 ", 8); /* gid */
188248590Smm	myAssertEqualMem(e + 124, "00000000012 ", 12); /* size */
189248590Smm	myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
190248590Smm	myAssertEqualMem(e + 148, "005335\0 ", 8); /* checksum */
191248590Smm	myAssertEqualMem(e + 156, "", 1); /* linkflag */
192248590Smm	myAssertEqualMem(e + 157, "", 1); /* linkname */
193248590Smm	assert(is_null(e + 0, 512));
194248590Smm	myAssertEqualMem(e + 512, "1234567890", 10);
195248590Smm	assert(is_null(e + 512, 512));
196248590Smm	e += 1024;
197248590Smm
198248590Smm	/* hardlink to "file" */
199248590Smm	myAssertEqualMem(e + 0, "linkfile", 9); /* Filename */
200248590Smm	myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
201248590Smm	myAssertEqualMem(e + 108, "000120 ", 8); /* uid */
202248590Smm	myAssertEqualMem(e + 116, "000132 ", 8); /* gid */
203248590Smm	myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
204248590Smm	myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
205248590Smm	myAssertEqualMem(e + 148, "007131\0 ", 8); /* checksum */
206248590Smm	myAssertEqualMem(e + 156, "1", 1); /* linkflag */
207248590Smm	myAssertEqualMem(e + 157, "file", 5); /* linkname */
208248590Smm	assert(is_null(e + 0, 512));
209248590Smm	e += 512;
210248590Smm
211248590Smm	/* "dir" */
212248590Smm	myAssertEqualMem(e + 0, "dir/", 4); /* Filename */
213248590Smm	myAssertEqualMem(e + 100, "000775 ", 8); /* mode */
214248590Smm	myAssertEqualMem(e + 108, "000000 ", 8); /* uid */
215248590Smm	myAssertEqualMem(e + 116, "000000 ", 8); /* gid */
216248590Smm	myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
217248590Smm	myAssertEqualMem(e + 136, "00000000002 ", 12); /* mtime */
218248590Smm	myAssertEqualMem(e + 148, "005243\0 ", 8); /* checksum */
219248590Smm	myAssertEqualMem(e + 156, "", 1); /* typeflag */
220248590Smm	myAssertEqualMem(e + 157, "", 1); /* linkname */
221248590Smm	assert(is_null(e + 0, 512));
222248590Smm	e += 512;
223248590Smm
224248590Smm	/* "symlink" pointing to "file" */
225248590Smm	myAssertEqualMem(e + 0, "symlink", 8); /* Filename */
226248590Smm	myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
227248590Smm	myAssertEqualMem(e + 108, "000130 ", 8); /* uid */
228248590Smm	myAssertEqualMem(e + 116, "000142 ", 8); /* gid */
229248590Smm	myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
230248590Smm	myAssertEqualMem(e + 136, "00000000003 ", 12); /* mtime */
231248590Smm	myAssertEqualMem(e + 148, "007027\0 ", 8); /* checksum */
232248590Smm	myAssertEqualMem(e + 156, "2", 1); /* linkflag */
233248590Smm	myAssertEqualMem(e + 157, "file", 5); /* linkname */
234248590Smm	assert(is_null(e + 0, 512));
235248590Smm	e += 512;
236248590Smm
237248590Smm	/* File with 99-char filename */
238248590Smm	myAssertEqualMem(e + 0, f99, 100); /* Filename */
239248590Smm	myAssertEqualMem(e + 100, "000664 ", 8); /* mode */
240248590Smm	myAssertEqualMem(e + 108, "000122 ", 8); /* uid */
241248590Smm	myAssertEqualMem(e + 116, "000135 ", 8); /* gid */
242248590Smm	myAssertEqualMem(e + 124, "00000000000 ", 12); /* size */
243248590Smm	myAssertEqualMem(e + 136, "00000000001 ", 12); /* mtime */
244248590Smm	myAssertEqualMem(e + 148, "031543\0 ", 8); /* checksum */
245248590Smm	myAssertEqualMem(e + 156, "", 1); /* linkflag */
246248590Smm	myAssertEqualMem(e + 157, "", 1); /* linkname */
247248590Smm	assert(is_null(e + 0, 512));
248248590Smm	e += 512;
249248590Smm
250248590Smm	/* TODO: Verify other types of entries. */
251248590Smm
252248590Smm	/* Last entry is end-of-archive marker. */
253248590Smm	assert(is_null(e, 1024));
254248590Smm	e += 1024;
255248590Smm
256248590Smm	assertEqualInt((int)used, e - buff);
257248590Smm
258248590Smm	free(buff);
259248590Smm}
260