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 	assertEqualString(archive_entry_gname_utf8(e), "group");
181 	assertEqualWString(archive_entry_gname_w(e), L"group");
182 	wcscpy(wbuff, L"wgroup");
183 	archive_entry_copy_gname_w(e, wbuff);
184 	assertEqualWString(archive_entry_gname_w(e), L"wgroup");
185 	memset(wbuff, 0, sizeof(wbuff));
186 	assertEqualWString(archive_entry_gname_w(e), L"wgroup");
187 	assertEqualString(archive_entry_gname_utf8(e), "wgroup");
188 	assertEqualString(archive_entry_gname(e), "wgroup");
189 	archive_entry_set_gname_utf8(e, "group");
190 	assertEqualString(archive_entry_gname_utf8(e), "group");
191 	assertEqualWString(archive_entry_gname_w(e), L"group");
192 	assertEqualString(archive_entry_gname(e), "group");
193 	archive_entry_update_gname_utf8(e, "group2");
194 	assertEqualString(archive_entry_gname_utf8(e), "group2");
195 	assertEqualWString(archive_entry_gname_w(e), L"group2");
196 	assertEqualString(archive_entry_gname(e), "group2");
197 
198 	/* hardlink */
199 	archive_entry_set_hardlink(e, "hardlinkname");
200 	assertEqualString(archive_entry_hardlink(e), "hardlinkname");
201 	assertEqualString(archive_entry_hardlink_utf8(e), "hardlinkname");
202 	assertEqualWString(archive_entry_hardlink_w(e), L"hardlinkname");
203 	strcpy(buff, "hardlinkname2");
204 	archive_entry_copy_hardlink(e, buff);
205 	assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
206 	assertEqualWString(archive_entry_hardlink_w(e), L"hardlinkname2");
207 	assertEqualString(archive_entry_hardlink_utf8(e), "hardlinkname2");
208 	memset(buff, 0, sizeof(buff));
209 	assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
210 	assertEqualString(archive_entry_hardlink_utf8(e), "hardlinkname2");
211 	assertEqualWString(archive_entry_hardlink_w(e), L"hardlinkname2");
212 	archive_entry_copy_hardlink(e, NULL);
213 	assertEqualString(archive_entry_hardlink(e), NULL);
214 	assertEqualWString(archive_entry_hardlink_w(e), NULL);
215 	assertEqualString(archive_entry_hardlink_utf8(e), NULL);
216 	wcscpy(wbuff, L"whardlink");
217 	archive_entry_copy_hardlink_w(e, wbuff);
218 	assertEqualWString(archive_entry_hardlink_w(e), L"whardlink");
219 	assertEqualString(archive_entry_hardlink_utf8(e), "whardlink");
220 	assertEqualString(archive_entry_hardlink(e), "whardlink");
221 	memset(wbuff, 0, sizeof(wbuff));
222 	assertEqualWString(archive_entry_hardlink_w(e), L"whardlink");
223 	archive_entry_copy_hardlink_w(e, NULL);
224 	assertEqualString(archive_entry_hardlink(e), NULL);
225 	assertEqualWString(archive_entry_hardlink_w(e), NULL);
226 	archive_entry_set_hardlink_utf8(e, "hardlinkname");
227 	assertEqualString(archive_entry_hardlink_utf8(e), "hardlinkname");
228 	assertEqualWString(archive_entry_hardlink_w(e), L"hardlinkname");
229 	assertEqualString(archive_entry_hardlink(e), "hardlinkname");
230 	archive_entry_update_hardlink_utf8(e, "hardlinkname2");
231 	assertEqualString(archive_entry_hardlink_utf8(e), "hardlinkname2");
232 	assertEqualWString(archive_entry_hardlink_w(e), L"hardlinkname2");
233 	assertEqualString(archive_entry_hardlink(e), "hardlinkname2");
234 
235 	/* ino */
236 	assert(!archive_entry_ino_is_set(e));
237 	archive_entry_set_ino(e, 8593);
238 	assert(archive_entry_ino_is_set(e));
239 	assertEqualInt(archive_entry_ino(e), 8593);
240 	assertEqualInt(archive_entry_ino64(e), 8593);
241 	archive_entry_set_ino64(e, 8594);
242 	assert(archive_entry_ino_is_set(e));
243 	assertEqualInt(archive_entry_ino(e), 8594);
244 	assertEqualInt(archive_entry_ino64(e), 8594);
245 
246 	/* link */
247 	archive_entry_set_hardlink(e, "hardlinkname");
248 	archive_entry_set_symlink(e, NULL);
249 	archive_entry_set_link(e, "link");
250 	assertEqualString(archive_entry_hardlink(e), "link");
251 	assertEqualString(archive_entry_symlink(e), NULL);
252 	archive_entry_copy_link(e, "link2");
253 	assertEqualString(archive_entry_hardlink(e), "link2");
254 	assertEqualString(archive_entry_symlink(e), NULL);
255 	archive_entry_copy_link_w(e, L"link3");
256 	assertEqualString(archive_entry_hardlink(e), "link3");
257 	assertEqualString(archive_entry_symlink(e), NULL);
258 	archive_entry_set_hardlink(e, NULL);
259 	archive_entry_set_symlink(e, "symlink");
260 	archive_entry_set_link(e, "link");
261 	assertEqualString(archive_entry_hardlink(e), NULL);
262 	assertEqualString(archive_entry_symlink(e), "link");
263 	archive_entry_copy_link(e, "link2");
264 	assertEqualString(archive_entry_hardlink(e), NULL);
265 	assertEqualString(archive_entry_symlink(e), "link2");
266 	archive_entry_copy_link_w(e, L"link3");
267 	assertEqualString(archive_entry_hardlink(e), NULL);
268 	assertEqualString(archive_entry_symlink(e), "link3");
269 	/* Arbitrarily override symlink if both hardlink and symlink set. */
270 	archive_entry_set_hardlink(e, "hardlink");
271 	archive_entry_set_symlink(e, "symlink");
272 	archive_entry_set_link(e, "link");
273 	assertEqualString(archive_entry_hardlink(e), "hardlink");
274 	assertEqualString(archive_entry_symlink(e), "link");
275 
276 	/* mode */
277 	archive_entry_set_mode(e, 0123456);
278 	assertEqualInt(archive_entry_mode(e), 0123456);
279 
280 	/* mtime */
281 	archive_entry_set_mtime(e, 13581, 24682);
282 	assertEqualInt(archive_entry_mtime(e), 13581);
283 	assertEqualInt(archive_entry_mtime_nsec(e), 24682);
284 	archive_entry_set_mtime(e, 13582, 1358297468);
285 	assertEqualInt(archive_entry_mtime(e), 13583);
286 	assertEqualInt(archive_entry_mtime_nsec(e), 358297468);
287 	archive_entry_set_mtime(e, 13583, -24682);
288 	assertEqualInt(archive_entry_mtime(e), 13582);
289 	assertEqualInt(archive_entry_mtime_nsec(e), 999975318);
290 	archive_entry_unset_mtime(e);
291 	assertEqualInt(archive_entry_mtime(e), 0);
292 	assertEqualInt(archive_entry_mtime_nsec(e), 0);
293 	assert(!archive_entry_mtime_is_set(e));
294 
295 	/* nlink */
296 	archive_entry_set_nlink(e, 736);
297 	assertEqualInt(archive_entry_nlink(e), 736);
298 
299 	/* pathname */
300 	archive_entry_set_pathname(e, "path");
301 	assertEqualString(archive_entry_pathname(e), "path");
302 	assertEqualString(archive_entry_pathname_utf8(e), "path");
303 	assertEqualWString(archive_entry_pathname_w(e), L"path");
304 	archive_entry_set_pathname(e, "path");
305 	assertEqualString(archive_entry_pathname(e), "path");
306 	assertEqualWString(archive_entry_pathname_w(e), L"path");
307 	assertEqualString(archive_entry_pathname_utf8(e), "path");
308 	strcpy(buff, "path2");
309 	archive_entry_copy_pathname(e, buff);
310 	assertEqualString(archive_entry_pathname(e), "path2");
311 	assertEqualWString(archive_entry_pathname_w(e), L"path2");
312 	assertEqualString(archive_entry_pathname_utf8(e), "path2");
313 	memset(buff, 0, sizeof(buff));
314 	assertEqualString(archive_entry_pathname(e), "path2");
315 	assertEqualString(archive_entry_pathname_utf8(e), "path2");
316 	assertEqualWString(archive_entry_pathname_w(e), L"path2");
317 	wcscpy(wbuff, L"wpath");
318 	archive_entry_copy_pathname_w(e, wbuff);
319 	assertEqualWString(archive_entry_pathname_w(e), L"wpath");
320 	assertEqualString(archive_entry_pathname_utf8(e), "wpath");
321 	assertEqualString(archive_entry_pathname(e), "wpath");
322 	memset(wbuff, 0, sizeof(wbuff));
323 	assertEqualWString(archive_entry_pathname_w(e), L"wpath");
324 	assertEqualString(archive_entry_pathname(e), "wpath");
325 	assertEqualString(archive_entry_pathname_utf8(e), "wpath");
326 	archive_entry_set_pathname_utf8(e, "path");
327 	assertEqualWString(archive_entry_pathname_w(e), L"path");
328 	assertEqualString(archive_entry_pathname(e), "path");
329 	assertEqualString(archive_entry_pathname_utf8(e), "path");
330 	archive_entry_update_pathname_utf8(e, "path2");
331 	assertEqualWString(archive_entry_pathname_w(e), L"path2");
332 	assertEqualString(archive_entry_pathname(e), "path2");
333 	assertEqualString(archive_entry_pathname_utf8(e), "path2");
334 
335 	/* rdev */
336 	archive_entry_set_rdev(e, 532);
337 	assertEqualInt(archive_entry_rdev(e), 532);
338 	/* rdevmajor/rdevminor are tested specially below. */
339 
340 	/* size */
341 	archive_entry_set_size(e, 987654321);
342 	assertEqualInt(archive_entry_size(e), 987654321);
343 	archive_entry_unset_size(e);
344 	assertEqualInt(archive_entry_size(e), 0);
345 	assert(!archive_entry_size_is_set(e));
346 
347 	/* sourcepath */
348 	archive_entry_copy_sourcepath(e, "path1");
349 	assertEqualString(archive_entry_sourcepath(e), "path1");
350 
351 	/* symlink */
352 	archive_entry_set_symlink(e, "symlinkname");
353 	assertEqualString(archive_entry_symlink(e), "symlinkname");
354 	assertEqualString(archive_entry_symlink_utf8(e), "symlinkname");
355 	assertEqualWString(archive_entry_symlink_w(e), L"symlinkname");
356 	strcpy(buff, "symlinkname2");
357 	archive_entry_copy_symlink(e, buff);
358 	assertEqualString(archive_entry_symlink(e), "symlinkname2");
359 	assertEqualWString(archive_entry_symlink_w(e), L"symlinkname2");
360 	assertEqualString(archive_entry_symlink_utf8(e), "symlinkname2");
361 	memset(buff, 0, sizeof(buff));
362 	assertEqualString(archive_entry_symlink(e), "symlinkname2");
363 	assertEqualString(archive_entry_symlink_utf8(e), "symlinkname2");
364 	assertEqualWString(archive_entry_symlink_w(e), L"symlinkname2");
365 	archive_entry_copy_symlink_w(e, NULL);
366 	assertEqualWString(archive_entry_symlink_w(e), NULL);
367 	assertEqualString(archive_entry_symlink(e), NULL);
368 	assertEqualString(archive_entry_symlink_utf8(e), NULL);
369 	archive_entry_copy_symlink_w(e, L"wsymlink");
370 	assertEqualWString(archive_entry_symlink_w(e), L"wsymlink");
371 	assertEqualString(archive_entry_symlink_utf8(e), "wsymlink");
372 	assertEqualString(archive_entry_symlink(e), "wsymlink");
373 	archive_entry_copy_symlink(e, NULL);
374 	assertEqualWString(archive_entry_symlink_w(e), NULL);
375 	assertEqualString(archive_entry_symlink(e), NULL);
376 	assertEqualString(archive_entry_symlink_utf8(e), NULL);
377 	archive_entry_set_symlink_utf8(e, "symlinkname");
378 	assertEqualWString(archive_entry_symlink_w(e), L"symlinkname");
379 	assertEqualString(archive_entry_symlink(e), "symlinkname");
380 	assertEqualString(archive_entry_symlink_utf8(e), "symlinkname");
381 	archive_entry_update_symlink_utf8(e, "symlinkname2");
382 	assertEqualWString(archive_entry_symlink_w(e), L"symlinkname2");
383 	assertEqualString(archive_entry_symlink(e), "symlinkname2");
384 	assertEqualString(archive_entry_symlink_utf8(e), "symlinkname2");
385 
386 	/* uid */
387 	archive_entry_set_uid(e, 83);
388 	assertEqualInt(archive_entry_uid(e), 83);
389 
390 	/* uname */
391 	archive_entry_set_uname(e, "user");
392 	assertEqualString(archive_entry_uname(e), "user");
393 	assertEqualString(archive_entry_uname_utf8(e), "user");
394 	assertEqualWString(archive_entry_uname_w(e), L"user");
395 	wcscpy(wbuff, L"wuser");
396 	archive_entry_copy_uname_w(e, wbuff);
397 	assertEqualWString(archive_entry_uname_w(e), L"wuser");
398 	memset(wbuff, 0, sizeof(wbuff));
399 	assertEqualWString(archive_entry_uname_w(e), L"wuser");
400 	assertEqualString(archive_entry_uname_utf8(e), "wuser");
401 	assertEqualString(archive_entry_uname(e), "wuser");
402 	archive_entry_set_uname_utf8(e, "user");
403 	assertEqualString(archive_entry_uname_utf8(e), "user");
404 	assertEqualWString(archive_entry_uname_w(e), L"user");
405 	assertEqualString(archive_entry_uname(e), "user");
406 	archive_entry_set_uname_utf8(e, "user");
407 	assertEqualWString(archive_entry_uname_w(e), L"user");
408 	assertEqualString(archive_entry_uname(e), "user");
409 	assertEqualString(archive_entry_uname_utf8(e), "user");
410 	archive_entry_update_uname_utf8(e, "user2");
411 	assertEqualWString(archive_entry_uname_w(e), L"user2");
412 	assertEqualString(archive_entry_uname(e), "user2");
413 	assertEqualString(archive_entry_uname_utf8(e), "user2");
414 
415 	/* Test fflags interface. */
416 	archive_entry_set_fflags(e, 0x55, 0xAA);
417 	archive_entry_fflags(e, &set, &clear);
418 	failure("Testing set/get of fflags data.");
419 	assertEqualInt(set, 0x55);
420 	failure("Testing set/get of fflags data.");
421 	assertEqualInt(clear, 0xAA);
422 #ifdef __FreeBSD__
423 	/* Converting fflags bitmap to string is currently system-dependent. */
424 	/* TODO: Make this system-independent. */
425 	assertEqualString(archive_entry_fflags_text(e),
426 	    "uappnd,nouchg,nodump,noopaque,uunlnk,nosystem");
427 #endif
428 
429 #if defined(__FreeBSD__) || defined(__APPLE__)
430 	/* Test archive_entry_copy_fflags_text_w() */
431 	archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,hidden");
432 	archive_entry_fflags(e, &set, &clear);
433 	assertEqualInt(UF_HIDDEN, set);
434 	assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
435 	/* Test archive_entry_copy_fflags_text() */
436 	archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,hidden");
437 	archive_entry_fflags(e, &set, &clear);
438 	assertEqualInt(UF_HIDDEN, set);
439 	assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
440 #elif defined(_WIN32) && !defined(CYGWIN)
441 	archive_entry_copy_fflags_text_w(e, L"rdonly,hidden,nosystem");
442 	archive_entry_fflags(e, &set, &clear);
443 	assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
444 	assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear);
445 	archive_entry_copy_fflags_text(e, "rdonly,hidden,nosystem");
446 	archive_entry_fflags(e, &set, &clear);
447 	assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
448 	assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear);
449 #elif defined FS_IOC_GETFLAGS /* Linux */
450 	archive_entry_copy_fflags_text_w(e, L"sappnd,schg,dump,noundel");
451 	archive_entry_fflags(e, &set, &clear);
452 	assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set);
453 	assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear);
454 	archive_entry_copy_fflags_text(e, "sappnd,schg,dump,noundel");
455 	archive_entry_fflags(e, &set, &clear);
456 	assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set);
457 	assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear);
458 #endif
459 
460 	/* See test_acl_basic.c for tests of ACL set/get consistency. */
461 
462 	/* Test xattrs set/get consistency. */
463 	archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12);
464 	assertEqualInt(1, archive_entry_xattr_reset(e));
465 	assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
466 	assertEqualString(xname, "xattr1");
467 	assertEqualString(xval, "xattrvalue1");
468 	assertEqualInt((int)xsize, 12);
469 	assertEqualInt(1, archive_entry_xattr_count(e));
470 	assertEqualInt(ARCHIVE_WARN,
471 	    archive_entry_xattr_next(e, &xname, &xval, &xsize));
472 	assertEqualString(xname, NULL);
473 	assertEqualString(xval, NULL);
474 	assertEqualInt((int)xsize, 0);
475 	archive_entry_xattr_clear(e);
476 	assertEqualInt(0, archive_entry_xattr_reset(e));
477 	assertEqualInt(ARCHIVE_WARN,
478 	    archive_entry_xattr_next(e, &xname, &xval, &xsize));
479 	assertEqualString(xname, NULL);
480 	assertEqualString(xval, NULL);
481 	assertEqualInt((int)xsize, 0);
482 	archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue1", 12);
483 	assertEqualInt(1, archive_entry_xattr_reset(e));
484 	archive_entry_xattr_add_entry(e, "xattr2", "xattrvalue2", 12);
485 	assertEqualInt(2, archive_entry_xattr_reset(e));
486 	assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
487 	assertEqualInt(0, archive_entry_xattr_next(e, &xname, &xval, &xsize));
488 	assertEqualInt(ARCHIVE_WARN,
489 	    archive_entry_xattr_next(e, &xname, &xval, &xsize));
490 	assertEqualString(xname, NULL);
491 	assertEqualString(xval, NULL);
492 	assertEqualInt((int)xsize, 0);
493 
494 
495 	/*
496 	 * Test clone() implementation.
497 	 */
498 
499 	/* Set values in 'e' */
500 	archive_entry_clear(e);
501 	archive_entry_set_atime(e, 13579, 24680);
502 	archive_entry_set_birthtime(e, 13779, 24990);
503 	archive_entry_set_ctime(e, 13580, 24681);
504 	archive_entry_set_dev(e, 235);
505 	archive_entry_set_fflags(e, 0x55, 0xAA);
506 	archive_entry_set_gid(e, 204);
507 	archive_entry_set_gname(e, "group");
508 	archive_entry_set_hardlink(e, "hardlinkname");
509 	archive_entry_set_ino(e, 8593);
510 	archive_entry_set_mode(e, 0123456);
511 	archive_entry_set_mtime(e, 13581, 24682);
512 	archive_entry_set_nlink(e, 736);
513 	archive_entry_set_pathname(e, "path");
514 	archive_entry_set_rdev(e, 532);
515 	archive_entry_set_size(e, 987654321);
516 	archive_entry_copy_sourcepath(e, "source");
517 	archive_entry_set_symlink(e, "symlinkname");
518 	archive_entry_set_uid(e, 83);
519 	archive_entry_set_uname(e, "user");
520 	/* Add an ACL entry. */
521 	archive_entry_acl_add_entry(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
522 	    ARCHIVE_ENTRY_ACL_READ, ARCHIVE_ENTRY_ACL_USER, 77, "user77");
523 	/* Add an extended attribute. */
524 	archive_entry_xattr_add_entry(e, "xattr1", "xattrvalue", 11);
525 
526 	/* Make a clone. */
527 	e2 = archive_entry_clone(e);
528 
529 	/* Clone should have same contents. */
530 	assertEqualInt(archive_entry_atime(e2), 13579);
531 	assertEqualInt(archive_entry_atime_nsec(e2), 24680);
532 	assertEqualInt(archive_entry_birthtime(e2), 13779);
533 	assertEqualInt(archive_entry_birthtime_nsec(e2), 24990);
534 	assertEqualInt(archive_entry_ctime(e2), 13580);
535 	assertEqualInt(archive_entry_ctime_nsec(e2), 24681);
536 	assertEqualInt(archive_entry_dev(e2), 235);
537 	archive_entry_fflags(e, &set, &clear);
538 	assertEqualInt(clear, 0xAA);
539 	assertEqualInt(set, 0x55);
540 	assertEqualInt(archive_entry_gid(e2), 204);
541 	assertEqualString(archive_entry_gname(e2), "group");
542 	assertEqualString(archive_entry_hardlink(e2), "hardlinkname");
543 	assertEqualInt(archive_entry_ino(e2), 8593);
544 	assertEqualInt(archive_entry_mode(e2), 0123456);
545 	assertEqualInt(archive_entry_mtime(e2), 13581);
546 	assertEqualInt(archive_entry_mtime_nsec(e2), 24682);
547 	assertEqualInt(archive_entry_nlink(e2), 736);
548 	assertEqualString(archive_entry_pathname(e2), "path");
549 	assertEqualInt(archive_entry_rdev(e2), 532);
550 	assertEqualInt(archive_entry_size(e2), 987654321);
551 	assertEqualString(archive_entry_sourcepath(e2), "source");
552 	assertEqualString(archive_entry_symlink(e2), "symlinkname");
553 	assertEqualInt(archive_entry_uid(e2), 83);
554 	assertEqualString(archive_entry_uname(e2), "user");
555 
556 	/* Verify ACL was copied. */
557 	assertEqualInt(4, archive_entry_acl_reset(e2,
558 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
559 	/* First three are standard permission bits. */
560 	assertEqualInt(0, archive_entry_acl_next(e2,
561 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
562 			   &type, &permset, &tag, &qual, &name));
563 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
564 	assertEqualInt(permset, 4);
565 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ);
566 	assertEqualInt(qual, -1);
567 	assertEqualString(name, NULL);
568 	assertEqualInt(0, archive_entry_acl_next(e2,
569 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
570 			   &type, &permset, &tag, &qual, &name));
571 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
572 	assertEqualInt(permset, 5);
573 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ);
574 	assertEqualInt(qual, -1);
575 	assertEqualString(name, NULL);
576 	assertEqualInt(0, archive_entry_acl_next(e2,
577 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
578 			   &type, &permset, &tag, &qual, &name));
579 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
580 	assertEqualInt(permset, 6);
581 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER);
582 	assertEqualInt(qual, -1);
583 	assertEqualString(name, NULL);
584 	/* Fourth is custom one. */
585 	assertEqualInt(0, archive_entry_acl_next(e2,
586 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
587 			   &type, &permset, &tag, &qual, &name));
588 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
589 	assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ);
590 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER);
591 	assertEqualInt(qual, 77);
592 	assertEqualString(name, "user77");
593 
594 	/* Verify xattr was copied. */
595 	assertEqualInt(1, archive_entry_xattr_reset(e2));
596 	assertEqualInt(0, archive_entry_xattr_next(e2, &xname, &xval, &xsize));
597 	assertEqualString(xname, "xattr1");
598 	assertEqualString(xval, "xattrvalue");
599 	assertEqualInt((int)xsize, 11);
600 	assertEqualInt(ARCHIVE_WARN,
601 	    archive_entry_xattr_next(e2, &xname, &xval, &xsize));
602 	assertEqualString(xname, NULL);
603 	assertEqualString(xval, NULL);
604 	assertEqualInt((int)xsize, 0);
605 
606 	/* Change the original */
607 	archive_entry_set_atime(e, 13580, 24690);
608 	archive_entry_set_birthtime(e, 13980, 24999);
609 	archive_entry_set_ctime(e, 13590, 24691);
610 	archive_entry_set_dev(e, 245);
611 	archive_entry_set_fflags(e, 0x85, 0xDA);
612 	archive_entry_set_filetype(e, AE_IFLNK);
613 	archive_entry_set_gid(e, 214);
614 	archive_entry_set_gname(e, "grouper");
615 	archive_entry_set_hardlink(e, "hardlinkpath");
616 	archive_entry_set_ino(e, 8763);
617 	archive_entry_set_mode(e, 0123654);
618 	archive_entry_set_mtime(e, 18351, 28642);
619 	archive_entry_set_nlink(e, 73);
620 	archive_entry_set_pathname(e, "pathest");
621 	archive_entry_set_rdev(e, 132);
622 	archive_entry_set_size(e, 987456321);
623 	archive_entry_copy_sourcepath(e, "source2");
624 	archive_entry_set_symlink(e, "symlinkpath");
625 	archive_entry_set_uid(e, 93);
626 	archive_entry_set_uname(e, "username");
627 	archive_entry_acl_clear(e);
628 	archive_entry_xattr_clear(e);
629 
630 	/* Clone should still have same contents. */
631 	assertEqualInt(archive_entry_atime(e2), 13579);
632 	assertEqualInt(archive_entry_atime_nsec(e2), 24680);
633 	assertEqualInt(archive_entry_birthtime(e2), 13779);
634 	assertEqualInt(archive_entry_birthtime_nsec(e2), 24990);
635 	assertEqualInt(archive_entry_ctime(e2), 13580);
636 	assertEqualInt(archive_entry_ctime_nsec(e2), 24681);
637 	assertEqualInt(archive_entry_dev(e2), 235);
638 	archive_entry_fflags(e2, &set, &clear);
639 	assertEqualInt(clear, 0xAA);
640 	assertEqualInt(set, 0x55);
641 	assertEqualInt(archive_entry_gid(e2), 204);
642 	assertEqualString(archive_entry_gname(e2), "group");
643 	assertEqualString(archive_entry_hardlink(e2), "hardlinkname");
644 	assertEqualInt(archive_entry_ino(e2), 8593);
645 	assertEqualInt(archive_entry_mode(e2), 0123456);
646 	assertEqualInt(archive_entry_mtime(e2), 13581);
647 	assertEqualInt(archive_entry_mtime_nsec(e2), 24682);
648 	assertEqualInt(archive_entry_nlink(e2), 736);
649 	assertEqualString(archive_entry_pathname(e2), "path");
650 	assertEqualInt(archive_entry_rdev(e2), 532);
651 	assertEqualInt(archive_entry_size(e2), 987654321);
652 	assertEqualString(archive_entry_sourcepath(e2), "source");
653 	assertEqualString(archive_entry_symlink(e2), "symlinkname");
654 	assertEqualInt(archive_entry_uid(e2), 83);
655 	assertEqualString(archive_entry_uname(e2), "user");
656 
657 	/* Verify ACL was unchanged. */
658 	assertEqualInt(4, archive_entry_acl_reset(e2,
659 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
660 	/* First three are standard permission bits. */
661 	assertEqualInt(0, archive_entry_acl_next(e2,
662 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
663 			   &type, &permset, &tag, &qual, &name));
664 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
665 	assertEqualInt(permset, 4);
666 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER_OBJ);
667 	assertEqualInt(qual, -1);
668 	assertEqualString(name, NULL);
669 	assertEqualInt(0, archive_entry_acl_next(e2,
670 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
671 			   &type, &permset, &tag, &qual, &name));
672 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
673 	assertEqualInt(permset, 5);
674 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_GROUP_OBJ);
675 	assertEqualInt(qual, -1);
676 	assertEqualString(name, NULL);
677 	assertEqualInt(0, archive_entry_acl_next(e2,
678 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
679 			   &type, &permset, &tag, &qual, &name));
680 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
681 	assertEqualInt(permset, 6);
682 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_OTHER);
683 	assertEqualInt(qual, -1);
684 	assertEqualString(name, NULL);
685 	/* Fourth is custom one. */
686 	assertEqualInt(0, archive_entry_acl_next(e2,
687 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
688 			   &type, &permset, &tag, &qual, &name));
689 	assertEqualInt(type, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
690 	assertEqualInt(permset, ARCHIVE_ENTRY_ACL_READ);
691 	assertEqualInt(tag, ARCHIVE_ENTRY_ACL_USER);
692 	assertEqualInt(qual, 77);
693 	assertEqualString(name, "user77");
694 	assertEqualInt(1, archive_entry_acl_next(e2,
695 			   ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
696 			   &type, &permset, &tag, &qual, &name));
697 	assertEqualInt(type, 0);
698 	assertEqualInt(permset, 0);
699 	assertEqualInt(tag, 0);
700 	assertEqualInt(qual, -1);
701 	assertEqualString(name, NULL);
702 
703 	/* Verify xattr was unchanged. */
704 	assertEqualInt(1, archive_entry_xattr_reset(e2));
705 
706 	/* Release clone. */
707 	archive_entry_free(e2);
708 
709 	/*
710 	 * Test clear() implementation.
711 	 */
712 	archive_entry_clear(e);
713 	assertEqualInt(archive_entry_atime(e), 0);
714 	assertEqualInt(archive_entry_atime_nsec(e), 0);
715 	assertEqualInt(archive_entry_birthtime(e), 0);
716 	assertEqualInt(archive_entry_birthtime_nsec(e), 0);
717 	assertEqualInt(archive_entry_ctime(e), 0);
718 	assertEqualInt(archive_entry_ctime_nsec(e), 0);
719 	assertEqualInt(archive_entry_dev(e), 0);
720 	archive_entry_fflags(e, &set, &clear);
721 	assertEqualInt(clear, 0);
722 	assertEqualInt(set, 0);
723 	assertEqualInt(archive_entry_filetype(e), 0);
724 	assertEqualInt(archive_entry_gid(e), 0);
725 	assertEqualString(archive_entry_gname(e), NULL);
726 	assertEqualString(archive_entry_hardlink(e), NULL);
727 	assertEqualInt(archive_entry_ino(e), 0);
728 	assertEqualInt(archive_entry_mode(e), 0);
729 	assertEqualInt(archive_entry_mtime(e), 0);
730 	assertEqualInt(archive_entry_mtime_nsec(e), 0);
731 	assertEqualInt(archive_entry_nlink(e), 0);
732 	assertEqualString(archive_entry_pathname(e), NULL);
733 	assertEqualInt(archive_entry_rdev(e), 0);
734 	assertEqualInt(archive_entry_size(e), 0);
735 	assertEqualString(archive_entry_symlink(e), NULL);
736 	assertEqualInt(archive_entry_uid(e), 0);
737 	assertEqualString(archive_entry_uname(e), NULL);
738 	/* ACLs should be cleared. */
739 	assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), 0);
740 	assertEqualInt(archive_entry_acl_count(e, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT), 0);
741 	/* Extended attributes should be cleared. */
742 	assertEqualInt(archive_entry_xattr_count(e), 0);
743 
744 	/*
745 	 * Test archive_entry_copy_stat().
746 	 */
747 	memset(&st, 0, sizeof(st));
748 	/* Set all of the standard 'struct stat' fields. */
749 	st.st_atime = 456789;
750 	st.st_ctime = 345678;
751 	st.st_dev = 123;
752 	st.st_gid = 34;
753 	st.st_ino = 234;
754 	st.st_mode = 077777;
755 	st.st_mtime = 234567;
756 	st.st_nlink = 345;
757 	st.st_size = 123456789;
758 	st.st_uid = 23;
759 #ifdef __FreeBSD__
760 	/* On FreeBSD, high-res timestamp data should come through. */
761 	st.st_atimespec.tv_nsec = 6543210;
762 	st.st_ctimespec.tv_nsec = 5432109;
763 	st.st_mtimespec.tv_nsec = 3210987;
764 	st.st_birthtimespec.tv_nsec = 7459386;
765 #endif
766 	/* Copy them into the entry. */
767 	archive_entry_copy_stat(e, &st);
768 	/* Read each one back separately and compare. */
769 	assertEqualInt(archive_entry_atime(e), 456789);
770 	assertEqualInt(archive_entry_ctime(e), 345678);
771 	assertEqualInt(archive_entry_dev(e), 123);
772 	assertEqualInt(archive_entry_gid(e), 34);
773 	assertEqualInt(archive_entry_ino(e), 234);
774 	assertEqualInt(archive_entry_mode(e), 077777);
775 	assertEqualInt(archive_entry_mtime(e), 234567);
776 	assertEqualInt(archive_entry_nlink(e), 345);
777 	assertEqualInt(archive_entry_size(e), 123456789);
778 	assertEqualInt(archive_entry_uid(e), 23);
779 #if __FreeBSD__
780 	/* On FreeBSD, high-res timestamp data should come through. */
781 	assertEqualInt(archive_entry_atime_nsec(e), 6543210);
782 	assertEqualInt(archive_entry_ctime_nsec(e), 5432109);
783 	assertEqualInt(archive_entry_mtime_nsec(e), 3210987);
784 	assertEqualInt(archive_entry_birthtime_nsec(e), 7459386);
785 #endif
786 
787 	/*
788 	 * Test archive_entry_stat().
789 	 */
790 	/* First, clear out any existing stat data. */
791 	memset(&st, 0, sizeof(st));
792 	archive_entry_copy_stat(e, &st);
793 	/* Set a bunch of fields individually. */
794 	archive_entry_set_atime(e, 456789, 321);
795 	archive_entry_set_ctime(e, 345678, 432);
796 	archive_entry_set_dev(e, 123);
797 	archive_entry_set_gid(e, 34);
798 	archive_entry_set_ino(e, 234);
799 	archive_entry_set_mode(e, 012345);
800 	archive_entry_set_mode(e, 012345);
801 	archive_entry_set_mtime(e, 234567, 543);
802 	archive_entry_set_nlink(e, 345);
803 	archive_entry_set_size(e, 123456789);
804 	archive_entry_set_uid(e, 23);
805 	/* Retrieve a stat structure. */
806 	assert((pst = archive_entry_stat(e)) != NULL);
807 	if (pst == NULL)
808 		return;
809 	/* Check that the values match. */
810 	assertEqualInt(pst->st_atime, 456789);
811 	assertEqualInt(pst->st_ctime, 345678);
812 	assertEqualInt(pst->st_dev, 123);
813 	assertEqualInt(pst->st_gid, 34);
814 	assertEqualInt(pst->st_ino, 234);
815 	assertEqualInt(pst->st_mode, 012345);
816 	assertEqualInt(pst->st_mtime, 234567);
817 	assertEqualInt(pst->st_nlink, 345);
818 	assertEqualInt(pst->st_size, 123456789);
819 	assertEqualInt(pst->st_uid, 23);
820 #ifdef __FreeBSD__
821 	/* On FreeBSD, high-res timestamp data should come through. */
822 	assertEqualInt(pst->st_atimespec.tv_nsec, 321);
823 	assertEqualInt(pst->st_ctimespec.tv_nsec, 432);
824 	assertEqualInt(pst->st_mtimespec.tv_nsec, 543);
825 #endif
826 
827 	/* Changing any one value should update struct stat. */
828 	archive_entry_set_atime(e, 456788, 0);
829 	assert((pst = archive_entry_stat(e)) != NULL);
830 	if (pst == NULL)
831 		return;
832 	assertEqualInt(pst->st_atime, 456788);
833 	archive_entry_set_ctime(e, 345677, 431);
834 	assert((pst = archive_entry_stat(e)) != NULL);
835 	if (pst == NULL)
836 		return;
837 	assertEqualInt(pst->st_ctime, 345677);
838 	archive_entry_set_dev(e, 122);
839 	assert((pst = archive_entry_stat(e)) != NULL);
840 	if (pst == NULL)
841 		return;
842 	assertEqualInt(pst->st_dev, 122);
843 	archive_entry_set_gid(e, 33);
844 	assert((pst = archive_entry_stat(e)) != NULL);
845 	if (pst == NULL)
846 		return;
847 	assertEqualInt(pst->st_gid, 33);
848 	archive_entry_set_ino(e, 233);
849 	assert((pst = archive_entry_stat(e)) != NULL);
850 	if (pst == NULL)
851 		return;
852 	assertEqualInt(pst->st_ino, 233);
853 	archive_entry_set_mode(e, 012344);
854 	assert((pst = archive_entry_stat(e)) != NULL);
855 	if (pst == NULL)
856 		return;
857 	assertEqualInt(pst->st_mode, 012344);
858 	archive_entry_set_mtime(e, 234566, 542);
859 	assert((pst = archive_entry_stat(e)) != NULL);
860 	if (pst == NULL)
861 		return;
862 	assertEqualInt(pst->st_mtime, 234566);
863 	archive_entry_set_nlink(e, 344);
864 	assert((pst = archive_entry_stat(e)) != NULL);
865 	if (pst == NULL)
866 		return;
867 	assertEqualInt(pst->st_nlink, 344);
868 	archive_entry_set_size(e, 123456788);
869 	assert((pst = archive_entry_stat(e)) != NULL);
870 	if (pst == NULL)
871 		return;
872 	assertEqualInt(pst->st_size, 123456788);
873 	archive_entry_set_uid(e, 22);
874 	assert((pst = archive_entry_stat(e)) != NULL);
875 	if (pst == NULL)
876 		return;
877 	assertEqualInt(pst->st_uid, 22);
878 	/* We don't need to check high-res fields here. */
879 
880 	/*
881 	 * Test dev/major/minor interfaces.  Setting 'dev' or 'rdev'
882 	 * should change the corresponding major/minor values, and
883 	 * vice versa.
884 	 *
885 	 * The test here is system-specific because it assumes that
886 	 * makedev(), major(), and minor() are defined in sys/stat.h.
887 	 * I'm not too worried about it, though, because the code is
888 	 * simple.  If it works on FreeBSD, it's unlikely to be broken
889 	 * anywhere else.  Note: The functionality is present on every
890 	 * platform even if these tests only run some places;
891 	 * libarchive's more extensive configuration logic should find
892 	 * the necessary definitions on every platform.
893 	 */
894 #if __FreeBSD__
895 	archive_entry_set_dev(e, 0x12345678);
896 	assertEqualInt(archive_entry_devmajor(e), major(0x12345678));
897 	assertEqualInt(archive_entry_devminor(e), minor(0x12345678));
898 	assertEqualInt(archive_entry_dev(e), 0x12345678);
899 	archive_entry_set_devmajor(e, 0xfe);
900 	archive_entry_set_devminor(e, 0xdcba98);
901 	assertEqualInt(archive_entry_devmajor(e), 0xfe);
902 	assertEqualInt(archive_entry_devminor(e), 0xdcba98);
903 	assertEqualInt(archive_entry_dev(e), makedev(0xfe, 0xdcba98));
904 	archive_entry_set_rdev(e, 0x12345678);
905 	assertEqualInt(archive_entry_rdevmajor(e), major(0x12345678));
906 	assertEqualInt(archive_entry_rdevminor(e), minor(0x12345678));
907 	assertEqualInt(archive_entry_rdev(e), 0x12345678);
908 	archive_entry_set_rdevmajor(e, 0xfe);
909 	archive_entry_set_rdevminor(e, 0xdcba98);
910 	assertEqualInt(archive_entry_rdevmajor(e), 0xfe);
911 	assertEqualInt(archive_entry_rdevminor(e), 0xdcba98);
912 	assertEqualInt(archive_entry_rdev(e), makedev(0xfe, 0xdcba98));
913 #endif
914 
915 	/*
916 	 * Exercise the character-conversion logic, if we can.
917 	 */
918 	if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
919 		skipping("Can't exercise charset-conversion logic without"
920 			" a suitable locale.");
921 	} else {
922 		/* A filename that cannot be converted to wide characters. */
923 		archive_entry_copy_pathname(e, "abc\314\214mno\374xyz");
924 		failure("Converting invalid chars to Unicode should fail.");
925 		assert(NULL == archive_entry_pathname_w(e));
926 		/*
927 		  failure("Converting invalid chars to UTF-8 should fail.");
928 		  assert(NULL == archive_entry_pathname_utf8(e));
929 		*/
930 
931 		/* A group name that cannot be converted. */
932 		archive_entry_copy_gname(e, "abc\314\214mno\374xyz");
933 		failure("Converting invalid chars to Unicode should fail.");
934 		assert(NULL == archive_entry_gname_w(e));
935 
936 		/* A user name that cannot be converted. */
937 		archive_entry_copy_uname(e, "abc\314\214mno\374xyz");
938 		failure("Converting invalid chars to Unicode should fail.");
939 		assert(NULL == archive_entry_uname_w(e));
940 
941 		/* A hardlink target that cannot be converted. */
942 		archive_entry_copy_hardlink(e, "abc\314\214mno\374xyz");
943 		failure("Converting invalid chars to Unicode should fail.");
944 		assert(NULL == archive_entry_hardlink_w(e));
945 
946 		/* A symlink target that cannot be converted. */
947 		archive_entry_copy_symlink(e, "abc\314\214mno\374xyz");
948 		failure("Converting invalid chars to Unicode should fail.");
949 		assert(NULL == archive_entry_symlink_w(e));
950 	}
951 
952 	l = 0x12345678L;
953 	wc = (wchar_t)l; /* Wide character too big for UTF-8. */
954 	if (NULL == setlocale(LC_ALL, "C") || (long)wc != l) {
955 		skipping("Testing charset conversion failure requires 32-bit wchar_t and support for \"C\" locale.");
956 	} else {
957 		/*
958 		 * Build the string L"xxx\U12345678yyy\u5678zzz" without
959 		 * using wcscpy or C99 \u#### syntax.
960 		 */
961 		name = "xxxAyyyBzzz";
962 		for (i = 0; i < (int)strlen(name); ++i)
963 			wbuff[i] = name[i];
964 		wbuff[3] = (wchar_t)0x12345678;
965 		wbuff[7] = (wchar_t)0x5678;
966 		/* A Unicode filename that cannot be converted to UTF-8. */
967 		archive_entry_copy_pathname_w(e, wbuff);
968 		failure("Converting wide characters from Unicode should fail.");
969 		assertEqualString(NULL, archive_entry_pathname(e));
970 	}
971 
972 	/* Release the experimental entry. */
973 	archive_entry_free(e);
974 }
975