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$");
27 
28 #include <locale.h>
29 
30 #ifndef HAVE_WCSCPY
31 static 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 
51 DEFINE_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");
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