1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 Tim Kientzle
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24228753Smm */
25228753Smm#include "test.h"
26228763Smm__FBSDID("$FreeBSD$");
27228753Smm
28228753Smmstatic void test_linkify_tar(void)
29228753Smm{
30228753Smm	struct archive_entry *entry, *e2;
31228753Smm	struct archive_entry_linkresolver *resolver;
32228753Smm
33228753Smm	/* Initialize the resolver. */
34228753Smm	assert(NULL != (resolver = archive_entry_linkresolver_new()));
35228753Smm	archive_entry_linkresolver_set_strategy(resolver,
36228753Smm	    ARCHIVE_FORMAT_TAR_USTAR);
37228753Smm
38228753Smm	/* Create an entry with only 1 link and try to linkify it. */
39228753Smm	assert(NULL != (entry = archive_entry_new()));
40228753Smm	archive_entry_set_pathname(entry, "test1");
41228753Smm	archive_entry_set_ino(entry, 1);
42228753Smm	archive_entry_set_dev(entry, 2);
43228753Smm	archive_entry_set_nlink(entry, 1);
44228753Smm	archive_entry_set_size(entry, 10);
45228753Smm	archive_entry_linkify(resolver, &entry, &e2);
46228753Smm
47228753Smm	/* Shouldn't have been changed. */
48228753Smm	assert(e2 == NULL);
49228753Smm	assertEqualInt(10, archive_entry_size(entry));
50228753Smm	assertEqualString("test1", archive_entry_pathname(entry));
51228753Smm
52228753Smm	/* Now, try again with an entry that has 2 links. */
53228753Smm	archive_entry_set_pathname(entry, "test2");
54228753Smm	archive_entry_set_nlink(entry, 2);
55228753Smm	archive_entry_set_ino(entry, 2);
56228753Smm	archive_entry_linkify(resolver, &entry, &e2);
57228753Smm	/* Shouldn't be altered, since it wasn't seen before. */
58228753Smm	assert(e2 == NULL);
59228753Smm	assertEqualString("test2", archive_entry_pathname(entry));
60228753Smm	assertEqualString(NULL, archive_entry_hardlink(entry));
61228753Smm	assertEqualInt(10, archive_entry_size(entry));
62228753Smm
63228753Smm	/* Match again and make sure it does get altered. */
64228753Smm	archive_entry_linkify(resolver, &entry, &e2);
65228753Smm	assert(e2 == NULL);
66228753Smm	assertEqualString("test2", archive_entry_pathname(entry));
67228753Smm	assertEqualString("test2", archive_entry_hardlink(entry));
68228753Smm	assertEqualInt(0, archive_entry_size(entry));
69228753Smm
70228753Smm
71228753Smm	/* Dirs should never be matched as hardlinks, regardless. */
72228753Smm	archive_entry_set_pathname(entry, "test3");
73228753Smm	archive_entry_set_nlink(entry, 2);
74228753Smm	archive_entry_set_filetype(entry, AE_IFDIR);
75228753Smm	archive_entry_set_ino(entry, 3);
76228753Smm	archive_entry_set_hardlink(entry, NULL);
77228753Smm	archive_entry_linkify(resolver, &entry, &e2);
78228753Smm	/* Shouldn't be altered, since it wasn't seen before. */
79228753Smm	assert(e2 == NULL);
80228753Smm	assertEqualString("test3", archive_entry_pathname(entry));
81228753Smm	assertEqualString(NULL, archive_entry_hardlink(entry));
82228753Smm
83228753Smm	/* Dir, so it shouldn't get matched. */
84228753Smm	archive_entry_linkify(resolver, &entry, &e2);
85228753Smm	assert(e2 == NULL);
86228753Smm	assertEqualString("test3", archive_entry_pathname(entry));
87228753Smm	assertEqualString(NULL, archive_entry_hardlink(entry));
88228753Smm
89228753Smm	archive_entry_free(entry);
90228753Smm	archive_entry_linkresolver_free(resolver);
91228753Smm}
92228753Smm
93228753Smmstatic void test_linkify_old_cpio(void)
94228753Smm{
95228753Smm	struct archive_entry *entry, *e2;
96228753Smm	struct archive_entry_linkresolver *resolver;
97228753Smm
98228753Smm	/* Initialize the resolver. */
99228753Smm	assert(NULL != (resolver = archive_entry_linkresolver_new()));
100228753Smm	archive_entry_linkresolver_set_strategy(resolver,
101228753Smm	    ARCHIVE_FORMAT_CPIO_POSIX);
102228753Smm
103228753Smm	/* Create an entry with 2 link and try to linkify it. */
104228753Smm	assert(NULL != (entry = archive_entry_new()));
105228753Smm	archive_entry_set_pathname(entry, "test1");
106228753Smm	archive_entry_set_ino(entry, 1);
107228753Smm	archive_entry_set_dev(entry, 2);
108228753Smm	archive_entry_set_nlink(entry, 2);
109228753Smm	archive_entry_set_size(entry, 10);
110228753Smm	archive_entry_linkify(resolver, &entry, &e2);
111228753Smm
112228753Smm	/* Shouldn't have been changed. */
113228753Smm	assert(e2 == NULL);
114228753Smm	assertEqualInt(10, archive_entry_size(entry));
115228753Smm	assertEqualString("test1", archive_entry_pathname(entry));
116228753Smm
117228753Smm	/* Still shouldn't be matched. */
118228753Smm	archive_entry_linkify(resolver, &entry, &e2);
119228753Smm	assert(e2 == NULL);
120228753Smm	assertEqualString("test1", archive_entry_pathname(entry));
121228753Smm	assertEqualString(NULL, archive_entry_hardlink(entry));
122228753Smm	assertEqualInt(10, archive_entry_size(entry));
123228753Smm
124228753Smm	archive_entry_free(entry);
125228753Smm	archive_entry_linkresolver_free(resolver);
126228753Smm}
127228753Smm
128228753Smmstatic void test_linkify_new_cpio(void)
129228753Smm{
130228753Smm	struct archive_entry *entry, *e2;
131228753Smm	struct archive_entry_linkresolver *resolver;
132228753Smm
133228753Smm	/* Initialize the resolver. */
134228753Smm	assert(NULL != (resolver = archive_entry_linkresolver_new()));
135228753Smm	archive_entry_linkresolver_set_strategy(resolver,
136228753Smm	    ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);
137228753Smm
138228753Smm	/* Create an entry with only 1 link and try to linkify it. */
139228753Smm	assert(NULL != (entry = archive_entry_new()));
140228753Smm	archive_entry_set_pathname(entry, "test1");
141228753Smm	archive_entry_set_ino(entry, 1);
142228753Smm	archive_entry_set_dev(entry, 2);
143228753Smm	archive_entry_set_nlink(entry, 1);
144228753Smm	archive_entry_set_size(entry, 10);
145228753Smm	archive_entry_linkify(resolver, &entry, &e2);
146228753Smm
147228753Smm	/* Shouldn't have been changed. */
148228753Smm	assert(e2 == NULL);
149228753Smm	assertEqualInt(10, archive_entry_size(entry));
150228753Smm	assertEqualString("test1", archive_entry_pathname(entry));
151228753Smm
152228753Smm	/* Now, try again with an entry that has 3 links. */
153228753Smm	archive_entry_set_pathname(entry, "test2");
154228753Smm	archive_entry_set_nlink(entry, 3);
155228753Smm	archive_entry_set_ino(entry, 2);
156228753Smm	archive_entry_linkify(resolver, &entry, &e2);
157228753Smm
158228753Smm	/* First time, it just gets swallowed. */
159228753Smm	assert(entry == NULL);
160228753Smm	assert(e2 == NULL);
161228753Smm
162228753Smm	/* Match again. */
163228753Smm	assert(NULL != (entry = archive_entry_new()));
164228753Smm	archive_entry_set_pathname(entry, "test3");
165228753Smm	archive_entry_set_ino(entry, 2);
166228753Smm	archive_entry_set_dev(entry, 2);
167228753Smm	archive_entry_set_nlink(entry, 2);
168228753Smm	archive_entry_set_size(entry, 10);
169228753Smm	archive_entry_linkify(resolver, &entry, &e2);
170228753Smm
171228753Smm	/* Should get back "test2" and nothing else. */
172228753Smm	assertEqualString("test2", archive_entry_pathname(entry));
173228753Smm	assertEqualInt(0, archive_entry_size(entry));
174228753Smm	archive_entry_free(entry);
175228753Smm	assert(NULL == e2);
176228753Smm	archive_entry_free(e2); /* This should be a no-op. */
177228753Smm
178228753Smm	/* Match a third time. */
179228753Smm	assert(NULL != (entry = archive_entry_new()));
180228753Smm	archive_entry_set_pathname(entry, "test4");
181228753Smm	archive_entry_set_ino(entry, 2);
182228753Smm	archive_entry_set_dev(entry, 2);
183228753Smm	archive_entry_set_nlink(entry, 3);
184228753Smm	archive_entry_set_size(entry, 10);
185228753Smm	archive_entry_linkify(resolver, &entry, &e2);
186228753Smm
187228753Smm	/* Should get back "test3". */
188228753Smm	assertEqualString("test3", archive_entry_pathname(entry));
189228753Smm	assertEqualInt(0, archive_entry_size(entry));
190228753Smm
191228753Smm	/* Since "test4" was the last link, should get it back also. */
192228753Smm	assertEqualString("test4", archive_entry_pathname(e2));
193228753Smm	assertEqualInt(10, archive_entry_size(e2));
194228753Smm
195228753Smm	archive_entry_free(entry);
196228753Smm	archive_entry_free(e2);
197228753Smm	archive_entry_linkresolver_free(resolver);
198228753Smm}
199228753Smm
200228753SmmDEFINE_TEST(test_link_resolver)
201228753Smm{
202228753Smm	test_linkify_tar();
203228753Smm	test_linkify_old_cpio();
204228753Smm	test_linkify_new_cpio();
205228753Smm}
206