1/*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25#include "test.h"
26__FBSDID("$FreeBSD: head/lib/libarchive/test/test_entry.c 201247 2009-12-30 05:59:21Z kientzle $");
27
28#include <locale.h>
29
30/*
31 * Most of these tests are system-independent, though a few depend on
32 * features of the local system.  Such tests are conditionalized on
33 * the platform name.  On unsupported platforms, only the
34 * system-independent features will be tested.
35 *
36 * No, I don't want to use config.h in the test files because I want
37 * the tests to also serve as a check on the correctness of config.h.
38 * A mis-configured library build should cause tests to fail.
39 */
40
41DEFINE_TEST(test_entry)
42{
43	char buff[128];
44	wchar_t wbuff[128];
45	struct stat st;
46	struct archive_entry *e, *e2;
47	const struct stat *pst;
48	unsigned long set, clear; /* For fflag testing. */
49	int type, permset, tag, qual; /* For ACL testing. */
50	const char *name; /* For ACL testing. */
51	const char *xname; /* For xattr tests. */
52	const void *xval; /* For xattr tests. */
53	size_t xsize; /* For xattr tests. */
54	wchar_t wc;
55	long l;
56
57	assert((e = archive_entry_new()) != NULL);
58
59	/*
60	 * Verify that the AE_IF* defines match S_IF* defines
61	 * on this platform. See comments in archive_entry.h.
62	 */
63#ifdef S_IFREG
64	assertEqualInt(S_IFREG, AE_IFREG);
65#endif
66#ifdef S_IFLNK
67	assertEqualInt(S_IFLNK, AE_IFLNK);
68#endif
69#ifdef S_IFSOCK
70	assertEqualInt(S_IFSOCK, AE_IFSOCK);
71#endif
72#ifdef S_IFCHR
73	assertEqualInt(S_IFCHR, AE_IFCHR);
74#endif
75/* Work around MinGW, which defines S_IFBLK wrong. */
76/* sourceforge.net/tracker/?func=detail&atid=102435&aid=1942809&group_id=2435 */
77#if defined(S_IFBLK) && !defined(_WIN32)
78	assertEqualInt(S_IFBLK, AE_IFBLK);
79#endif
80#ifdef S_IFDIR
81	assertEqualInt(S_IFDIR, AE_IFDIR);
82#endif
83#ifdef S_IFIFO
84	assertEqualInt(S_IFIFO, AE_IFIFO);
85#endif
86
87	/*
88	 * Basic set/read tests for all fields.
89	 * We should be able to set any field and read
90	 * back the same value.
91	 *
92	 * For methods that "copy" a string, we should be able
93	 * to overwrite the original passed-in string without
94	 * changing the value in the entry.
95	 *
96	 * The following tests are ordered alphabetically by the
97	 * name of the field.
98	 */
99
100	/* atime */
101	archive_entry_set_atime(e, 13579, 24680);
102	assertEqualInt(archive_entry_atime(e), 13579);
103	assertEqualInt(archive_entry_atime_nsec(e), 24680);
104	archive_entry_unset_atime(e);
105	assertEqualInt(archive_entry_atime(e), 0);
106	assertEqualInt(archive_entry_atime_nsec(e), 0);
107	assert(!archive_entry_atime_is_set(e));
108
109	/* birthtime */
110	archive_entry_set_birthtime(e, 17579, 24990);
111	assertEqualInt(archive_entry_birthtime(e), 17579);
112	assertEqualInt(archive_entry_birthtime_nsec(e), 24990);
113	archive_entry_unset_birthtime(e);
114	assertEqualInt(archive_entry_birthtime(e), 0);
115	assertEqualInt(archive_entry_birthtime_nsec(e), 0);
116	assert(!archive_entry_birthtime_is_set(e));
117
118	/* ctime */
119	archive_entry_set_ctime(e, 13580, 24681);
120	assertEqualInt(archive_entry_ctime(e), 13580);
121	assertEqualInt(archive_entry_ctime_nsec(e), 24681);
122	archive_entry_unset_ctime(e);
123	assertEqualInt(archive_entry_ctime(e), 0);
124	assertEqualInt(archive_entry_ctime_nsec(e), 0);
125	assert(!archive_entry_ctime_is_set(e));
126
127#if ARCHIVE_VERSION_NUMBER >= 1009000
128	/* dev */
129	archive_entry_set_dev(e, 235);
130	assertEqualInt(archive_entry_dev(e), 235);
131#else
132	skipping("archive_entry_dev()");
133#endif
134	/* devmajor/devminor are tested specially below. */
135
136#if ARCHIVE_VERSION_NUMBER >= 1009000
137	/* filetype */
138	archive_entry_set_filetype(e, AE_IFREG);
139	assertEqualInt(archive_entry_filetype(e), AE_IFREG);
140#else
141	skipping("archive_entry_filetype()");
142#endif
143
144	/* fflags are tested specially below */
145
146	/* gid */
147	archive_entry_set_gid(e, 204);
148	assertEqualInt(archive_entry_gid(e), 204);
149
150	/* gname */
151	archive_entry_set_gname(e, "group");
152	assertEqualString(archive_entry_gname(e), "group");
153	wcscpy(wbuff, L"wgroup");
154	archive_entry_copy_gname_w(e, wbuff);
155	assertEqualWString(archive_entry_gname_w(e), L"wgroup");
156	memset(wbuff, 0, sizeof(wbuff));
157	assertEqualWString(archive_entry_gname_w(e), L"wgroup");
158
159	/* hardlink */
160	archive_entry_set_hardlink(e, "hardlinkname");
161	assertEqualString(archive_entry_hardlink(e), "hardlinkname");
162	strcpy(buff, "hardlinkname2");
163	archive_entry_copy_hardlink(e, buff);
164	assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
165	memset(buff, 0, sizeof(buff));
166	assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
167	archive_entry_copy_hardlink(e, NULL);
168	assertEqualString(archive_entry_hardlink(e), NULL);
169	assertEqualWString(archive_entry_hardlink_w(e), NULL);
170	wcscpy(wbuff, L"whardlink");
171	archive_entry_copy_hardlink_w(e, wbuff);
172	assertEqualWString(archive_entry_hardlink_w(e), L"whardlink");
173	memset(wbuff, 0, sizeof(wbuff));
174	assertEqualWString(archive_entry_hardlink_w(e), L"whardlink");
175	archive_entry_copy_hardlink_w(e, NULL);
176	assertEqualString(archive_entry_hardlink(e), NULL);
177	assertEqualWString(archive_entry_hardlink_w(e), NULL);
178#if ARCHIVE_VERSION_NUMBER >= 1009000
179	/* ino */
180	archive_entry_set_ino(e, 8593);
181	assertEqualInt(archive_entry_ino(e), 8593);
182#else
183	skipping("archive_entry_ino()");
184#endif
185
186	/* link */
187	archive_entry_set_hardlink(e, "hardlinkname");
188	archive_entry_set_symlink(e, NULL);
189	archive_entry_set_link(e, "link");
190	assertEqualString(archive_entry_hardlink(e), "link");
191	assertEqualString(archive_entry_symlink(e), NULL);
192	archive_entry_copy_link(e, "link2");
193	assertEqualString(archive_entry_hardlink(e), "link2");
194	assertEqualString(archive_entry_symlink(e), NULL);
195	archive_entry_copy_link_w(e, L"link3");
196	assertEqualString(archive_entry_hardlink(e), "link3");
197	assertEqualString(archive_entry_symlink(e), NULL);
198	archive_entry_set_hardlink(e, NULL);
199	archive_entry_set_symlink(e, "symlink");
200	archive_entry_set_link(e, "link");
201	assertEqualString(archive_entry_hardlink(e), NULL);
202	assertEqualString(archive_entry_symlink(e), "link");
203	archive_entry_copy_link(e, "link2");
204	assertEqualString(archive_entry_hardlink(e), NULL);
205	assertEqualString(archive_entry_symlink(e), "link2");
206	archive_entry_copy_link_w(e, L"link3");
207	assertEqualString(archive_entry_hardlink(e), NULL);
208	assertEqualString(archive_entry_symlink(e), "link3");
209	/* Arbitrarily override symlink if both hardlink and symlink set. */
210	archive_entry_set_hardlink(e, "hardlink");
211	archive_entry_set_symlink(e, "symlink");
212	archive_entry_set_link(e, "link");
213	assertEqualString(archive_entry_hardlink(e), "hardlink");
214	assertEqualString(archive_entry_symlink(e), "link");
215
216	/* mode */
217	archive_entry_set_mode(e, 0123456);
218	assertEqualInt(archive_entry_mode(e), 0123456);
219
220	/* mtime */
221	archive_entry_set_mtime(e, 13581, 24682);
222	assertEqualInt(archive_entry_mtime(e), 13581);
223	assertEqualInt(archive_entry_mtime_nsec(e), 24682);
224	archive_entry_unset_mtime(e);
225	assertEqualInt(archive_entry_mtime(e), 0);
226	assertEqualInt(archive_entry_mtime_nsec(e), 0);
227	assert(!archive_entry_mtime_is_set(e));
228
229#if ARCHIVE_VERSION_NUMBER >= 1009000
230	/* nlink */
231	archive_entry_set_nlink(e, 736);
232	assertEqualInt(archive_entry_nlink(e), 736);
233#else
234	skipping("archive_entry_nlink()");
235#endif
236
237	/* pathname */
238	archive_entry_set_pathname(e, "path");
239	assertEqualString(archive_entry_pathname(e), "path");
240	archive_entry_set_pathname(e, "path");
241	assertEqualString(archive_entry_pathname(e), "path");
242	strcpy(buff, "path2");
243	archive_entry_copy_pathname(e, buff);
244	assertEqualString(archive_entry_pathname(e), "path2");
245	memset(buff, 0, sizeof(buff));
246	assertEqualString(archive_entry_pathname(e), "path2");
247	wcscpy(wbuff, L"wpath");
248	archive_entry_copy_pathname_w(e, wbuff);
249	assertEqualWString(archive_entry_pathname_w(e), L"wpath");
250	memset(wbuff, 0, sizeof(wbuff));
251	assertEqualWString(archive_entry_pathname_w(e), L"wpath");
252
253#if ARCHIVE_VERSION_NUMBER >= 1009000
254	/* rdev */
255	archive_entry_set_rdev(e, 532);
256	assertEqualInt(archive_entry_rdev(e), 532);
257#else
258	skipping("archive_entry_rdev()");
259#endif
260	/* rdevmajor/rdevminor are tested specially below. */
261
262	/* size */
263	archive_entry_set_size(e, 987654321);
264	assertEqualInt(archive_entry_size(e), 987654321);
265	archive_entry_unset_size(e);
266	assertEqualInt(archive_entry_size(e), 0);
267	assert(!archive_entry_size_is_set(e));
268
269	/* sourcepath */
270	archive_entry_copy_sourcepath(e, "path1");
271	assertEqualString(archive_entry_sourcepath(e), "path1");
272
273	/* symlink */
274	archive_entry_set_symlink(e, "symlinkname");
275	assertEqualString(archive_entry_symlink(e), "symlinkname");
276#if ARCHIVE_VERSION_NUMBER >= 1009000
277	strcpy(buff, "symlinkname2");
278	archive_entry_copy_symlink(e, buff);
279	assertEqualString(archive_entry_symlink(e), "symlinkname2");
280	memset(buff, 0, sizeof(buff));
281	assertEqualString(archive_entry_symlink(e), "symlinkname2");
282#endif
283	archive_entry_copy_symlink_w(e, NULL);
284	assertEqualWString(archive_entry_symlink_w(e), NULL);
285	assertEqualString(archive_entry_symlink(e), NULL);
286	archive_entry_copy_symlink_w(e, L"wsymlink");
287	assertEqualWString(archive_entry_symlink_w(e), L"wsymlink");
288	archive_entry_copy_symlink(e, NULL);
289	assertEqualWString(archive_entry_symlink_w(e), NULL);
290	assertEqualString(archive_entry_symlink(e), NULL);
291
292	/* uid */
293	archive_entry_set_uid(e, 83);
294	assertEqualInt(archive_entry_uid(e), 83);
295
296	/* uname */
297	archive_entry_set_uname(e, "user");
298	assertEqualString(archive_entry_uname(e), "user");
299	wcscpy(wbuff, L"wuser");
300	archive_entry_copy_gname_w(e, wbuff);
301	assertEqualWString(archive_entry_gname_w(e), L"wuser");
302	memset(wbuff, 0, sizeof(wbuff));
303	assertEqualWString(archive_entry_gname_w(e), L"wuser");
304
305	/* Test fflags interface. */
306	archive_entry_set_fflags(e, 0x55, 0xAA);
307	archive_entry_fflags(e, &set, &clear);
308	failure("Testing set/get of fflags data.");
309	assertEqualInt(set, 0x55);
310	failure("Testing set/get of fflags data.");
311	assertEqualInt(clear, 0xAA);
312#ifdef __FreeBSD__
313	/* Converting fflags bitmap to string is currently system-dependent. */
314	/* TODO: Make this system-independent. */
315	assertEqualString(archive_entry_fflags_text(e),
316	    "uappnd,nouchg,nodump,noopaque,uunlnk");
317	/* Test archive_entry_copy_fflags_text_w() */
318	archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,uunlnk");
319	archive_entry_fflags(e, &set, &clear);
320	assertEqualInt(16, set);
321	assertEqualInt(7, clear);
322	/* Test archive_entry_copy_fflags_text() */
323	archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,uunlnk");
324	archive_entry_fflags(e, &set, &clear);
325	assertEqualInt(16, set);
326	assertEqualInt(7, clear);
327#endif
328
329	/* See test_acl_basic.c for tests of ACL set/get consistency. */
330
331	/* Test xattrs set/get consistency. */
332	archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12);
333	assertEqualInt(1, archive_entry_xattr_reset(e));
334	assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
335	assertEqualString(xname, "xattr1");
336	assertEqualString(xval, "xattrvalue1");
337	assertEqualInt((int)xsize, 12);
338	assertEqualInt(1, archive_entry_xattr_count(e));
339	assertEqualInt(ARCHIVE_WARN,
340	    archive_entry_xattr_next(e, &xname, &xval, &xsize));
341	assertEqualString(xname, NULL);
342	assertEqualString(xval, NULL);
343	assertEqualInt((int)xsize, 0);
344	archive_entry_xattr_clear(e);
345	assertEqualInt(0, archive_entry_xattr_reset(e));
346	assertEqualInt(ARCHIVE_WARN,
347	    archive_entry_xattr_next(e, &xname, &xval, &xsize));
348	assertEqualString(xname, NULL);
349	assertEqualString(xval, NULL);
350	assertEqualInt((int)xsize, 0);
351	archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12);
352	assertEqualInt(1, archive_entry_xattr_reset(e));
353	archive_entry_xattr_add_entry(e, "xattr2", "xattrvalue2", 12);
354	assertEqualInt(2, archive_entry_xattr_reset(e));
355	assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
356	assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
357	assertEqualInt(ARCHIVE_WARN,
358	    archive_entry_xattr_next(e, &xname, &xval, &xsize));
359	assertEqualString(xname, NULL);
360	assertEqualString(xval, NULL);
361	assertEqualInt((int)xsize, 0);
362
363
364	/*
365	 * Test clone() implementation.
366	 */
367
368	/* Set values in 'e' */
369	archive_entry_clear(e);
370	archive_entry_set_atime(e, 13579, 24680);
371	archive_entry_set_birthtime(e, 13779, 24990);
372	archive_entry_set_ctime(e, 13580, 24681);
373#if ARCHIVE_VERSION_NUMBER >= 1009000
374	archive_entry_set_dev(e, 235);
375#endif
376	archive_entry_set_fflags(e, 0x55, 0xAA);
377	archive_entry_set_gid(e, 204);
378	archive_entry_set_gname(e, "group");
379	archive_entry_set_hardlink(e, "hardlinkname");
380#if ARCHIVE_VERSION_NUMBER >= 1009000
381	archive_entry_set_ino(e, 8593);
382#endif
383	archive_entry_set_mode(e, 0123456);
384	archive_entry_set_mtime(e, 13581, 24682);
385#if ARCHIVE_VERSION_NUMBER >= 1009000
386	archive_entry_set_nlink(e, 736);
387#endif
388	archive_entry_set_pathname(e, "path");
389#if ARCHIVE_VERSION_NUMBER >= 1009000
390	archive_entry_set_rdev(e, 532);
391#endif
392	archive_entry_set_size(e, 987654321);
393	archive_entry_copy_sourcepath(e, "source");
394	archive_entry_set_symlink(e, "symlinkname");
395	archive_entry_set_uid(e, 83);
396	archive_entry_set_uname(e, "user");
397	/* Add an ACL entry. */
398	archive_entry_acl_add_entry(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
399	    ARCHIVE_ENTRY_ACL_READ, ARCHIVE_ENTRY_ACL_USER, 77, "user77");
400	/* Add an extended attribute. */
401	archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue", 11);
402
403	/* Make a clone. */
404	e2 = archive_entry_clone(e);
405
406	/* Clone should have same contents. */
407	assertEqualInt(archive_entry_atime(e2), 13579);
408	assertEqualInt(archive_entry_atime_nsec(e2), 24680);
409	assertEqualInt(archive_entry_birthtime(e2), 13779);
410	assertEqualInt(archive_entry_birthtime_nsec(e2), 24990);
411	assertEqualInt(archive_entry_ctime(e2), 13580);
412	assertEqualInt(archive_entry_ctime_nsec(e2), 24681);
413#if ARCHIVE_VERSION_NUMBER >= 1009000
414	assertEqualInt(archive_entry_dev(e2), 235);
415#endif
416	archive_entry_fflags(e, &set, &clear);
417	assertEqualInt(clear, 0xAA);
418	assertEqualInt(set, 0x55);
419	assertEqualInt(archive_entry_gid(e2), 204);
420	assertEqualString(archive_entry_gname(e2), "group");
421	assertEqualString(archive_entry_hardlink(e2), "hardlinkname");
422#if ARCHIVE_VERSION_NUMBER >= 1009000
423	assertEqualInt(archive_entry_ino(e2), 8593);
424#endif
425	assertEqualInt(archive_entry_mode(e2), 0123456);
426	assertEqualInt(archive_entry_mtime(e2), 13581);
427	assertEqualInt(archive_entry_mtime_nsec(e2), 24682);
428#if ARCHIVE_VERSION_NUMBER >= 1009000
429	assertEqualInt(archive_entry_nlink(e2), 736);
430#endif
431	assertEqualString(archive_entry_pathname(e2), "path");
432#if ARCHIVE_VERSION_NUMBER >= 1009000
433	assertEqualInt(archive_entry_rdev(e2), 532);
434#endif
435	assertEqualInt(archive_entry_size(e2), 987654321);
436	assertEqualString(archive_entry_sourcepath(e2), "source");
437	assertEqualString(archive_entry_symlink(e2), "symlinkname");
438	assertEqualInt(archive_entry_uid(e2), 83);
439	assertEqualString(archive_entry_uname(e2), "user");
440#if ARCHIVE_VERSION_NUMBER < 1009000
441	skipping("ACL preserved by archive_entry_clone()");
442#else
443	/* Verify ACL was copied. */
444	assertEqualInt(4, archive_entry_acl_reset(e2,
445			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
446	/* First three are standard permission bits. */
447	assertEqualInt(0, archive_entry_acl_next(e2,
448			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
449			   &type, &permset, &tag, &qual, &name));
450	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
451	assertEqualInt(permset, 4);
452	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ);
453	assertEqualInt(qual, -1);
454	assertEqualString(name, NULL);
455	assertEqualInt(0, archive_entry_acl_next(e2,
456			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
457			   &type, &permset, &tag, &qual, &name));
458	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
459	assertEqualInt(permset, 5);
460	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ);
461	assertEqualInt(qual, -1);
462	assertEqualString(name, NULL);
463	assertEqualInt(0, archive_entry_acl_next(e2,
464			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
465			   &type, &permset, &tag, &qual, &name));
466	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
467	assertEqualInt(permset, 6);
468	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER);
469	assertEqualInt(qual, -1);
470	assertEqualString(name, NULL);
471	/* Fourth is custom one. */
472	assertEqualInt(0, archive_entry_acl_next(e2,
473			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
474			   &type, &permset, &tag, &qual, &name));
475	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
476	assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ);
477	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER);
478	assertEqualInt(qual, 77);
479	assertEqualString(name, "user77");
480#endif
481#if ARCHIVE_VERSION_NUMBER < 1009000
482	skipping("xattr data preserved by archive_entry_clone");
483#else
484	/* Verify xattr was copied. */
485	assertEqualInt(1, archive_entry_xattr_reset(e2));
486	assertEqualInt(0, archive_entry_xattr_next(e2, &xname, &xval, &xsize));
487	assertEqualString(xname, "xattr1");
488	assertEqualString(xval, "xattrvalue");
489	assertEqualInt((int)xsize, 11);
490	assertEqualInt(ARCHIVE_WARN,
491	    archive_entry_xattr_next(e2, &xname, &xval, &xsize));
492	assertEqualString(xname, NULL);
493	assertEqualString(xval, NULL);
494	assertEqualInt((int)xsize, 0);
495#endif
496
497	/* Change the original */
498	archive_entry_set_atime(e, 13580, 24690);
499	archive_entry_set_birthtime(e, 13980, 24999);
500	archive_entry_set_ctime(e, 13590, 24691);
501#if ARCHIVE_VERSION_NUMBER >= 1009000
502	archive_entry_set_dev(e, 245);
503#endif
504	archive_entry_set_fflags(e, 0x85, 0xDA);
505#if ARCHIVE_VERSION_NUMBER >= 1009000
506	archive_entry_set_filetype(e, AE_IFLNK);
507#endif
508	archive_entry_set_gid(e, 214);
509	archive_entry_set_gname(e, "grouper");
510	archive_entry_set_hardlink(e, "hardlinkpath");
511#if ARCHIVE_VERSION_NUMBER >= 1009000
512	archive_entry_set_ino(e, 8763);
513#endif
514	archive_entry_set_mode(e, 0123654);
515	archive_entry_set_mtime(e, 18351, 28642);
516#if ARCHIVE_VERSION_NUMBER >= 1009000
517	archive_entry_set_nlink(e, 73);
518#endif
519	archive_entry_set_pathname(e, "pathest");
520#if ARCHIVE_VERSION_NUMBER >= 1009000
521	archive_entry_set_rdev(e, 132);
522#endif
523	archive_entry_set_size(e, 987456321);
524	archive_entry_copy_sourcepath(e, "source2");
525	archive_entry_set_symlink(e, "symlinkpath");
526	archive_entry_set_uid(e, 93);
527	archive_entry_set_uname(e, "username");
528	archive_entry_acl_clear(e);
529	archive_entry_xattr_clear(e);
530
531	/* Clone should still have same contents. */
532	assertEqualInt(archive_entry_atime(e2), 13579);
533	assertEqualInt(archive_entry_atime_nsec(e2), 24680);
534	assertEqualInt(archive_entry_birthtime(e2), 13779);
535	assertEqualInt(archive_entry_birthtime_nsec(e2), 24990);
536	assertEqualInt(archive_entry_ctime(e2), 13580);
537	assertEqualInt(archive_entry_ctime_nsec(e2), 24681);
538#if ARCHIVE_VERSION_NUMBER >= 1009000
539	assertEqualInt(archive_entry_dev(e2), 235);
540#endif
541	archive_entry_fflags(e2, &set, &clear);
542	assertEqualInt(clear, 0xAA);
543	assertEqualInt(set, 0x55);
544	assertEqualInt(archive_entry_gid(e2), 204);
545	assertEqualString(archive_entry_gname(e2), "group");
546	assertEqualString(archive_entry_hardlink(e2), "hardlinkname");
547#if ARCHIVE_VERSION_NUMBER >= 1009000
548	assertEqualInt(archive_entry_ino(e2), 8593);
549#endif
550	assertEqualInt(archive_entry_mode(e2), 0123456);
551	assertEqualInt(archive_entry_mtime(e2), 13581);
552	assertEqualInt(archive_entry_mtime_nsec(e2), 24682);
553#if ARCHIVE_VERSION_NUMBER >= 1009000
554	assertEqualInt(archive_entry_nlink(e2), 736);
555#endif
556	assertEqualString(archive_entry_pathname(e2), "path");
557#if ARCHIVE_VERSION_NUMBER >= 1009000
558	assertEqualInt(archive_entry_rdev(e2), 532);
559#endif
560	assertEqualInt(archive_entry_size(e2), 987654321);
561	assertEqualString(archive_entry_sourcepath(e2), "source");
562	assertEqualString(archive_entry_symlink(e2), "symlinkname");
563	assertEqualInt(archive_entry_uid(e2), 83);
564	assertEqualString(archive_entry_uname(e2), "user");
565#if ARCHIVE_VERSION_NUMBER < 1009000
566	skipping("ACL held by clone of archive_entry");
567#else
568	/* Verify ACL was unchanged. */
569	assertEqualInt(4, archive_entry_acl_reset(e2,
570			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
571	/* First three are standard permission bits. */
572	assertEqualInt(0, archive_entry_acl_next(e2,
573			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
574			   &type, &permset, &tag, &qual, &name));
575	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
576	assertEqualInt(permset, 4);
577	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ);
578	assertEqualInt(qual, -1);
579	assertEqualString(name, NULL);
580	assertEqualInt(0, archive_entry_acl_next(e2,
581			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
582			   &type, &permset, &tag, &qual, &name));
583	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
584	assertEqualInt(permset, 5);
585	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ);
586	assertEqualInt(qual, -1);
587	assertEqualString(name, NULL);
588	assertEqualInt(0, archive_entry_acl_next(e2,
589			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
590			   &type, &permset, &tag, &qual, &name));
591	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
592	assertEqualInt(permset, 6);
593	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER);
594	assertEqualInt(qual, -1);
595	assertEqualString(name, NULL);
596	/* Fourth is custom one. */
597	assertEqualInt(0, archive_entry_acl_next(e2,
598			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
599			   &type, &permset, &tag, &qual, &name));
600	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
601	assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ);
602	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER);
603	assertEqualInt(qual, 77);
604	assertEqualString(name, "user77");
605	assertEqualInt(1, archive_entry_acl_next(e2,
606			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
607			   &type, &permset, &tag, &qual, &name));
608	assertEqualInt(type, 0);
609	assertEqualInt(permset, 0);
610	assertEqualInt(tag, 0);
611	assertEqualInt(qual, -1);
612	assertEqualString(name, NULL);
613#endif
614#if ARCHIVE_VERSION_NUMBER < 1009000
615	skipping("xattr preserved in archive_entry copy");
616#else
617	/* Verify xattr was unchanged. */
618	assertEqualInt(1, archive_entry_xattr_reset(e2));
619#endif
620
621	/* Release clone. */
622	archive_entry_free(e2);
623
624	/*
625	 * Test clear() implementation.
626	 */
627	archive_entry_clear(e);
628	assertEqualInt(archive_entry_atime(e), 0);
629	assertEqualInt(archive_entry_atime_nsec(e), 0);
630	assertEqualInt(archive_entry_birthtime(e), 0);
631	assertEqualInt(archive_entry_birthtime_nsec(e), 0);
632	assertEqualInt(archive_entry_ctime(e), 0);
633	assertEqualInt(archive_entry_ctime_nsec(e), 0);
634	assertEqualInt(archive_entry_dev(e), 0);
635	archive_entry_fflags(e, &set, &clear);
636	assertEqualInt(clear, 0);
637	assertEqualInt(set, 0);
638#if ARCHIVE_VERSION_NUMBER >= 1009000
639	assertEqualInt(archive_entry_filetype(e), 0);
640#endif
641	assertEqualInt(archive_entry_gid(e), 0);
642	assertEqualString(archive_entry_gname(e), NULL);
643	assertEqualString(archive_entry_hardlink(e), NULL);
644	assertEqualInt(archive_entry_ino(e), 0);
645	assertEqualInt(archive_entry_mode(e), 0);
646	assertEqualInt(archive_entry_mtime(e), 0);
647	assertEqualInt(archive_entry_mtime_nsec(e), 0);
648#if ARCHIVE_VERSION_NUMBER >= 1009000
649	assertEqualInt(archive_entry_nlink(e), 0);
650#endif
651	assertEqualString(archive_entry_pathname(e), NULL);
652	assertEqualInt(archive_entry_rdev(e), 0);
653	assertEqualInt(archive_entry_size(e), 0);
654	assertEqualString(archive_entry_symlink(e), NULL);
655	assertEqualInt(archive_entry_uid(e), 0);
656	assertEqualString(archive_entry_uname(e), NULL);
657	/* ACLs should be cleared. */
658	assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), 0);
659	assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), 0);
660	/* Extended attributes should be cleared. */
661	assertEqualInt(archive_entry_xattr_count(e), 0);
662
663	/*
664	 * Test archive_entry_copy_stat().
665	 */
666	memset(&st, 0, sizeof(st));
667	/* Set all of the standard 'struct stat' fields. */
668	st.st_atime = 456789;
669	st.st_ctime = 345678;
670	st.st_dev = 123;
671	st.st_gid = 34;
672	st.st_ino = 234;
673	st.st_mode = 077777;
674	st.st_mtime = 234567;
675	st.st_nlink = 345;
676	st.st_size = 123456789;
677	st.st_uid = 23;
678#ifdef __FreeBSD__
679	/* On FreeBSD, high-res timestamp data should come through. */
680	st.st_atimespec.tv_nsec = 6543210;
681	st.st_ctimespec.tv_nsec = 5432109;
682	st.st_mtimespec.tv_nsec = 3210987;
683	st.st_birthtimespec.tv_nsec = 7459386;
684#endif
685	/* Copy them into the entry. */
686	archive_entry_copy_stat(e, &st);
687	/* Read each one back separately and compare. */
688	assertEqualInt(archive_entry_atime(e), 456789);
689	assertEqualInt(archive_entry_ctime(e), 345678);
690	assertEqualInt(archive_entry_dev(e), 123);
691	assertEqualInt(archive_entry_gid(e), 34);
692	assertEqualInt(archive_entry_ino(e), 234);
693	assertEqualInt(archive_entry_mode(e), 077777);
694	assertEqualInt(archive_entry_mtime(e), 234567);
695#if ARCHIVE_VERSION_NUMBER >= 1009000
696	assertEqualInt(archive_entry_nlink(e), 345);
697#endif
698	assertEqualInt(archive_entry_size(e), 123456789);
699	assertEqualInt(archive_entry_uid(e), 23);
700#if __FreeBSD__
701	/* On FreeBSD, high-res timestamp data should come through. */
702	assertEqualInt(archive_entry_atime_nsec(e), 6543210);
703	assertEqualInt(archive_entry_ctime_nsec(e), 5432109);
704	assertEqualInt(archive_entry_mtime_nsec(e), 3210987);
705	assertEqualInt(archive_entry_birthtime_nsec(e), 7459386);
706#endif
707
708	/*
709	 * Test archive_entry_stat().
710	 */
711	/* First, clear out any existing stat data. */
712	memset(&st, 0, sizeof(st));
713	archive_entry_copy_stat(e, &st);
714	/* Set a bunch of fields individually. */
715	archive_entry_set_atime(e, 456789, 321);
716	archive_entry_set_ctime(e, 345678, 432);
717#if ARCHIVE_VERSION_NUMBER >= 1009000
718	archive_entry_set_dev(e, 123);
719#endif
720	archive_entry_set_gid(e, 34);
721#if ARCHIVE_VERSION_NUMBER >= 1009000
722	archive_entry_set_ino(e, 234);
723#endif
724	archive_entry_set_mode(e, 012345);
725	archive_entry_set_mode(e, 012345);
726	archive_entry_set_mtime(e, 234567, 543);
727#if ARCHIVE_VERSION_NUMBER >= 1009000
728	archive_entry_set_nlink(e, 345);
729#endif
730	archive_entry_set_size(e, 123456789);
731	archive_entry_set_uid(e, 23);
732	/* Retrieve a stat structure. */
733	assert((pst = archive_entry_stat(e)) != NULL);
734	/* Check that the values match. */
735	assertEqualInt(pst->st_atime, 456789);
736	assertEqualInt(pst->st_ctime, 345678);
737#if ARCHIVE_VERSION_NUMBER >= 1009000
738	assertEqualInt(pst->st_dev, 123);
739#endif
740	assertEqualInt(pst->st_gid, 34);
741#if ARCHIVE_VERSION_NUMBER >= 1009000
742	assertEqualInt(pst->st_ino, 234);
743#endif
744	assertEqualInt(pst->st_mode, 012345);
745	assertEqualInt(pst->st_mtime, 234567);
746#if ARCHIVE_VERSION_NUMBER >= 1009000
747	assertEqualInt(pst->st_nlink, 345);
748#endif
749	assertEqualInt(pst->st_size, 123456789);
750	assertEqualInt(pst->st_uid, 23);
751#ifdef __FreeBSD__
752	/* On FreeBSD, high-res timestamp data should come through. */
753	assertEqualInt(pst->st_atimespec.tv_nsec, 321);
754	assertEqualInt(pst->st_ctimespec.tv_nsec, 432);
755	assertEqualInt(pst->st_mtimespec.tv_nsec, 543);
756#endif
757
758	/* Changing any one value should update struct stat. */
759	archive_entry_set_atime(e, 456788, 0);
760	assert((pst = archive_entry_stat(e)) != NULL);
761	assertEqualInt(pst->st_atime, 456788);
762	archive_entry_set_ctime(e, 345677, 431);
763	assert((pst = archive_entry_stat(e)) != NULL);
764	assertEqualInt(pst->st_ctime, 345677);
765#if ARCHIVE_VERSION_NUMBER >= 1009000
766	archive_entry_set_dev(e, 122);
767	assert((pst = archive_entry_stat(e)) != NULL);
768	assertEqualInt(pst->st_dev, 122);
769#endif
770	archive_entry_set_gid(e, 33);
771	assert((pst = archive_entry_stat(e)) != NULL);
772	assertEqualInt(pst->st_gid, 33);
773#if ARCHIVE_VERSION_NUMBER >= 1009000
774	archive_entry_set_ino(e, 233);
775	assert((pst = archive_entry_stat(e)) != NULL);
776	assertEqualInt(pst->st_ino, 233);
777#endif
778	archive_entry_set_mode(e, 012344);
779	assert((pst = archive_entry_stat(e)) != NULL);
780	assertEqualInt(pst->st_mode, 012344);
781	archive_entry_set_mtime(e, 234566, 542);
782	assert((pst = archive_entry_stat(e)) != NULL);
783	assertEqualInt(pst->st_mtime, 234566);
784#if ARCHIVE_VERSION_NUMBER >= 1009000
785	archive_entry_set_nlink(e, 344);
786	assert((pst = archive_entry_stat(e)) != NULL);
787	assertEqualInt(pst->st_nlink, 344);
788#endif
789	archive_entry_set_size(e, 123456788);
790	assert((pst = archive_entry_stat(e)) != NULL);
791	assertEqualInt(pst->st_size, 123456788);
792	archive_entry_set_uid(e, 22);
793	assert((pst = archive_entry_stat(e)) != NULL);
794	assertEqualInt(pst->st_uid, 22);
795	/* We don't need to check high-res fields here. */
796
797	/*
798	 * Test dev/major/minor interfaces.  Setting 'dev' or 'rdev'
799	 * should change the corresponding major/minor values, and
800	 * vice versa.
801	 *
802	 * The test here is system-specific because it assumes that
803	 * makedev(), major(), and minor() are defined in sys/stat.h.
804	 * I'm not too worried about it, though, because the code is
805	 * simple.  If it works on FreeBSD, it's unlikely to be broken
806	 * anywhere else.  Note: The functionality is present on every
807	 * platform even if these tests only run some places;
808	 * libarchive's more extensive configuration logic should find
809	 * the necessary definitions on every platform.
810	 */
811#if __FreeBSD__
812#if ARCHIVE_VERSION_NUMBER >= 1009000
813	archive_entry_set_dev(e, 0x12345678);
814	assertEqualInt(archive_entry_devmajor(e), major(0x12345678));
815	assertEqualInt(archive_entry_devminor(e), minor(0x12345678));
816	assertEqualInt(archive_entry_dev(e), 0x12345678);
817	archive_entry_set_devmajor(e, 0xfe);
818	archive_entry_set_devminor(e, 0xdcba98);
819	assertEqualInt(archive_entry_devmajor(e), 0xfe);
820	assertEqualInt(archive_entry_devminor(e), 0xdcba98);
821	assertEqualInt(archive_entry_dev(e), makedev(0xfe, 0xdcba98));
822	archive_entry_set_rdev(e, 0x12345678);
823	assertEqualInt(archive_entry_rdevmajor(e), major(0x12345678));
824	assertEqualInt(archive_entry_rdevminor(e), minor(0x12345678));
825	assertEqualInt(archive_entry_rdev(e), 0x12345678);
826	archive_entry_set_rdevmajor(e, 0xfe);
827	archive_entry_set_rdevminor(e, 0xdcba98);
828	assertEqualInt(archive_entry_rdevmajor(e), 0xfe);
829	assertEqualInt(archive_entry_rdevminor(e), 0xdcba98);
830	assertEqualInt(archive_entry_rdev(e), makedev(0xfe, 0xdcba98));
831#endif
832#endif
833
834	/*
835	 * Exercise the character-conversion logic, if we can.
836	 */
837	if (NULL == LOCALE_UTF8 || NULL == setlocale(LC_ALL, LOCALE_UTF8)) {
838		skipping("Can't exercise charset-conversion logic without"
839			" a suitable locale.");
840	} else {
841		/* A filename that cannot be converted to wide characters. */
842		archive_entry_copy_pathname(e, "abc\314\214mno\374xyz");
843		failure("Converting invalid chars to Unicode should fail.");
844		assert(NULL == archive_entry_pathname_w(e));
845		//failure("Converting invalid chars to UTF-8 should fail.");
846		//assert(NULL == archive_entry_pathname_utf8(e));
847
848		/* A group name that cannot be converted. */
849		archive_entry_copy_gname(e, "abc\314\214mno\374xyz");
850		failure("Converting invalid chars to Unicode should fail.");
851		assert(NULL == archive_entry_gname_w(e));
852
853		/* A user name that cannot be converted. */
854		archive_entry_copy_uname(e, "abc\314\214mno\374xyz");
855		failure("Converting invalid chars to Unicode should fail.");
856		assert(NULL == archive_entry_uname_w(e));
857
858		/* A hardlink target that cannot be converted. */
859		archive_entry_copy_hardlink(e, "abc\314\214mno\374xyz");
860		failure("Converting invalid chars to Unicode should fail.");
861		assert(NULL == archive_entry_hardlink_w(e));
862
863		/* A symlink target that cannot be converted. */
864		archive_entry_copy_symlink(e, "abc\314\214mno\374xyz");
865		failure("Converting invalid chars to Unicode should fail.");
866		assert(NULL == archive_entry_symlink_w(e));
867	}
868
869	l = 0x12345678L;
870	wc = (wchar_t)l; /* Wide character too big for UTF-8. */
871	if (NULL == setlocale(LC_ALL, "C") || (long)wc != l) {
872		skipping("Testing charset conversion failure requires 32-bit wchar_t and support for \"C\" locale.");
873	} else {
874		/*
875		 * Build the string L"xxx\U12345678yyy\u5678zzz" without
876		 * using C99 \u#### syntax, which isn't uniformly
877		 * supported.  (GCC 3.4.6, for instance, defaults to
878		 * "c89 plus GNU extensions.")
879		 */
880		wcscpy(wbuff, L"xxxAyyyBzzz");
881		wbuff[3] = (wchar_t)0x12345678;
882		wbuff[7] = (wchar_t)0x5678;
883		/* A wide filename that cannot be converted to narrow. */
884		archive_entry_copy_pathname_w(e, wbuff);
885		failure("Converting wide characters from Unicode should fail.");
886		assertEqualString(NULL, archive_entry_pathname(e));
887	}
888
889	/* Release the experimental entry. */
890	archive_entry_free(e);
891}
892