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