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