libarchive-static 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/Makefile +6 -0
- data/ext/extconf.rb +61 -0
- data/ext/libarchive-0.1.1/COPYING.libarchive +60 -0
- data/ext/libarchive-0.1.1/LICENSE.libbzip2 +42 -0
- data/ext/libarchive-0.1.1/README.txt +143 -0
- data/ext/libarchive-0.1.1/ext/Makefile.in +0 -0
- data/ext/libarchive-0.1.1/ext/archive_read_support_compression.c +31 -0
- data/ext/libarchive-0.1.1/ext/archive_read_support_compression.h +6 -0
- data/ext/libarchive-0.1.1/ext/archive_read_support_format.c +32 -0
- data/ext/libarchive-0.1.1/ext/archive_read_support_format.h +6 -0
- data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.c +29 -0
- data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.h +6 -0
- data/ext/libarchive-0.1.1/ext/archive_write_set_compression.c +32 -0
- data/ext/libarchive-0.1.1/ext/archive_write_set_compression.h +6 -0
- data/ext/libarchive-0.1.1/ext/config.h.in +22 -0
- data/ext/libarchive-0.1.1/ext/configure +3904 -0
- data/ext/libarchive-0.1.1/ext/configure.in +11 -0
- data/ext/libarchive-0.1.1/ext/depend +19 -0
- data/ext/libarchive-0.1.1/ext/extconf.rb +6 -0
- data/ext/libarchive-0.1.1/ext/install-sh +250 -0
- data/ext/libarchive-0.1.1/ext/libarchive.c +89 -0
- data/ext/libarchive-0.1.1/ext/libarchive_archive.c +84 -0
- data/ext/libarchive-0.1.1/ext/libarchive_entry.c +1015 -0
- data/ext/libarchive-0.1.1/ext/libarchive_internal.h +155 -0
- data/ext/libarchive-0.1.1/ext/libarchive_reader.c +328 -0
- data/ext/libarchive-0.1.1/ext/libarchive_win32.h +52 -0
- data/ext/libarchive-0.1.1/ext/libarchive_writer.c +246 -0
- data/ext/libarchive-0.1.1/libarchive.c +1762 -0
- data/ext/libarchive-2.8.4/Makefile.in +7076 -0
- data/ext/libarchive-2.8.4/build/autoconf/check_stdcall_func.m4 +51 -0
- data/ext/libarchive-2.8.4/build/autoconf/compile +143 -0
- data/ext/libarchive-2.8.4/build/autoconf/config.guess +1502 -0
- data/ext/libarchive-2.8.4/build/autoconf/config.sub +1708 -0
- data/ext/libarchive-2.8.4/build/autoconf/depcomp +630 -0
- data/ext/libarchive-2.8.4/build/autoconf/install-sh +291 -0
- data/ext/libarchive-2.8.4/build/autoconf/la_uid_t.m4 +20 -0
- data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +8406 -0
- data/ext/libarchive-2.8.4/build/autoconf/missing +376 -0
- data/ext/libarchive-2.8.4/build/pkgconfig/libarchive.pc.in +10 -0
- data/ext/libarchive-2.8.4/config.h.in +772 -0
- data/ext/libarchive-2.8.4/configure +17916 -0
- data/ext/libarchive-2.8.4/libarchive/archive.h +741 -0
- data/ext/libarchive-2.8.4/libarchive/archive_check_magic.c +134 -0
- data/ext/libarchive-2.8.4/libarchive/archive_crc32.h +66 -0
- data/ext/libarchive-2.8.4/libarchive/archive_endian.h +162 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry.c +2202 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry.h +524 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_copy_bhfi.c +74 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_copy_stat.c +77 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_link_resolver.c +405 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_private.h +184 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_stat.c +118 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_strmode.c +87 -0
- data/ext/libarchive-2.8.4/libarchive/archive_entry_xattr.c +158 -0
- data/ext/libarchive-2.8.4/libarchive/archive_hash.h +281 -0
- data/ext/libarchive-2.8.4/libarchive/archive_platform.h +165 -0
- data/ext/libarchive-2.8.4/libarchive/archive_private.h +124 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read.c +1249 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_data_into_fd.c +93 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +198 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +570 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk_private.h +62 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_disk_set_standard_lookup.c +303 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_extract.c +182 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_open_fd.c +190 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_open_file.c +165 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +272 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_open_memory.c +156 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_private.h +199 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_all.c +60 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_bzip2.c +353 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_compress.c +444 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_gzip.c +465 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_none.c +40 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_program.c +459 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_rpm.c +287 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_uu.c +627 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_xz.c +708 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_all.c +43 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_ar.c +584 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +777 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_empty.c +93 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_iso9660.c +2830 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +1304 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_raw.c +185 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_tar.c +2418 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_xar.c +3151 -0
- data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +903 -0
- data/ext/libarchive-2.8.4/libarchive/archive_string.c +453 -0
- data/ext/libarchive-2.8.4/libarchive/archive_string.h +148 -0
- data/ext/libarchive-2.8.4/libarchive/archive_string_sprintf.c +164 -0
- data/ext/libarchive-2.8.4/libarchive/archive_util.c +391 -0
- data/ext/libarchive-2.8.4/libarchive/archive_virtual.c +94 -0
- data/ext/libarchive-2.8.4/libarchive/archive_windows.c +1236 -0
- data/ext/libarchive-2.8.4/libarchive/archive_windows.h +347 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write.c +466 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +2628 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_disk_private.h +38 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_disk_set_standard_lookup.c +262 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_open_fd.c +141 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_open_file.c +105 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_open_filename.c +162 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_open_memory.c +126 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_private.h +122 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +408 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_compress.c +492 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +477 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +257 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +347 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +438 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format.c +72 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_ar.c +550 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_by_name.c +76 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +344 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +295 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +1050 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_pax.c +1386 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_shar.c +626 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_ustar.c +587 -0
- data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +667 -0
- data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +154 -0
- data/ext/libarchive-2.8.4/libarchive/filter_fork.c +161 -0
- data/ext/libarchive-2.8.4/libarchive/filter_fork.h +41 -0
- data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +113 -0
- data/ext/libarchive-static-makefile +80 -0
- data/ext/libarchive-static-wrapper-makefile +22 -0
- data/ext/zlib-1.2.5/Makefile.in +257 -0
- data/ext/zlib-1.2.5/adler32.c +169 -0
- data/ext/zlib-1.2.5/compress.c +80 -0
- data/ext/zlib-1.2.5/configure +596 -0
- data/ext/zlib-1.2.5/crc32.c +442 -0
- data/ext/zlib-1.2.5/crc32.h +441 -0
- data/ext/zlib-1.2.5/deflate.c +1834 -0
- data/ext/zlib-1.2.5/deflate.h +342 -0
- data/ext/zlib-1.2.5/example.c +565 -0
- data/ext/zlib-1.2.5/gzclose.c +25 -0
- data/ext/zlib-1.2.5/gzguts.h +132 -0
- data/ext/zlib-1.2.5/gzlib.c +537 -0
- data/ext/zlib-1.2.5/gzread.c +653 -0
- data/ext/zlib-1.2.5/gzwrite.c +531 -0
- data/ext/zlib-1.2.5/infback.c +632 -0
- data/ext/zlib-1.2.5/inffast.c +340 -0
- data/ext/zlib-1.2.5/inffast.h +11 -0
- data/ext/zlib-1.2.5/inffixed.h +94 -0
- data/ext/zlib-1.2.5/inflate.c +1480 -0
- data/ext/zlib-1.2.5/inflate.h +122 -0
- data/ext/zlib-1.2.5/inftrees.c +330 -0
- data/ext/zlib-1.2.5/inftrees.h +62 -0
- data/ext/zlib-1.2.5/minigzip.c +440 -0
- data/ext/zlib-1.2.5/trees.c +1244 -0
- data/ext/zlib-1.2.5/trees.h +128 -0
- data/ext/zlib-1.2.5/uncompr.c +59 -0
- data/ext/zlib-1.2.5/zconf.h +428 -0
- data/ext/zlib-1.2.5/zlib.h +1613 -0
- data/ext/zlib-1.2.5/zutil.c +318 -0
- data/ext/zlib-1.2.5/zutil.h +274 -0
- metadata +211 -0
|
@@ -0,0 +1,405 @@
|
|
|
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
|
+
|
|
26
|
+
#include "archive_platform.h"
|
|
27
|
+
__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_link_resolver.c 201100 2009-12-28 03:05:31Z kientzle $");
|
|
28
|
+
|
|
29
|
+
#ifdef HAVE_SYS_STAT_H
|
|
30
|
+
#include <sys/stat.h>
|
|
31
|
+
#endif
|
|
32
|
+
#ifdef HAVE_ERRNO_H
|
|
33
|
+
#include <errno.h>
|
|
34
|
+
#endif
|
|
35
|
+
#include <stdio.h>
|
|
36
|
+
#ifdef HAVE_STDLIB_H
|
|
37
|
+
#include <stdlib.h>
|
|
38
|
+
#endif
|
|
39
|
+
#ifdef HAVE_STRING_H
|
|
40
|
+
#include <string.h>
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
#include "archive.h"
|
|
44
|
+
#include "archive_entry.h"
|
|
45
|
+
|
|
46
|
+
/*
|
|
47
|
+
* This is mostly a pretty straightforward hash table implementation.
|
|
48
|
+
* The only interesting bit is the different strategies used to
|
|
49
|
+
* match up links. These strategies match those used by various
|
|
50
|
+
* archiving formats:
|
|
51
|
+
* tar - content stored with first link, remainder refer back to it.
|
|
52
|
+
* This requires us to match each subsequent link up with the
|
|
53
|
+
* first appearance.
|
|
54
|
+
* cpio - Old cpio just stored body with each link, match-ups were
|
|
55
|
+
* implicit. This is trivial.
|
|
56
|
+
* new cpio - New cpio only stores body with last link, match-ups
|
|
57
|
+
* are implicit. This is actually quite tricky; see the notes
|
|
58
|
+
* below.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/* Users pass us a format code, we translate that into a strategy here. */
|
|
62
|
+
#define ARCHIVE_ENTRY_LINKIFY_LIKE_TAR 0
|
|
63
|
+
#define ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE 1
|
|
64
|
+
#define ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO 2
|
|
65
|
+
#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 3
|
|
66
|
+
|
|
67
|
+
/* Initial size of link cache. */
|
|
68
|
+
#define links_cache_initial_size 1024
|
|
69
|
+
|
|
70
|
+
struct links_entry {
|
|
71
|
+
struct links_entry *next;
|
|
72
|
+
struct links_entry *previous;
|
|
73
|
+
int links; /* # links not yet seen */
|
|
74
|
+
int hash;
|
|
75
|
+
struct archive_entry *canonical;
|
|
76
|
+
struct archive_entry *entry;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
struct archive_entry_linkresolver {
|
|
80
|
+
struct links_entry **buckets;
|
|
81
|
+
struct links_entry *spare;
|
|
82
|
+
unsigned long number_entries;
|
|
83
|
+
size_t number_buckets;
|
|
84
|
+
int strategy;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
static struct links_entry *find_entry(struct archive_entry_linkresolver *,
|
|
88
|
+
struct archive_entry *);
|
|
89
|
+
static void grow_hash(struct archive_entry_linkresolver *);
|
|
90
|
+
static struct links_entry *insert_entry(struct archive_entry_linkresolver *,
|
|
91
|
+
struct archive_entry *);
|
|
92
|
+
static struct links_entry *next_entry(struct archive_entry_linkresolver *);
|
|
93
|
+
|
|
94
|
+
struct archive_entry_linkresolver *
|
|
95
|
+
archive_entry_linkresolver_new(void)
|
|
96
|
+
{
|
|
97
|
+
struct archive_entry_linkresolver *res;
|
|
98
|
+
size_t i;
|
|
99
|
+
|
|
100
|
+
res = malloc(sizeof(struct archive_entry_linkresolver));
|
|
101
|
+
if (res == NULL)
|
|
102
|
+
return (NULL);
|
|
103
|
+
memset(res, 0, sizeof(struct archive_entry_linkresolver));
|
|
104
|
+
res->number_buckets = links_cache_initial_size;
|
|
105
|
+
res->buckets = malloc(res->number_buckets *
|
|
106
|
+
sizeof(res->buckets[0]));
|
|
107
|
+
if (res->buckets == NULL) {
|
|
108
|
+
free(res);
|
|
109
|
+
return (NULL);
|
|
110
|
+
}
|
|
111
|
+
for (i = 0; i < res->number_buckets; i++)
|
|
112
|
+
res->buckets[i] = NULL;
|
|
113
|
+
return (res);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
void
|
|
117
|
+
archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
|
|
118
|
+
int fmt)
|
|
119
|
+
{
|
|
120
|
+
int fmtbase = fmt & ARCHIVE_FORMAT_BASE_MASK;
|
|
121
|
+
|
|
122
|
+
switch (fmtbase) {
|
|
123
|
+
case ARCHIVE_FORMAT_CPIO:
|
|
124
|
+
switch (fmt) {
|
|
125
|
+
case ARCHIVE_FORMAT_CPIO_SVR4_NOCRC:
|
|
126
|
+
case ARCHIVE_FORMAT_CPIO_SVR4_CRC:
|
|
127
|
+
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO;
|
|
128
|
+
break;
|
|
129
|
+
default:
|
|
130
|
+
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
case ARCHIVE_FORMAT_MTREE:
|
|
135
|
+
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE;
|
|
136
|
+
break;
|
|
137
|
+
case ARCHIVE_FORMAT_TAR:
|
|
138
|
+
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
|
|
139
|
+
break;
|
|
140
|
+
default:
|
|
141
|
+
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
void
|
|
147
|
+
archive_entry_linkresolver_free(struct archive_entry_linkresolver *res)
|
|
148
|
+
{
|
|
149
|
+
struct links_entry *le;
|
|
150
|
+
|
|
151
|
+
if (res == NULL)
|
|
152
|
+
return;
|
|
153
|
+
|
|
154
|
+
if (res->buckets != NULL) {
|
|
155
|
+
while ((le = next_entry(res)) != NULL)
|
|
156
|
+
archive_entry_free(le->entry);
|
|
157
|
+
free(res->buckets);
|
|
158
|
+
res->buckets = NULL;
|
|
159
|
+
}
|
|
160
|
+
free(res);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void
|
|
164
|
+
archive_entry_linkify(struct archive_entry_linkresolver *res,
|
|
165
|
+
struct archive_entry **e, struct archive_entry **f)
|
|
166
|
+
{
|
|
167
|
+
struct links_entry *le;
|
|
168
|
+
struct archive_entry *t;
|
|
169
|
+
|
|
170
|
+
*f = NULL; /* Default: Don't return a second entry. */
|
|
171
|
+
|
|
172
|
+
if (*e == NULL) {
|
|
173
|
+
le = next_entry(res);
|
|
174
|
+
if (le != NULL) {
|
|
175
|
+
*e = le->entry;
|
|
176
|
+
le->entry = NULL;
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* If it has only one link, then we're done. */
|
|
182
|
+
if (archive_entry_nlink(*e) == 1)
|
|
183
|
+
return;
|
|
184
|
+
/* Directories, devices never have hardlinks. */
|
|
185
|
+
if (archive_entry_filetype(*e) == AE_IFDIR
|
|
186
|
+
|| archive_entry_filetype(*e) == AE_IFBLK
|
|
187
|
+
|| archive_entry_filetype(*e) == AE_IFCHR)
|
|
188
|
+
return;
|
|
189
|
+
|
|
190
|
+
switch (res->strategy) {
|
|
191
|
+
case ARCHIVE_ENTRY_LINKIFY_LIKE_TAR:
|
|
192
|
+
le = find_entry(res, *e);
|
|
193
|
+
if (le != NULL) {
|
|
194
|
+
archive_entry_unset_size(*e);
|
|
195
|
+
archive_entry_copy_hardlink(*e,
|
|
196
|
+
archive_entry_pathname(le->canonical));
|
|
197
|
+
} else
|
|
198
|
+
insert_entry(res, *e);
|
|
199
|
+
return;
|
|
200
|
+
case ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE:
|
|
201
|
+
le = find_entry(res, *e);
|
|
202
|
+
if (le != NULL) {
|
|
203
|
+
archive_entry_copy_hardlink(*e,
|
|
204
|
+
archive_entry_pathname(le->canonical));
|
|
205
|
+
} else
|
|
206
|
+
insert_entry(res, *e);
|
|
207
|
+
return;
|
|
208
|
+
case ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO:
|
|
209
|
+
/* This one is trivial. */
|
|
210
|
+
return;
|
|
211
|
+
case ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO:
|
|
212
|
+
le = find_entry(res, *e);
|
|
213
|
+
if (le != NULL) {
|
|
214
|
+
/*
|
|
215
|
+
* Put the new entry in le, return the
|
|
216
|
+
* old entry from le.
|
|
217
|
+
*/
|
|
218
|
+
t = *e;
|
|
219
|
+
*e = le->entry;
|
|
220
|
+
le->entry = t;
|
|
221
|
+
/* Make the old entry into a hardlink. */
|
|
222
|
+
archive_entry_unset_size(*e);
|
|
223
|
+
archive_entry_copy_hardlink(*e,
|
|
224
|
+
archive_entry_pathname(le->canonical));
|
|
225
|
+
/* If we ran out of links, return the
|
|
226
|
+
* final entry as well. */
|
|
227
|
+
if (le->links == 0) {
|
|
228
|
+
*f = le->entry;
|
|
229
|
+
le->entry = NULL;
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
/*
|
|
233
|
+
* If we haven't seen it, tuck it away
|
|
234
|
+
* for future use.
|
|
235
|
+
*/
|
|
236
|
+
le = insert_entry(res, *e);
|
|
237
|
+
le->entry = *e;
|
|
238
|
+
*e = NULL;
|
|
239
|
+
}
|
|
240
|
+
return;
|
|
241
|
+
default:
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static struct links_entry *
|
|
248
|
+
find_entry(struct archive_entry_linkresolver *res,
|
|
249
|
+
struct archive_entry *entry)
|
|
250
|
+
{
|
|
251
|
+
struct links_entry *le;
|
|
252
|
+
int hash, bucket;
|
|
253
|
+
dev_t dev;
|
|
254
|
+
int64_t ino;
|
|
255
|
+
|
|
256
|
+
/* Free a held entry. */
|
|
257
|
+
if (res->spare != NULL) {
|
|
258
|
+
archive_entry_free(res->spare->canonical);
|
|
259
|
+
archive_entry_free(res->spare->entry);
|
|
260
|
+
free(res->spare);
|
|
261
|
+
res->spare = NULL;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* If the links cache overflowed and got flushed, don't bother. */
|
|
265
|
+
if (res->buckets == NULL)
|
|
266
|
+
return (NULL);
|
|
267
|
+
|
|
268
|
+
dev = archive_entry_dev(entry);
|
|
269
|
+
ino = archive_entry_ino64(entry);
|
|
270
|
+
hash = (int)(dev ^ ino);
|
|
271
|
+
|
|
272
|
+
/* Try to locate this entry in the links cache. */
|
|
273
|
+
bucket = hash % res->number_buckets;
|
|
274
|
+
for (le = res->buckets[bucket]; le != NULL; le = le->next) {
|
|
275
|
+
if (le->hash == hash
|
|
276
|
+
&& dev == archive_entry_dev(le->canonical)
|
|
277
|
+
&& ino == archive_entry_ino64(le->canonical)) {
|
|
278
|
+
/*
|
|
279
|
+
* Decrement link count each time and release
|
|
280
|
+
* the entry if it hits zero. This saves
|
|
281
|
+
* memory and is necessary for detecting
|
|
282
|
+
* missed links.
|
|
283
|
+
*/
|
|
284
|
+
--le->links;
|
|
285
|
+
if (le->links > 0)
|
|
286
|
+
return (le);
|
|
287
|
+
/* Remove it from this hash bucket. */
|
|
288
|
+
if (le->previous != NULL)
|
|
289
|
+
le->previous->next = le->next;
|
|
290
|
+
if (le->next != NULL)
|
|
291
|
+
le->next->previous = le->previous;
|
|
292
|
+
if (res->buckets[bucket] == le)
|
|
293
|
+
res->buckets[bucket] = le->next;
|
|
294
|
+
res->number_entries--;
|
|
295
|
+
/* Defer freeing this entry. */
|
|
296
|
+
res->spare = le;
|
|
297
|
+
return (le);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return (NULL);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
static struct links_entry *
|
|
304
|
+
next_entry(struct archive_entry_linkresolver *res)
|
|
305
|
+
{
|
|
306
|
+
struct links_entry *le;
|
|
307
|
+
size_t bucket;
|
|
308
|
+
|
|
309
|
+
/* Free a held entry. */
|
|
310
|
+
if (res->spare != NULL) {
|
|
311
|
+
archive_entry_free(res->spare->canonical);
|
|
312
|
+
free(res->spare);
|
|
313
|
+
res->spare = NULL;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* If the links cache overflowed and got flushed, don't bother. */
|
|
317
|
+
if (res->buckets == NULL)
|
|
318
|
+
return (NULL);
|
|
319
|
+
|
|
320
|
+
/* Look for next non-empty bucket in the links cache. */
|
|
321
|
+
for (bucket = 0; bucket < res->number_buckets; bucket++) {
|
|
322
|
+
le = res->buckets[bucket];
|
|
323
|
+
if (le != NULL) {
|
|
324
|
+
/* Remove it from this hash bucket. */
|
|
325
|
+
if (le->next != NULL)
|
|
326
|
+
le->next->previous = le->previous;
|
|
327
|
+
res->buckets[bucket] = le->next;
|
|
328
|
+
res->number_entries--;
|
|
329
|
+
/* Defer freeing this entry. */
|
|
330
|
+
res->spare = le;
|
|
331
|
+
return (le);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return (NULL);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
static struct links_entry *
|
|
338
|
+
insert_entry(struct archive_entry_linkresolver *res,
|
|
339
|
+
struct archive_entry *entry)
|
|
340
|
+
{
|
|
341
|
+
struct links_entry *le;
|
|
342
|
+
int hash, bucket;
|
|
343
|
+
|
|
344
|
+
/* Add this entry to the links cache. */
|
|
345
|
+
le = malloc(sizeof(struct links_entry));
|
|
346
|
+
if (le == NULL)
|
|
347
|
+
return (NULL);
|
|
348
|
+
memset(le, 0, sizeof(*le));
|
|
349
|
+
le->canonical = archive_entry_clone(entry);
|
|
350
|
+
|
|
351
|
+
/* If the links cache is getting too full, enlarge the hash table. */
|
|
352
|
+
if (res->number_entries > res->number_buckets * 2)
|
|
353
|
+
grow_hash(res);
|
|
354
|
+
|
|
355
|
+
hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry);
|
|
356
|
+
bucket = hash % res->number_buckets;
|
|
357
|
+
|
|
358
|
+
/* If we could allocate the entry, record it. */
|
|
359
|
+
if (res->buckets[bucket] != NULL)
|
|
360
|
+
res->buckets[bucket]->previous = le;
|
|
361
|
+
res->number_entries++;
|
|
362
|
+
le->next = res->buckets[bucket];
|
|
363
|
+
le->previous = NULL;
|
|
364
|
+
res->buckets[bucket] = le;
|
|
365
|
+
le->hash = hash;
|
|
366
|
+
le->links = archive_entry_nlink(entry) - 1;
|
|
367
|
+
return (le);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
static void
|
|
371
|
+
grow_hash(struct archive_entry_linkresolver *res)
|
|
372
|
+
{
|
|
373
|
+
struct links_entry *le, **new_buckets;
|
|
374
|
+
size_t new_size;
|
|
375
|
+
size_t i, bucket;
|
|
376
|
+
|
|
377
|
+
/* Try to enlarge the bucket list. */
|
|
378
|
+
new_size = res->number_buckets * 2;
|
|
379
|
+
new_buckets = malloc(new_size * sizeof(struct links_entry *));
|
|
380
|
+
|
|
381
|
+
if (new_buckets != NULL) {
|
|
382
|
+
memset(new_buckets, 0,
|
|
383
|
+
new_size * sizeof(struct links_entry *));
|
|
384
|
+
for (i = 0; i < res->number_buckets; i++) {
|
|
385
|
+
while (res->buckets[i] != NULL) {
|
|
386
|
+
/* Remove entry from old bucket. */
|
|
387
|
+
le = res->buckets[i];
|
|
388
|
+
res->buckets[i] = le->next;
|
|
389
|
+
|
|
390
|
+
/* Add entry to new bucket. */
|
|
391
|
+
bucket = le->hash % new_size;
|
|
392
|
+
|
|
393
|
+
if (new_buckets[bucket] != NULL)
|
|
394
|
+
new_buckets[bucket]->previous =
|
|
395
|
+
le;
|
|
396
|
+
le->next = new_buckets[bucket];
|
|
397
|
+
le->previous = NULL;
|
|
398
|
+
new_buckets[bucket] = le;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
free(res->buckets);
|
|
402
|
+
res->buckets = new_buckets;
|
|
403
|
+
res->number_buckets = new_size;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
* $FreeBSD: head/lib/libarchive/archive_entry_private.h 201096 2009-12-28 02:41:27Z kientzle $
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
#ifndef __LIBARCHIVE_BUILD
|
|
29
|
+
#error This header is only to be used internally to libarchive.
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
|
|
33
|
+
#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
|
|
34
|
+
|
|
35
|
+
#include "archive_string.h"
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* Handle wide character (i.e., Unicode) and non-wide character
|
|
39
|
+
* strings transparently.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
struct aes {
|
|
43
|
+
struct archive_string aes_mbs;
|
|
44
|
+
struct archive_string aes_utf8;
|
|
45
|
+
const wchar_t *aes_wcs;
|
|
46
|
+
/* Bitmap of which of the above are valid. Because we're lazy
|
|
47
|
+
* about malloc-ing and reusing the underlying storage, we
|
|
48
|
+
* can't rely on NULL pointers to indicate whether a string
|
|
49
|
+
* has been set. */
|
|
50
|
+
int aes_set;
|
|
51
|
+
#define AES_SET_MBS 1
|
|
52
|
+
#define AES_SET_UTF8 2
|
|
53
|
+
#define AES_SET_WCS 4
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
struct ae_acl {
|
|
57
|
+
struct ae_acl *next;
|
|
58
|
+
int type; /* E.g., access or default */
|
|
59
|
+
int tag; /* E.g., user/group/other/mask */
|
|
60
|
+
int permset; /* r/w/x bits */
|
|
61
|
+
int id; /* uid/gid for user/group */
|
|
62
|
+
struct aes name; /* uname/gname */
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
struct ae_xattr {
|
|
66
|
+
struct ae_xattr *next;
|
|
67
|
+
|
|
68
|
+
char *name;
|
|
69
|
+
void *value;
|
|
70
|
+
size_t size;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* Description of an archive entry.
|
|
75
|
+
*
|
|
76
|
+
* Basically, this is a "struct stat" with a few text fields added in.
|
|
77
|
+
*
|
|
78
|
+
* TODO: Add "comment", "charset", and possibly other entries
|
|
79
|
+
* that are supported by "pax interchange" format. However, GNU, ustar,
|
|
80
|
+
* cpio, and other variants don't support these features, so they're not an
|
|
81
|
+
* excruciatingly high priority right now.
|
|
82
|
+
*
|
|
83
|
+
* TODO: "pax interchange" format allows essentially arbitrary
|
|
84
|
+
* key/value attributes to be attached to any entry. Supporting
|
|
85
|
+
* such extensions may make this library useful for special
|
|
86
|
+
* applications (e.g., a package manager could attach special
|
|
87
|
+
* package-management attributes to each entry). There are tricky
|
|
88
|
+
* API issues involved, so this is not going to happen until
|
|
89
|
+
* there's a real demand for it.
|
|
90
|
+
*
|
|
91
|
+
* TODO: Design a good API for handling sparse files.
|
|
92
|
+
*/
|
|
93
|
+
struct archive_entry {
|
|
94
|
+
/*
|
|
95
|
+
* Note that ae_stat.st_mode & AE_IFMT can be 0!
|
|
96
|
+
*
|
|
97
|
+
* This occurs when the actual file type of the object is not
|
|
98
|
+
* in the archive. For example, 'tar' archives store
|
|
99
|
+
* hardlinks without marking the type of the underlying
|
|
100
|
+
* object.
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
* Read archive_entry_copy_stat.c for an explanation of why I
|
|
105
|
+
* don't just use "struct stat" instead of "struct aest" here
|
|
106
|
+
* and why I have this odd pointer to a separately-allocated
|
|
107
|
+
* struct stat.
|
|
108
|
+
*/
|
|
109
|
+
void *stat;
|
|
110
|
+
int stat_valid; /* Set to 0 whenever a field in aest changes. */
|
|
111
|
+
|
|
112
|
+
struct aest {
|
|
113
|
+
int64_t aest_atime;
|
|
114
|
+
uint32_t aest_atime_nsec;
|
|
115
|
+
int64_t aest_ctime;
|
|
116
|
+
uint32_t aest_ctime_nsec;
|
|
117
|
+
int64_t aest_mtime;
|
|
118
|
+
uint32_t aest_mtime_nsec;
|
|
119
|
+
int64_t aest_birthtime;
|
|
120
|
+
uint32_t aest_birthtime_nsec;
|
|
121
|
+
gid_t aest_gid;
|
|
122
|
+
int64_t aest_ino;
|
|
123
|
+
mode_t aest_mode;
|
|
124
|
+
uint32_t aest_nlink;
|
|
125
|
+
uint64_t aest_size;
|
|
126
|
+
uid_t aest_uid;
|
|
127
|
+
/*
|
|
128
|
+
* Because converting between device codes and
|
|
129
|
+
* major/minor values is platform-specific and
|
|
130
|
+
* inherently a bit risky, we only do that conversion
|
|
131
|
+
* lazily. That way, we will do a better job of
|
|
132
|
+
* preserving information in those cases where no
|
|
133
|
+
* conversion is actually required.
|
|
134
|
+
*/
|
|
135
|
+
int aest_dev_is_broken_down;
|
|
136
|
+
dev_t aest_dev;
|
|
137
|
+
dev_t aest_devmajor;
|
|
138
|
+
dev_t aest_devminor;
|
|
139
|
+
int aest_rdev_is_broken_down;
|
|
140
|
+
dev_t aest_rdev;
|
|
141
|
+
dev_t aest_rdevmajor;
|
|
142
|
+
dev_t aest_rdevminor;
|
|
143
|
+
} ae_stat;
|
|
144
|
+
|
|
145
|
+
int ae_set; /* bitmap of fields that are currently set */
|
|
146
|
+
#define AE_SET_HARDLINK 1
|
|
147
|
+
#define AE_SET_SYMLINK 2
|
|
148
|
+
#define AE_SET_ATIME 4
|
|
149
|
+
#define AE_SET_CTIME 8
|
|
150
|
+
#define AE_SET_MTIME 16
|
|
151
|
+
#define AE_SET_BIRTHTIME 32
|
|
152
|
+
#define AE_SET_SIZE 64
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
* Use aes here so that we get transparent mbs<->wcs conversions.
|
|
156
|
+
*/
|
|
157
|
+
struct aes ae_fflags_text; /* Text fflags per fflagstostr(3) */
|
|
158
|
+
unsigned long ae_fflags_set; /* Bitmap fflags */
|
|
159
|
+
unsigned long ae_fflags_clear;
|
|
160
|
+
struct aes ae_gname; /* Name of owning group */
|
|
161
|
+
struct aes ae_hardlink; /* Name of target for hardlink */
|
|
162
|
+
struct aes ae_pathname; /* Name of entry */
|
|
163
|
+
struct aes ae_symlink; /* symlink contents */
|
|
164
|
+
struct aes ae_uname; /* Name of owner */
|
|
165
|
+
|
|
166
|
+
/* Not used within libarchive; useful for some clients. */
|
|
167
|
+
struct aes ae_sourcepath; /* Path this entry is sourced from. */
|
|
168
|
+
|
|
169
|
+
/* ACL support. */
|
|
170
|
+
struct ae_acl *acl_head;
|
|
171
|
+
struct ae_acl *acl_p;
|
|
172
|
+
int acl_state; /* See acl_next for details. */
|
|
173
|
+
wchar_t *acl_text_w;
|
|
174
|
+
|
|
175
|
+
/* extattr support. */
|
|
176
|
+
struct ae_xattr *xattr_head;
|
|
177
|
+
struct ae_xattr *xattr_p;
|
|
178
|
+
|
|
179
|
+
/* Miscellaneous. */
|
|
180
|
+
char strmode[12];
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
|
|
26
|
+
#include "archive_platform.h"
|
|
27
|
+
__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_stat.c 201100 2009-12-28 03:05:31Z kientzle $");
|
|
28
|
+
|
|
29
|
+
#ifdef HAVE_SYS_STAT_H
|
|
30
|
+
#include <sys/stat.h>
|
|
31
|
+
#endif
|
|
32
|
+
#ifdef HAVE_STDLIB_H
|
|
33
|
+
#include <stdlib.h>
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#include "archive_entry.h"
|
|
37
|
+
#include "archive_entry_private.h"
|
|
38
|
+
|
|
39
|
+
const struct stat *
|
|
40
|
+
archive_entry_stat(struct archive_entry *entry)
|
|
41
|
+
{
|
|
42
|
+
struct stat *st;
|
|
43
|
+
if (entry->stat == NULL) {
|
|
44
|
+
entry->stat = malloc(sizeof(*st));
|
|
45
|
+
if (entry->stat == NULL)
|
|
46
|
+
return (NULL);
|
|
47
|
+
entry->stat_valid = 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/*
|
|
51
|
+
* If none of the underlying fields have been changed, we
|
|
52
|
+
* don't need to regenerate. In theory, we could use a bitmap
|
|
53
|
+
* here to flag only those items that have changed, but the
|
|
54
|
+
* extra complexity probably isn't worth it. It will be very
|
|
55
|
+
* rare for anyone to change just one field then request a new
|
|
56
|
+
* stat structure.
|
|
57
|
+
*/
|
|
58
|
+
if (entry->stat_valid)
|
|
59
|
+
return (entry->stat);
|
|
60
|
+
|
|
61
|
+
st = entry->stat;
|
|
62
|
+
/*
|
|
63
|
+
* Use the public interfaces to extract items, so that
|
|
64
|
+
* the appropriate conversions get invoked.
|
|
65
|
+
*/
|
|
66
|
+
st->st_atime = archive_entry_atime(entry);
|
|
67
|
+
#if HAVE_STRUCT_STAT_ST_BIRTHTIME
|
|
68
|
+
st->st_birthtime = archive_entry_birthtime(entry);
|
|
69
|
+
#endif
|
|
70
|
+
st->st_ctime = archive_entry_ctime(entry);
|
|
71
|
+
st->st_mtime = archive_entry_mtime(entry);
|
|
72
|
+
st->st_dev = archive_entry_dev(entry);
|
|
73
|
+
st->st_gid = archive_entry_gid(entry);
|
|
74
|
+
st->st_uid = archive_entry_uid(entry);
|
|
75
|
+
st->st_ino = archive_entry_ino64(entry);
|
|
76
|
+
st->st_nlink = archive_entry_nlink(entry);
|
|
77
|
+
st->st_rdev = archive_entry_rdev(entry);
|
|
78
|
+
st->st_size = archive_entry_size(entry);
|
|
79
|
+
st->st_mode = archive_entry_mode(entry);
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
* On systems that support high-res timestamps, copy that
|
|
83
|
+
* information into struct stat.
|
|
84
|
+
*/
|
|
85
|
+
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
|
86
|
+
st->st_atimespec.tv_nsec = archive_entry_atime_nsec(entry);
|
|
87
|
+
st->st_ctimespec.tv_nsec = archive_entry_ctime_nsec(entry);
|
|
88
|
+
st->st_mtimespec.tv_nsec = archive_entry_mtime_nsec(entry);
|
|
89
|
+
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
|
90
|
+
st->st_atim.tv_nsec = archive_entry_atime_nsec(entry);
|
|
91
|
+
st->st_ctim.tv_nsec = archive_entry_ctime_nsec(entry);
|
|
92
|
+
st->st_mtim.tv_nsec = archive_entry_mtime_nsec(entry);
|
|
93
|
+
#elif HAVE_STRUCT_STAT_ST_MTIME_N
|
|
94
|
+
st->st_atime_n = archive_entry_atime_nsec(entry);
|
|
95
|
+
st->st_ctime_n = archive_entry_ctime_nsec(entry);
|
|
96
|
+
st->st_mtime_n = archive_entry_mtime_nsec(entry);
|
|
97
|
+
#elif HAVE_STRUCT_STAT_ST_UMTIME
|
|
98
|
+
st->st_uatime = archive_entry_atime_nsec(entry) / 1000;
|
|
99
|
+
st->st_uctime = archive_entry_ctime_nsec(entry) / 1000;
|
|
100
|
+
st->st_umtime = archive_entry_mtime_nsec(entry) / 1000;
|
|
101
|
+
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
|
|
102
|
+
st->st_atime_usec = archive_entry_atime_nsec(entry) / 1000;
|
|
103
|
+
st->st_ctime_usec = archive_entry_ctime_nsec(entry) / 1000;
|
|
104
|
+
st->st_mtime_usec = archive_entry_mtime_nsec(entry) / 1000;
|
|
105
|
+
#endif
|
|
106
|
+
#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
|
|
107
|
+
st->st_birthtimespec.tv_nsec = archive_entry_birthtime_nsec(entry);
|
|
108
|
+
#endif
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* TODO: On Linux, store 32 or 64 here depending on whether
|
|
112
|
+
* the cached stat structure is a stat32 or a stat64. This
|
|
113
|
+
* will allow us to support both variants interchangably.
|
|
114
|
+
*/
|
|
115
|
+
entry->stat_valid = 1;
|
|
116
|
+
|
|
117
|
+
return (st);
|
|
118
|
+
}
|