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.
Files changed (157) hide show
  1. data/ext/Makefile +6 -0
  2. data/ext/extconf.rb +61 -0
  3. data/ext/libarchive-0.1.1/COPYING.libarchive +60 -0
  4. data/ext/libarchive-0.1.1/LICENSE.libbzip2 +42 -0
  5. data/ext/libarchive-0.1.1/README.txt +143 -0
  6. data/ext/libarchive-0.1.1/ext/Makefile.in +0 -0
  7. data/ext/libarchive-0.1.1/ext/archive_read_support_compression.c +31 -0
  8. data/ext/libarchive-0.1.1/ext/archive_read_support_compression.h +6 -0
  9. data/ext/libarchive-0.1.1/ext/archive_read_support_format.c +32 -0
  10. data/ext/libarchive-0.1.1/ext/archive_read_support_format.h +6 -0
  11. data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.c +29 -0
  12. data/ext/libarchive-0.1.1/ext/archive_write_open_rb_str.h +6 -0
  13. data/ext/libarchive-0.1.1/ext/archive_write_set_compression.c +32 -0
  14. data/ext/libarchive-0.1.1/ext/archive_write_set_compression.h +6 -0
  15. data/ext/libarchive-0.1.1/ext/config.h.in +22 -0
  16. data/ext/libarchive-0.1.1/ext/configure +3904 -0
  17. data/ext/libarchive-0.1.1/ext/configure.in +11 -0
  18. data/ext/libarchive-0.1.1/ext/depend +19 -0
  19. data/ext/libarchive-0.1.1/ext/extconf.rb +6 -0
  20. data/ext/libarchive-0.1.1/ext/install-sh +250 -0
  21. data/ext/libarchive-0.1.1/ext/libarchive.c +89 -0
  22. data/ext/libarchive-0.1.1/ext/libarchive_archive.c +84 -0
  23. data/ext/libarchive-0.1.1/ext/libarchive_entry.c +1015 -0
  24. data/ext/libarchive-0.1.1/ext/libarchive_internal.h +155 -0
  25. data/ext/libarchive-0.1.1/ext/libarchive_reader.c +328 -0
  26. data/ext/libarchive-0.1.1/ext/libarchive_win32.h +52 -0
  27. data/ext/libarchive-0.1.1/ext/libarchive_writer.c +246 -0
  28. data/ext/libarchive-0.1.1/libarchive.c +1762 -0
  29. data/ext/libarchive-2.8.4/Makefile.in +7076 -0
  30. data/ext/libarchive-2.8.4/build/autoconf/check_stdcall_func.m4 +51 -0
  31. data/ext/libarchive-2.8.4/build/autoconf/compile +143 -0
  32. data/ext/libarchive-2.8.4/build/autoconf/config.guess +1502 -0
  33. data/ext/libarchive-2.8.4/build/autoconf/config.sub +1708 -0
  34. data/ext/libarchive-2.8.4/build/autoconf/depcomp +630 -0
  35. data/ext/libarchive-2.8.4/build/autoconf/install-sh +291 -0
  36. data/ext/libarchive-2.8.4/build/autoconf/la_uid_t.m4 +20 -0
  37. data/ext/libarchive-2.8.4/build/autoconf/ltmain.sh +8406 -0
  38. data/ext/libarchive-2.8.4/build/autoconf/missing +376 -0
  39. data/ext/libarchive-2.8.4/build/pkgconfig/libarchive.pc.in +10 -0
  40. data/ext/libarchive-2.8.4/config.h.in +772 -0
  41. data/ext/libarchive-2.8.4/configure +17916 -0
  42. data/ext/libarchive-2.8.4/libarchive/archive.h +741 -0
  43. data/ext/libarchive-2.8.4/libarchive/archive_check_magic.c +134 -0
  44. data/ext/libarchive-2.8.4/libarchive/archive_crc32.h +66 -0
  45. data/ext/libarchive-2.8.4/libarchive/archive_endian.h +162 -0
  46. data/ext/libarchive-2.8.4/libarchive/archive_entry.c +2202 -0
  47. data/ext/libarchive-2.8.4/libarchive/archive_entry.h +524 -0
  48. data/ext/libarchive-2.8.4/libarchive/archive_entry_copy_bhfi.c +74 -0
  49. data/ext/libarchive-2.8.4/libarchive/archive_entry_copy_stat.c +77 -0
  50. data/ext/libarchive-2.8.4/libarchive/archive_entry_link_resolver.c +405 -0
  51. data/ext/libarchive-2.8.4/libarchive/archive_entry_private.h +184 -0
  52. data/ext/libarchive-2.8.4/libarchive/archive_entry_stat.c +118 -0
  53. data/ext/libarchive-2.8.4/libarchive/archive_entry_strmode.c +87 -0
  54. data/ext/libarchive-2.8.4/libarchive/archive_entry_xattr.c +158 -0
  55. data/ext/libarchive-2.8.4/libarchive/archive_hash.h +281 -0
  56. data/ext/libarchive-2.8.4/libarchive/archive_platform.h +165 -0
  57. data/ext/libarchive-2.8.4/libarchive/archive_private.h +124 -0
  58. data/ext/libarchive-2.8.4/libarchive/archive_read.c +1249 -0
  59. data/ext/libarchive-2.8.4/libarchive/archive_read_data_into_fd.c +93 -0
  60. data/ext/libarchive-2.8.4/libarchive/archive_read_disk.c +198 -0
  61. data/ext/libarchive-2.8.4/libarchive/archive_read_disk_entry_from_file.c +570 -0
  62. data/ext/libarchive-2.8.4/libarchive/archive_read_disk_private.h +62 -0
  63. data/ext/libarchive-2.8.4/libarchive/archive_read_disk_set_standard_lookup.c +303 -0
  64. data/ext/libarchive-2.8.4/libarchive/archive_read_extract.c +182 -0
  65. data/ext/libarchive-2.8.4/libarchive/archive_read_open_fd.c +190 -0
  66. data/ext/libarchive-2.8.4/libarchive/archive_read_open_file.c +165 -0
  67. data/ext/libarchive-2.8.4/libarchive/archive_read_open_filename.c +272 -0
  68. data/ext/libarchive-2.8.4/libarchive/archive_read_open_memory.c +156 -0
  69. data/ext/libarchive-2.8.4/libarchive/archive_read_private.h +199 -0
  70. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_all.c +60 -0
  71. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_bzip2.c +353 -0
  72. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_compress.c +444 -0
  73. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_gzip.c +465 -0
  74. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_none.c +40 -0
  75. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_program.c +459 -0
  76. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_rpm.c +287 -0
  77. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_uu.c +627 -0
  78. data/ext/libarchive-2.8.4/libarchive/archive_read_support_compression_xz.c +708 -0
  79. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_all.c +43 -0
  80. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_ar.c +584 -0
  81. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_cpio.c +777 -0
  82. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_empty.c +93 -0
  83. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_iso9660.c +2830 -0
  84. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_mtree.c +1304 -0
  85. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_raw.c +185 -0
  86. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_tar.c +2418 -0
  87. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_xar.c +3151 -0
  88. data/ext/libarchive-2.8.4/libarchive/archive_read_support_format_zip.c +903 -0
  89. data/ext/libarchive-2.8.4/libarchive/archive_string.c +453 -0
  90. data/ext/libarchive-2.8.4/libarchive/archive_string.h +148 -0
  91. data/ext/libarchive-2.8.4/libarchive/archive_string_sprintf.c +164 -0
  92. data/ext/libarchive-2.8.4/libarchive/archive_util.c +391 -0
  93. data/ext/libarchive-2.8.4/libarchive/archive_virtual.c +94 -0
  94. data/ext/libarchive-2.8.4/libarchive/archive_windows.c +1236 -0
  95. data/ext/libarchive-2.8.4/libarchive/archive_windows.h +347 -0
  96. data/ext/libarchive-2.8.4/libarchive/archive_write.c +466 -0
  97. data/ext/libarchive-2.8.4/libarchive/archive_write_disk.c +2628 -0
  98. data/ext/libarchive-2.8.4/libarchive/archive_write_disk_private.h +38 -0
  99. data/ext/libarchive-2.8.4/libarchive/archive_write_disk_set_standard_lookup.c +262 -0
  100. data/ext/libarchive-2.8.4/libarchive/archive_write_open_fd.c +141 -0
  101. data/ext/libarchive-2.8.4/libarchive/archive_write_open_file.c +105 -0
  102. data/ext/libarchive-2.8.4/libarchive/archive_write_open_filename.c +162 -0
  103. data/ext/libarchive-2.8.4/libarchive/archive_write_open_memory.c +126 -0
  104. data/ext/libarchive-2.8.4/libarchive/archive_write_private.h +122 -0
  105. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_bzip2.c +408 -0
  106. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_compress.c +492 -0
  107. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_gzip.c +477 -0
  108. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_none.c +257 -0
  109. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_program.c +347 -0
  110. data/ext/libarchive-2.8.4/libarchive/archive_write_set_compression_xz.c +438 -0
  111. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format.c +72 -0
  112. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_ar.c +550 -0
  113. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_by_name.c +76 -0
  114. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio.c +344 -0
  115. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_cpio_newc.c +295 -0
  116. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_mtree.c +1050 -0
  117. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_pax.c +1386 -0
  118. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_shar.c +626 -0
  119. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_ustar.c +587 -0
  120. data/ext/libarchive-2.8.4/libarchive/archive_write_set_format_zip.c +667 -0
  121. data/ext/libarchive-2.8.4/libarchive/config_freebsd.h +154 -0
  122. data/ext/libarchive-2.8.4/libarchive/filter_fork.c +161 -0
  123. data/ext/libarchive-2.8.4/libarchive/filter_fork.h +41 -0
  124. data/ext/libarchive-2.8.4/libarchive/filter_fork_windows.c +113 -0
  125. data/ext/libarchive-static-makefile +80 -0
  126. data/ext/libarchive-static-wrapper-makefile +22 -0
  127. data/ext/zlib-1.2.5/Makefile.in +257 -0
  128. data/ext/zlib-1.2.5/adler32.c +169 -0
  129. data/ext/zlib-1.2.5/compress.c +80 -0
  130. data/ext/zlib-1.2.5/configure +596 -0
  131. data/ext/zlib-1.2.5/crc32.c +442 -0
  132. data/ext/zlib-1.2.5/crc32.h +441 -0
  133. data/ext/zlib-1.2.5/deflate.c +1834 -0
  134. data/ext/zlib-1.2.5/deflate.h +342 -0
  135. data/ext/zlib-1.2.5/example.c +565 -0
  136. data/ext/zlib-1.2.5/gzclose.c +25 -0
  137. data/ext/zlib-1.2.5/gzguts.h +132 -0
  138. data/ext/zlib-1.2.5/gzlib.c +537 -0
  139. data/ext/zlib-1.2.5/gzread.c +653 -0
  140. data/ext/zlib-1.2.5/gzwrite.c +531 -0
  141. data/ext/zlib-1.2.5/infback.c +632 -0
  142. data/ext/zlib-1.2.5/inffast.c +340 -0
  143. data/ext/zlib-1.2.5/inffast.h +11 -0
  144. data/ext/zlib-1.2.5/inffixed.h +94 -0
  145. data/ext/zlib-1.2.5/inflate.c +1480 -0
  146. data/ext/zlib-1.2.5/inflate.h +122 -0
  147. data/ext/zlib-1.2.5/inftrees.c +330 -0
  148. data/ext/zlib-1.2.5/inftrees.h +62 -0
  149. data/ext/zlib-1.2.5/minigzip.c +440 -0
  150. data/ext/zlib-1.2.5/trees.c +1244 -0
  151. data/ext/zlib-1.2.5/trees.h +128 -0
  152. data/ext/zlib-1.2.5/uncompr.c +59 -0
  153. data/ext/zlib-1.2.5/zconf.h +428 -0
  154. data/ext/zlib-1.2.5/zlib.h +1613 -0
  155. data/ext/zlib-1.2.5/zutil.c +318 -0
  156. data/ext/zlib-1.2.5/zutil.h +274 -0
  157. metadata +211 -0
@@ -0,0 +1,2628 @@
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
+ * in this position and unchanged.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ */
26
+
27
+ #include "archive_platform.h"
28
+ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
29
+
30
+ #ifdef HAVE_SYS_TYPES_H
31
+ #include <sys/types.h>
32
+ #endif
33
+ #ifdef HAVE_SYS_ACL_H
34
+ #include <sys/acl.h>
35
+ #endif
36
+ #ifdef HAVE_SYS_EXTATTR_H
37
+ #include <sys/extattr.h>
38
+ #endif
39
+ #ifdef HAVE_SYS_XATTR_H
40
+ #include <sys/xattr.h>
41
+ #endif
42
+ #ifdef HAVE_ATTR_XATTR_H
43
+ #include <attr/xattr.h>
44
+ #endif
45
+ #ifdef HAVE_SYS_IOCTL_H
46
+ #include <sys/ioctl.h>
47
+ #endif
48
+ #ifdef HAVE_SYS_STAT_H
49
+ #include <sys/stat.h>
50
+ #endif
51
+ #ifdef HAVE_SYS_TIME_H
52
+ #include <sys/time.h>
53
+ #endif
54
+ #ifdef HAVE_SYS_UTIME_H
55
+ #include <sys/utime.h>
56
+ #endif
57
+ #ifdef HAVE_ERRNO_H
58
+ #include <errno.h>
59
+ #endif
60
+ #ifdef HAVE_FCNTL_H
61
+ #include <fcntl.h>
62
+ #endif
63
+ #ifdef HAVE_GRP_H
64
+ #include <grp.h>
65
+ #endif
66
+ #ifdef HAVE_LINUX_FS_H
67
+ #include <linux/fs.h> /* for Linux file flags */
68
+ #endif
69
+ /*
70
+ * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
71
+ * As the include guards don't agree, the order of include is important.
72
+ */
73
+ #ifdef HAVE_LINUX_EXT2_FS_H
74
+ #include <linux/ext2_fs.h> /* for Linux file flags */
75
+ #endif
76
+ #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
77
+ #include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
78
+ #endif
79
+ #ifdef HAVE_LIMITS_H
80
+ #include <limits.h>
81
+ #endif
82
+ #ifdef HAVE_PWD_H
83
+ #include <pwd.h>
84
+ #endif
85
+ #include <stdio.h>
86
+ #ifdef HAVE_STDLIB_H
87
+ #include <stdlib.h>
88
+ #endif
89
+ #ifdef HAVE_STRING_H
90
+ #include <string.h>
91
+ #endif
92
+ #ifdef HAVE_UNISTD_H
93
+ #include <unistd.h>
94
+ #endif
95
+ #ifdef HAVE_UTIME_H
96
+ #include <utime.h>
97
+ #endif
98
+
99
+ #include "archive.h"
100
+ #include "archive_string.h"
101
+ #include "archive_entry.h"
102
+ #include "archive_private.h"
103
+
104
+ #ifndef O_BINARY
105
+ #define O_BINARY 0
106
+ #endif
107
+
108
+ struct fixup_entry {
109
+ struct fixup_entry *next;
110
+ mode_t mode;
111
+ int64_t atime;
112
+ int64_t birthtime;
113
+ int64_t mtime;
114
+ unsigned long atime_nanos;
115
+ unsigned long birthtime_nanos;
116
+ unsigned long mtime_nanos;
117
+ unsigned long fflags_set;
118
+ int fixup; /* bitmask of what needs fixing */
119
+ char *name;
120
+ };
121
+
122
+ /*
123
+ * We use a bitmask to track which operations remain to be done for
124
+ * this file. In particular, this helps us avoid unnecessary
125
+ * operations when it's possible to take care of one step as a
126
+ * side-effect of another. For example, mkdir() can specify the mode
127
+ * for the newly-created object but symlink() cannot. This means we
128
+ * can skip chmod() if mkdir() succeeded, but we must explicitly
129
+ * chmod() if we're trying to create a directory that already exists
130
+ * (mkdir() failed) or if we're restoring a symlink. Similarly, we
131
+ * need to verify UID/GID before trying to restore SUID/SGID bits;
132
+ * that verification can occur explicitly through a stat() call or
133
+ * implicitly because of a successful chown() call.
134
+ */
135
+ #define TODO_MODE_FORCE 0x40000000
136
+ #define TODO_MODE_BASE 0x20000000
137
+ #define TODO_SUID 0x10000000
138
+ #define TODO_SUID_CHECK 0x08000000
139
+ #define TODO_SGID 0x04000000
140
+ #define TODO_SGID_CHECK 0x02000000
141
+ #define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID)
142
+ #define TODO_TIMES ARCHIVE_EXTRACT_TIME
143
+ #define TODO_OWNER ARCHIVE_EXTRACT_OWNER
144
+ #define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS
145
+ #define TODO_ACLS ARCHIVE_EXTRACT_ACL
146
+ #define TODO_XATTR ARCHIVE_EXTRACT_XATTR
147
+
148
+ struct archive_write_disk {
149
+ struct archive archive;
150
+
151
+ mode_t user_umask;
152
+ struct fixup_entry *fixup_list;
153
+ struct fixup_entry *current_fixup;
154
+ uid_t user_uid;
155
+ dev_t skip_file_dev;
156
+ ino_t skip_file_ino;
157
+ time_t start_time;
158
+
159
+ gid_t (*lookup_gid)(void *private, const char *gname, gid_t gid);
160
+ void (*cleanup_gid)(void *private);
161
+ void *lookup_gid_data;
162
+ uid_t (*lookup_uid)(void *private, const char *gname, gid_t gid);
163
+ void (*cleanup_uid)(void *private);
164
+ void *lookup_uid_data;
165
+
166
+ /*
167
+ * Full path of last file to satisfy symlink checks.
168
+ */
169
+ struct archive_string path_safe;
170
+
171
+ /*
172
+ * Cached stat data from disk for the current entry.
173
+ * If this is valid, pst points to st. Otherwise,
174
+ * pst is null.
175
+ */
176
+ struct stat st;
177
+ struct stat *pst;
178
+
179
+ /* Information about the object being restored right now. */
180
+ struct archive_entry *entry; /* Entry being extracted. */
181
+ char *name; /* Name of entry, possibly edited. */
182
+ struct archive_string _name_data; /* backing store for 'name' */
183
+ /* Tasks remaining for this object. */
184
+ int todo;
185
+ /* Tasks deferred until end-of-archive. */
186
+ int deferred;
187
+ /* Options requested by the client. */
188
+ int flags;
189
+ /* Handle for the file we're restoring. */
190
+ int fd;
191
+ /* Current offset for writing data to the file. */
192
+ off_t offset;
193
+ /* Last offset actually written to disk. */
194
+ off_t fd_offset;
195
+ /* Maximum size of file, -1 if unknown. */
196
+ off_t filesize;
197
+ /* Dir we were in before this restore; only for deep paths. */
198
+ int restore_pwd;
199
+ /* Mode we should use for this entry; affected by _PERM and umask. */
200
+ mode_t mode;
201
+ /* UID/GID to use in restoring this entry. */
202
+ uid_t uid;
203
+ gid_t gid;
204
+ };
205
+
206
+ /*
207
+ * Default mode for dirs created automatically (will be modified by umask).
208
+ * Note that POSIX specifies 0777 for implicity-created dirs, "modified
209
+ * by the process' file creation mask."
210
+ */
211
+ #define DEFAULT_DIR_MODE 0777
212
+ /*
213
+ * Dir modes are restored in two steps: During the extraction, the permissions
214
+ * in the archive are modified to match the following limits. During
215
+ * the post-extract fixup pass, the permissions from the archive are
216
+ * applied.
217
+ */
218
+ #define MINIMUM_DIR_MODE 0700
219
+ #define MAXIMUM_DIR_MODE 0775
220
+
221
+ static int check_symlinks(struct archive_write_disk *);
222
+ static int create_filesystem_object(struct archive_write_disk *);
223
+ static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
224
+ #ifdef HAVE_FCHDIR
225
+ static void edit_deep_directories(struct archive_write_disk *ad);
226
+ #endif
227
+ static int cleanup_pathname(struct archive_write_disk *);
228
+ static int create_dir(struct archive_write_disk *, char *);
229
+ static int create_parent_dir(struct archive_write_disk *, char *);
230
+ static int older(struct stat *, struct archive_entry *);
231
+ static int restore_entry(struct archive_write_disk *);
232
+ #ifdef HAVE_POSIX_ACL
233
+ static int set_acl(struct archive_write_disk *, int fd, struct archive_entry *,
234
+ acl_type_t, int archive_entry_acl_type, const char *tn);
235
+ #endif
236
+ static int set_acls(struct archive_write_disk *);
237
+ static int set_xattrs(struct archive_write_disk *);
238
+ static int set_fflags(struct archive_write_disk *);
239
+ static int set_fflags_platform(struct archive_write_disk *, int fd,
240
+ const char *name, mode_t mode,
241
+ unsigned long fflags_set, unsigned long fflags_clear);
242
+ static int set_ownership(struct archive_write_disk *);
243
+ static int set_mode(struct archive_write_disk *, int mode);
244
+ static int set_time(int, int, const char *, time_t, long, time_t, long);
245
+ static int set_times(struct archive_write_disk *);
246
+ static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
247
+ static gid_t trivial_lookup_gid(void *, const char *, gid_t);
248
+ static uid_t trivial_lookup_uid(void *, const char *, uid_t);
249
+ static ssize_t write_data_block(struct archive_write_disk *,
250
+ const char *, size_t);
251
+
252
+ static struct archive_vtable *archive_write_disk_vtable(void);
253
+
254
+ static int _archive_write_close(struct archive *);
255
+ static int _archive_write_finish(struct archive *);
256
+ static int _archive_write_header(struct archive *, struct archive_entry *);
257
+ static int _archive_write_finish_entry(struct archive *);
258
+ static ssize_t _archive_write_data(struct archive *, const void *, size_t);
259
+ static ssize_t _archive_write_data_block(struct archive *, const void *, size_t, off_t);
260
+
261
+ static int
262
+ _archive_write_disk_lazy_stat(struct archive_write_disk *a)
263
+ {
264
+ if (a->pst != NULL) {
265
+ /* Already have stat() data available. */
266
+ return (ARCHIVE_OK);
267
+ }
268
+ #ifdef HAVE_FSTAT
269
+ if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) {
270
+ a->pst = &a->st;
271
+ return (ARCHIVE_OK);
272
+ }
273
+ #endif
274
+ /*
275
+ * XXX At this point, symlinks should not be hit, otherwise
276
+ * XXX a race occured. Do we want to check explicitly for that?
277
+ */
278
+ if (lstat(a->name, &a->st) == 0) {
279
+ a->pst = &a->st;
280
+ return (ARCHIVE_OK);
281
+ }
282
+ archive_set_error(&a->archive, errno, "Couldn't stat file");
283
+ return (ARCHIVE_WARN);
284
+ }
285
+
286
+ static struct archive_vtable *
287
+ archive_write_disk_vtable(void)
288
+ {
289
+ static struct archive_vtable av;
290
+ static int inited = 0;
291
+
292
+ if (!inited) {
293
+ av.archive_close = _archive_write_close;
294
+ av.archive_finish = _archive_write_finish;
295
+ av.archive_write_header = _archive_write_header;
296
+ av.archive_write_finish_entry = _archive_write_finish_entry;
297
+ av.archive_write_data = _archive_write_data;
298
+ av.archive_write_data_block = _archive_write_data_block;
299
+ }
300
+ return (&av);
301
+ }
302
+
303
+
304
+ int
305
+ archive_write_disk_set_options(struct archive *_a, int flags)
306
+ {
307
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
308
+
309
+ a->flags = flags;
310
+ return (ARCHIVE_OK);
311
+ }
312
+
313
+
314
+ /*
315
+ * Extract this entry to disk.
316
+ *
317
+ * TODO: Validate hardlinks. According to the standards, we're
318
+ * supposed to check each extracted hardlink and squawk if it refers
319
+ * to a file that we didn't restore. I'm not entirely convinced this
320
+ * is a good idea, but more importantly: Is there any way to validate
321
+ * hardlinks without keeping a complete list of filenames from the
322
+ * entire archive?? Ugh.
323
+ *
324
+ */
325
+ static int
326
+ _archive_write_header(struct archive *_a, struct archive_entry *entry)
327
+ {
328
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
329
+ struct fixup_entry *fe;
330
+ int ret, r;
331
+
332
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
333
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
334
+ "archive_write_disk_header");
335
+ archive_clear_error(&a->archive);
336
+ if (a->archive.state & ARCHIVE_STATE_DATA) {
337
+ r = _archive_write_finish_entry(&a->archive);
338
+ if (r == ARCHIVE_FATAL)
339
+ return (r);
340
+ }
341
+
342
+ /* Set up for this particular entry. */
343
+ a->pst = NULL;
344
+ a->current_fixup = NULL;
345
+ a->deferred = 0;
346
+ if (a->entry) {
347
+ archive_entry_free(a->entry);
348
+ a->entry = NULL;
349
+ }
350
+ a->entry = archive_entry_clone(entry);
351
+ a->fd = -1;
352
+ a->fd_offset = 0;
353
+ a->offset = 0;
354
+ a->uid = a->user_uid;
355
+ a->mode = archive_entry_mode(a->entry);
356
+ if (archive_entry_size_is_set(a->entry))
357
+ a->filesize = archive_entry_size(a->entry);
358
+ else
359
+ a->filesize = -1;
360
+ archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry));
361
+ a->name = a->_name_data.s;
362
+ archive_clear_error(&a->archive);
363
+
364
+ /*
365
+ * Clean up the requested path. This is necessary for correct
366
+ * dir restores; the dir restore logic otherwise gets messed
367
+ * up by nonsense like "dir/.".
368
+ */
369
+ ret = cleanup_pathname(a);
370
+ if (ret != ARCHIVE_OK)
371
+ return (ret);
372
+
373
+ /*
374
+ * Set the umask to zero so we get predictable mode settings.
375
+ * This gets done on every call to _write_header in case the
376
+ * user edits their umask during the extraction for some
377
+ * reason. This will be reset before we return. Note that we
378
+ * don't need to do this in _finish_entry, as the chmod(), etc,
379
+ * system calls don't obey umask.
380
+ */
381
+ a->user_umask = umask(0);
382
+ /* From here on, early exit requires "goto done" to clean up. */
383
+
384
+ /* Figure out what we need to do for this entry. */
385
+ a->todo = TODO_MODE_BASE;
386
+ if (a->flags & ARCHIVE_EXTRACT_PERM) {
387
+ a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
388
+ /*
389
+ * SGID requires an extra "check" step because we
390
+ * cannot easily predict the GID that the system will
391
+ * assign. (Different systems assign GIDs to files
392
+ * based on a variety of criteria, including process
393
+ * credentials and the gid of the enclosing
394
+ * directory.) We can only restore the SGID bit if
395
+ * the file has the right GID, and we only know the
396
+ * GID if we either set it (see set_ownership) or if
397
+ * we've actually called stat() on the file after it
398
+ * was restored. Since there are several places at
399
+ * which we might verify the GID, we need a TODO bit
400
+ * to keep track.
401
+ */
402
+ if (a->mode & S_ISGID)
403
+ a->todo |= TODO_SGID | TODO_SGID_CHECK;
404
+ /*
405
+ * Verifying the SUID is simpler, but can still be
406
+ * done in multiple ways, hence the separate "check" bit.
407
+ */
408
+ if (a->mode & S_ISUID)
409
+ a->todo |= TODO_SUID | TODO_SUID_CHECK;
410
+ } else {
411
+ /*
412
+ * User didn't request full permissions, so don't
413
+ * restore SUID, SGID bits and obey umask.
414
+ */
415
+ a->mode &= ~S_ISUID;
416
+ a->mode &= ~S_ISGID;
417
+ a->mode &= ~S_ISVTX;
418
+ a->mode &= ~a->user_umask;
419
+ }
420
+ #if !defined(_WIN32) || defined(__CYGWIN__)
421
+ if (a->flags & ARCHIVE_EXTRACT_OWNER)
422
+ a->todo |= TODO_OWNER;
423
+ #endif
424
+ if (a->flags & ARCHIVE_EXTRACT_TIME)
425
+ a->todo |= TODO_TIMES;
426
+ if (a->flags & ARCHIVE_EXTRACT_ACL)
427
+ a->todo |= TODO_ACLS;
428
+ if (a->flags & ARCHIVE_EXTRACT_XATTR)
429
+ a->todo |= TODO_XATTR;
430
+ if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
431
+ a->todo |= TODO_FFLAGS;
432
+ if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
433
+ ret = check_symlinks(a);
434
+ if (ret != ARCHIVE_OK)
435
+ goto done;
436
+ }
437
+ #ifdef HAVE_FCHDIR
438
+ /* If path exceeds PATH_MAX, shorten the path. */
439
+ edit_deep_directories(a);
440
+ #endif
441
+
442
+ ret = restore_entry(a);
443
+
444
+ /*
445
+ * TODO: There are rumours that some extended attributes must
446
+ * be restored before file data is written. If this is true,
447
+ * then we either need to write all extended attributes both
448
+ * before and after restoring the data, or find some rule for
449
+ * determining which must go first and which last. Due to the
450
+ * many ways people are using xattrs, this may prove to be an
451
+ * intractable problem.
452
+ */
453
+
454
+ #ifdef HAVE_FCHDIR
455
+ /* If we changed directory above, restore it here. */
456
+ if (a->restore_pwd >= 0) {
457
+ r = fchdir(a->restore_pwd);
458
+ if (r != 0) {
459
+ archive_set_error(&a->archive, errno, "chdir() failure");
460
+ ret = ARCHIVE_FATAL;
461
+ }
462
+ close(a->restore_pwd);
463
+ a->restore_pwd = -1;
464
+ }
465
+ #endif
466
+
467
+ /*
468
+ * Fixup uses the unedited pathname from archive_entry_pathname(),
469
+ * because it is relative to the base dir and the edited path
470
+ * might be relative to some intermediate dir as a result of the
471
+ * deep restore logic.
472
+ */
473
+ if (a->deferred & TODO_MODE) {
474
+ fe = current_fixup(a, archive_entry_pathname(entry));
475
+ fe->fixup |= TODO_MODE_BASE;
476
+ fe->mode = a->mode;
477
+ }
478
+
479
+ if ((a->deferred & TODO_TIMES)
480
+ && (archive_entry_mtime_is_set(entry)
481
+ || archive_entry_atime_is_set(entry))) {
482
+ fe = current_fixup(a, archive_entry_pathname(entry));
483
+ fe->fixup |= TODO_TIMES;
484
+ if (archive_entry_atime_is_set(entry)) {
485
+ fe->atime = archive_entry_atime(entry);
486
+ fe->atime_nanos = archive_entry_atime_nsec(entry);
487
+ } else {
488
+ /* If atime is unset, use start time. */
489
+ fe->atime = a->start_time;
490
+ fe->atime_nanos = 0;
491
+ }
492
+ if (archive_entry_mtime_is_set(entry)) {
493
+ fe->mtime = archive_entry_mtime(entry);
494
+ fe->mtime_nanos = archive_entry_mtime_nsec(entry);
495
+ } else {
496
+ /* If mtime is unset, use start time. */
497
+ fe->mtime = a->start_time;
498
+ fe->mtime_nanos = 0;
499
+ }
500
+ if (archive_entry_birthtime_is_set(entry)) {
501
+ fe->birthtime = archive_entry_birthtime(entry);
502
+ fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
503
+ } else {
504
+ /* If birthtime is unset, use mtime. */
505
+ fe->birthtime = fe->mtime;
506
+ fe->birthtime_nanos = fe->mtime_nanos;
507
+ }
508
+ }
509
+
510
+ if (a->deferred & TODO_FFLAGS) {
511
+ fe = current_fixup(a, archive_entry_pathname(entry));
512
+ fe->fixup |= TODO_FFLAGS;
513
+ /* TODO: Complete this.. defer fflags from below. */
514
+ }
515
+
516
+ /* We've created the object and are ready to pour data into it. */
517
+ if (ret >= ARCHIVE_WARN)
518
+ a->archive.state = ARCHIVE_STATE_DATA;
519
+ /*
520
+ * If it's not open, tell our client not to try writing.
521
+ * In particular, dirs, links, etc, don't get written to.
522
+ */
523
+ if (a->fd < 0) {
524
+ archive_entry_set_size(entry, 0);
525
+ a->filesize = 0;
526
+ }
527
+ done:
528
+ /* Restore the user's umask before returning. */
529
+ umask(a->user_umask);
530
+
531
+ return (ret);
532
+ }
533
+
534
+ int
535
+ archive_write_disk_set_skip_file(struct archive *_a, dev_t d, ino_t i)
536
+ {
537
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
538
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
539
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
540
+ a->skip_file_dev = d;
541
+ a->skip_file_ino = i;
542
+ return (ARCHIVE_OK);
543
+ }
544
+
545
+ static ssize_t
546
+ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
547
+ {
548
+ uint64_t start_size = size;
549
+ ssize_t bytes_written = 0;
550
+ ssize_t block_size = 0, bytes_to_write;
551
+
552
+ if (size == 0)
553
+ return (ARCHIVE_OK);
554
+
555
+ if (a->filesize == 0 || a->fd < 0) {
556
+ archive_set_error(&a->archive, 0,
557
+ "Attempt to write to an empty file");
558
+ return (ARCHIVE_WARN);
559
+ }
560
+
561
+ if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
562
+ #if HAVE_STRUCT_STAT_ST_BLKSIZE
563
+ int r;
564
+ if ((r = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
565
+ return (r);
566
+ block_size = a->pst->st_blksize;
567
+ #else
568
+ /* XXX TODO XXX Is there a more appropriate choice here ? */
569
+ /* This needn't match the filesystem allocation size. */
570
+ block_size = 16*1024;
571
+ #endif
572
+ }
573
+
574
+ /* If this write would run beyond the file size, truncate it. */
575
+ if (a->filesize >= 0 && (off_t)(a->offset + size) > a->filesize)
576
+ start_size = size = (size_t)(a->filesize - a->offset);
577
+
578
+ /* Write the data. */
579
+ while (size > 0) {
580
+ if (block_size == 0) {
581
+ bytes_to_write = size;
582
+ } else {
583
+ /* We're sparsifying the file. */
584
+ const char *p, *end;
585
+ off_t block_end;
586
+
587
+ /* Skip leading zero bytes. */
588
+ for (p = buff, end = buff + size; p < end; ++p) {
589
+ if (*p != '\0')
590
+ break;
591
+ }
592
+ a->offset += p - buff;
593
+ size -= p - buff;
594
+ buff = p;
595
+ if (size == 0)
596
+ break;
597
+
598
+ /* Calculate next block boundary after offset. */
599
+ block_end
600
+ = (a->offset / block_size + 1) * block_size;
601
+
602
+ /* If the adjusted write would cross block boundary,
603
+ * truncate it to the block boundary. */
604
+ bytes_to_write = size;
605
+ if (a->offset + bytes_to_write > block_end)
606
+ bytes_to_write = block_end - a->offset;
607
+ }
608
+ /* Seek if necessary to the specified offset. */
609
+ if (a->offset != a->fd_offset) {
610
+ if (lseek(a->fd, a->offset, SEEK_SET) < 0) {
611
+ archive_set_error(&a->archive, errno,
612
+ "Seek failed");
613
+ return (ARCHIVE_FATAL);
614
+ }
615
+ a->fd_offset = a->offset;
616
+ a->archive.file_position = a->offset;
617
+ a->archive.raw_position = a->offset;
618
+ }
619
+ bytes_written = write(a->fd, buff, bytes_to_write);
620
+ if (bytes_written < 0) {
621
+ archive_set_error(&a->archive, errno, "Write failed");
622
+ return (ARCHIVE_WARN);
623
+ }
624
+ buff += bytes_written;
625
+ size -= bytes_written;
626
+ a->offset += bytes_written;
627
+ a->archive.file_position += bytes_written;
628
+ a->archive.raw_position += bytes_written;
629
+ a->fd_offset = a->offset;
630
+ }
631
+ return (start_size - size);
632
+ }
633
+
634
+ static ssize_t
635
+ _archive_write_data_block(struct archive *_a,
636
+ const void *buff, size_t size, off_t offset)
637
+ {
638
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
639
+ ssize_t r;
640
+
641
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
642
+ ARCHIVE_STATE_DATA, "archive_write_disk_block");
643
+
644
+ a->offset = offset;
645
+ r = write_data_block(a, buff, size);
646
+ if (r < ARCHIVE_OK)
647
+ return (r);
648
+ if ((size_t)r < size) {
649
+ archive_set_error(&a->archive, 0,
650
+ "Write request too large");
651
+ return (ARCHIVE_WARN);
652
+ }
653
+ return (ARCHIVE_OK);
654
+ }
655
+
656
+ static ssize_t
657
+ _archive_write_data(struct archive *_a, const void *buff, size_t size)
658
+ {
659
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
660
+
661
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
662
+ ARCHIVE_STATE_DATA, "archive_write_data");
663
+
664
+ return (write_data_block(a, buff, size));
665
+ }
666
+
667
+ static int
668
+ _archive_write_finish_entry(struct archive *_a)
669
+ {
670
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
671
+ int ret = ARCHIVE_OK;
672
+
673
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
674
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
675
+ "archive_write_finish_entry");
676
+ if (a->archive.state & ARCHIVE_STATE_HEADER)
677
+ return (ARCHIVE_OK);
678
+ archive_clear_error(&a->archive);
679
+
680
+ /* Pad or truncate file to the right size. */
681
+ if (a->fd < 0) {
682
+ /* There's no file. */
683
+ } else if (a->filesize < 0) {
684
+ /* File size is unknown, so we can't set the size. */
685
+ } else if (a->fd_offset == a->filesize) {
686
+ /* Last write ended at exactly the filesize; we're done. */
687
+ /* Hopefully, this is the common case. */
688
+ } else {
689
+ #if HAVE_FTRUNCATE
690
+ if (ftruncate(a->fd, a->filesize) == -1 &&
691
+ a->filesize == 0) {
692
+ archive_set_error(&a->archive, errno,
693
+ "File size could not be restored");
694
+ return (ARCHIVE_FAILED);
695
+ }
696
+ #endif
697
+ /*
698
+ * Not all platforms implement the XSI option to
699
+ * extend files via ftruncate. Stat() the file again
700
+ * to see what happened.
701
+ */
702
+ a->pst = NULL;
703
+ if ((ret = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
704
+ return (ret);
705
+ /* We can use lseek()/write() to extend the file if
706
+ * ftruncate didn't work or isn't available. */
707
+ if (a->st.st_size < a->filesize) {
708
+ const char nul = '\0';
709
+ if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
710
+ archive_set_error(&a->archive, errno,
711
+ "Seek failed");
712
+ return (ARCHIVE_FATAL);
713
+ }
714
+ if (write(a->fd, &nul, 1) < 0) {
715
+ archive_set_error(&a->archive, errno,
716
+ "Write to restore size failed");
717
+ return (ARCHIVE_FATAL);
718
+ }
719
+ a->pst = NULL;
720
+ }
721
+ }
722
+
723
+ /* Restore metadata. */
724
+
725
+ /*
726
+ * Look up the "real" UID only if we're going to need it.
727
+ * TODO: the TODO_SGID condition can be dropped here, can't it?
728
+ */
729
+ if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
730
+ a->uid = a->lookup_uid(a->lookup_uid_data,
731
+ archive_entry_uname(a->entry),
732
+ archive_entry_uid(a->entry));
733
+ }
734
+ /* Look up the "real" GID only if we're going to need it. */
735
+ /* TODO: the TODO_SUID condition can be dropped here, can't it? */
736
+ if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
737
+ a->gid = a->lookup_gid(a->lookup_gid_data,
738
+ archive_entry_gname(a->entry),
739
+ archive_entry_gid(a->entry));
740
+ }
741
+ /*
742
+ * If restoring ownership, do it before trying to restore suid/sgid
743
+ * bits. If we set the owner, we know what it is and can skip
744
+ * a stat() call to examine the ownership of the file on disk.
745
+ */
746
+ if (a->todo & TODO_OWNER)
747
+ ret = set_ownership(a);
748
+ if (a->todo & TODO_MODE) {
749
+ int r2 = set_mode(a, a->mode);
750
+ if (r2 < ret) ret = r2;
751
+ }
752
+ if (a->todo & TODO_ACLS) {
753
+ int r2 = set_acls(a);
754
+ if (r2 < ret) ret = r2;
755
+ }
756
+
757
+ /*
758
+ * Security-related extended attributes (such as
759
+ * security.capability on Linux) have to be restored last,
760
+ * since they're implicitly removed by other file changes.
761
+ */
762
+ if (a->todo & TODO_XATTR) {
763
+ int r2 = set_xattrs(a);
764
+ if (r2 < ret) ret = r2;
765
+ }
766
+
767
+ /*
768
+ * Some flags prevent file modification; they must be restored after
769
+ * file contents are written.
770
+ */
771
+ if (a->todo & TODO_FFLAGS) {
772
+ int r2 = set_fflags(a);
773
+ if (r2 < ret) ret = r2;
774
+ }
775
+ /*
776
+ * Time has to be restored after all other metadata;
777
+ * otherwise atime will get changed.
778
+ */
779
+ if (a->todo & TODO_TIMES) {
780
+ int r2 = set_times(a);
781
+ if (r2 < ret) ret = r2;
782
+ }
783
+
784
+ /* If there's an fd, we can close it now. */
785
+ if (a->fd >= 0) {
786
+ close(a->fd);
787
+ a->fd = -1;
788
+ }
789
+ /* If there's an entry, we can release it now. */
790
+ if (a->entry) {
791
+ archive_entry_free(a->entry);
792
+ a->entry = NULL;
793
+ }
794
+ a->archive.state = ARCHIVE_STATE_HEADER;
795
+ return (ret);
796
+ }
797
+
798
+ int
799
+ archive_write_disk_set_group_lookup(struct archive *_a,
800
+ void *private_data,
801
+ gid_t (*lookup_gid)(void *private, const char *gname, gid_t gid),
802
+ void (*cleanup_gid)(void *private))
803
+ {
804
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
805
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
806
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
807
+
808
+ a->lookup_gid = lookup_gid;
809
+ a->cleanup_gid = cleanup_gid;
810
+ a->lookup_gid_data = private_data;
811
+ return (ARCHIVE_OK);
812
+ }
813
+
814
+ int
815
+ archive_write_disk_set_user_lookup(struct archive *_a,
816
+ void *private_data,
817
+ uid_t (*lookup_uid)(void *private, const char *uname, uid_t uid),
818
+ void (*cleanup_uid)(void *private))
819
+ {
820
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
821
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
822
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
823
+
824
+ a->lookup_uid = lookup_uid;
825
+ a->cleanup_uid = cleanup_uid;
826
+ a->lookup_uid_data = private_data;
827
+ return (ARCHIVE_OK);
828
+ }
829
+
830
+
831
+ /*
832
+ * Create a new archive_write_disk object and initialize it with global state.
833
+ */
834
+ struct archive *
835
+ archive_write_disk_new(void)
836
+ {
837
+ struct archive_write_disk *a;
838
+
839
+ a = (struct archive_write_disk *)malloc(sizeof(*a));
840
+ if (a == NULL)
841
+ return (NULL);
842
+ memset(a, 0, sizeof(*a));
843
+ a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
844
+ /* We're ready to write a header immediately. */
845
+ a->archive.state = ARCHIVE_STATE_HEADER;
846
+ a->archive.vtable = archive_write_disk_vtable();
847
+ a->lookup_uid = trivial_lookup_uid;
848
+ a->lookup_gid = trivial_lookup_gid;
849
+ a->start_time = time(NULL);
850
+ #ifdef HAVE_GETEUID
851
+ a->user_uid = geteuid();
852
+ #endif /* HAVE_GETEUID */
853
+ if (archive_string_ensure(&a->path_safe, 512) == NULL) {
854
+ free(a);
855
+ return (NULL);
856
+ }
857
+ return (&a->archive);
858
+ }
859
+
860
+
861
+ /*
862
+ * If pathname is longer than PATH_MAX, chdir to a suitable
863
+ * intermediate dir and edit the path down to a shorter suffix. Note
864
+ * that this routine never returns an error; if the chdir() attempt
865
+ * fails for any reason, we just go ahead with the long pathname. The
866
+ * object creation is likely to fail, but any error will get handled
867
+ * at that time.
868
+ */
869
+ #ifdef HAVE_FCHDIR
870
+ static void
871
+ edit_deep_directories(struct archive_write_disk *a)
872
+ {
873
+ int ret;
874
+ char *tail = a->name;
875
+
876
+ a->restore_pwd = -1;
877
+
878
+ /* If path is short, avoid the open() below. */
879
+ if (strlen(tail) <= PATH_MAX)
880
+ return;
881
+
882
+ /* Try to record our starting dir. */
883
+ a->restore_pwd = open(".", O_RDONLY | O_BINARY);
884
+ if (a->restore_pwd < 0)
885
+ return;
886
+
887
+ /* As long as the path is too long... */
888
+ while (strlen(tail) > PATH_MAX) {
889
+ /* Locate a dir prefix shorter than PATH_MAX. */
890
+ tail += PATH_MAX - 8;
891
+ while (tail > a->name && *tail != '/')
892
+ tail--;
893
+ /* Exit if we find a too-long path component. */
894
+ if (tail <= a->name)
895
+ return;
896
+ /* Create the intermediate dir and chdir to it. */
897
+ *tail = '\0'; /* Terminate dir portion */
898
+ ret = create_dir(a, a->name);
899
+ if (ret == ARCHIVE_OK && chdir(a->name) != 0)
900
+ ret = ARCHIVE_FAILED;
901
+ *tail = '/'; /* Restore the / we removed. */
902
+ if (ret != ARCHIVE_OK)
903
+ return;
904
+ tail++;
905
+ /* The chdir() succeeded; we've now shortened the path. */
906
+ a->name = tail;
907
+ }
908
+ return;
909
+ }
910
+ #endif
911
+
912
+ /*
913
+ * The main restore function.
914
+ */
915
+ static int
916
+ restore_entry(struct archive_write_disk *a)
917
+ {
918
+ int ret = ARCHIVE_OK, en;
919
+
920
+ if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
921
+ /*
922
+ * TODO: Fix this. Apparently, there are platforms
923
+ * that still allow root to hose the entire filesystem
924
+ * by unlinking a dir. The S_ISDIR() test above
925
+ * prevents us from using unlink() here if the new
926
+ * object is a dir, but that doesn't mean the old
927
+ * object isn't a dir.
928
+ */
929
+ if (unlink(a->name) == 0) {
930
+ /* We removed it, reset cached stat. */
931
+ a->pst = NULL;
932
+ } else if (errno == ENOENT) {
933
+ /* File didn't exist, that's just as good. */
934
+ } else if (rmdir(a->name) == 0) {
935
+ /* It was a dir, but now it's gone. */
936
+ a->pst = NULL;
937
+ } else {
938
+ /* We tried, but couldn't get rid of it. */
939
+ archive_set_error(&a->archive, errno,
940
+ "Could not unlink");
941
+ return(ARCHIVE_FAILED);
942
+ }
943
+ }
944
+
945
+ /* Try creating it first; if this fails, we'll try to recover. */
946
+ en = create_filesystem_object(a);
947
+
948
+ if ((en == ENOTDIR || en == ENOENT)
949
+ && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
950
+ /* If the parent dir doesn't exist, try creating it. */
951
+ create_parent_dir(a, a->name);
952
+ /* Now try to create the object again. */
953
+ en = create_filesystem_object(a);
954
+ }
955
+
956
+ if ((en == EISDIR || en == EEXIST)
957
+ && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
958
+ /* If we're not overwriting, we're done. */
959
+ archive_set_error(&a->archive, en, "Already exists");
960
+ return (ARCHIVE_FAILED);
961
+ }
962
+
963
+ /*
964
+ * Some platforms return EISDIR if you call
965
+ * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
966
+ * return EEXIST. POSIX is ambiguous, requiring EISDIR
967
+ * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
968
+ * on an existing item.
969
+ */
970
+ if (en == EISDIR) {
971
+ /* A dir is in the way of a non-dir, rmdir it. */
972
+ if (rmdir(a->name) != 0) {
973
+ archive_set_error(&a->archive, errno,
974
+ "Can't remove already-existing dir");
975
+ return (ARCHIVE_FAILED);
976
+ }
977
+ a->pst = NULL;
978
+ /* Try again. */
979
+ en = create_filesystem_object(a);
980
+ } else if (en == EEXIST) {
981
+ /*
982
+ * We know something is in the way, but we don't know what;
983
+ * we need to find out before we go any further.
984
+ */
985
+ int r = 0;
986
+ /*
987
+ * The SECURE_SYMLINK logic has already removed a
988
+ * symlink to a dir if the client wants that. So
989
+ * follow the symlink if we're creating a dir.
990
+ */
991
+ if (S_ISDIR(a->mode))
992
+ r = stat(a->name, &a->st);
993
+ /*
994
+ * If it's not a dir (or it's a broken symlink),
995
+ * then don't follow it.
996
+ */
997
+ if (r != 0 || !S_ISDIR(a->mode))
998
+ r = lstat(a->name, &a->st);
999
+ if (r != 0) {
1000
+ archive_set_error(&a->archive, errno,
1001
+ "Can't stat existing object");
1002
+ return (ARCHIVE_FAILED);
1003
+ }
1004
+
1005
+ /*
1006
+ * NO_OVERWRITE_NEWER doesn't apply to directories.
1007
+ */
1008
+ if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
1009
+ && !S_ISDIR(a->st.st_mode)) {
1010
+ if (!older(&(a->st), a->entry)) {
1011
+ archive_set_error(&a->archive, 0,
1012
+ "File on disk is not older; skipping.");
1013
+ return (ARCHIVE_FAILED);
1014
+ }
1015
+ }
1016
+
1017
+ /* If it's our archive, we're done. */
1018
+ if (a->skip_file_dev > 0 &&
1019
+ a->skip_file_ino > 0 &&
1020
+ a->st.st_dev == a->skip_file_dev &&
1021
+ a->st.st_ino == a->skip_file_ino) {
1022
+ archive_set_error(&a->archive, 0, "Refusing to overwrite archive");
1023
+ return (ARCHIVE_FAILED);
1024
+ }
1025
+
1026
+ if (!S_ISDIR(a->st.st_mode)) {
1027
+ /* A non-dir is in the way, unlink it. */
1028
+ if (unlink(a->name) != 0) {
1029
+ archive_set_error(&a->archive, errno,
1030
+ "Can't unlink already-existing object");
1031
+ return (ARCHIVE_FAILED);
1032
+ }
1033
+ a->pst = NULL;
1034
+ /* Try again. */
1035
+ en = create_filesystem_object(a);
1036
+ } else if (!S_ISDIR(a->mode)) {
1037
+ /* A dir is in the way of a non-dir, rmdir it. */
1038
+ if (rmdir(a->name) != 0) {
1039
+ archive_set_error(&a->archive, errno,
1040
+ "Can't remove already-existing dir");
1041
+ return (ARCHIVE_FAILED);
1042
+ }
1043
+ /* Try again. */
1044
+ en = create_filesystem_object(a);
1045
+ } else {
1046
+ /*
1047
+ * There's a dir in the way of a dir. Don't
1048
+ * waste time with rmdir()/mkdir(), just fix
1049
+ * up the permissions on the existing dir.
1050
+ * Note that we don't change perms on existing
1051
+ * dirs unless _EXTRACT_PERM is specified.
1052
+ */
1053
+ if ((a->mode != a->st.st_mode)
1054
+ && (a->todo & TODO_MODE_FORCE))
1055
+ a->deferred |= (a->todo & TODO_MODE);
1056
+ /* Ownership doesn't need deferred fixup. */
1057
+ en = 0; /* Forget the EEXIST. */
1058
+ }
1059
+ }
1060
+
1061
+ if (en) {
1062
+ /* Everything failed; give up here. */
1063
+ archive_set_error(&a->archive, en, "Can't create '%s'",
1064
+ a->name);
1065
+ return (ARCHIVE_FAILED);
1066
+ }
1067
+
1068
+ a->pst = NULL; /* Cached stat data no longer valid. */
1069
+ return (ret);
1070
+ }
1071
+
1072
+ /*
1073
+ * Returns 0 if creation succeeds, or else returns errno value from
1074
+ * the failed system call. Note: This function should only ever perform
1075
+ * a single system call.
1076
+ */
1077
+ static int
1078
+ create_filesystem_object(struct archive_write_disk *a)
1079
+ {
1080
+ /* Create the entry. */
1081
+ const char *linkname;
1082
+ mode_t final_mode, mode;
1083
+ int r;
1084
+
1085
+ /* We identify hard/symlinks according to the link names. */
1086
+ /* Since link(2) and symlink(2) don't handle modes, we're done here. */
1087
+ linkname = archive_entry_hardlink(a->entry);
1088
+ if (linkname != NULL) {
1089
+ #if !HAVE_LINK
1090
+ return (EPERM);
1091
+ #else
1092
+ r = link(linkname, a->name) ? errno : 0;
1093
+ /*
1094
+ * New cpio and pax formats allow hardlink entries
1095
+ * to carry data, so we may have to open the file
1096
+ * for hardlink entries.
1097
+ *
1098
+ * If the hardlink was successfully created and
1099
+ * the archive doesn't have carry data for it,
1100
+ * consider it to be non-authoritive for meta data.
1101
+ * This is consistent with GNU tar and BSD pax.
1102
+ * If the hardlink does carry data, let the last
1103
+ * archive entry decide ownership.
1104
+ */
1105
+ if (r == 0 && a->filesize <= 0) {
1106
+ a->todo = 0;
1107
+ a->deferred = 0;
1108
+ } if (r == 0 && a->filesize > 0) {
1109
+ a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY);
1110
+ if (a->fd < 0)
1111
+ r = errno;
1112
+ }
1113
+ return (r);
1114
+ #endif
1115
+ }
1116
+ linkname = archive_entry_symlink(a->entry);
1117
+ if (linkname != NULL) {
1118
+ #if HAVE_SYMLINK
1119
+ return symlink(linkname, a->name) ? errno : 0;
1120
+ #else
1121
+ return (EPERM);
1122
+ #endif
1123
+ }
1124
+
1125
+ /*
1126
+ * The remaining system calls all set permissions, so let's
1127
+ * try to take advantage of that to avoid an extra chmod()
1128
+ * call. (Recall that umask is set to zero right now!)
1129
+ */
1130
+
1131
+ /* Mode we want for the final restored object (w/o file type bits). */
1132
+ final_mode = a->mode & 07777;
1133
+ /*
1134
+ * The mode that will actually be restored in this step. Note
1135
+ * that SUID, SGID, etc, require additional work to ensure
1136
+ * security, so we never restore them at this point.
1137
+ */
1138
+ mode = final_mode & 0777;
1139
+
1140
+ switch (a->mode & AE_IFMT) {
1141
+ default:
1142
+ /* POSIX requires that we fall through here. */
1143
+ /* FALLTHROUGH */
1144
+ case AE_IFREG:
1145
+ a->fd = open(a->name,
1146
+ O_WRONLY | O_CREAT | O_EXCL | O_BINARY, mode);
1147
+ r = (a->fd < 0);
1148
+ break;
1149
+ case AE_IFCHR:
1150
+ #ifdef HAVE_MKNOD
1151
+ /* Note: we use AE_IFCHR for the case label, and
1152
+ * S_IFCHR for the mknod() call. This is correct. */
1153
+ r = mknod(a->name, mode | S_IFCHR,
1154
+ archive_entry_rdev(a->entry));
1155
+ break;
1156
+ #else
1157
+ /* TODO: Find a better way to warn about our inability
1158
+ * to restore a char device node. */
1159
+ return (EINVAL);
1160
+ #endif /* HAVE_MKNOD */
1161
+ case AE_IFBLK:
1162
+ #ifdef HAVE_MKNOD
1163
+ r = mknod(a->name, mode | S_IFBLK,
1164
+ archive_entry_rdev(a->entry));
1165
+ break;
1166
+ #else
1167
+ /* TODO: Find a better way to warn about our inability
1168
+ * to restore a block device node. */
1169
+ return (EINVAL);
1170
+ #endif /* HAVE_MKNOD */
1171
+ case AE_IFDIR:
1172
+ mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
1173
+ r = mkdir(a->name, mode);
1174
+ if (r == 0) {
1175
+ /* Defer setting dir times. */
1176
+ a->deferred |= (a->todo & TODO_TIMES);
1177
+ a->todo &= ~TODO_TIMES;
1178
+ /* Never use an immediate chmod(). */
1179
+ /* We can't avoid the chmod() entirely if EXTRACT_PERM
1180
+ * because of SysV SGID inheritance. */
1181
+ if ((mode != final_mode)
1182
+ || (a->flags & ARCHIVE_EXTRACT_PERM))
1183
+ a->deferred |= (a->todo & TODO_MODE);
1184
+ a->todo &= ~TODO_MODE;
1185
+ }
1186
+ break;
1187
+ case AE_IFIFO:
1188
+ #ifdef HAVE_MKFIFO
1189
+ r = mkfifo(a->name, mode);
1190
+ break;
1191
+ #else
1192
+ /* TODO: Find a better way to warn about our inability
1193
+ * to restore a fifo. */
1194
+ return (EINVAL);
1195
+ #endif /* HAVE_MKFIFO */
1196
+ }
1197
+
1198
+ /* All the system calls above set errno on failure. */
1199
+ if (r)
1200
+ return (errno);
1201
+
1202
+ /* If we managed to set the final mode, we've avoided a chmod(). */
1203
+ if (mode == final_mode)
1204
+ a->todo &= ~TODO_MODE;
1205
+ return (0);
1206
+ }
1207
+
1208
+ /*
1209
+ * Cleanup function for archive_extract. Mostly, this involves processing
1210
+ * the fixup list, which is used to address a number of problems:
1211
+ * * Dir permissions might prevent us from restoring a file in that
1212
+ * dir, so we restore the dir with minimum 0700 permissions first,
1213
+ * then correct the mode at the end.
1214
+ * * Similarly, the act of restoring a file touches the directory
1215
+ * and changes the timestamp on the dir, so we have to touch-up dir
1216
+ * timestamps at the end as well.
1217
+ * * Some file flags can interfere with the restore by, for example,
1218
+ * preventing the creation of hardlinks to those files.
1219
+ *
1220
+ * Note that tar/cpio do not require that archives be in a particular
1221
+ * order; there is no way to know when the last file has been restored
1222
+ * within a directory, so there's no way to optimize the memory usage
1223
+ * here by fixing up the directory any earlier than the
1224
+ * end-of-archive.
1225
+ *
1226
+ * XXX TODO: Directory ACLs should be restored here, for the same
1227
+ * reason we set directory perms here. XXX
1228
+ */
1229
+ static int
1230
+ _archive_write_close(struct archive *_a)
1231
+ {
1232
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1233
+ struct fixup_entry *next, *p;
1234
+ int ret;
1235
+
1236
+ __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1237
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1238
+ "archive_write_disk_close");
1239
+ ret = _archive_write_finish_entry(&a->archive);
1240
+
1241
+ /* Sort dir list so directories are fixed up in depth-first order. */
1242
+ p = sort_dir_list(a->fixup_list);
1243
+
1244
+ while (p != NULL) {
1245
+ a->pst = NULL; /* Mark stat cache as out-of-date. */
1246
+ if (p->fixup & TODO_TIMES) {
1247
+ #ifdef HAVE_UTIMES
1248
+ /* {f,l,}utimes() are preferred, when available. */
1249
+ #if defined(_WIN32) && !defined(__CYGWIN__)
1250
+ struct __timeval times[2];
1251
+ #else
1252
+ struct timeval times[2];
1253
+ #endif
1254
+ times[0].tv_sec = p->atime;
1255
+ times[0].tv_usec = p->atime_nanos / 1000;
1256
+ #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1257
+ /* if it's valid and not mtime, push the birthtime first */
1258
+ if (((times[1].tv_sec = p->birthtime) < p->mtime) &&
1259
+ (p->birthtime > 0))
1260
+ {
1261
+ times[1].tv_usec = p->birthtime_nanos / 1000;
1262
+ utimes(p->name, times);
1263
+ }
1264
+ #endif
1265
+ times[1].tv_sec = p->mtime;
1266
+ times[1].tv_usec = p->mtime_nanos / 1000;
1267
+ #ifdef HAVE_LUTIMES
1268
+ lutimes(p->name, times);
1269
+ #else
1270
+ utimes(p->name, times);
1271
+ #endif
1272
+ #else
1273
+ /* utime() is more portable, but less precise. */
1274
+ struct utimbuf times;
1275
+ times.modtime = p->mtime;
1276
+ times.actime = p->atime;
1277
+
1278
+ utime(p->name, &times);
1279
+ #endif
1280
+ }
1281
+ if (p->fixup & TODO_MODE_BASE)
1282
+ chmod(p->name, p->mode);
1283
+
1284
+ if (p->fixup & TODO_FFLAGS)
1285
+ set_fflags_platform(a, -1, p->name,
1286
+ p->mode, p->fflags_set, 0);
1287
+
1288
+ next = p->next;
1289
+ free(p->name);
1290
+ free(p);
1291
+ p = next;
1292
+ }
1293
+ a->fixup_list = NULL;
1294
+ return (ret);
1295
+ }
1296
+
1297
+ static int
1298
+ _archive_write_finish(struct archive *_a)
1299
+ {
1300
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
1301
+ int ret;
1302
+ ret = _archive_write_close(&a->archive);
1303
+ if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
1304
+ (a->cleanup_gid)(a->lookup_gid_data);
1305
+ if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
1306
+ (a->cleanup_uid)(a->lookup_uid_data);
1307
+ if (a->entry)
1308
+ archive_entry_free(a->entry);
1309
+ archive_string_free(&a->_name_data);
1310
+ archive_string_free(&a->archive.error_string);
1311
+ archive_string_free(&a->path_safe);
1312
+ free(a);
1313
+ return (ret);
1314
+ }
1315
+
1316
+ /*
1317
+ * Simple O(n log n) merge sort to order the fixup list. In
1318
+ * particular, we want to restore dir timestamps depth-first.
1319
+ */
1320
+ static struct fixup_entry *
1321
+ sort_dir_list(struct fixup_entry *p)
1322
+ {
1323
+ struct fixup_entry *a, *b, *t;
1324
+
1325
+ if (p == NULL)
1326
+ return (NULL);
1327
+ /* A one-item list is already sorted. */
1328
+ if (p->next == NULL)
1329
+ return (p);
1330
+
1331
+ /* Step 1: split the list. */
1332
+ t = p;
1333
+ a = p->next->next;
1334
+ while (a != NULL) {
1335
+ /* Step a twice, t once. */
1336
+ a = a->next;
1337
+ if (a != NULL)
1338
+ a = a->next;
1339
+ t = t->next;
1340
+ }
1341
+ /* Now, t is at the mid-point, so break the list here. */
1342
+ b = t->next;
1343
+ t->next = NULL;
1344
+ a = p;
1345
+
1346
+ /* Step 2: Recursively sort the two sub-lists. */
1347
+ a = sort_dir_list(a);
1348
+ b = sort_dir_list(b);
1349
+
1350
+ /* Step 3: Merge the returned lists. */
1351
+ /* Pick the first element for the merged list. */
1352
+ if (strcmp(a->name, b->name) > 0) {
1353
+ t = p = a;
1354
+ a = a->next;
1355
+ } else {
1356
+ t = p = b;
1357
+ b = b->next;
1358
+ }
1359
+
1360
+ /* Always put the later element on the list first. */
1361
+ while (a != NULL && b != NULL) {
1362
+ if (strcmp(a->name, b->name) > 0) {
1363
+ t->next = a;
1364
+ a = a->next;
1365
+ } else {
1366
+ t->next = b;
1367
+ b = b->next;
1368
+ }
1369
+ t = t->next;
1370
+ }
1371
+
1372
+ /* Only one list is non-empty, so just splice it on. */
1373
+ if (a != NULL)
1374
+ t->next = a;
1375
+ if (b != NULL)
1376
+ t->next = b;
1377
+
1378
+ return (p);
1379
+ }
1380
+
1381
+ /*
1382
+ * Returns a new, initialized fixup entry.
1383
+ *
1384
+ * TODO: Reduce the memory requirements for this list by using a tree
1385
+ * structure rather than a simple list of names.
1386
+ */
1387
+ static struct fixup_entry *
1388
+ new_fixup(struct archive_write_disk *a, const char *pathname)
1389
+ {
1390
+ struct fixup_entry *fe;
1391
+
1392
+ fe = (struct fixup_entry *)malloc(sizeof(struct fixup_entry));
1393
+ if (fe == NULL)
1394
+ return (NULL);
1395
+ fe->next = a->fixup_list;
1396
+ a->fixup_list = fe;
1397
+ fe->fixup = 0;
1398
+ fe->name = strdup(pathname);
1399
+ return (fe);
1400
+ }
1401
+
1402
+ /*
1403
+ * Returns a fixup structure for the current entry.
1404
+ */
1405
+ static struct fixup_entry *
1406
+ current_fixup(struct archive_write_disk *a, const char *pathname)
1407
+ {
1408
+ if (a->current_fixup == NULL)
1409
+ a->current_fixup = new_fixup(a, pathname);
1410
+ return (a->current_fixup);
1411
+ }
1412
+
1413
+ /* TODO: Make this work. */
1414
+ /*
1415
+ * TODO: The deep-directory support bypasses this; disable deep directory
1416
+ * support if we're doing symlink checks.
1417
+ */
1418
+ /*
1419
+ * TODO: Someday, integrate this with the deep dir support; they both
1420
+ * scan the path and both can be optimized by comparing against other
1421
+ * recent paths.
1422
+ */
1423
+ /* TODO: Extend this to support symlinks on Windows Vista and later. */
1424
+ static int
1425
+ check_symlinks(struct archive_write_disk *a)
1426
+ {
1427
+ #if !defined(HAVE_LSTAT)
1428
+ /* Platform doesn't have lstat, so we can't look for symlinks. */
1429
+ (void)a; /* UNUSED */
1430
+ return (ARCHIVE_OK);
1431
+ #else
1432
+ char *pn, *p;
1433
+ char c;
1434
+ int r;
1435
+ struct stat st;
1436
+
1437
+ /*
1438
+ * Guard against symlink tricks. Reject any archive entry whose
1439
+ * destination would be altered by a symlink.
1440
+ */
1441
+ /* Whatever we checked last time doesn't need to be re-checked. */
1442
+ pn = a->name;
1443
+ p = a->path_safe.s;
1444
+ while ((*pn != '\0') && (*p == *pn))
1445
+ ++p, ++pn;
1446
+ c = pn[0];
1447
+ /* Keep going until we've checked the entire name. */
1448
+ while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
1449
+ /* Skip the next path element. */
1450
+ while (*pn != '\0' && *pn != '/')
1451
+ ++pn;
1452
+ c = pn[0];
1453
+ pn[0] = '\0';
1454
+ /* Check that we haven't hit a symlink. */
1455
+ r = lstat(a->name, &st);
1456
+ if (r != 0) {
1457
+ /* We've hit a dir that doesn't exist; stop now. */
1458
+ if (errno == ENOENT)
1459
+ break;
1460
+ } else if (S_ISLNK(st.st_mode)) {
1461
+ if (c == '\0') {
1462
+ /*
1463
+ * Last element is symlink; remove it
1464
+ * so we can overwrite it with the
1465
+ * item being extracted.
1466
+ */
1467
+ if (unlink(a->name)) {
1468
+ archive_set_error(&a->archive, errno,
1469
+ "Could not remove symlink %s",
1470
+ a->name);
1471
+ pn[0] = c;
1472
+ return (ARCHIVE_FAILED);
1473
+ }
1474
+ a->pst = NULL;
1475
+ /*
1476
+ * Even if we did remove it, a warning
1477
+ * is in order. The warning is silly,
1478
+ * though, if we're just replacing one
1479
+ * symlink with another symlink.
1480
+ */
1481
+ if (!S_ISLNK(a->mode)) {
1482
+ archive_set_error(&a->archive, 0,
1483
+ "Removing symlink %s",
1484
+ a->name);
1485
+ }
1486
+ /* Symlink gone. No more problem! */
1487
+ pn[0] = c;
1488
+ return (0);
1489
+ } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
1490
+ /* User asked us to remove problems. */
1491
+ if (unlink(a->name) != 0) {
1492
+ archive_set_error(&a->archive, 0,
1493
+ "Cannot remove intervening symlink %s",
1494
+ a->name);
1495
+ pn[0] = c;
1496
+ return (ARCHIVE_FAILED);
1497
+ }
1498
+ a->pst = NULL;
1499
+ } else {
1500
+ archive_set_error(&a->archive, 0,
1501
+ "Cannot extract through symlink %s",
1502
+ a->name);
1503
+ pn[0] = c;
1504
+ return (ARCHIVE_FAILED);
1505
+ }
1506
+ }
1507
+ }
1508
+ pn[0] = c;
1509
+ /* We've checked and/or cleaned the whole path, so remember it. */
1510
+ archive_strcpy(&a->path_safe, a->name);
1511
+ return (ARCHIVE_OK);
1512
+ #endif
1513
+ }
1514
+
1515
+ #if defined(_WIN32) || defined(__CYGWIN__)
1516
+ /*
1517
+ * 1. Convert a path separator from '\' to '/' .
1518
+ * We shouldn't check multi-byte character directly because some
1519
+ * character-set have been using the '\' character for a part of
1520
+ * its multibyte character code.
1521
+ * 2. Replace unusable characters in Windows with underscore('_').
1522
+ * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
1523
+ */
1524
+ static void
1525
+ cleanup_pathname_win(struct archive_write_disk *a)
1526
+ {
1527
+ wchar_t wc;
1528
+ char *p;
1529
+ size_t alen, l;
1530
+
1531
+ alen = 0;
1532
+ l = 0;
1533
+ for (p = a->name; *p != '\0'; p++) {
1534
+ ++alen;
1535
+ if (*p == '\\')
1536
+ l = 1;
1537
+ /* Rewrite the path name if its character is a unusable. */
1538
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
1539
+ *p == '<' || *p == '>' || *p == '|')
1540
+ *p = '_';
1541
+ }
1542
+ if (alen == 0 || l == 0)
1543
+ return;
1544
+ /*
1545
+ * Convert path separator.
1546
+ */
1547
+ p = a->name;
1548
+ while (*p != '\0' && alen) {
1549
+ l = mbtowc(&wc, p, alen);
1550
+ if (l == -1) {
1551
+ while (*p != '\0') {
1552
+ if (*p == '\\')
1553
+ *p = '/';
1554
+ ++p;
1555
+ }
1556
+ break;
1557
+ }
1558
+ if (l == 1 && wc == L'\\')
1559
+ *p = '/';
1560
+ p += l;
1561
+ alen -= l;
1562
+ }
1563
+ }
1564
+ #endif
1565
+
1566
+ /*
1567
+ * Canonicalize the pathname. In particular, this strips duplicate
1568
+ * '/' characters, '.' elements, and trailing '/'. It also raises an
1569
+ * error for an empty path, a trailing '..' or (if _SECURE_NODOTDOT is
1570
+ * set) any '..' in the path.
1571
+ */
1572
+ static int
1573
+ cleanup_pathname(struct archive_write_disk *a)
1574
+ {
1575
+ char *dest, *src;
1576
+ char separator = '\0';
1577
+
1578
+ dest = src = a->name;
1579
+ if (*src == '\0') {
1580
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1581
+ "Invalid empty pathname");
1582
+ return (ARCHIVE_FAILED);
1583
+ }
1584
+
1585
+ #if defined(_WIN32) || defined(__CYGWIN__)
1586
+ cleanup_pathname_win(a);
1587
+ #endif
1588
+ /* Skip leading '/'. */
1589
+ if (*src == '/')
1590
+ separator = *src++;
1591
+
1592
+ /* Scan the pathname one element at a time. */
1593
+ for (;;) {
1594
+ /* src points to first char after '/' */
1595
+ if (src[0] == '\0') {
1596
+ break;
1597
+ } else if (src[0] == '/') {
1598
+ /* Found '//', ignore second one. */
1599
+ src++;
1600
+ continue;
1601
+ } else if (src[0] == '.') {
1602
+ if (src[1] == '\0') {
1603
+ /* Ignore trailing '.' */
1604
+ break;
1605
+ } else if (src[1] == '/') {
1606
+ /* Skip './'. */
1607
+ src += 2;
1608
+ continue;
1609
+ } else if (src[1] == '.') {
1610
+ if (src[2] == '/' || src[2] == '\0') {
1611
+ /* Conditionally warn about '..' */
1612
+ if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
1613
+ archive_set_error(&a->archive,
1614
+ ARCHIVE_ERRNO_MISC,
1615
+ "Path contains '..'");
1616
+ return (ARCHIVE_FAILED);
1617
+ }
1618
+ }
1619
+ /*
1620
+ * Note: Under no circumstances do we
1621
+ * remove '..' elements. In
1622
+ * particular, restoring
1623
+ * '/foo/../bar/' should create the
1624
+ * 'foo' dir as a side-effect.
1625
+ */
1626
+ }
1627
+ }
1628
+
1629
+ /* Copy current element, including leading '/'. */
1630
+ if (separator)
1631
+ *dest++ = '/';
1632
+ while (*src != '\0' && *src != '/') {
1633
+ *dest++ = *src++;
1634
+ }
1635
+
1636
+ if (*src == '\0')
1637
+ break;
1638
+
1639
+ /* Skip '/' separator. */
1640
+ separator = *src++;
1641
+ }
1642
+ /*
1643
+ * We've just copied zero or more path elements, not including the
1644
+ * final '/'.
1645
+ */
1646
+ if (dest == a->name) {
1647
+ /*
1648
+ * Nothing got copied. The path must have been something
1649
+ * like '.' or '/' or './' or '/././././/./'.
1650
+ */
1651
+ if (separator)
1652
+ *dest++ = '/';
1653
+ else
1654
+ *dest++ = '.';
1655
+ }
1656
+ /* Terminate the result. */
1657
+ *dest = '\0';
1658
+ return (ARCHIVE_OK);
1659
+ }
1660
+
1661
+ /*
1662
+ * Create the parent directory of the specified path, assuming path
1663
+ * is already in mutable storage.
1664
+ */
1665
+ static int
1666
+ create_parent_dir(struct archive_write_disk *a, char *path)
1667
+ {
1668
+ char *slash;
1669
+ int r;
1670
+
1671
+ /* Remove tail element to obtain parent name. */
1672
+ slash = strrchr(path, '/');
1673
+ if (slash == NULL)
1674
+ return (ARCHIVE_OK);
1675
+ *slash = '\0';
1676
+ r = create_dir(a, path);
1677
+ *slash = '/';
1678
+ return (r);
1679
+ }
1680
+
1681
+ /*
1682
+ * Create the specified dir, recursing to create parents as necessary.
1683
+ *
1684
+ * Returns ARCHIVE_OK if the path exists when we're done here.
1685
+ * Otherwise, returns ARCHIVE_FAILED.
1686
+ * Assumes path is in mutable storage; path is unchanged on exit.
1687
+ */
1688
+ static int
1689
+ create_dir(struct archive_write_disk *a, char *path)
1690
+ {
1691
+ struct stat st;
1692
+ struct fixup_entry *le;
1693
+ char *slash, *base;
1694
+ mode_t mode_final, mode;
1695
+ int r;
1696
+
1697
+ /* Check for special names and just skip them. */
1698
+ slash = strrchr(path, '/');
1699
+ if (slash == NULL)
1700
+ base = path;
1701
+ else
1702
+ base = slash + 1;
1703
+
1704
+ if (base[0] == '\0' ||
1705
+ (base[0] == '.' && base[1] == '\0') ||
1706
+ (base[0] == '.' && base[1] == '.' && base[2] == '\0')) {
1707
+ /* Don't bother trying to create null path, '.', or '..'. */
1708
+ if (slash != NULL) {
1709
+ *slash = '\0';
1710
+ r = create_dir(a, path);
1711
+ *slash = '/';
1712
+ return (r);
1713
+ }
1714
+ return (ARCHIVE_OK);
1715
+ }
1716
+
1717
+ /*
1718
+ * Yes, this should be stat() and not lstat(). Using lstat()
1719
+ * here loses the ability to extract through symlinks. Also note
1720
+ * that this should not use the a->st cache.
1721
+ */
1722
+ if (stat(path, &st) == 0) {
1723
+ if (S_ISDIR(st.st_mode))
1724
+ return (ARCHIVE_OK);
1725
+ if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
1726
+ archive_set_error(&a->archive, EEXIST,
1727
+ "Can't create directory '%s'", path);
1728
+ return (ARCHIVE_FAILED);
1729
+ }
1730
+ if (unlink(path) != 0) {
1731
+ archive_set_error(&a->archive, errno,
1732
+ "Can't create directory '%s': "
1733
+ "Conflicting file cannot be removed");
1734
+ return (ARCHIVE_FAILED);
1735
+ }
1736
+ } else if (errno != ENOENT && errno != ENOTDIR) {
1737
+ /* Stat failed? */
1738
+ archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
1739
+ return (ARCHIVE_FAILED);
1740
+ } else if (slash != NULL) {
1741
+ *slash = '\0';
1742
+ r = create_dir(a, path);
1743
+ *slash = '/';
1744
+ if (r != ARCHIVE_OK)
1745
+ return (r);
1746
+ }
1747
+
1748
+ /*
1749
+ * Mode we want for the final restored directory. Per POSIX,
1750
+ * implicitly-created dirs must be created obeying the umask.
1751
+ * There's no mention whether this is different for privileged
1752
+ * restores (which the rest of this code handles by pretending
1753
+ * umask=0). I've chosen here to always obey the user's umask for
1754
+ * implicit dirs, even if _EXTRACT_PERM was specified.
1755
+ */
1756
+ mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
1757
+ /* Mode we want on disk during the restore process. */
1758
+ mode = mode_final;
1759
+ mode |= MINIMUM_DIR_MODE;
1760
+ mode &= MAXIMUM_DIR_MODE;
1761
+ if (mkdir(path, mode) == 0) {
1762
+ if (mode != mode_final) {
1763
+ le = new_fixup(a, path);
1764
+ le->fixup |=TODO_MODE_BASE;
1765
+ le->mode = mode_final;
1766
+ }
1767
+ return (ARCHIVE_OK);
1768
+ }
1769
+
1770
+ /*
1771
+ * Without the following check, a/b/../b/c/d fails at the
1772
+ * second visit to 'b', so 'd' can't be created. Note that we
1773
+ * don't add it to the fixup list here, as it's already been
1774
+ * added.
1775
+ */
1776
+ if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
1777
+ return (ARCHIVE_OK);
1778
+
1779
+ archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
1780
+ path);
1781
+ return (ARCHIVE_FAILED);
1782
+ }
1783
+
1784
+ /*
1785
+ * Note: Although we can skip setting the user id if the desired user
1786
+ * id matches the current user, we cannot skip setting the group, as
1787
+ * many systems set the gid based on the containing directory. So
1788
+ * we have to perform a chown syscall if we want to set the SGID
1789
+ * bit. (The alternative is to stat() and then possibly chown(); it's
1790
+ * more efficient to skip the stat() and just always chown().) Note
1791
+ * that a successful chown() here clears the TODO_SGID_CHECK bit, which
1792
+ * allows set_mode to skip the stat() check for the GID.
1793
+ */
1794
+ static int
1795
+ set_ownership(struct archive_write_disk *a)
1796
+ {
1797
+ #ifndef __CYGWIN__
1798
+ /* unfortunately, on win32 there is no 'root' user with uid 0,
1799
+ so we just have to try the chown and see if it works */
1800
+
1801
+ /* If we know we can't change it, don't bother trying. */
1802
+ if (a->user_uid != 0 && a->user_uid != a->uid) {
1803
+ archive_set_error(&a->archive, errno,
1804
+ "Can't set UID=%d", a->uid);
1805
+ return (ARCHIVE_WARN);
1806
+ }
1807
+ #endif
1808
+
1809
+ #ifdef HAVE_FCHOWN
1810
+ /* If we have an fd, we can avoid a race. */
1811
+ if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) {
1812
+ /* We've set owner and know uid/gid are correct. */
1813
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
1814
+ return (ARCHIVE_OK);
1815
+ }
1816
+ #endif
1817
+
1818
+ /* We prefer lchown() but will use chown() if that's all we have. */
1819
+ /* Of course, if we have neither, this will always fail. */
1820
+ #ifdef HAVE_LCHOWN
1821
+ if (lchown(a->name, a->uid, a->gid) == 0) {
1822
+ /* We've set owner and know uid/gid are correct. */
1823
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
1824
+ return (ARCHIVE_OK);
1825
+ }
1826
+ #elif HAVE_CHOWN
1827
+ if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) {
1828
+ /* We've set owner and know uid/gid are correct. */
1829
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
1830
+ return (ARCHIVE_OK);
1831
+ }
1832
+ #endif
1833
+
1834
+ archive_set_error(&a->archive, errno,
1835
+ "Can't set user=%d/group=%d for %s", a->uid, a->gid,
1836
+ a->name);
1837
+ return (ARCHIVE_WARN);
1838
+ }
1839
+
1840
+
1841
+ #if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS)
1842
+ /*
1843
+ * utimensat() and futimens() are defined in POSIX.1-2008. They provide ns
1844
+ * resolution and setting times on fd and on symlinks, too.
1845
+ */
1846
+ static int
1847
+ set_time(int fd, int mode, const char *name,
1848
+ time_t atime, long atime_nsec,
1849
+ time_t mtime, long mtime_nsec)
1850
+ {
1851
+ struct timespec ts[2];
1852
+ ts[0].tv_sec = atime;
1853
+ ts[0].tv_nsec = atime_nsec;
1854
+ ts[1].tv_sec = mtime;
1855
+ ts[1].tv_nsec = mtime_nsec;
1856
+ if (fd >= 0)
1857
+ return futimens(fd, ts);
1858
+ return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW);
1859
+ }
1860
+ #elif HAVE_UTIMES
1861
+ /*
1862
+ * The utimes()-family functions provide µs-resolution and
1863
+ * a way to set time on an fd or a symlink. We prefer them
1864
+ * when they're available and utimensat/futimens aren't there.
1865
+ */
1866
+ static int
1867
+ set_time(int fd, int mode, const char *name,
1868
+ time_t atime, long atime_nsec,
1869
+ time_t mtime, long mtime_nsec)
1870
+ {
1871
+ #if defined(_WIN32) && !defined(__CYGWIN__)
1872
+ struct __timeval times[2];
1873
+ #else
1874
+ struct timeval times[2];
1875
+ #endif
1876
+
1877
+ times[0].tv_sec = atime;
1878
+ times[0].tv_usec = atime_nsec / 1000;
1879
+ times[1].tv_sec = mtime;
1880
+ times[1].tv_usec = mtime_nsec / 1000;
1881
+
1882
+ #ifdef HAVE_FUTIMES
1883
+ if (fd >= 0)
1884
+ return (futimes(fd, times));
1885
+ #else
1886
+ (void)fd; /* UNUSED */
1887
+ #endif
1888
+ #ifdef HAVE_LUTIMES
1889
+ (void)mode; /* UNUSED */
1890
+ return (lutimes(name, times));
1891
+ #else
1892
+ if (S_ISLNK(mode))
1893
+ return (0);
1894
+ return (utimes(name, times));
1895
+ #endif
1896
+ }
1897
+ #elif defined(HAVE_UTIME)
1898
+ /*
1899
+ * utime() is an older, more standard interface that we'll use
1900
+ * if utimes() isn't available.
1901
+ */
1902
+ static int
1903
+ set_time(int fd, int mode, const char *name,
1904
+ time_t atime, long atime_nsec,
1905
+ time_t mtime, long mtime_nsec)
1906
+ {
1907
+ struct utimbuf times;
1908
+ (void)fd; /* UNUSED */
1909
+ (void)name; /* UNUSED */
1910
+ (void)atime_nsec; /* UNUSED */
1911
+ (void)mtime_nsec; /* UNUSED */
1912
+ times.actime = atime;
1913
+ times.modtime = mtime;
1914
+ if (S_ISLNK(mode))
1915
+ return (ARCHIVE_OK);
1916
+ return (utime(name, &times));
1917
+ }
1918
+ #else
1919
+ static int
1920
+ set_time(int fd, int mode, const char *name,
1921
+ time_t atime, long atime_nsec,
1922
+ time_t mtime, long mtime_nsec)
1923
+ {
1924
+ return (ARCHIVE_WARN);
1925
+ }
1926
+ #endif
1927
+
1928
+ static int
1929
+ set_times(struct archive_write_disk *a)
1930
+ {
1931
+ time_t atime = a->start_time, mtime = a->start_time;
1932
+ long atime_nsec = 0, mtime_nsec = 0;
1933
+
1934
+ /* If no time was provided, we're done. */
1935
+ if (!archive_entry_atime_is_set(a->entry)
1936
+ #if HAVE_STRUCT_STAT_ST_BIRTHTIME
1937
+ && !archive_entry_birthtime_is_set(a->entry)
1938
+ #endif
1939
+ && !archive_entry_mtime_is_set(a->entry))
1940
+ return (ARCHIVE_OK);
1941
+
1942
+ /* If no atime was specified, use start time instead. */
1943
+ /* In theory, it would be marginally more correct to use
1944
+ * time(NULL) here, but that would cost us an extra syscall
1945
+ * for little gain. */
1946
+ if (archive_entry_atime_is_set(a->entry)) {
1947
+ atime = archive_entry_atime(a->entry);
1948
+ atime_nsec = archive_entry_atime_nsec(a->entry);
1949
+ }
1950
+
1951
+ /*
1952
+ * If you have struct stat.st_birthtime, we assume BSD birthtime
1953
+ * semantics, in which {f,l,}utimes() updates birthtime to earliest
1954
+ * mtime. So we set the time twice, first using the birthtime,
1955
+ * then using the mtime.
1956
+ */
1957
+ #if HAVE_STRUCT_STAT_ST_BIRTHTIME
1958
+ /* If birthtime is set, flush that through to disk first. */
1959
+ if (archive_entry_birthtime_is_set(a->entry))
1960
+ if (set_time(a->fd, a->mode, a->name, atime, atime_nsec,
1961
+ archive_entry_birthtime(a->entry),
1962
+ archive_entry_birthtime_nsec(a->entry))) {
1963
+ archive_set_error(&a->archive, errno,
1964
+ "Can't update time for %s",
1965
+ a->name);
1966
+ return (ARCHIVE_WARN);
1967
+ }
1968
+ #endif
1969
+
1970
+ if (archive_entry_mtime_is_set(a->entry)) {
1971
+ mtime = archive_entry_mtime(a->entry);
1972
+ mtime_nsec = archive_entry_mtime_nsec(a->entry);
1973
+ }
1974
+ if (set_time(a->fd, a->mode, a->name,
1975
+ atime, atime_nsec, mtime, mtime_nsec)) {
1976
+ archive_set_error(&a->archive, errno,
1977
+ "Can't update time for %s",
1978
+ a->name);
1979
+ return (ARCHIVE_WARN);
1980
+ }
1981
+
1982
+ /*
1983
+ * Note: POSIX does not provide a portable way to restore ctime.
1984
+ * (Apart from resetting the system clock, which is distasteful.)
1985
+ * So, any restoration of ctime will necessarily be OS-specific.
1986
+ */
1987
+
1988
+ return (ARCHIVE_OK);
1989
+ }
1990
+
1991
+ static int
1992
+ set_mode(struct archive_write_disk *a, int mode)
1993
+ {
1994
+ int r = ARCHIVE_OK;
1995
+ mode &= 07777; /* Strip off file type bits. */
1996
+
1997
+ if (a->todo & TODO_SGID_CHECK) {
1998
+ /*
1999
+ * If we don't know the GID is right, we must stat()
2000
+ * to verify it. We can't just check the GID of this
2001
+ * process, since systems sometimes set GID from
2002
+ * the enclosing dir or based on ACLs.
2003
+ */
2004
+ if ((r = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
2005
+ return (r);
2006
+ if (a->pst->st_gid != a->gid) {
2007
+ mode &= ~ S_ISGID;
2008
+ #if !defined(_WIN32) || defined(__CYGWIN__)
2009
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
2010
+ /*
2011
+ * This is only an error if you
2012
+ * requested owner restore. If you
2013
+ * didn't, we'll try to restore
2014
+ * sgid/suid, but won't consider it a
2015
+ * problem if we can't.
2016
+ */
2017
+ archive_set_error(&a->archive, -1,
2018
+ "Can't restore SGID bit");
2019
+ r = ARCHIVE_WARN;
2020
+ }
2021
+ #endif
2022
+ }
2023
+ /* While we're here, double-check the UID. */
2024
+ if (a->pst->st_uid != a->uid
2025
+ && (a->todo & TODO_SUID)) {
2026
+ mode &= ~ S_ISUID;
2027
+ #if !defined(_WIN32) || defined(__CYGWIN__)
2028
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
2029
+ archive_set_error(&a->archive, -1,
2030
+ "Can't restore SUID bit");
2031
+ r = ARCHIVE_WARN;
2032
+ }
2033
+ #endif
2034
+ }
2035
+ a->todo &= ~TODO_SGID_CHECK;
2036
+ a->todo &= ~TODO_SUID_CHECK;
2037
+ } else if (a->todo & TODO_SUID_CHECK) {
2038
+ /*
2039
+ * If we don't know the UID is right, we can just check
2040
+ * the user, since all systems set the file UID from
2041
+ * the process UID.
2042
+ */
2043
+ if (a->user_uid != a->uid) {
2044
+ mode &= ~ S_ISUID;
2045
+ #if !defined(_WIN32) || defined(__CYGWIN__)
2046
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
2047
+ archive_set_error(&a->archive, -1,
2048
+ "Can't make file SUID");
2049
+ r = ARCHIVE_WARN;
2050
+ }
2051
+ #endif
2052
+ }
2053
+ a->todo &= ~TODO_SUID_CHECK;
2054
+ }
2055
+
2056
+ if (S_ISLNK(a->mode)) {
2057
+ #ifdef HAVE_LCHMOD
2058
+ /*
2059
+ * If this is a symlink, use lchmod(). If the
2060
+ * platform doesn't support lchmod(), just skip it. A
2061
+ * platform that doesn't provide a way to set
2062
+ * permissions on symlinks probably ignores
2063
+ * permissions on symlinks, so a failure here has no
2064
+ * impact.
2065
+ */
2066
+ if (lchmod(a->name, mode) != 0) {
2067
+ archive_set_error(&a->archive, errno,
2068
+ "Can't set permissions to 0%o", (int)mode);
2069
+ r = ARCHIVE_WARN;
2070
+ }
2071
+ #endif
2072
+ } else if (!S_ISDIR(a->mode)) {
2073
+ /*
2074
+ * If it's not a symlink and not a dir, then use
2075
+ * fchmod() or chmod(), depending on whether we have
2076
+ * an fd. Dirs get their perms set during the
2077
+ * post-extract fixup, which is handled elsewhere.
2078
+ */
2079
+ #ifdef HAVE_FCHMOD
2080
+ if (a->fd >= 0) {
2081
+ if (fchmod(a->fd, mode) != 0) {
2082
+ archive_set_error(&a->archive, errno,
2083
+ "Can't set permissions to 0%o", (int)mode);
2084
+ r = ARCHIVE_WARN;
2085
+ }
2086
+ } else
2087
+ #endif
2088
+ /* If this platform lacks fchmod(), then
2089
+ * we'll just use chmod(). */
2090
+ if (chmod(a->name, mode) != 0) {
2091
+ archive_set_error(&a->archive, errno,
2092
+ "Can't set permissions to 0%o", (int)mode);
2093
+ r = ARCHIVE_WARN;
2094
+ }
2095
+ }
2096
+ return (r);
2097
+ }
2098
+
2099
+ static int
2100
+ set_fflags(struct archive_write_disk *a)
2101
+ {
2102
+ struct fixup_entry *le;
2103
+ unsigned long set, clear;
2104
+ int r;
2105
+ int critical_flags;
2106
+ mode_t mode = archive_entry_mode(a->entry);
2107
+
2108
+ /*
2109
+ * Make 'critical_flags' hold all file flags that can't be
2110
+ * immediately restored. For example, on BSD systems,
2111
+ * SF_IMMUTABLE prevents hardlinks from being created, so
2112
+ * should not be set until after any hardlinks are created. To
2113
+ * preserve some semblance of portability, this uses #ifdef
2114
+ * extensively. Ugly, but it works.
2115
+ *
2116
+ * Yes, Virginia, this does create a security race. It's mitigated
2117
+ * somewhat by the practice of creating dirs 0700 until the extract
2118
+ * is done, but it would be nice if we could do more than that.
2119
+ * People restoring critical file systems should be wary of
2120
+ * other programs that might try to muck with files as they're
2121
+ * being restored.
2122
+ */
2123
+ /* Hopefully, the compiler will optimize this mess into a constant. */
2124
+ critical_flags = 0;
2125
+ #ifdef SF_IMMUTABLE
2126
+ critical_flags |= SF_IMMUTABLE;
2127
+ #endif
2128
+ #ifdef UF_IMMUTABLE
2129
+ critical_flags |= UF_IMMUTABLE;
2130
+ #endif
2131
+ #ifdef SF_APPEND
2132
+ critical_flags |= SF_APPEND;
2133
+ #endif
2134
+ #ifdef UF_APPEND
2135
+ critical_flags |= UF_APPEND;
2136
+ #endif
2137
+ #ifdef EXT2_APPEND_FL
2138
+ critical_flags |= EXT2_APPEND_FL;
2139
+ #endif
2140
+ #ifdef EXT2_IMMUTABLE_FL
2141
+ critical_flags |= EXT2_IMMUTABLE_FL;
2142
+ #endif
2143
+
2144
+ if (a->todo & TODO_FFLAGS) {
2145
+ archive_entry_fflags(a->entry, &set, &clear);
2146
+
2147
+ /*
2148
+ * The first test encourages the compiler to eliminate
2149
+ * all of this if it's not necessary.
2150
+ */
2151
+ if ((critical_flags != 0) && (set & critical_flags)) {
2152
+ le = current_fixup(a, a->name);
2153
+ le->fixup |= TODO_FFLAGS;
2154
+ le->fflags_set = set;
2155
+ /* Store the mode if it's not already there. */
2156
+ if ((le->fixup & TODO_MODE) == 0)
2157
+ le->mode = mode;
2158
+ } else {
2159
+ r = set_fflags_platform(a, a->fd,
2160
+ a->name, mode, set, clear);
2161
+ if (r != ARCHIVE_OK)
2162
+ return (r);
2163
+ }
2164
+ }
2165
+ return (ARCHIVE_OK);
2166
+ }
2167
+
2168
+
2169
+ #if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS)
2170
+ /*
2171
+ * BSD reads flags using stat() and sets them with one of {f,l,}chflags()
2172
+ */
2173
+ static int
2174
+ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
2175
+ mode_t mode, unsigned long set, unsigned long clear)
2176
+ {
2177
+ int r;
2178
+
2179
+ (void)mode; /* UNUSED */
2180
+ if (set == 0 && clear == 0)
2181
+ return (ARCHIVE_OK);
2182
+
2183
+ /*
2184
+ * XXX Is the stat here really necessary? Or can I just use
2185
+ * the 'set' flags directly? In particular, I'm not sure
2186
+ * about the correct approach if we're overwriting an existing
2187
+ * file that already has flags on it. XXX
2188
+ */
2189
+ if ((r = _archive_write_disk_lazy_stat(a)) != ARCHIVE_OK)
2190
+ return (r);
2191
+
2192
+ a->st.st_flags &= ~clear;
2193
+ a->st.st_flags |= set;
2194
+ #ifdef HAVE_FCHFLAGS
2195
+ /* If platform has fchflags() and we were given an fd, use it. */
2196
+ if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0)
2197
+ return (ARCHIVE_OK);
2198
+ #endif
2199
+ /*
2200
+ * If we can't use the fd to set the flags, we'll use the
2201
+ * pathname to set flags. We prefer lchflags() but will use
2202
+ * chflags() if we must.
2203
+ */
2204
+ #ifdef HAVE_LCHFLAGS
2205
+ if (lchflags(name, a->st.st_flags) == 0)
2206
+ return (ARCHIVE_OK);
2207
+ #elif defined(HAVE_CHFLAGS)
2208
+ if (S_ISLNK(a->st.st_mode)) {
2209
+ archive_set_error(&a->archive, errno,
2210
+ "Can't set file flags on symlink.");
2211
+ return (ARCHIVE_WARN);
2212
+ }
2213
+ if (chflags(name, a->st.st_flags) == 0)
2214
+ return (ARCHIVE_OK);
2215
+ #endif
2216
+ archive_set_error(&a->archive, errno,
2217
+ "Failed to set file flags");
2218
+ return (ARCHIVE_WARN);
2219
+ }
2220
+
2221
+ #elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS)
2222
+ /*
2223
+ * Linux uses ioctl() to read and write file flags.
2224
+ */
2225
+ static int
2226
+ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
2227
+ mode_t mode, unsigned long set, unsigned long clear)
2228
+ {
2229
+ int ret;
2230
+ int myfd = fd;
2231
+ unsigned long newflags, oldflags;
2232
+ unsigned long sf_mask = 0;
2233
+
2234
+ if (set == 0 && clear == 0)
2235
+ return (ARCHIVE_OK);
2236
+ /* Only regular files and dirs can have flags. */
2237
+ if (!S_ISREG(mode) && !S_ISDIR(mode))
2238
+ return (ARCHIVE_OK);
2239
+
2240
+ /* If we weren't given an fd, open it ourselves. */
2241
+ if (myfd < 0)
2242
+ myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY);
2243
+ if (myfd < 0)
2244
+ return (ARCHIVE_OK);
2245
+
2246
+ /*
2247
+ * Linux has no define for the flags that are only settable by
2248
+ * the root user. This code may seem a little complex, but
2249
+ * there seem to be some Linux systems that lack these
2250
+ * defines. (?) The code below degrades reasonably gracefully
2251
+ * if sf_mask is incomplete.
2252
+ */
2253
+ #ifdef EXT2_IMMUTABLE_FL
2254
+ sf_mask |= EXT2_IMMUTABLE_FL;
2255
+ #endif
2256
+ #ifdef EXT2_APPEND_FL
2257
+ sf_mask |= EXT2_APPEND_FL;
2258
+ #endif
2259
+ /*
2260
+ * XXX As above, this would be way simpler if we didn't have
2261
+ * to read the current flags from disk. XXX
2262
+ */
2263
+ ret = ARCHIVE_OK;
2264
+ /* Try setting the flags as given. */
2265
+ if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) {
2266
+ newflags = (oldflags & ~clear) | set;
2267
+ if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
2268
+ goto cleanup;
2269
+ if (errno != EPERM)
2270
+ goto fail;
2271
+ }
2272
+ /* If we couldn't set all the flags, try again with a subset. */
2273
+ if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) {
2274
+ newflags &= ~sf_mask;
2275
+ oldflags &= sf_mask;
2276
+ newflags |= oldflags;
2277
+ if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
2278
+ goto cleanup;
2279
+ }
2280
+ /* We couldn't set the flags, so report the failure. */
2281
+ fail:
2282
+ archive_set_error(&a->archive, errno,
2283
+ "Failed to set file flags");
2284
+ ret = ARCHIVE_WARN;
2285
+ cleanup:
2286
+ if (fd < 0)
2287
+ close(myfd);
2288
+ return (ret);
2289
+ }
2290
+
2291
+ #else
2292
+
2293
+ /*
2294
+ * Of course, some systems have neither BSD chflags() nor Linux' flags
2295
+ * support through ioctl().
2296
+ */
2297
+ static int
2298
+ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
2299
+ mode_t mode, unsigned long set, unsigned long clear)
2300
+ {
2301
+ (void)a; /* UNUSED */
2302
+ (void)fd; /* UNUSED */
2303
+ (void)name; /* UNUSED */
2304
+ (void)mode; /* UNUSED */
2305
+ (void)set; /* UNUSED */
2306
+ (void)clear; /* UNUSED */
2307
+ return (ARCHIVE_OK);
2308
+ }
2309
+
2310
+ #endif /* __linux */
2311
+
2312
+ #ifndef HAVE_POSIX_ACL
2313
+ /* Default empty function body to satisfy mainline code. */
2314
+ static int
2315
+ set_acls(struct archive_write_disk *a)
2316
+ {
2317
+ (void)a; /* UNUSED */
2318
+ return (ARCHIVE_OK);
2319
+ }
2320
+
2321
+ #else
2322
+
2323
+ /*
2324
+ * XXX TODO: What about ACL types other than ACCESS and DEFAULT?
2325
+ */
2326
+ static int
2327
+ set_acls(struct archive_write_disk *a)
2328
+ {
2329
+ int ret;
2330
+
2331
+ ret = set_acl(a, a->fd, a->entry, ACL_TYPE_ACCESS,
2332
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
2333
+ if (ret != ARCHIVE_OK)
2334
+ return (ret);
2335
+ ret = set_acl(a, a->fd, a->entry, ACL_TYPE_DEFAULT,
2336
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
2337
+ return (ret);
2338
+ }
2339
+
2340
+
2341
+ static int
2342
+ set_acl(struct archive_write_disk *a, int fd, struct archive_entry *entry,
2343
+ acl_type_t acl_type, int ae_requested_type, const char *tname)
2344
+ {
2345
+ acl_t acl;
2346
+ acl_entry_t acl_entry;
2347
+ acl_permset_t acl_permset;
2348
+ int ret;
2349
+ int ae_type, ae_permset, ae_tag, ae_id;
2350
+ uid_t ae_uid;
2351
+ gid_t ae_gid;
2352
+ const char *ae_name;
2353
+ int entries;
2354
+ const char *name;
2355
+
2356
+ ret = ARCHIVE_OK;
2357
+ entries = archive_entry_acl_reset(entry, ae_requested_type);
2358
+ if (entries == 0)
2359
+ return (ARCHIVE_OK);
2360
+ acl = acl_init(entries);
2361
+ while (archive_entry_acl_next(entry, ae_requested_type, &ae_type,
2362
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
2363
+ acl_create_entry(&acl, &acl_entry);
2364
+
2365
+ switch (ae_tag) {
2366
+ case ARCHIVE_ENTRY_ACL_USER:
2367
+ acl_set_tag_type(acl_entry, ACL_USER);
2368
+ ae_uid = a->lookup_uid(a->lookup_uid_data,
2369
+ ae_name, ae_id);
2370
+ acl_set_qualifier(acl_entry, &ae_uid);
2371
+ break;
2372
+ case ARCHIVE_ENTRY_ACL_GROUP:
2373
+ acl_set_tag_type(acl_entry, ACL_GROUP);
2374
+ ae_gid = a->lookup_gid(a->lookup_gid_data,
2375
+ ae_name, ae_id);
2376
+ acl_set_qualifier(acl_entry, &ae_gid);
2377
+ break;
2378
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
2379
+ acl_set_tag_type(acl_entry, ACL_USER_OBJ);
2380
+ break;
2381
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
2382
+ acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
2383
+ break;
2384
+ case ARCHIVE_ENTRY_ACL_MASK:
2385
+ acl_set_tag_type(acl_entry, ACL_MASK);
2386
+ break;
2387
+ case ARCHIVE_ENTRY_ACL_OTHER:
2388
+ acl_set_tag_type(acl_entry, ACL_OTHER);
2389
+ break;
2390
+ default:
2391
+ /* XXX */
2392
+ break;
2393
+ }
2394
+
2395
+ acl_get_permset(acl_entry, &acl_permset);
2396
+ acl_clear_perms(acl_permset);
2397
+ if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
2398
+ acl_add_perm(acl_permset, ACL_EXECUTE);
2399
+ if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
2400
+ acl_add_perm(acl_permset, ACL_WRITE);
2401
+ if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
2402
+ acl_add_perm(acl_permset, ACL_READ);
2403
+ }
2404
+
2405
+ name = archive_entry_pathname(entry);
2406
+
2407
+ /* Try restoring the ACL through 'fd' if we can. */
2408
+ #if HAVE_ACL_SET_FD
2409
+ if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
2410
+ ret = ARCHIVE_OK;
2411
+ else
2412
+ #else
2413
+ #if HAVE_ACL_SET_FD_NP
2414
+ if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
2415
+ ret = ARCHIVE_OK;
2416
+ else
2417
+ #endif
2418
+ #endif
2419
+ if (acl_set_file(name, acl_type, acl) != 0) {
2420
+ archive_set_error(&a->archive, errno, "Failed to set %s acl", tname);
2421
+ ret = ARCHIVE_WARN;
2422
+ }
2423
+ acl_free(acl);
2424
+ return (ret);
2425
+ }
2426
+ #endif
2427
+
2428
+ #if HAVE_LSETXATTR
2429
+ /*
2430
+ * Restore extended attributes - Linux implementation
2431
+ */
2432
+ static int
2433
+ set_xattrs(struct archive_write_disk *a)
2434
+ {
2435
+ struct archive_entry *entry = a->entry;
2436
+ static int warning_done = 0;
2437
+ int ret = ARCHIVE_OK;
2438
+ int i = archive_entry_xattr_reset(entry);
2439
+
2440
+ while (i--) {
2441
+ const char *name;
2442
+ const void *value;
2443
+ size_t size;
2444
+ archive_entry_xattr_next(entry, &name, &value, &size);
2445
+ if (name != NULL &&
2446
+ strncmp(name, "xfsroot.", 8) != 0 &&
2447
+ strncmp(name, "system.", 7) != 0) {
2448
+ int e;
2449
+ #if HAVE_FSETXATTR
2450
+ if (a->fd >= 0)
2451
+ e = fsetxattr(a->fd, name, value, size, 0);
2452
+ else
2453
+ #endif
2454
+ {
2455
+ e = lsetxattr(archive_entry_pathname(entry),
2456
+ name, value, size, 0);
2457
+ }
2458
+ if (e == -1) {
2459
+ if (errno == ENOTSUP) {
2460
+ if (!warning_done) {
2461
+ warning_done = 1;
2462
+ archive_set_error(&a->archive, errno,
2463
+ "Cannot restore extended "
2464
+ "attributes on this file "
2465
+ "system");
2466
+ }
2467
+ } else
2468
+ archive_set_error(&a->archive, errno,
2469
+ "Failed to set extended attribute");
2470
+ ret = ARCHIVE_WARN;
2471
+ }
2472
+ } else {
2473
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2474
+ "Invalid extended attribute encountered");
2475
+ ret = ARCHIVE_WARN;
2476
+ }
2477
+ }
2478
+ return (ret);
2479
+ }
2480
+ #elif HAVE_EXTATTR_SET_FILE && HAVE_DECL_EXTATTR_NAMESPACE_USER
2481
+ /*
2482
+ * Restore extended attributes - FreeBSD implementation
2483
+ */
2484
+ static int
2485
+ set_xattrs(struct archive_write_disk *a)
2486
+ {
2487
+ struct archive_entry *entry = a->entry;
2488
+ static int warning_done = 0;
2489
+ int ret = ARCHIVE_OK;
2490
+ int i = archive_entry_xattr_reset(entry);
2491
+
2492
+ while (i--) {
2493
+ const char *name;
2494
+ const void *value;
2495
+ size_t size;
2496
+ archive_entry_xattr_next(entry, &name, &value, &size);
2497
+ if (name != NULL) {
2498
+ int e;
2499
+ int namespace;
2500
+
2501
+ if (strncmp(name, "user.", 5) == 0) {
2502
+ /* "user." attributes go to user namespace */
2503
+ name += 5;
2504
+ namespace = EXTATTR_NAMESPACE_USER;
2505
+ } else {
2506
+ /* Warn about other extended attributes. */
2507
+ archive_set_error(&a->archive,
2508
+ ARCHIVE_ERRNO_FILE_FORMAT,
2509
+ "Can't restore extended attribute ``%s''",
2510
+ name);
2511
+ ret = ARCHIVE_WARN;
2512
+ continue;
2513
+ }
2514
+ errno = 0;
2515
+ #if HAVE_EXTATTR_SET_FD
2516
+ if (a->fd >= 0)
2517
+ e = extattr_set_fd(a->fd, namespace, name, value, size);
2518
+ else
2519
+ #endif
2520
+ /* TODO: should we use extattr_set_link() instead? */
2521
+ {
2522
+ e = extattr_set_file(archive_entry_pathname(entry),
2523
+ namespace, name, value, size);
2524
+ }
2525
+ if (e != (int)size) {
2526
+ if (errno == ENOTSUP) {
2527
+ if (!warning_done) {
2528
+ warning_done = 1;
2529
+ archive_set_error(&a->archive, errno,
2530
+ "Cannot restore extended "
2531
+ "attributes on this file "
2532
+ "system");
2533
+ }
2534
+ } else {
2535
+ archive_set_error(&a->archive, errno,
2536
+ "Failed to set extended attribute");
2537
+ }
2538
+
2539
+ ret = ARCHIVE_WARN;
2540
+ }
2541
+ }
2542
+ }
2543
+ return (ret);
2544
+ }
2545
+ #else
2546
+ /*
2547
+ * Restore extended attributes - stub implementation for unsupported systems
2548
+ */
2549
+ static int
2550
+ set_xattrs(struct archive_write_disk *a)
2551
+ {
2552
+ static int warning_done = 0;
2553
+
2554
+ /* If there aren't any extended attributes, then it's okay not
2555
+ * to extract them, otherwise, issue a single warning. */
2556
+ if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
2557
+ warning_done = 1;
2558
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2559
+ "Cannot restore extended attributes on this system");
2560
+ return (ARCHIVE_WARN);
2561
+ }
2562
+ /* Warning was already emitted; suppress further warnings. */
2563
+ return (ARCHIVE_OK);
2564
+ }
2565
+ #endif
2566
+
2567
+
2568
+ /*
2569
+ * Trivial implementations of gid/uid lookup functions.
2570
+ * These are normally overridden by the client, but these stub
2571
+ * versions ensure that we always have something that works.
2572
+ */
2573
+ static gid_t
2574
+ trivial_lookup_gid(void *private_data, const char *gname, gid_t gid)
2575
+ {
2576
+ (void)private_data; /* UNUSED */
2577
+ (void)gname; /* UNUSED */
2578
+ return (gid);
2579
+ }
2580
+
2581
+ static uid_t
2582
+ trivial_lookup_uid(void *private_data, const char *uname, uid_t uid)
2583
+ {
2584
+ (void)private_data; /* UNUSED */
2585
+ (void)uname; /* UNUSED */
2586
+ return (uid);
2587
+ }
2588
+
2589
+ /*
2590
+ * Test if file on disk is older than entry.
2591
+ */
2592
+ static int
2593
+ older(struct stat *st, struct archive_entry *entry)
2594
+ {
2595
+ /* First, test the seconds and return if we have a definite answer. */
2596
+ /* Definitely older. */
2597
+ if (st->st_mtime < archive_entry_mtime(entry))
2598
+ return (1);
2599
+ /* Definitely younger. */
2600
+ if (st->st_mtime > archive_entry_mtime(entry))
2601
+ return (0);
2602
+ /* If this platform supports fractional seconds, try those. */
2603
+ #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
2604
+ /* Definitely older. */
2605
+ if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry))
2606
+ return (1);
2607
+ #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
2608
+ /* Definitely older. */
2609
+ if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry))
2610
+ return (1);
2611
+ #elif HAVE_STRUCT_STAT_ST_MTIME_N
2612
+ /* older. */
2613
+ if (st->st_mtime_n < archive_entry_mtime_nsec(entry))
2614
+ return (1);
2615
+ #elif HAVE_STRUCT_STAT_ST_UMTIME
2616
+ /* older. */
2617
+ if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry))
2618
+ return (1);
2619
+ #elif HAVE_STRUCT_STAT_ST_MTIME_USEC
2620
+ /* older. */
2621
+ if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry))
2622
+ return (1);
2623
+ #else
2624
+ /* This system doesn't have high-res timestamps. */
2625
+ #endif
2626
+ /* Same age or newer, so not older. */
2627
+ return (0);
2628
+ }