diff options
author | Tim Kientzle <kientzle@FreeBSD.org> | 2008-05-26 17:00:24 +0000 |
---|---|---|
committer | Tim Kientzle <kientzle@FreeBSD.org> | 2008-05-26 17:00:24 +0000 |
commit | fa07de5eeb36516701b3393f13acc1e1f702c634 (patch) | |
tree | d200bbdabe22d32b68a61172999be232d0c31d75 /lib/libarchive/archive_entry.h | |
parent | 037dab5792a349d02f4bb134d55e9402f3254c7c (diff) |
MFp4: libarchive 2.5.4b. (Still 'b' until I get a bit more
feedback, but the 2.5 branch is shaping up nicely.)
In addition to many small bug fixes and code improvements:
* Another iteration of versioning; I think I've got it right now.
* Portability: A lot of progress on Windows support (though I'm
not committing all of the Windows support files to FreeBSD CVS)
* Explicit tracking of MBS, WCS, and UTF-8 versions of strings
in archive_entry; the archive_entry routines now correctly return
NULL only when something is unset, setting NULL properly clears
string values. Most charset conversions have been pushed down to
archive_string.
* Better handling of charset conversion failure when writing or
reading UTF-8 headers in pax archives
* archive_entry_linkify() provides multiple strategies for
hardlink matching to suit different format expectations
* More accurate bzip2 format detection
* Joerg Sonnenberger's extensive improvements to mtree support
* Rough support for self-extracting ZIP archives. Not an ideal
approach, but it works for the archives I've tried.
* New "sparsify" option in archive_write_disk converts blocks of nulls
into seeks.
* Better default behavior for the test harness; it now reports
all failures by default instead of coredumping at the first one.
Notes
Notes:
svn path=/head/; revision=179321
Diffstat (limited to 'lib/libarchive/archive_entry.h')
-rw-r--r-- | lib/libarchive/archive_entry.h | 329 |
1 files changed, 223 insertions, 106 deletions
diff --git a/lib/libarchive/archive_entry.h b/lib/libarchive/archive_entry.h index 8c61b9553b63..c453483a65ac 100644 --- a/lib/libarchive/archive_entry.h +++ b/lib/libarchive/archive_entry.h @@ -28,20 +28,74 @@ #ifndef ARCHIVE_ENTRY_H_INCLUDED #define ARCHIVE_ENTRY_H_INCLUDED +/* + * Note: archive_entry.h is for use outside of libarchive; the + * configuration headers (config.h, archive_platform.h, etc.) are + * purely internal. Do NOT use HAVE_XXX configuration macros to + * control the behavior of this header! If you must conditionalize, + * use predefined compiler and/or platform macros. + */ + #include <sys/types.h> #include <stddef.h> /* for wchar_t */ #include <time.h> + +/* Get appropriate definitions of standard POSIX-style types. */ +/* These should match the types used in 'struct stat' */ +#ifdef _WIN32 +#define __LA_UID_T unsigned int +#define __LA_GID_T unsigned int +#define __LA_DEV_T unsigned int +#define __LA_MODE_T unsigned short +#else #include <unistd.h> +#define __LA_UID_T uid_t +#define __LA_GID_T gid_t +#define __LA_DEV_T dev_t +#define __LA_MODE_T mode_t +#endif + +/* + * XXX Is this defined for all Windows compilers? If so, in what + * header? It would be nice to remove the __LA_INO_T indirection and + * just use plain ino_t everywhere. Likewise for the other types just + * above. + */ +#define __LA_INO_T ino_t + + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllimport)) extern +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries on all platforms and shared libraries on non-Windows. */ +# define __LA_DECL +#endif #ifdef __cplusplus extern "C" { #endif - /* * Description of an archive entry. * - * Basically, a "struct stat" with a few text fields added in. + * You can think of this as "struct stat" with some text fields added in. * * TODO: Add "comment", "charset", and possibly other entries that are * supported by "pax interchange" format. However, GNU, ustar, cpio, @@ -90,50 +144,51 @@ struct archive_entry; * Basic object manipulation */ -struct archive_entry *archive_entry_clear(struct archive_entry *); +__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); /* The 'clone' function does a deep copy; all of the strings are copied too. */ -struct archive_entry *archive_entry_clone(struct archive_entry *); -void archive_entry_free(struct archive_entry *); -struct archive_entry *archive_entry_new(void); +__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); +__LA_DECL void archive_entry_free(struct archive_entry *); +__LA_DECL struct archive_entry *archive_entry_new(void); /* * Retrieve fields from an archive_entry. */ -time_t archive_entry_atime(struct archive_entry *); -long archive_entry_atime_nsec(struct archive_entry *); -time_t archive_entry_ctime(struct archive_entry *); -long archive_entry_ctime_nsec(struct archive_entry *); -dev_t archive_entry_dev(struct archive_entry *); -dev_t archive_entry_devmajor(struct archive_entry *); -dev_t archive_entry_devminor(struct archive_entry *); -mode_t archive_entry_filetype(struct archive_entry *); -void archive_entry_fflags(struct archive_entry *, +__LA_DECL time_t archive_entry_atime(struct archive_entry *); +__LA_DECL long archive_entry_atime_nsec(struct archive_entry *); +__LA_DECL time_t archive_entry_ctime(struct archive_entry *); +__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); +__LA_DECL dev_t archive_entry_dev(struct archive_entry *); +__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_devminor(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); +__LA_DECL void archive_entry_fflags(struct archive_entry *, unsigned long * /* set */, unsigned long * /* clear */); -const char *archive_entry_fflags_text(struct archive_entry *); -gid_t archive_entry_gid(struct archive_entry *); -const char *archive_entry_gname(struct archive_entry *); -const wchar_t *archive_entry_gname_w(struct archive_entry *); -const char *archive_entry_hardlink(struct archive_entry *); -const wchar_t *archive_entry_hardlink_w(struct archive_entry *); -ino_t archive_entry_ino(struct archive_entry *); -mode_t archive_entry_mode(struct archive_entry *); -time_t archive_entry_mtime(struct archive_entry *); -long archive_entry_mtime_nsec(struct archive_entry *); -unsigned int archive_entry_nlink(struct archive_entry *); -const char *archive_entry_pathname(struct archive_entry *); -const wchar_t *archive_entry_pathname_w(struct archive_entry *); -dev_t archive_entry_rdev(struct archive_entry *); -dev_t archive_entry_rdevmajor(struct archive_entry *); -dev_t archive_entry_rdevminor(struct archive_entry *); -int64_t archive_entry_size(struct archive_entry *); -const char *archive_entry_strmode(struct archive_entry *); -const char *archive_entry_symlink(struct archive_entry *); -const wchar_t *archive_entry_symlink_w(struct archive_entry *); -uid_t archive_entry_uid(struct archive_entry *); -const char *archive_entry_uname(struct archive_entry *); -const wchar_t *archive_entry_uname_w(struct archive_entry *); +__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); +__LA_DECL __LA_GID_T archive_entry_gid(struct archive_entry *); +__LA_DECL const char *archive_entry_gname(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); +__LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); +__LA_DECL time_t archive_entry_mtime(struct archive_entry *); +__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); +__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdev(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); +__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); +__LA_DECL int64_t archive_entry_size(struct archive_entry *); +__LA_DECL const char *archive_entry_strmode(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); +__LA_DECL __LA_UID_T archive_entry_uid(struct archive_entry *); +__LA_DECL const char *archive_entry_uname(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); /* * Set fields in an archive_entry. @@ -142,48 +197,54 @@ const wchar_t *archive_entry_uname_w(struct archive_entry *); * In contrast, 'copy' functions do copy the object pointed to. */ -void archive_entry_set_atime(struct archive_entry *, time_t, long); -void archive_entry_set_ctime(struct archive_entry *, time_t, long); -void archive_entry_set_dev(struct archive_entry *, dev_t); -void archive_entry_set_devmajor(struct archive_entry *, dev_t); -void archive_entry_set_devminor(struct archive_entry *, dev_t); -void archive_entry_set_filetype(struct archive_entry *, unsigned int); -void archive_entry_set_fflags(struct archive_entry *, +__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_fflags(struct archive_entry *, unsigned long /* set */, unsigned long /* clear */); /* Returns pointer to start of first invalid token, or NULL if none. */ /* Note that all recognized tokens are processed, regardless. */ -const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, +__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, + const char *); +__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_gid(struct archive_entry *, gid_t); -void archive_entry_set_gname(struct archive_entry *, const char *); -void archive_entry_copy_gname(struct archive_entry *, const char *); -void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_hardlink(struct archive_entry *, const char *); -void archive_entry_copy_hardlink(struct archive_entry *, const char *); -void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_ino(struct archive_entry *, unsigned long); -void archive_entry_set_link(struct archive_entry *, const char *); -void archive_entry_copy_link(struct archive_entry *, const char *); -void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_mode(struct archive_entry *, mode_t); -void archive_entry_set_mtime(struct archive_entry *, time_t, long); -void archive_entry_set_nlink(struct archive_entry *, unsigned int); -void archive_entry_set_pathname(struct archive_entry *, const char *); -void archive_entry_copy_pathname(struct archive_entry *, const char *); -void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_perm(struct archive_entry *, mode_t); -void archive_entry_set_rdev(struct archive_entry *, dev_t); -void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); -void archive_entry_set_rdevminor(struct archive_entry *, dev_t); -void archive_entry_set_size(struct archive_entry *, int64_t); -void archive_entry_set_symlink(struct archive_entry *, const char *); -void archive_entry_copy_symlink(struct archive_entry *, const char *); -void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); -void archive_entry_set_uid(struct archive_entry *, uid_t); -void archive_entry_set_uname(struct archive_entry *, const char *); -void archive_entry_copy_uname(struct archive_entry *, const char *); -void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); - +__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_GID_T); +__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL void archive_entry_set_ino(struct archive_entry *, unsigned long); +__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_size(struct archive_entry *, int64_t); +__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_UID_T); +__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); /* * Routines to bulk copy fields to/from a platform-native "struct * stat." Libarchive used to just store a struct stat inside of each @@ -193,8 +254,8 @@ void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); * * TODO: On Linux, provide both stat32 and stat64 versions of these functions. */ -const struct stat *archive_entry_stat(struct archive_entry *); -void archive_entry_copy_stat(struct archive_entry *, const struct stat *); +__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); +__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); /* * ACL routines. This used to simply store and return text-format ACL @@ -242,11 +303,11 @@ void archive_entry_copy_stat(struct archive_entry *, const struct stat *); * POSIX.1e) is useful for handling archive formats that combine * default and access information in a single ACL list. */ -void archive_entry_acl_clear(struct archive_entry *); -void archive_entry_acl_add_entry(struct archive_entry *, +__LA_DECL void archive_entry_acl_clear(struct archive_entry *); +__LA_DECL void archive_entry_acl_add_entry(struct archive_entry *, int /* type */, int /* permset */, int /* tag */, int /* qual */, const char * /* name */); -void archive_entry_acl_add_entry_w(struct archive_entry *, +__LA_DECL void archive_entry_acl_add_entry_w(struct archive_entry *, int /* type */, int /* permset */, int /* tag */, int /* qual */, const wchar_t * /* name */); @@ -255,11 +316,11 @@ void archive_entry_acl_add_entry_w(struct archive_entry *, * "next" entry. The want_type parameter allows you to request only * access entries or only default entries. */ -int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); -int archive_entry_acl_next(struct archive_entry *, int /* want_type */, +__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); +__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, int * /* type */, int * /* permset */, int * /* tag */, int * /* qual */, const char ** /* name */); -int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, +__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, int * /* type */, int * /* permset */, int * /* tag */, int * /* qual */, const wchar_t ** /* name */); @@ -276,11 +337,11 @@ int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, */ #define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 #define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 -const wchar_t *archive_entry_acl_text_w(struct archive_entry *, +__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, int /* flags */); /* Return a count of entries matching 'want_type' */ -int archive_entry_acl_count(struct archive_entry *, int /* want_type */); +__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); /* * Private ACL parser. This is private because it handles some @@ -295,15 +356,15 @@ int archive_entry_acl_count(struct archive_entry *, int /* want_type */); * TODO: Move this declaration out of the public header and into * a private header. Warnings above are silly. */ -int __archive_entry_acl_parse_w(struct archive_entry *, +__LA_DECL int __archive_entry_acl_parse_w(struct archive_entry *, const wchar_t *, int /* type */); /* * extended attributes */ -void archive_entry_xattr_clear(struct archive_entry *); -void archive_entry_xattr_add_entry(struct archive_entry *, +__LA_DECL void archive_entry_xattr_clear(struct archive_entry *); +__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, const char * /* name */, const void * /* value */, size_t /* size */); @@ -312,37 +373,93 @@ void archive_entry_xattr_add_entry(struct archive_entry *, * "next" entry. */ -int archive_entry_xattr_count(struct archive_entry *); -int archive_entry_xattr_reset(struct archive_entry *); -int archive_entry_xattr_next(struct archive_entry *, +__LA_DECL int archive_entry_xattr_count(struct archive_entry *); +__LA_DECL int archive_entry_xattr_reset(struct archive_entry *); +__LA_DECL int archive_entry_xattr_next(struct archive_entry *, const char ** /* name */, const void ** /* value */, size_t *); /* - * Utility to detect hardlinks. + * Utility to match up hardlinks. + * + * The 'struct archive_entry_linkresolver' is a cache of archive entries + * for files with multiple links. Here's how to use it: + * 1. Create a lookup object with archive_entry_linkresolver_new() + * 2. Tell it the archive format you're using. + * 3. Hand each archive_entry to archive_entry_linkify(). + * That function will return 0, 1, or 2 entries that should + * be written. + * 4. Call archive_entry_linkify(resolver, NULL) until + * no more entries are returned. + * 5. Call archive_entry_link_resolver_free(resolver) to free resources. * - * The 'struct archive_hardlink_lookup' is a cache of entry - * names and dev/ino numbers. Here's how to use it: - * 1. Create a lookup object with archive_hardlink_lookup_new() - * 2. Hand each archive_entry to archive_hardlink_lookup(). - * That function will return NULL (this is not a hardlink to - * a previous entry) or the pathname of the first entry - * that matched this. - * 3. Use archive_hardlink_lookup_free() to release the cache. + * The entries returned have their hardlink and size fields updated + * appropriately. If an entry is passed in that does not refer to + * a file with multiple links, it is returned unchanged. The intention + * is that you should be able to simply filter all entries through + * this machine. * * To make things more efficient, be sure that each entry has a valid * nlinks value. The hardlink cache uses this to track when all links * have been found. If the nlinks value is zero, it will keep every * name in the cache indefinitely, which can use a lot of memory. + * + * Note that archive_entry_size() is reset to zero if the file + * body should not be written to the archive. Pay attention! */ -struct archive_entry_linkresolver; +__LA_DECL struct archive_entry_linkresolver; -struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); -void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); -const char *archive_entry_linkresolve(struct archive_entry_linkresolver *, - struct archive_entry *); +/* + * There are three different strategies for marking hardlinks. + * The descriptions below name them after the best-known + * formats that rely on each strategy: + * + * "Old cpio" is the simplest, it always returns any entry unmodified. + * As far as I know, only cpio formats use this. Old cpio archives + * store every link with the full body; the onus is on the dearchiver + * to detect and properly link the files as they are restored. + * "tar" is also pretty simple; it caches a copy the first time it sees + * any link. Subsequent appearances are modified to be hardlink + * references to the first one without any body. Used by all tar + * formats, although the newest tar formats permit the "old cpio" strategy + * as well. This strategy is very simple for the dearchiver, + * and reasonably straightforward for the archiver. + * "new cpio" is trickier. It stores the body only with the last + * occurrence. The complication is that we might not + * see every link to a particular file in a single session, so + * there's no easy way to know when we've seen the last occurrence. + * The solution here is to queue one link until we see the next. + * At the end of the session, you can enumerate any remaining + * entries by calling archive_entry_linkify(NULL) and store those + * bodies. If you have a file with three links l1, l2, and l3, + * you'll get the following behavior if you see all three links: + * linkify(l1) => NULL (the resolver stores l1 internally) + * linkify(l2) => l1 (resolver stores l2, you write l1) + * linkify(l3) => l2, l3 (all links seen, you can write both). + * If you only see l1 and l2, you'll get this behavior: + * linkify(l1) => NULL + * linkify(l2) => l1 + * linkify(NULL) => l2 (at end, you retrieve remaining links) + * As the name suggests, this strategy is used by newer cpio variants. + * It's noticably more complex for the archiver, slightly more complex + * for the dearchiver than the tar strategy, but makes it straightforward + * to restore a file using any link by simply continuing to scan until + * you see a link that is stored with a body. In contrast, the tar + * strategy requires you to rescan the archive from the beginning to + * correctly extract an arbitrary link. + */ + +__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); +__LA_DECL void archive_entry_linkresolver_set_strategy( + struct archive_entry_linkresolver *, int /* format_code */); +__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); +__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, + struct archive_entry **, struct archive_entry **); #ifdef __cplusplus } #endif +/* This is meaningless outside of this header. */ +#undef __LA_DECL + #endif /* !ARCHIVE_ENTRY_H_INCLUDED */ |