]> git.ipfire.org Git - thirdparty/libarchive.git/blame - libarchive/archive_write_disk_posix.c
zip: update AppleDouble support for directories (#2100)
[thirdparty/libarchive.git] / libarchive / archive_write_disk_posix.c
CommitLineData
8f776fd9 1/*-
2f3c9ee6 2 * Copyright (c) 2003-2010 Tim Kientzle
fb67a295 3 * Copyright (c) 2012 Michihiro NAKAJIMA
8f776fd9
TK
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer
11 * in this position and unchanged.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "archive_platform.h"
5b3644c3
MN
29
30#if !defined(_WIN32) || defined(__CYGWIN__)
8f776fd9
TK
31
32#ifdef HAVE_SYS_TYPES_H
33#include <sys/types.h>
34#endif
4d920441
MN
35#ifdef HAVE_SYS_ACL_H
36#include <sys/acl.h>
37#endif
b21f351a
TK
38#ifdef HAVE_SYS_EXTATTR_H
39#include <sys/extattr.h>
40#endif
365a91de 41#if HAVE_SYS_XATTR_H
280540e0 42#include <sys/xattr.h>
365a91de 43#elif HAVE_ATTR_XATTR_H
97bf284c 44#include <attr/xattr.h>
280540e0 45#endif
d4da0242 46#ifdef HAVE_SYS_EA_H
0d621852
BJ
47#include <sys/ea.h>
48#endif
8f776fd9
TK
49#ifdef HAVE_SYS_IOCTL_H
50#include <sys/ioctl.h>
51#endif
52#ifdef HAVE_SYS_STAT_H
53#include <sys/stat.h>
54#endif
55#ifdef HAVE_SYS_TIME_H
56#include <sys/time.h>
57#endif
58#ifdef HAVE_SYS_UTIME_H
59#include <sys/utime.h>
60#endif
b8ad1655
TK
61#ifdef HAVE_COPYFILE_H
62#include <copyfile.h>
63#endif
8f776fd9
TK
64#ifdef HAVE_ERRNO_H
65#include <errno.h>
66#endif
67#ifdef HAVE_FCNTL_H
68#include <fcntl.h>
69#endif
70#ifdef HAVE_GRP_H
71#include <grp.h>
72#endif
a4b94153
MN
73#ifdef HAVE_LANGINFO_H
74#include <langinfo.h>
75#endif
8f776fd9
TK
76#ifdef HAVE_LINUX_FS_H
77#include <linux/fs.h> /* for Linux file flags */
78#endif
06710c34
JS
79/*
80 * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
81 * As the include guards don't agree, the order of include is important.
82 */
83#ifdef HAVE_LINUX_EXT2_FS_H
84#include <linux/ext2_fs.h> /* for Linux file flags */
85#endif
86#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
87#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
88#endif
8f776fd9
TK
89#ifdef HAVE_LIMITS_H
90#include <limits.h>
91#endif
92#ifdef HAVE_PWD_H
93#include <pwd.h>
94#endif
95#include <stdio.h>
96#ifdef HAVE_STDLIB_H
97#include <stdlib.h>
98#endif
99#ifdef HAVE_STRING_H
100#include <string.h>
101#endif
102#ifdef HAVE_UNISTD_H
103#include <unistd.h>
104#endif
105#ifdef HAVE_UTIME_H
106#include <utime.h>
107#endif
631247e1
BJ
108#ifdef F_GETTIMES /* Tru64 specific */
109#include <sys/fcntl1.h>
110#endif
8f776fd9 111
c89d1a1e
BS
112/*
113 * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
114 *
115 * It assumes that the input is an integer type of no more than 64 bits.
116 * If the number is less than zero, t must be a signed type, so it fits in
117 * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
118 * without loss. But it could be a large unsigned value, so we have to clip it
119 * to INT64_MAX.*
120 */
121#define to_int64_time(t) \
122 ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
123
b8ad1655
TK
124#if __APPLE__
125#include <TargetConditionals.h>
126#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
127#include <quarantine.h>
128#define HAVE_QUARANTINE 1
129#endif
130#endif
131
fb67a295
MN
132#ifdef HAVE_ZLIB_H
133#include <zlib.h>
134#endif
135
b8ad1655
TK
136/* TODO: Support Mac OS 'quarantine' feature. This is really just a
137 * standard tag to mark files that have been downloaded as "tainted".
138 * On Mac OS, we should mark the extracted files as tainted if the
139 * archive being read was tainted. Windows has a similar feature; we
140 * should investigate ways to support this generically. */
141
8f776fd9 142#include "archive.h"
ec502e2d 143#include "archive_acl_private.h"
8f776fd9 144#include "archive_string.h"
fb67a295 145#include "archive_endian.h"
8f776fd9
TK
146#include "archive_entry.h"
147#include "archive_private.h"
f67370d5 148#include "archive_write_disk_private.h"
8f776fd9
TK
149
150#ifndef O_BINARY
151#define O_BINARY 0
152#endif
60141df1 153#ifndef O_CLOEXEC
9f0dee22
TK
154#define O_CLOEXEC 0
155#endif
156
157/* Ignore non-int O_NOFOLLOW constant. */
158/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
159#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
160#undef O_NOFOLLOW
161#endif
162
163#ifndef O_NOFOLLOW
164#define O_NOFOLLOW 0
60141df1 165#endif
8f776fd9 166
b6655592
MM
167#ifndef AT_FDCWD
168#define AT_FDCWD -100
169#endif
170
8f776fd9
TK
171struct fixup_entry {
172 struct fixup_entry *next;
b01b4bc1 173 struct archive_acl acl;
8f776fd9 174 mode_t mode;
ede459d2 175 __LA_MODE_T filetype;
8f776fd9 176 int64_t atime;
82e3bb2a
TK
177 int64_t birthtime;
178 int64_t mtime;
b648c6c7 179 int64_t ctime;
8f776fd9 180 unsigned long atime_nanos;
82e3bb2a
TK
181 unsigned long birthtime_nanos;
182 unsigned long mtime_nanos;
b648c6c7 183 unsigned long ctime_nanos;
8f776fd9 184 unsigned long fflags_set;
b8ad1655
TK
185 size_t mac_metadata_size;
186 void *mac_metadata;
8f776fd9
TK
187 int fixup; /* bitmask of what needs fixing */
188 char *name;
189};
190
191/*
192 * We use a bitmask to track which operations remain to be done for
193 * this file. In particular, this helps us avoid unnecessary
194 * operations when it's possible to take care of one step as a
195 * side-effect of another. For example, mkdir() can specify the mode
196 * for the newly-created object but symlink() cannot. This means we
197 * can skip chmod() if mkdir() succeeded, but we must explicitly
198 * chmod() if we're trying to create a directory that already exists
199 * (mkdir() failed) or if we're restoring a symlink. Similarly, we
200 * need to verify UID/GID before trying to restore SUID/SGID bits;
201 * that verification can occur explicitly through a stat() call or
202 * implicitly because of a successful chown() call.
203 */
204#define TODO_MODE_FORCE 0x40000000
205#define TODO_MODE_BASE 0x20000000
206#define TODO_SUID 0x10000000
207#define TODO_SUID_CHECK 0x08000000
208#define TODO_SGID 0x04000000
209#define TODO_SGID_CHECK 0x02000000
a70241b7 210#define TODO_APPLEDOUBLE 0x01000000
8f776fd9
TK
211#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID)
212#define TODO_TIMES ARCHIVE_EXTRACT_TIME
213#define TODO_OWNER ARCHIVE_EXTRACT_OWNER
214#define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS
215#define TODO_ACLS ARCHIVE_EXTRACT_ACL
216#define TODO_XATTR ARCHIVE_EXTRACT_XATTR
b8ad1655 217#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA
6238bed6 218#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
8f776fd9
TK
219
220struct archive_write_disk {
221 struct archive archive;
222
223 mode_t user_umask;
224 struct fixup_entry *fixup_list;
225 struct fixup_entry *current_fixup;
73f39d90 226 int64_t user_uid;
7457cf54 227 int skip_file_set;
7d2cbbc5
MN
228 int64_t skip_file_dev;
229 int64_t skip_file_ino;
da0cee61 230 time_t start_time;
8f776fd9 231
73f39d90 232 int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
8f776fd9
TK
233 void (*cleanup_gid)(void *private);
234 void *lookup_gid_data;
73f39d90 235 int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid);
8f776fd9
TK
236 void (*cleanup_uid)(void *private);
237 void *lookup_uid_data;
238
239 /*
240 * Full path of last file to satisfy symlink checks.
241 */
242 struct archive_string path_safe;
243
244 /*
245 * Cached stat data from disk for the current entry.
246 * If this is valid, pst points to st. Otherwise,
247 * pst is null.
248 */
249 struct stat st;
250 struct stat *pst;
251
252 /* Information about the object being restored right now. */
253 struct archive_entry *entry; /* Entry being extracted. */
254 char *name; /* Name of entry, possibly edited. */
255 struct archive_string _name_data; /* backing store for 'name' */
b51d6b62 256 char *tmpname; /* Temporary name * */
257 struct archive_string _tmpname_data; /* backing store for 'tmpname' */
8f776fd9
TK
258 /* Tasks remaining for this object. */
259 int todo;
260 /* Tasks deferred until end-of-archive. */
261 int deferred;
262 /* Options requested by the client. */
263 int flags;
264 /* Handle for the file we're restoring. */
265 int fd;
266 /* Current offset for writing data to the file. */
911dc2bf 267 int64_t offset;
b6c8e140 268 /* Last offset actually written to disk. */
911dc2bf
TK
269 int64_t fd_offset;
270 /* Total bytes actually written to files. */
271 int64_t total_bytes_written;
5b5d1d58 272 /* Maximum size of file, -1 if unknown. */
911dc2bf 273 int64_t filesize;
8f776fd9
TK
274 /* Dir we were in before this restore; only for deep paths. */
275 int restore_pwd;
276 /* Mode we should use for this entry; affected by _PERM and umask. */
277 mode_t mode;
278 /* UID/GID to use in restoring this entry. */
73f39d90
TK
279 int64_t uid;
280 int64_t gid;
fb67a295
MN
281 /*
282 * HFS+ Compression.
283 */
fb67a295 284 /* Xattr "com.apple.decmpfs". */
3c8570c2
MN
285 uint32_t decmpfs_attr_size;
286 unsigned char *decmpfs_header_p;
fb67a295
MN
287 /* ResourceFork set options used for fsetxattr. */
288 int rsrc_xattr_options;
289 /* Xattr "com.apple.ResourceFork". */
290 unsigned char *resource_fork;
291 size_t resource_fork_allocated_size;
292 unsigned int decmpfs_block_count;
293 uint32_t *decmpfs_block_info;
294 /* Buffer for compressed data. */
295 unsigned char *compressed_buffer;
296 size_t compressed_buffer_size;
297 size_t compressed_buffer_remaining;
298 /* The offset of the ResourceFork where compressed data will
299 * be placed. */
300 uint32_t compressed_rsrc_position;
fe61ff64 301 uint32_t compressed_rsrc_position_v;
fb67a295
MN
302 /* Buffer for uncompressed data. */
303 char *uncompressed_buffer;
304 size_t block_remaining_bytes;
305 size_t file_remaining_bytes;
306#ifdef HAVE_ZLIB_H
307 z_stream stream;
308 int stream_valid;
309 int decmpfs_compression_level;
310#endif
8f776fd9
TK
311};
312
313/*
314 * Default mode for dirs created automatically (will be modified by umask).
cafcd565 315 * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
8f776fd9
TK
316 * by the process' file creation mask."
317 */
318#define DEFAULT_DIR_MODE 0777
319/*
320 * Dir modes are restored in two steps: During the extraction, the permissions
321 * in the archive are modified to match the following limits. During
322 * the post-extract fixup pass, the permissions from the archive are
323 * applied.
324 */
325#define MINIMUM_DIR_MODE 0700
326#define MAXIMUM_DIR_MODE 0775
327
fb67a295 328/*
0b29066b 329 * Maximum uncompressed size of a decmpfs block.
fb67a295
MN
330 */
331#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
332/*
333 * HFS+ compression type.
334 */
335#define CMP_XATTR 3/* Compressed data in xattr. */
336#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */
337/*
338 * HFS+ compression resource fork.
339 */
340#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */
341#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
342/* Size to write compressed data to resource fork. */
343#define COMPRESSED_W_SIZE (64 * 1024)
0b29066b 344/* decmpfs definitions. */
3c8570c2
MN
345#define MAX_DECMPFS_XATTR_SIZE 3802
346#ifndef DECMPFS_XATTR_NAME
347#define DECMPFS_XATTR_NAME "com.apple.decmpfs"
348#endif
349#define DECMPFS_MAGIC 0x636d7066
350#define DECMPFS_COMPRESSION_MAGIC 0
351#define DECMPFS_COMPRESSION_TYPE 4
352#define DECMPFS_UNCOMPRESSED_SIZE 8
353#define DECMPFS_HEADER_SIZE 16
fb67a295 354
8f7fbd41 355#define HFS_BLOCKS(s) ((s) >> 12)
fb67a295 356
b6655592
MM
357
358static int la_opendirat(int, const char *);
b51d6b62 359static int la_mktemp(struct archive_write_disk *);
ede459d2 360static int la_verify_filetype(mode_t, __LA_MODE_T);
1bed2f31
MM
361static void fsobj_error(int *, struct archive_string *, int, const char *,
362 const char *);
363static int check_symlinks_fsobj(char *, int *, struct archive_string *,
5e646b89 364 int, int);
8f776fd9
TK
365static int check_symlinks(struct archive_write_disk *);
366static int create_filesystem_object(struct archive_write_disk *);
cc9cbbb1
MM
367static struct fixup_entry *current_fixup(struct archive_write_disk *,
368 const char *pathname);
29dfb1f6 369#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
8f776fd9
TK
370static void edit_deep_directories(struct archive_write_disk *ad);
371#endif
1bed2f31
MM
372static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
373 int);
8f776fd9
TK
374static int cleanup_pathname(struct archive_write_disk *);
375static int create_dir(struct archive_write_disk *, char *);
376static int create_parent_dir(struct archive_write_disk *, char *);
fb67a295
MN
377static ssize_t hfs_write_data_block(struct archive_write_disk *,
378 const char *, size_t);
a70241b7 379static int fixup_appledouble(struct archive_write_disk *, const char *);
8f776fd9
TK
380static int older(struct stat *, struct archive_entry *);
381static int restore_entry(struct archive_write_disk *);
b8ad1655
TK
382static int set_mac_metadata(struct archive_write_disk *, const char *,
383 const void *, size_t);
8f776fd9 384static int set_xattrs(struct archive_write_disk *);
6a595ef6 385static int clear_nochange_fflags(struct archive_write_disk *);
8f776fd9
TK
386static int set_fflags(struct archive_write_disk *);
387static int set_fflags_platform(struct archive_write_disk *, int fd,
388 const char *name, mode_t mode,
389 unsigned long fflags_set, unsigned long fflags_clear);
390static int set_ownership(struct archive_write_disk *);
391static int set_mode(struct archive_write_disk *, int mode);
82e3bb2a 392static int set_time(int, int, const char *, time_t, long, time_t, long);
21ebff3b 393static int set_times(struct archive_write_disk *, int, int, const char *,
b648c6c7 394 time_t, long, time_t, long, time_t, long, time_t, long);
5223514b 395static int set_times_from_entry(struct archive_write_disk *);
8f776fd9 396static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
5b5d1d58 397static ssize_t write_data_block(struct archive_write_disk *,
b6c8e140 398 const char *, size_t);
0cb9df7f 399static void close_file_descriptor(struct archive_write_disk *);
8f776fd9 400
911dc2bf
TK
401static int _archive_write_disk_close(struct archive *);
402static int _archive_write_disk_free(struct archive *);
cc9cbbb1
MM
403static int _archive_write_disk_header(struct archive *,
404 struct archive_entry *);
911dc2bf
TK
405static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
406static int _archive_write_disk_finish_entry(struct archive *);
cc9cbbb1
MM
407static ssize_t _archive_write_disk_data(struct archive *, const void *,
408 size_t);
409static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
410 size_t, int64_t);
8f776fd9 411
b51d6b62 412static int
413la_mktemp(struct archive_write_disk *a)
414{
415 int oerrno, fd;
416 mode_t mode;
417
418 archive_string_empty(&a->_tmpname_data);
419 archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
420 a->tmpname = a->_tmpname_data.s;
421
422 fd = __archive_mkstemp(a->tmpname);
423 if (fd == -1)
424 return -1;
425
426 mode = a->mode & 0777 & ~a->user_umask;
427 if (fchmod(fd, mode) == -1) {
428 oerrno = errno;
429 close(fd);
430 errno = oerrno;
431 return -1;
432 }
433 return fd;
434}
435
b6655592
MM
436static int
437la_opendirat(int fd, const char *path) {
438 const int flags = O_CLOEXEC
439#if defined(O_BINARY)
440 | O_BINARY
441#endif
442#if defined(O_DIRECTORY)
443 | O_DIRECTORY
444#endif
445#if defined(O_PATH)
446 | O_PATH
447#elif defined(O_SEARCH)
448 | O_SEARCH
16ad251f 449#elif defined(__FreeBSD__) && defined(O_EXEC)
b6655592
MM
450 | O_EXEC
451#else
452 | O_RDONLY
453#endif
454 ;
455
456#if !defined(HAVE_OPENAT)
457 if (fd != AT_FDCWD) {
458 errno = ENOTSUP;
459 return (-1);
460 } else
36c675a4 461 return (open(path, flags));
b6655592
MM
462#else
463 return (openat(fd, path, flags));
464#endif
465}
466
ede459d2
MM
467static int
468la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
469 int ret = 0;
470
471 switch (filetype) {
472 case AE_IFREG:
473 ret = (S_ISREG(mode));
474 break;
475 case AE_IFDIR:
476 ret = (S_ISDIR(mode));
477 break;
478 case AE_IFLNK:
479 ret = (S_ISLNK(mode));
480 break;
481 case AE_IFSOCK:
482 ret = (S_ISSOCK(mode));
483 break;
484 case AE_IFCHR:
485 ret = (S_ISCHR(mode));
486 break;
487 case AE_IFBLK:
488 ret = (S_ISBLK(mode));
489 break;
490 case AE_IFIFO:
491 ret = (S_ISFIFO(mode));
492 break;
493 default:
494 break;
495 }
496
497 return (ret);
498}
499
2f8873c2 500static int
911dc2bf 501lazy_stat(struct archive_write_disk *a)
2f8873c2
JS
502{
503 if (a->pst != NULL) {
504 /* Already have stat() data available. */
505 return (ARCHIVE_OK);
506 }
507#ifdef HAVE_FSTAT
508 if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) {
509 a->pst = &a->st;
510 return (ARCHIVE_OK);
511 }
512#endif
513 /*
514 * XXX At this point, symlinks should not be hit, otherwise
cafcd565 515 * XXX a race occurred. Do we want to check explicitly for that?
2f8873c2 516 */
e6056040 517#ifdef HAVE_LSTAT
518 if (lstat(a->name, &a->st) == 0)
519#else
520 if (la_stat(a->name, &a->st) == 0)
521#endif
522 {
2f8873c2
JS
523 a->pst = &a->st;
524 return (ARCHIVE_OK);
525 }
526 archive_set_error(&a->archive, errno, "Couldn't stat file");
527 return (ARCHIVE_WARN);
528}
529
ee99f7fc
EV
530static const struct archive_vtable
531archive_write_disk_vtable = {
532 .archive_close = _archive_write_disk_close,
533 .archive_filter_bytes = _archive_write_disk_filter_bytes,
534 .archive_free = _archive_write_disk_free,
535 .archive_write_header = _archive_write_disk_header,
536 .archive_write_finish_entry = _archive_write_disk_finish_entry,
537 .archive_write_data = _archive_write_disk_data,
538 .archive_write_data_block = _archive_write_disk_data_block,
539};
8f776fd9 540
911dc2bf
TK
541static int64_t
542_archive_write_disk_filter_bytes(struct archive *_a, int n)
543{
911dc2bf 544 struct archive_write_disk *a = (struct archive_write_disk *)_a;
0eb2fe95 545 (void)n; /* UNUSED */
911dc2bf
TK
546 if (n == -1 || n == 0)
547 return (a->total_bytes_written);
548 return (-1);
549}
550
8f776fd9
TK
551
552int
553archive_write_disk_set_options(struct archive *_a, int flags)
554{
555 struct archive_write_disk *a = (struct archive_write_disk *)_a;
556
557 a->flags = flags;
558 return (ARCHIVE_OK);
559}
560
561
562/*
563 * Extract this entry to disk.
564 *
565 * TODO: Validate hardlinks. According to the standards, we're
566 * supposed to check each extracted hardlink and squawk if it refers
567 * to a file that we didn't restore. I'm not entirely convinced this
568 * is a good idea, but more importantly: Is there any way to validate
569 * hardlinks without keeping a complete list of filenames from the
570 * entire archive?? Ugh.
571 *
572 */
573static int
911dc2bf 574_archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
8f776fd9
TK
575{
576 struct archive_write_disk *a = (struct archive_write_disk *)_a;
577 struct fixup_entry *fe;
b3073af2 578 const char *linkname;
8f776fd9
TK
579 int ret, r;
580
42c1f3e1 581 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9
TK
582 ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
583 "archive_write_disk_header");
584 archive_clear_error(&a->archive);
585 if (a->archive.state & ARCHIVE_STATE_DATA) {
911dc2bf 586 r = _archive_write_disk_finish_entry(&a->archive);
9d2e02e2 587 if (r == ARCHIVE_FATAL)
8f776fd9
TK
588 return (r);
589 }
590
591 /* Set up for this particular entry. */
592 a->pst = NULL;
593 a->current_fixup = NULL;
594 a->deferred = 0;
595 if (a->entry) {
596 archive_entry_free(a->entry);
597 a->entry = NULL;
598 }
599 a->entry = archive_entry_clone(entry);
600 a->fd = -1;
b6c8e140 601 a->fd_offset = 0;
8f776fd9 602 a->offset = 0;
fa32d137 603 a->restore_pwd = -1;
8f776fd9
TK
604 a->uid = a->user_uid;
605 a->mode = archive_entry_mode(a->entry);
5b5d1d58
TK
606 if (archive_entry_size_is_set(a->entry))
607 a->filesize = archive_entry_size(a->entry);
608 else
609 a->filesize = -1;
8f776fd9
TK
610 archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry));
611 a->name = a->_name_data.s;
612 archive_clear_error(&a->archive);
613
614 /*
615 * Clean up the requested path. This is necessary for correct
616 * dir restores; the dir restore logic otherwise gets messed
617 * up by nonsense like "dir/.".
618 */
619 ret = cleanup_pathname(a);
620 if (ret != ARCHIVE_OK)
621 return (ret);
622
b3073af2
MM
623 /*
624 * Check if we have a hardlink that points to itself.
625 */
626 linkname = archive_entry_hardlink(a->entry);
627 if (linkname != NULL && strcmp(a->name, linkname) == 0) {
628 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
629 "Skipping hardlink pointing to itself: %s",
630 a->name);
631 return (ARCHIVE_WARN);
632 }
633
8f776fd9 634 /*
efaf972d 635 * Query the umask so we get predictable mode settings.
8f776fd9
TK
636 * This gets done on every call to _write_header in case the
637 * user edits their umask during the extraction for some
efaf972d 638 * reason.
8f776fd9 639 */
efaf972d 640 umask(a->user_umask = umask(0));
8f776fd9
TK
641
642 /* Figure out what we need to do for this entry. */
643 a->todo = TODO_MODE_BASE;
644 if (a->flags & ARCHIVE_EXTRACT_PERM) {
645 a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
646 /*
647 * SGID requires an extra "check" step because we
648 * cannot easily predict the GID that the system will
649 * assign. (Different systems assign GIDs to files
650 * based on a variety of criteria, including process
651 * credentials and the gid of the enclosing
652 * directory.) We can only restore the SGID bit if
653 * the file has the right GID, and we only know the
654 * GID if we either set it (see set_ownership) or if
655 * we've actually called stat() on the file after it
656 * was restored. Since there are several places at
657 * which we might verify the GID, we need a TODO bit
658 * to keep track.
659 */
660 if (a->mode & S_ISGID)
661 a->todo |= TODO_SGID | TODO_SGID_CHECK;
662 /*
663 * Verifying the SUID is simpler, but can still be
664 * done in multiple ways, hence the separate "check" bit.
665 */
666 if (a->mode & S_ISUID)
667 a->todo |= TODO_SUID | TODO_SUID_CHECK;
668 } else {
669 /*
670 * User didn't request full permissions, so don't
671 * restore SUID, SGID bits and obey umask.
672 */
673 a->mode &= ~S_ISUID;
674 a->mode &= ~S_ISGID;
675 a->mode &= ~S_ISVTX;
676 a->mode &= ~a->user_umask;
677 }
678 if (a->flags & ARCHIVE_EXTRACT_OWNER)
679 a->todo |= TODO_OWNER;
680 if (a->flags & ARCHIVE_EXTRACT_TIME)
681 a->todo |= TODO_TIMES;
b01b4bc1 682 if (a->flags & ARCHIVE_EXTRACT_ACL) {
bea9f9cf
MM
683#if ARCHIVE_ACL_DARWIN
684 /*
685 * On MacOS, platform ACLs get stored in mac_metadata, too.
686 * If we intend to extract mac_metadata and it is present
687 * we skip extracting libarchive NFSv4 ACLs.
688 */
689 size_t metadata_size;
690
691 if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
692 archive_entry_mac_metadata(a->entry,
693 &metadata_size) == NULL || metadata_size == 0)
694#endif
695#if ARCHIVE_ACL_LIBRICHACL
696 /*
697 * RichACLs are stored in an extended attribute.
698 * If we intend to extract extended attributes and have this
699 * attribute we skip extracting libarchive NFSv4 ACLs.
700 */
701 short extract_acls = 1;
702 if (a->flags & ARCHIVE_EXTRACT_XATTR && (
703 archive_entry_acl_types(a->entry) &
704 ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
705 const char *attr_name;
706 const void *attr_value;
707 size_t attr_size;
708 int i = archive_entry_xattr_reset(a->entry);
709 while (i--) {
710 archive_entry_xattr_next(a->entry, &attr_name,
711 &attr_value, &attr_size);
712 if (attr_name != NULL && attr_value != NULL &&
713 attr_size > 0 && strcmp(attr_name,
714 "trusted.richacl") == 0) {
715 extract_acls = 0;
716 break;
717 }
718 }
719 }
720 if (extract_acls)
721#endif
722#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
723 {
724#endif
b01b4bc1
TK
725 if (archive_entry_filetype(a->entry) == AE_IFDIR)
726 a->deferred |= TODO_ACLS;
727 else
728 a->todo |= TODO_ACLS;
bea9f9cf
MM
729#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
730 }
731#endif
b01b4bc1 732 }
b8ad1655
TK
733 if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
734 if (archive_entry_filetype(a->entry) == AE_IFDIR)
735 a->deferred |= TODO_MAC_METADATA;
736 else
737 a->todo |= TODO_MAC_METADATA;
738 }
213a263c 739#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
6238bed6
MN
740 if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) {
741 unsigned long set, clear;
742 archive_entry_fflags(a->entry, &set, &clear);
743 if ((set & ~clear) & UF_COMPRESSED) {
cfb7792c 744 a->todo |= TODO_HFS_COMPRESSION;
6238bed6
MN
745 a->decmpfs_block_count = (unsigned)-1;
746 }
747 }
748 if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 &&
fb67a295 749 (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) {
cfb7792c 750 a->todo |= TODO_HFS_COMPRESSION;
fb67a295
MN
751 a->decmpfs_block_count = (unsigned)-1;
752 }
a70241b7
MN
753 {
754 const char *p;
755
756 /* Check if the current file name is a type of the
757 * resource fork file. */
758 p = strrchr(a->name, '/');
759 if (p == NULL)
760 p = a->name;
761 else
762 p++;
763 if (p[0] == '.' && p[1] == '_') {
764 /* Do not compress "._XXX" files. */
765 a->todo &= ~TODO_HFS_COMPRESSION;
766 if (a->filesize > 0)
767 a->todo |= TODO_APPLEDOUBLE;
768 }
769 }
6238bed6
MN
770#endif
771
365a91de
MM
772 if (a->flags & ARCHIVE_EXTRACT_XATTR) {
773#if ARCHIVE_XATTR_DARWIN
774 /*
775 * On MacOS, extended attributes get stored in mac_metadata,
776 * too. If we intend to extract mac_metadata and it is present
777 * we skip extracting extended attributes.
778 */
779 size_t metadata_size;
780
781 if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
782 archive_entry_mac_metadata(a->entry,
783 &metadata_size) == NULL || metadata_size == 0)
784#endif
b21f351a 785 a->todo |= TODO_XATTR;
365a91de 786 }
8f776fd9
TK
787 if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
788 a->todo |= TODO_FFLAGS;
789 if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
790 ret = check_symlinks(a);
791 if (ret != ARCHIVE_OK)
efaf972d 792 return (ret);
8f776fd9 793 }
bbb7fde3 794#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
8f776fd9
TK
795 /* If path exceeds PATH_MAX, shorten the path. */
796 edit_deep_directories(a);
797#endif
798
799 ret = restore_entry(a);
800
213a263c 801#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
cb02c0ff
MN
802 /*
803 * Check if the filesystem the file is restoring on supports
804 * HFS+ Compression. If not, cancel HFS+ Compression.
805 */
806 if (a->todo | TODO_HFS_COMPRESSION) {
807 /*
808 * NOTE: UF_COMPRESSED is ignored even if the filesystem
809 * supports HFS+ Compression because the file should
0b29066b 810 * have at least an extended attribute "com.apple.decmpfs"
cb02c0ff 811 * before the flag is set to indicate that the file have
0b29066b 812 * been compressed. If the filesystem does not support
cb02c0ff
MN
813 * HFS+ Compression the system call will fail.
814 */
815 if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
816 a->todo &= ~TODO_HFS_COMPRESSION;
817 }
818#endif
819
b21f351a 820 /*
26f63f45
TK
821 * TODO: There are rumours that some extended attributes must
822 * be restored before file data is written. If this is true,
823 * then we either need to write all extended attributes both
824 * before and after restoring the data, or find some rule for
825 * determining which must go first and which last. Due to the
826 * many ways people are using xattrs, this may prove to be an
827 * intractable problem.
b21f351a 828 */
b21f351a 829
8f776fd9
TK
830#ifdef HAVE_FCHDIR
831 /* If we changed directory above, restore it here. */
832 if (a->restore_pwd >= 0) {
b7f3d08e
TK
833 r = fchdir(a->restore_pwd);
834 if (r != 0) {
cc9cbbb1
MM
835 archive_set_error(&a->archive, errno,
836 "chdir() failure");
b7f3d08e
TK
837 ret = ARCHIVE_FATAL;
838 }
8f776fd9
TK
839 close(a->restore_pwd);
840 a->restore_pwd = -1;
841 }
842#endif
843
844 /*
845 * Fixup uses the unedited pathname from archive_entry_pathname(),
846 * because it is relative to the base dir and the edited path
847 * might be relative to some intermediate dir as a result of the
848 * deep restore logic.
849 */
850 if (a->deferred & TODO_MODE) {
851 fe = current_fixup(a, archive_entry_pathname(entry));
62756a10
MN
852 if (fe == NULL)
853 return (ARCHIVE_FATAL);
ede459d2 854 fe->filetype = archive_entry_filetype(entry);
8f776fd9
TK
855 fe->fixup |= TODO_MODE_BASE;
856 fe->mode = a->mode;
857 }
858
8e71fa72
TK
859 if ((a->deferred & TODO_TIMES)
860 && (archive_entry_mtime_is_set(entry)
0d6b5cc7 861 || archive_entry_atime_is_set(entry))) {
8f776fd9 862 fe = current_fixup(a, archive_entry_pathname(entry));
62756a10
MN
863 if (fe == NULL)
864 return (ARCHIVE_FATAL);
ede459d2 865 fe->filetype = archive_entry_filetype(entry);
5223514b 866 fe->mode = a->mode;
8f776fd9 867 fe->fixup |= TODO_TIMES;
82e3bb2a
TK
868 if (archive_entry_atime_is_set(entry)) {
869 fe->atime = archive_entry_atime(entry);
870 fe->atime_nanos = archive_entry_atime_nsec(entry);
871 } else {
872 /* If atime is unset, use start time. */
873 fe->atime = a->start_time;
874 fe->atime_nanos = 0;
875 }
8e71fa72
TK
876 if (archive_entry_mtime_is_set(entry)) {
877 fe->mtime = archive_entry_mtime(entry);
878 fe->mtime_nanos = archive_entry_mtime_nsec(entry);
879 } else {
82e3bb2a 880 /* If mtime is unset, use start time. */
f5eb945d
TK
881 fe->mtime = a->start_time;
882 fe->mtime_nanos = 0;
8e71fa72 883 }
82e3bb2a
TK
884 if (archive_entry_birthtime_is_set(entry)) {
885 fe->birthtime = archive_entry_birthtime(entry);
cc9cbbb1
MM
886 fe->birthtime_nanos = archive_entry_birthtime_nsec(
887 entry);
da0cee61 888 } else {
82e3bb2a
TK
889 /* If birthtime is unset, use mtime. */
890 fe->birthtime = fe->mtime;
891 fe->birthtime_nanos = fe->mtime_nanos;
da0cee61 892 }
8f776fd9
TK
893 }
894
b01b4bc1
TK
895 if (a->deferred & TODO_ACLS) {
896 fe = current_fixup(a, archive_entry_pathname(entry));
62756a10
MN
897 if (fe == NULL)
898 return (ARCHIVE_FATAL);
ede459d2 899 fe->filetype = archive_entry_filetype(entry);
f67370d5 900 fe->fixup |= TODO_ACLS;
b01b4bc1
TK
901 archive_acl_copy(&fe->acl, archive_entry_acl(entry));
902 }
903
b8ad1655
TK
904 if (a->deferred & TODO_MAC_METADATA) {
905 const void *metadata;
906 size_t metadata_size;
907 metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
908 if (metadata != NULL && metadata_size > 0) {
909 fe = current_fixup(a, archive_entry_pathname(entry));
62756a10
MN
910 if (fe == NULL)
911 return (ARCHIVE_FATAL);
ede459d2 912 fe->filetype = archive_entry_filetype(entry);
b8ad1655
TK
913 fe->mac_metadata = malloc(metadata_size);
914 if (fe->mac_metadata != NULL) {
cc9cbbb1
MM
915 memcpy(fe->mac_metadata, metadata,
916 metadata_size);
b8ad1655
TK
917 fe->mac_metadata_size = metadata_size;
918 fe->fixup |= TODO_MAC_METADATA;
919 }
920 }
921 }
922
8f776fd9
TK
923 if (a->deferred & TODO_FFLAGS) {
924 fe = current_fixup(a, archive_entry_pathname(entry));
62756a10
MN
925 if (fe == NULL)
926 return (ARCHIVE_FATAL);
ede459d2 927 fe->filetype = archive_entry_filetype(entry);
8f776fd9
TK
928 fe->fixup |= TODO_FFLAGS;
929 /* TODO: Complete this.. defer fflags from below. */
930 }
931
932 /* We've created the object and are ready to pour data into it. */
7d4496e9 933 if (ret >= ARCHIVE_WARN)
8f776fd9
TK
934 a->archive.state = ARCHIVE_STATE_DATA;
935 /*
936 * If it's not open, tell our client not to try writing.
937 * In particular, dirs, links, etc, don't get written to.
938 */
939 if (a->fd < 0) {
940 archive_entry_set_size(entry, 0);
941 a->filesize = 0;
942 }
8f776fd9
TK
943
944 return (ret);
945}
946
73f39d90 947int
c10875db 948archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
8f776fd9
TK
949{
950 struct archive_write_disk *a = (struct archive_write_disk *)_a;
42c1f3e1 951 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9 952 ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
7457cf54 953 a->skip_file_set = 1;
8f776fd9
TK
954 a->skip_file_dev = d;
955 a->skip_file_ino = i;
956 return (ARCHIVE_OK);
957}
958
959static ssize_t
b6c8e140 960write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
8f776fd9 961{
b6c8e140 962 uint64_t start_size = size;
8f776fd9 963 ssize_t bytes_written = 0;
5b5d1d58 964 ssize_t block_size = 0, bytes_to_write;
8f776fd9 965
398d89f6
TK
966 if (size == 0)
967 return (ARCHIVE_OK);
968
5b5d1d58
TK
969 if (a->filesize == 0 || a->fd < 0) {
970 archive_set_error(&a->archive, 0,
971 "Attempt to write to an empty file");
8f776fd9
TK
972 return (ARCHIVE_WARN);
973 }
8f776fd9 974
51300afe 975 if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
e55af97f 976#if HAVE_STRUCT_STAT_ST_BLKSIZE
5c6d3586 977 int r;
911dc2bf 978 if ((r = lazy_stat(a)) != ARCHIVE_OK)
51300afe
JS
979 return (r);
980 block_size = a->pst->st_blksize;
e55af97f
TK
981#else
982 /* XXX TODO XXX Is there a more appropriate choice here ? */
983 /* This needn't match the filesystem allocation size. */
984 block_size = 16*1024;
985#endif
8f776fd9
TK
986 }
987
b6c8e140 988 /* If this write would run beyond the file size, truncate it. */
911dc2bf 989 if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
b6c8e140 990 start_size = size = (size_t)(a->filesize - a->offset);
5b5d1d58 991
8f776fd9 992 /* Write the data. */
51300afe 993 while (size > 0) {
5b5d1d58
TK
994 if (block_size == 0) {
995 bytes_to_write = size;
996 } else {
997 /* We're sparsifying the file. */
998 const char *p, *end;
911dc2bf 999 int64_t block_end;
51300afe 1000
5b5d1d58
TK
1001 /* Skip leading zero bytes. */
1002 for (p = buff, end = buff + size; p < end; ++p) {
1003 if (*p != '\0')
51300afe
JS
1004 break;
1005 }
b6c8e140 1006 a->offset += p - buff;
5b5d1d58
TK
1007 size -= p - buff;
1008 buff = p;
51300afe
JS
1009 if (size == 0)
1010 break;
5b5d1d58
TK
1011
1012 /* Calculate next block boundary after offset. */
1013 block_end
b6c8e140 1014 = (a->offset / block_size + 1) * block_size;
5b5d1d58
TK
1015
1016 /* If the adjusted write would cross block boundary,
1017 * truncate it to the block boundary. */
51300afe 1018 bytes_to_write = size;
b6c8e140
TK
1019 if (a->offset + bytes_to_write > block_end)
1020 bytes_to_write = block_end - a->offset;
5b5d1d58 1021 }
51300afe 1022 /* Seek if necessary to the specified offset. */
b6c8e140
TK
1023 if (a->offset != a->fd_offset) {
1024 if (lseek(a->fd, a->offset, SEEK_SET) < 0) {
5b5d1d58
TK
1025 archive_set_error(&a->archive, errno,
1026 "Seek failed");
51300afe
JS
1027 return (ARCHIVE_FATAL);
1028 }
b6c8e140 1029 a->fd_offset = a->offset;
cafcd565 1030 }
5b5d1d58 1031 bytes_written = write(a->fd, buff, bytes_to_write);
8f776fd9
TK
1032 if (bytes_written < 0) {
1033 archive_set_error(&a->archive, errno, "Write failed");
1034 return (ARCHIVE_WARN);
1035 }
5b5d1d58 1036 buff += bytes_written;
8f776fd9 1037 size -= bytes_written;
911dc2bf 1038 a->total_bytes_written += bytes_written;
b6c8e140 1039 a->offset += bytes_written;
b6c8e140 1040 a->fd_offset = a->offset;
8f776fd9 1041 }
b6c8e140 1042 return (start_size - size);
5b5d1d58
TK
1043}
1044
213a263c
MN
1045#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
1046 && defined(HAVE_ZLIB_H)
fb67a295 1047
cfb7792c
MN
1048/*
1049 * Set UF_COMPRESSED file flag.
1050 * This have to be called after hfs_write_decmpfs() because if the
1051 * file does not have "com.apple.decmpfs" xattr the flag is ignored.
1052 */
1053static int
1054hfs_set_compressed_fflag(struct archive_write_disk *a)
1055{
1056 int r;
1057
1058 if ((r = lazy_stat(a)) != ARCHIVE_OK)
1059 return (r);
1060
1061 a->st.st_flags |= UF_COMPRESSED;
1062 if (fchflags(a->fd, a->st.st_flags) != 0) {
1063 archive_set_error(&a->archive, errno,
1064 "Failed to set UF_COMPRESSED file flag");
1065 return (ARCHIVE_WARN);
1066 }
1067 return (ARCHIVE_OK);
1068}
1069
fb67a295
MN
1070/*
1071 * HFS+ Compression decmpfs
1072 *
cfb7792c 1073 * +------------------------------+ +0
fb67a295
MN
1074 * | Magic(LE 4 bytes) |
1075 * +------------------------------+
1076 * | Type(LE 4 bytes) |
1077 * +------------------------------+
1078 * | Uncompressed size(LE 8 bytes)|
cfb7792c 1079 * +------------------------------+ +16
fb67a295
MN
1080 * | |
1081 * | Compressed data |
1082 * | (Placed only if Type == 3) |
1083 * | |
1084 * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE
1085 *
1086 * Type is 3: decmpfs has compressed data.
1087 * Type is 4: Resource Fork has compressed data.
1088 */
1089/*
1090 * Write "com.apple.decmpfs"
1091 */
1092static int
1093hfs_write_decmpfs(struct archive_write_disk *a)
1094{
fb67a295 1095 int r;
3c8570c2 1096 uint32_t compression_type;
fb67a295 1097
3c8570c2
MN
1098 r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p,
1099 a->decmpfs_attr_size, 0, 0);
fb67a295
MN
1100 if (r < 0) {
1101 archive_set_error(&a->archive, errno,
1102 "Cannot restore xattr:%s", DECMPFS_XATTR_NAME);
a08a9fd4
MN
1103 compression_type = archive_le32dec(
1104 &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]);
3c8570c2 1105 if (compression_type == CMP_RESOURCE_FORK)
fb67a295
MN
1106 fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME,
1107 XATTR_SHOWCOMPRESSION);
1108 return (ARCHIVE_WARN);
1109 }
1110 return (ARCHIVE_OK);
1111}
1112
1113/*
1114 * HFS+ Compression Resource Fork
1115 *
1116 * +-----------------------------+
1117 * | Header(260 bytes) |
1118 * +-----------------------------+
1119 * | Block count(LE 4 bytes) |
1120 * +-----------------------------+ --+
fe61ff64
MN
1121 * +-- | Offset (LE 4 bytes) | |
1122 * | | [distance from Block count] | | Block 0
1123 * | +-----------------------------+ |
1124 * | | Compressed size(LE 4 bytes) | |
fb67a295
MN
1125 * | +-----------------------------+ --+
1126 * | | |
1127 * | | .................. |
1128 * | | |
1129 * | +-----------------------------+ --+
fe61ff64 1130 * | | Offset (LE 4 bytes) | |
fb67a295
MN
1131 * | +-----------------------------+ | Block (Block count -1)
1132 * | | Compressed size(LE 4 bytes) | |
fe61ff64
MN
1133 * +-> +-----------------------------+ --+
1134 * | Compressed data(n bytes) | Block 0
fb67a295
MN
1135 * +-----------------------------+
1136 * | |
1137 * | .................. |
1138 * | |
1139 * +-----------------------------+
1140 * | Compressed data(n bytes) | Block (Block count -1)
1141 * +-----------------------------+
1142 * | Footer(50 bytes) |
1143 * +-----------------------------+
1144 *
1145 */
1146/*
1147 * Write the header of "com.apple.ResourceFork"
1148 */
1149static int
1150hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff,
1151 size_t bytes, uint32_t position)
1152{
1153 int ret;
1154
1155 ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes,
1156 position, a->rsrc_xattr_options);
1157 if (ret < 0) {
1158 archive_set_error(&a->archive, errno,
1159 "Cannot restore xattr: %s at %u pos %u bytes",
1160 XATTR_RESOURCEFORK_NAME,
1161 (unsigned)position,
1162 (unsigned)bytes);
1163 return (ARCHIVE_WARN);
1164 }
1165 a->rsrc_xattr_options &= ~XATTR_CREATE;
1166 return (ARCHIVE_OK);
1167}
1168
1169static int
1170hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed)
1171{
1172 int ret;
1173
1174 ret = hfs_write_resource_fork(a, a->compressed_buffer,
1175 bytes_compressed, a->compressed_rsrc_position);
1176 if (ret == ARCHIVE_OK)
1177 a->compressed_rsrc_position += bytes_compressed;
1178 return (ret);
1179}
1180
1181static int
1182hfs_write_resource_fork_header(struct archive_write_disk *a)
1183{
1184 unsigned char *buff;
1185 uint32_t rsrc_bytes;
1186 uint32_t rsrc_header_bytes;
1187
1188 /*
1189 * Write resource fork header + block info.
1190 */
1191 buff = a->resource_fork;
fe61ff64 1192 rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE;
fb67a295
MN
1193 rsrc_header_bytes =
1194 RSRC_H_SIZE + /* Header base size. */
1195 4 + /* Block count. */
1196 (a->decmpfs_block_count * 8);/* Block info */
1197 archive_be32enc(buff, 0x100);
1198 archive_be32enc(buff + 4, rsrc_bytes);
1199 archive_be32enc(buff + 8, rsrc_bytes - 256);
1200 archive_be32enc(buff + 12, 0x32);
1201 memset(buff + 16, 0, 240);
1202 archive_be32enc(buff + 256, rsrc_bytes - 260);
1203 return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0);
1204}
1205
1206static size_t
1207hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size)
1208{
1209 static const char rsrc_footer[RSRC_F_SIZE] = {
1210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm',
1214 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01,
1215 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1216 0x00, 0x00
1217 };
1218 if (buff_size < sizeof(rsrc_footer))
1219 return (0);
1220 memcpy(buff, rsrc_footer, sizeof(rsrc_footer));
1221 return (sizeof(rsrc_footer));
1222}
1223
fb67a295
MN
1224static int
1225hfs_reset_compressor(struct archive_write_disk *a)
1226{
1227 int ret;
1228
1229 if (a->stream_valid)
1230 ret = deflateReset(&a->stream);
1231 else
1232 ret = deflateInit(&a->stream, a->decmpfs_compression_level);
1233
1234 if (ret != Z_OK) {
1235 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1236 "Failed to initialize compressor");
1237 return (ARCHIVE_FATAL);
1238 } else
1239 a->stream_valid = 1;
1240
1241 return (ARCHIVE_OK);
1242}
1243
8f7fbd41
MN
1244static int
1245hfs_decompress(struct archive_write_disk *a)
1246{
1247 uint32_t *block_info;
1248 unsigned int block_count;
1249 uint32_t data_pos, data_size;
1250 ssize_t r;
1251 ssize_t bytes_written, bytes_to_write;
1252 unsigned char *b;
1253
1254 block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
1255 block_count = archive_le32dec(block_info++);
1256 while (block_count--) {
1257 data_pos = RSRC_H_SIZE + archive_le32dec(block_info++);
1258 data_size = archive_le32dec(block_info++);
1259 r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME,
1260 a->compressed_buffer, data_size, data_pos, 0);
1261 if (r != data_size) {
1262 archive_set_error(&a->archive,
1263 (r < 0)?errno:ARCHIVE_ERRNO_MISC,
1264 "Failed to read resource fork");
1265 return (ARCHIVE_WARN);
1266 }
1267 if (a->compressed_buffer[0] == 0xff) {
1268 bytes_to_write = data_size -1;
1269 b = a->compressed_buffer + 1;
1270 } else {
1271 uLong dest_len = MAX_DECMPFS_BLOCK_SIZE;
1272 int zr;
1273
1274 zr = uncompress((Bytef *)a->uncompressed_buffer,
1275 &dest_len, a->compressed_buffer, data_size);
1276 if (zr != Z_OK) {
1277 archive_set_error(&a->archive,
1278 ARCHIVE_ERRNO_MISC,
1279 "Failed to decompress resource fork");
1280 return (ARCHIVE_WARN);
1281 }
1282 bytes_to_write = dest_len;
1283 b = (unsigned char *)a->uncompressed_buffer;
1284 }
1285 do {
1286 bytes_written = write(a->fd, b, bytes_to_write);
1287 if (bytes_written < 0) {
1288 archive_set_error(&a->archive, errno,
1289 "Write failed");
1290 return (ARCHIVE_WARN);
1291 }
1292 bytes_to_write -= bytes_written;
1293 b += bytes_written;
1294 } while (bytes_to_write > 0);
1295 }
1296 r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0);
1297 if (r == -1) {
1298 archive_set_error(&a->archive, errno,
1299 "Failed to remove resource fork");
1300 return (ARCHIVE_WARN);
1301 }
1302 return (ARCHIVE_OK);
1303}
1304
fb67a295
MN
1305static int
1306hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
1307 size_t size)
1308{
1309 unsigned char *buffer_compressed;
1310 size_t bytes_compressed;
a08a9fd4 1311 size_t bytes_used;
fb67a295
MN
1312 int ret;
1313
1314 ret = hfs_reset_compressor(a);
1315 if (ret != ARCHIVE_OK)
1316 return (ret);
1317
1318 if (a->compressed_buffer == NULL) {
1319 size_t block_size;
1320
1321 block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE +
1322 + compressBound(MAX_DECMPFS_BLOCK_SIZE);
1323 a->compressed_buffer = malloc(block_size);
1324 if (a->compressed_buffer == NULL) {
1325 archive_set_error(&a->archive, ENOMEM,
1326 "Can't allocate memory for Resource Fork");
1327 return (ARCHIVE_FATAL);
1328 }
1329 a->compressed_buffer_size = block_size;
1330 a->compressed_buffer_remaining = block_size;
1331 }
1332
1333 buffer_compressed = a->compressed_buffer +
1334 a->compressed_buffer_size - a->compressed_buffer_remaining;
1335 a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff;
1336 a->stream.avail_in = size;
1337 a->stream.next_out = buffer_compressed;
1338 a->stream.avail_out = a->compressed_buffer_remaining;
1339 do {
1340 ret = deflate(&a->stream, Z_FINISH);
1341 switch (ret) {
1342 case Z_OK:
1343 case Z_STREAM_END:
1344 break;
1345 default:
1346 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1347 "Failed to compress data");
1348 return (ARCHIVE_FAILED);
1349 }
1350 } while (ret == Z_OK);
1351 bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out;
1352
1353 /*
1354 * If the compressed size is larger than the original size,
1355 * throw away compressed data, use uncompressed data instead.
1356 */
1357 if (bytes_compressed > size) {
1358 buffer_compressed[0] = 0xFF;/* uncompressed marker. */
1359 memcpy(buffer_compressed + 1, buff, size);
1360 bytes_compressed = size + 1;
1361 }
1362 a->compressed_buffer_remaining -= bytes_compressed;
1363
1364 /*
1365 * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE
1366 * and the block count in the file is only one, store compressed
1367 * data to decmpfs xattr instead of the resource fork.
1368 */
1369 if (a->decmpfs_block_count == 1 &&
3c8570c2 1370 (a->decmpfs_attr_size + bytes_compressed)
fb67a295 1371 <= MAX_DECMPFS_XATTR_SIZE) {
a08a9fd4
MN
1372 archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
1373 CMP_XATTR);
3c8570c2 1374 memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE,
fb67a295 1375 buffer_compressed, bytes_compressed);
3c8570c2 1376 a->decmpfs_attr_size += bytes_compressed;
a08a9fd4 1377 a->compressed_buffer_remaining = a->compressed_buffer_size;
fb67a295 1378 /*
cfb7792c
MN
1379 * Finish HFS+ Compression.
1380 * - Write the decmpfs xattr.
1381 * - Set the UF_COMPRESSED file flag.
fb67a295 1382 */
cfb7792c
MN
1383 ret = hfs_write_decmpfs(a);
1384 if (ret == ARCHIVE_OK)
1385 ret = hfs_set_compressed_fflag(a);
1386 return (ret);
fb67a295
MN
1387 }
1388
1389 /* Update block info. */
fe61ff64
MN
1390 archive_le32enc(a->decmpfs_block_info++,
1391 a->compressed_rsrc_position_v - RSRC_H_SIZE);
fb67a295 1392 archive_le32enc(a->decmpfs_block_info++, bytes_compressed);
fe61ff64 1393 a->compressed_rsrc_position_v += bytes_compressed;
fb67a295 1394
fb67a295
MN
1395 /*
1396 * Write the compressed data to the resource fork.
1397 */
a08a9fd4
MN
1398 bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining;
1399 while (bytes_used >= COMPRESSED_W_SIZE) {
1400 ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE);
1401 if (ret != ARCHIVE_OK)
1402 return (ret);
1403 bytes_used -= COMPRESSED_W_SIZE;
1404 if (bytes_used > COMPRESSED_W_SIZE)
1405 memmove(a->compressed_buffer,
1406 a->compressed_buffer + COMPRESSED_W_SIZE,
1407 bytes_used);
1408 else
1409 memcpy(a->compressed_buffer,
1410 a->compressed_buffer + COMPRESSED_W_SIZE,
1411 bytes_used);
1412 }
1413 a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used;
1414
1415 /*
1416 * If the current block is the last block, write the remaining
1417 * compressed data and the resource fork footer.
1418 */
fb67a295
MN
1419 if (a->file_remaining_bytes == 0) {
1420 size_t rsrc_size;
8f7fbd41 1421 int64_t bk;
fb67a295 1422
a08a9fd4 1423 /* Append the resource footer. */
fb67a295 1424 rsrc_size = hfs_set_resource_fork_footer(
1fd95bd6 1425 a->compressed_buffer + bytes_used,
fb67a295 1426 a->compressed_buffer_remaining);
a08a9fd4 1427 ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
fb67a295 1428 a->compressed_buffer_remaining = a->compressed_buffer_size;
8f7fbd41 1429
0b29066b 1430 /* If the compressed size is not enough smaller than
8f7fbd41
MN
1431 * the uncompressed size. cancel HFS+ compression.
1432 * TODO: study a behavior of ditto utility and improve
1433 * the condition to fall back into no HFS+ compression. */
1434 bk = HFS_BLOCKS(a->compressed_rsrc_position);
1435 bk += bk >> 7;
1436 if (bk > HFS_BLOCKS(a->filesize))
1437 return hfs_decompress(a);
fb67a295
MN
1438 /*
1439 * Write the resourcefork header.
1440 */
1441 if (ret == ARCHIVE_OK)
1442 ret = hfs_write_resource_fork_header(a);
1443 /*
cfb7792c
MN
1444 * Finish HFS+ Compression.
1445 * - Write the decmpfs xattr.
1446 * - Set the UF_COMPRESSED file flag.
fb67a295
MN
1447 */
1448 if (ret == ARCHIVE_OK)
1449 ret = hfs_write_decmpfs(a);
cfb7792c
MN
1450 if (ret == ARCHIVE_OK)
1451 ret = hfs_set_compressed_fflag(a);
fb67a295
MN
1452 }
1453 return (ret);
1454}
1455
1456static ssize_t
1457hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
1458 size_t size)
1459{
1460 const char *buffer_to_write;
1461 size_t bytes_to_write;
1462 int ret;
1463
1464 if (a->decmpfs_block_count == (unsigned)-1) {
1465 void *new_block;
1466 size_t new_size;
aed6038c 1467 unsigned int block_count;
fb67a295
MN
1468
1469 if (a->decmpfs_header_p == NULL) {
1470 new_block = malloc(MAX_DECMPFS_XATTR_SIZE
1471 + sizeof(uint32_t));
1472 if (new_block == NULL) {
1473 archive_set_error(&a->archive, ENOMEM,
1474 "Can't allocate memory for decmpfs");
1475 return (ARCHIVE_FATAL);
1476 }
1477 a->decmpfs_header_p = new_block;
1478 }
3c8570c2 1479 a->decmpfs_attr_size = DECMPFS_HEADER_SIZE;
a08a9fd4
MN
1480 archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC],
1481 DECMPFS_MAGIC);
1482 archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
1483 CMP_RESOURCE_FORK);
1484 archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE],
1485 a->filesize);
fb67a295
MN
1486
1487 /* Calculate a block count of the file. */
aed6038c 1488 block_count =
fb67a295
MN
1489 (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) /
1490 MAX_DECMPFS_BLOCK_SIZE;
fb67a295
MN
1491 /*
1492 * Allocate buffer for resource fork.
1493 * Set up related pointers;
1494 */
1495 new_size =
1496 RSRC_H_SIZE + /* header */
1497 4 + /* Block count */
aed6038c 1498 (block_count * sizeof(uint32_t) * 2) +
fb67a295
MN
1499 RSRC_F_SIZE; /* footer */
1500 if (new_size > a->resource_fork_allocated_size) {
1501 new_block = realloc(a->resource_fork, new_size);
1502 if (new_block == NULL) {
1503 archive_set_error(&a->archive, ENOMEM,
1504 "Can't allocate memory for ResourceFork");
1505 return (ARCHIVE_FATAL);
1506 }
1507 a->resource_fork_allocated_size = new_size;
1508 a->resource_fork = new_block;
1509 }
1510
1511 /* Allocate uncompressed buffer */
1512 if (a->uncompressed_buffer == NULL) {
1513 new_block = malloc(MAX_DECMPFS_BLOCK_SIZE);
1514 if (new_block == NULL) {
1515 archive_set_error(&a->archive, ENOMEM,
1516 "Can't allocate memory for decmpfs");
1517 return (ARCHIVE_FATAL);
1518 }
1519 a->uncompressed_buffer = new_block;
1520 }
1521 a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
1522 a->file_remaining_bytes = a->filesize;
a08a9fd4 1523 a->compressed_buffer_remaining = a->compressed_buffer_size;
fb67a295
MN
1524
1525 /*
1526 * Set up a resource fork.
1527 */
fb67a295
MN
1528 a->rsrc_xattr_options = XATTR_CREATE;
1529 /* Get the position where we are going to set a bunch
1530 * of block info. */
1531 a->decmpfs_block_info =
1532 (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
1533 /* Set the block count to the resource fork. */
aed6038c 1534 archive_le32enc(a->decmpfs_block_info++, block_count);
0b29066b 1535 /* Get the position where we are going to set compressed
fb67a295
MN
1536 * data. */
1537 a->compressed_rsrc_position =
aed6038c 1538 RSRC_H_SIZE + 4 + (block_count * 8);
fe61ff64 1539 a->compressed_rsrc_position_v = a->compressed_rsrc_position;
aed6038c 1540 a->decmpfs_block_count = block_count;
fb67a295
MN
1541 }
1542
1543 /* Ignore redundant bytes. */
1544 if (a->file_remaining_bytes == 0)
1545 return ((ssize_t)size);
1546
1547 /* Do not overrun a block size. */
1548 if (size > a->block_remaining_bytes)
1549 bytes_to_write = a->block_remaining_bytes;
1550 else
1551 bytes_to_write = size;
1552 /* Do not overrun the file size. */
1553 if (bytes_to_write > a->file_remaining_bytes)
1554 bytes_to_write = a->file_remaining_bytes;
1555
1556 /* For efficiency, if a copy length is full of the uncompressed
1557 * buffer size, do not copy writing data to it. */
1558 if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE)
1559 buffer_to_write = buff;
1560 else {
1561 memcpy(a->uncompressed_buffer +
1562 MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes,
1563 buff, bytes_to_write);
1564 buffer_to_write = a->uncompressed_buffer;
1565 }
1566 a->block_remaining_bytes -= bytes_to_write;
1567 a->file_remaining_bytes -= bytes_to_write;
1568
1569 if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) {
1570 ret = hfs_drive_compressor(a, buffer_to_write,
1571 MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes);
1572 if (ret < 0)
1573 return (ret);
1574 a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
1575 }
1576 /* Ignore redundant bytes. */
1577 if (a->file_remaining_bytes == 0)
1578 return ((ssize_t)size);
1579 return (bytes_to_write);
1580}
1581
1582static ssize_t
1583hfs_write_data_block(struct archive_write_disk *a, const char *buff,
1584 size_t size)
1585{
1586 uint64_t start_size = size;
1587 ssize_t bytes_written = 0;
1588 ssize_t bytes_to_write;
1589
1590 if (size == 0)
1591 return (ARCHIVE_OK);
1592
1593 if (a->filesize == 0 || a->fd < 0) {
1594 archive_set_error(&a->archive, 0,
1595 "Attempt to write to an empty file");
1596 return (ARCHIVE_WARN);
1597 }
1598
1599 /* If this write would run beyond the file size, truncate it. */
1600 if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
1601 start_size = size = (size_t)(a->filesize - a->offset);
1602
1603 /* Write the data. */
1604 while (size > 0) {
1605 bytes_to_write = size;
1606 /* Seek if necessary to the specified offset. */
1607 if (a->offset < a->fd_offset) {
0b29066b 1608 /* Can't support backward move. */
fb67a295
MN
1609 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1610 "Seek failed");
1611 return (ARCHIVE_FATAL);
1612 } else if (a->offset > a->fd_offset) {
e7b2ab7a 1613 uint64_t skip = a->offset - a->fd_offset;
fb67a295
MN
1614 char nullblock[1024];
1615
1616 memset(nullblock, 0, sizeof(nullblock));
1617 while (skip > 0) {
e7b2ab7a 1618 if (skip > sizeof(nullblock))
fb67a295
MN
1619 bytes_written = hfs_write_decmpfs_block(
1620 a, nullblock, sizeof(nullblock));
1621 else
1622 bytes_written = hfs_write_decmpfs_block(
1623 a, nullblock, skip);
1624 if (bytes_written < 0) {
1625 archive_set_error(&a->archive, errno,
1626 "Write failed");
1627 return (ARCHIVE_WARN);
1628 }
1629 skip -= bytes_written;
1630 }
1631
1632 a->fd_offset = a->offset;
1633 }
1634 bytes_written =
1635 hfs_write_decmpfs_block(a, buff, bytes_to_write);
1636 if (bytes_written < 0)
1637 return (bytes_written);
1638 buff += bytes_written;
1639 size -= bytes_written;
1640 a->total_bytes_written += bytes_written;
1641 a->offset += bytes_written;
1642 a->fd_offset = a->offset;
1643 }
1644 return (start_size - size);
1645}
1646#else
1647static ssize_t
1648hfs_write_data_block(struct archive_write_disk *a, const char *buff,
1649 size_t size)
1650{
1651 return (write_data_block(a, buff, size));
1652}
1653#endif
1654
5b5d1d58 1655static ssize_t
911dc2bf 1656_archive_write_disk_data_block(struct archive *_a,
73f39d90 1657 const void *buff, size_t size, int64_t offset)
5b5d1d58
TK
1658{
1659 struct archive_write_disk *a = (struct archive_write_disk *)_a;
1660 ssize_t r;
1661
42c1f3e1 1662 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
911dc2bf 1663 ARCHIVE_STATE_DATA, "archive_write_data_block");
5b5d1d58 1664
b6c8e140 1665 a->offset = offset;
fb67a295
MN
1666 if (a->todo & TODO_HFS_COMPRESSION)
1667 r = hfs_write_data_block(a, buff, size);
1668 else
1669 r = write_data_block(a, buff, size);
b6c8e140 1670 if (r < ARCHIVE_OK)
5b5d1d58
TK
1671 return (r);
1672 if ((size_t)r < size) {
1673 archive_set_error(&a->archive, 0,
cc9cbbb1
MM
1674 "Too much data: Truncating file at %ju bytes",
1675 (uintmax_t)a->filesize);
5b5d1d58
TK
1676 return (ARCHIVE_WARN);
1677 }
a654d8a0 1678#if ARCHIVE_VERSION_NUMBER < 3999000
5b5d1d58 1679 return (ARCHIVE_OK);
a654d8a0
TK
1680#else
1681 return (size);
1682#endif
8f776fd9
TK
1683}
1684
1685static ssize_t
911dc2bf 1686_archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
8f776fd9
TK
1687{
1688 struct archive_write_disk *a = (struct archive_write_disk *)_a;
8f776fd9 1689
42c1f3e1 1690 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9 1691 ARCHIVE_STATE_DATA, "archive_write_data");
8f776fd9 1692
fb67a295
MN
1693 if (a->todo & TODO_HFS_COMPRESSION)
1694 return (hfs_write_data_block(a, buff, size));
b6c8e140 1695 return (write_data_block(a, buff, size));
8f776fd9
TK
1696}
1697
1698static int
911dc2bf 1699_archive_write_disk_finish_entry(struct archive *_a)
8f776fd9
TK
1700{
1701 struct archive_write_disk *a = (struct archive_write_disk *)_a;
1702 int ret = ARCHIVE_OK;
1703
42c1f3e1 1704 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9
TK
1705 ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1706 "archive_write_finish_entry");
1707 if (a->archive.state & ARCHIVE_STATE_HEADER)
1708 return (ARCHIVE_OK);
1709 archive_clear_error(&a->archive);
1710
5b5d1d58
TK
1711 /* Pad or truncate file to the right size. */
1712 if (a->fd < 0) {
1713 /* There's no file. */
1714 } else if (a->filesize < 0) {
1715 /* File size is unknown, so we can't set the size. */
b6c8e140 1716 } else if (a->fd_offset == a->filesize) {
5b5d1d58
TK
1717 /* Last write ended at exactly the filesize; we're done. */
1718 /* Hopefully, this is the common case. */
213a263c 1719#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
fb67a295
MN
1720 } else if (a->todo & TODO_HFS_COMPRESSION) {
1721 char null_d[1024];
1722 ssize_t r;
1723
1724 if (a->file_remaining_bytes)
1725 memset(null_d, 0, sizeof(null_d));
1726 while (a->file_remaining_bytes) {
1727 if (a->file_remaining_bytes > sizeof(null_d))
1728 r = hfs_write_data_block(
1729 a, null_d, sizeof(null_d));
1730 else
1731 r = hfs_write_data_block(
1732 a, null_d, a->file_remaining_bytes);
e7b2ab7a 1733 if (r < 0) {
092631ce 1734 close_file_descriptor(a);
fb67a295 1735 return ((int)r);
e7b2ab7a 1736 }
fb67a295
MN
1737 }
1738#endif
5b5d1d58 1739 } else {
e55af97f 1740#if HAVE_FTRUNCATE
beca31d2
JS
1741 if (ftruncate(a->fd, a->filesize) == -1 &&
1742 a->filesize == 0) {
51300afe 1743 archive_set_error(&a->archive, errno,
beca31d2 1744 "File size could not be restored");
092631ce 1745 close_file_descriptor(a);
51300afe
JS
1746 return (ARCHIVE_FAILED);
1747 }
e55af97f 1748#endif
beca31d2 1749 /*
95cfd8e4
TK
1750 * Not all platforms implement the XSI option to
1751 * extend files via ftruncate. Stat() the file again
1752 * to see what happened.
beca31d2 1753 */
51300afe 1754 a->pst = NULL;
f030f3ff
SG
1755 if ((ret = lazy_stat(a)) != ARCHIVE_OK) {
1756 close_file_descriptor(a);
1757 return (ret);
1758 }
95cfd8e4
TK
1759 /* We can use lseek()/write() to extend the file if
1760 * ftruncate didn't work or isn't available. */
1761 if (a->st.st_size < a->filesize) {
beca31d2 1762 const char nul = '\0';
95cfd8e4 1763 if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
beca31d2
JS
1764 archive_set_error(&a->archive, errno,
1765 "Seek failed");
092631ce 1766 close_file_descriptor(a);
beca31d2
JS
1767 return (ARCHIVE_FATAL);
1768 }
1769 if (write(a->fd, &nul, 1) < 0) {
1770 archive_set_error(&a->archive, errno,
1771 "Write to restore size failed");
092631ce 1772 close_file_descriptor(a);
beca31d2
JS
1773 return (ARCHIVE_FATAL);
1774 }
1775 a->pst = NULL;
1776 }
51300afe
JS
1777 }
1778
8f776fd9
TK
1779 /* Restore metadata. */
1780
a70241b7
MN
1781 /*
1782 * This is specific to Mac OS X.
1783 * If the current file is an AppleDouble file, it should be
1784 * linked with the data fork file and remove it.
1785 */
1786 if (a->todo & TODO_APPLEDOUBLE) {
1787 int r2 = fixup_appledouble(a, a->name);
1788 if (r2 == ARCHIVE_EOF) {
1789 /* The current file has been successfully linked
1790 * with the data fork file and removed. So there
1791 * is nothing to do on the current file. */
1792 goto finish_metadata;
1793 }
1794 if (r2 < ret) ret = r2;
1795 }
1796
8f776fd9 1797 /*
71362fca
TK
1798 * Look up the "real" UID only if we're going to need it.
1799 * TODO: the TODO_SGID condition can be dropped here, can't it?
8f776fd9
TK
1800 */
1801 if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
f4f791ea 1802 a->uid = archive_write_disk_uid(&a->archive,
8f776fd9
TK
1803 archive_entry_uname(a->entry),
1804 archive_entry_uid(a->entry));
1805 }
1806 /* Look up the "real" GID only if we're going to need it. */
71362fca 1807 /* TODO: the TODO_SUID condition can be dropped here, can't it? */
8f776fd9 1808 if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
f4f791ea 1809 a->gid = archive_write_disk_gid(&a->archive,
8f776fd9
TK
1810 archive_entry_gname(a->entry),
1811 archive_entry_gid(a->entry));
1812 }
2f3c9ee6 1813
8f776fd9 1814 /*
2f3c9ee6 1815 * Restore ownership before set_mode tries to restore suid/sgid
8f776fd9
TK
1816 * bits. If we set the owner, we know what it is and can skip
1817 * a stat() call to examine the ownership of the file on disk.
1818 */
a70241b7
MN
1819 if (a->todo & TODO_OWNER) {
1820 int r2 = set_ownership(a);
1821 if (r2 < ret) ret = r2;
1822 }
5a796cc6 1823
ad58bd61 1824 /*
5a796cc6
EB
1825 * HYPOTHESIS:
1826 * If we're not root, we won't be setting any security
1827 * attributes that may be wiped by the set_mode() routine
1828 * below. We also can't set xattr on non-owner-writable files,
1829 * which may be the state after set_mode(). Perform
1830 * set_xattrs() first based on these constraints.
ad58bd61 1831 */
d30a8faa
EB
1832 if (a->user_uid != 0 &&
1833 (a->todo & TODO_XATTR)) {
ad58bd61
EB
1834 int r2 = set_xattrs(a);
1835 if (r2 < ret) ret = r2;
1836 }
2f3c9ee6
TK
1837
1838 /*
1839 * set_mode must precede ACLs on systems such as Solaris and
1840 * FreeBSD where setting the mode implicitly clears extended ACLs
1841 */
8f776fd9
TK
1842 if (a->todo & TODO_MODE) {
1843 int r2 = set_mode(a, a->mode);
1844 if (r2 < ret) ret = r2;
1845 }
26f63f45
TK
1846
1847 /*
1848 * Security-related extended attributes (such as
1849 * security.capability on Linux) have to be restored last,
1850 * since they're implicitly removed by other file changes.
5a796cc6 1851 * We do this last only when root.
26f63f45 1852 */
d30a8faa
EB
1853 if (a->user_uid == 0 &&
1854 (a->todo & TODO_XATTR)) {
26f63f45
TK
1855 int r2 = set_xattrs(a);
1856 if (r2 < ret) ret = r2;
1857 }
1858
b21f351a
TK
1859 /*
1860 * Some flags prevent file modification; they must be restored after
1861 * file contents are written.
1862 */
8f776fd9
TK
1863 if (a->todo & TODO_FFLAGS) {
1864 int r2 = set_fflags(a);
1865 if (r2 < ret) ret = r2;
1866 }
b8ad1655 1867
b21f351a 1868 /*
2f3c9ee6 1869 * Time must follow most other metadata;
b21f351a
TK
1870 * otherwise atime will get changed.
1871 */
d583bb4e 1872 if (a->todo & TODO_TIMES) {
5223514b 1873 int r2 = set_times_from_entry(a);
d583bb4e
TK
1874 if (r2 < ret) ret = r2;
1875 }
8f776fd9 1876
b8ad1655
TK
1877 /*
1878 * Mac extended metadata includes ACLs.
1879 */
1880 if (a->todo & TODO_MAC_METADATA) {
1881 const void *metadata;
1882 size_t metadata_size;
1883 metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
1884 if (metadata != NULL && metadata_size > 0) {
a70241b7
MN
1885 int r2 = set_mac_metadata(a, archive_entry_pathname(
1886 a->entry), metadata, metadata_size);
b8ad1655
TK
1887 if (r2 < ret) ret = r2;
1888 }
1889 }
1890
21ebff3b
TK
1891 /*
1892 * ACLs must be restored after timestamps because there are
1893 * ACLs that prevent attribute changes (including time).
1894 */
1895 if (a->todo & TODO_ACLS) {
9f43a7d6 1896 int r2;
9f43a7d6
MM
1897 r2 = archive_write_disk_set_acls(&a->archive, a->fd,
1898 archive_entry_pathname(a->entry),
bea9f9cf
MM
1899 archive_entry_acl(a->entry),
1900 archive_entry_mode(a->entry));
21ebff3b
TK
1901 if (r2 < ret) ret = r2;
1902 }
1903
a70241b7 1904finish_metadata:
8f776fd9
TK
1905 /* If there's an fd, we can close it now. */
1906 if (a->fd >= 0) {
1907 close(a->fd);
1908 a->fd = -1;
b51d6b62 1909 if (a->tmpname) {
1910 if (rename(a->tmpname, a->name) == -1) {
1911 archive_set_error(&a->archive, errno,
f001f3b0
MM
1912 "Failed to rename temporary file");
1913 ret = ARCHIVE_FAILED;
1914 unlink(a->tmpname);
b51d6b62 1915 }
1916 a->tmpname = NULL;
1917 }
8f776fd9
TK
1918 }
1919 /* If there's an entry, we can release it now. */
4736e4e7
ME
1920 archive_entry_free(a->entry);
1921 a->entry = NULL;
8f776fd9
TK
1922 a->archive.state = ARCHIVE_STATE_HEADER;
1923 return (ret);
1924}
1925
73f39d90
TK
1926int
1927archive_write_disk_set_group_lookup(struct archive *_a,
1928 void *private_data,
c10875db 1929 la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
73f39d90 1930 void (*cleanup_gid)(void *private))
8f776fd9
TK
1931{
1932 struct archive_write_disk *a = (struct archive_write_disk *)_a;
42c1f3e1 1933 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9
TK
1934 ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
1935
f4f791ea
TK
1936 if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
1937 (a->cleanup_gid)(a->lookup_gid_data);
1938
8f776fd9
TK
1939 a->lookup_gid = lookup_gid;
1940 a->cleanup_gid = cleanup_gid;
1941 a->lookup_gid_data = private_data;
1942 return (ARCHIVE_OK);
1943}
1944
73f39d90
TK
1945int
1946archive_write_disk_set_user_lookup(struct archive *_a,
1947 void *private_data,
1948 int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid),
1949 void (*cleanup_uid)(void *private))
8f776fd9
TK
1950{
1951 struct archive_write_disk *a = (struct archive_write_disk *)_a;
42c1f3e1 1952 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9
TK
1953 ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
1954
f4f791ea
TK
1955 if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
1956 (a->cleanup_uid)(a->lookup_uid_data);
1957
8f776fd9
TK
1958 a->lookup_uid = lookup_uid;
1959 a->cleanup_uid = cleanup_uid;
1960 a->lookup_uid_data = private_data;
1961 return (ARCHIVE_OK);
1962}
1963
f4f791ea 1964int64_t
c10875db 1965archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
f4f791ea
TK
1966{
1967 struct archive_write_disk *a = (struct archive_write_disk *)_a;
1968 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1969 ARCHIVE_STATE_ANY, "archive_write_disk_gid");
1970 if (a->lookup_gid)
1971 return (a->lookup_gid)(a->lookup_gid_data, name, id);
1972 return (id);
1973}
1974
1975int64_t
c10875db 1976archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
f4f791ea 1977{
f67370d5
TK
1978 struct archive_write_disk *a = (struct archive_write_disk *)_a;
1979 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1980 ARCHIVE_STATE_ANY, "archive_write_disk_uid");
1981 if (a->lookup_uid)
1982 return (a->lookup_uid)(a->lookup_uid_data, name, id);
1983 return (id);
f4f791ea 1984}
8f776fd9
TK
1985
1986/*
1987 * Create a new archive_write_disk object and initialize it with global state.
1988 */
1989struct archive *
1990archive_write_disk_new(void)
1991{
1992 struct archive_write_disk *a;
1993
72abdbb8 1994 a = (struct archive_write_disk *)calloc(1, sizeof(*a));
8f776fd9
TK
1995 if (a == NULL)
1996 return (NULL);
8f776fd9
TK
1997 a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
1998 /* We're ready to write a header immediately. */
1999 a->archive.state = ARCHIVE_STATE_HEADER;
ee99f7fc 2000 a->archive.vtable = &archive_write_disk_vtable;
da0cee61 2001 a->start_time = time(NULL);
efaf972d
TK
2002 /* Query and restore the umask. */
2003 umask(a->user_umask = umask(0));
8f776fd9
TK
2004#ifdef HAVE_GETEUID
2005 a->user_uid = geteuid();
2006#endif /* HAVE_GETEUID */
2007 if (archive_string_ensure(&a->path_safe, 512) == NULL) {
2008 free(a);
2009 return (NULL);
2010 }
0483f5d6
EO
2011 a->path_safe.s[0] = 0;
2012
fb67a295 2013#ifdef HAVE_ZLIB_H
fe61ff64 2014 a->decmpfs_compression_level = 5;
fb67a295 2015#endif
8f776fd9
TK
2016 return (&a->archive);
2017}
2018
2019
2020/*
2021 * If pathname is longer than PATH_MAX, chdir to a suitable
2022 * intermediate dir and edit the path down to a shorter suffix. Note
2023 * that this routine never returns an error; if the chdir() attempt
2024 * fails for any reason, we just go ahead with the long pathname. The
2025 * object creation is likely to fail, but any error will get handled
2026 * at that time.
2027 */
bbb7fde3 2028#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
8f776fd9
TK
2029static void
2030edit_deep_directories(struct archive_write_disk *a)
2031{
2032 int ret;
2033 char *tail = a->name;
2034
8f776fd9 2035 /* If path is short, avoid the open() below. */
dc1882e4 2036 if (strlen(tail) < PATH_MAX)
8f776fd9
TK
2037 return;
2038
2039 /* Try to record our starting dir. */
6d520405 2040 a->restore_pwd = la_opendirat(AT_FDCWD, ".");
60141df1 2041 __archive_ensure_cloexec_flag(a->restore_pwd);
8f776fd9
TK
2042 if (a->restore_pwd < 0)
2043 return;
2044
2045 /* As long as the path is too long... */
dc1882e4 2046 while (strlen(tail) >= PATH_MAX) {
8f776fd9
TK
2047 /* Locate a dir prefix shorter than PATH_MAX. */
2048 tail += PATH_MAX - 8;
2049 while (tail > a->name && *tail != '/')
2050 tail--;
2051 /* Exit if we find a too-long path component. */
2052 if (tail <= a->name)
2053 return;
2054 /* Create the intermediate dir and chdir to it. */
2055 *tail = '\0'; /* Terminate dir portion */
2056 ret = create_dir(a, a->name);
2057 if (ret == ARCHIVE_OK && chdir(a->name) != 0)
7d4496e9 2058 ret = ARCHIVE_FAILED;
8f776fd9
TK
2059 *tail = '/'; /* Restore the / we removed. */
2060 if (ret != ARCHIVE_OK)
2061 return;
2062 tail++;
2063 /* The chdir() succeeded; we've now shortened the path. */
2064 a->name = tail;
2065 }
2066 return;
2067}
2068#endif
2069
2070/*
2071 * The main restore function.
2072 */
2073static int
2074restore_entry(struct archive_write_disk *a)
2075{
2076 int ret = ARCHIVE_OK, en;
2077
2078 if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
2079 /*
2080 * TODO: Fix this. Apparently, there are platforms
2081 * that still allow root to hose the entire filesystem
2082 * by unlinking a dir. The S_ISDIR() test above
2083 * prevents us from using unlink() here if the new
2084 * object is a dir, but that doesn't mean the old
2085 * object isn't a dir.
2086 */
6a595ef6
BD
2087 if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
2088 (void)clear_nochange_fflags(a);
8f776fd9 2089 if (unlink(a->name) == 0) {
2f8873c2
JS
2090 /* We removed it, reset cached stat. */
2091 a->pst = NULL;
8f776fd9
TK
2092 } else if (errno == ENOENT) {
2093 /* File didn't exist, that's just as good. */
2094 } else if (rmdir(a->name) == 0) {
2095 /* It was a dir, but now it's gone. */
2f8873c2 2096 a->pst = NULL;
8f776fd9
TK
2097 } else {
2098 /* We tried, but couldn't get rid of it. */
2099 archive_set_error(&a->archive, errno,
2100 "Could not unlink");
7d4496e9 2101 return(ARCHIVE_FAILED);
8f776fd9
TK
2102 }
2103 }
2104
2105 /* Try creating it first; if this fails, we'll try to recover. */
2106 en = create_filesystem_object(a);
2107
2108 if ((en == ENOTDIR || en == ENOENT)
2109 && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
2110 /* If the parent dir doesn't exist, try creating it. */
2111 create_parent_dir(a, a->name);
2112 /* Now try to create the object again. */
2113 en = create_filesystem_object(a);
2114 }
2115
99d593a4
GP
2116 if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
2117 archive_set_error(&a->archive, en,
2118 "Hard-link target '%s' does not exist.",
2119 archive_entry_hardlink(a->entry));
2120 return (ARCHIVE_FAILED);
2121 }
2122
8f776fd9
TK
2123 if ((en == EISDIR || en == EEXIST)
2124 && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
2125 /* If we're not overwriting, we're done. */
6674b4aa
PS
2126 if (S_ISDIR(a->mode)) {
2127 /* Don't overwrite any settings on existing directories. */
2128 a->todo = 0;
2129 }
4ec97d24
TK
2130 archive_entry_unset_size(a->entry);
2131 return (ARCHIVE_OK);
8f776fd9
TK
2132 }
2133
2134 /*
2135 * Some platforms return EISDIR if you call
2136 * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
2137 * return EEXIST. POSIX is ambiguous, requiring EISDIR
2138 * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
2139 * on an existing item.
2140 */
2141 if (en == EISDIR) {
2142 /* A dir is in the way of a non-dir, rmdir it. */
2143 if (rmdir(a->name) != 0) {
2144 archive_set_error(&a->archive, errno,
2145 "Can't remove already-existing dir");
7d4496e9 2146 return (ARCHIVE_FAILED);
8f776fd9 2147 }
2f8873c2 2148 a->pst = NULL;
8f776fd9
TK
2149 /* Try again. */
2150 en = create_filesystem_object(a);
2151 } else if (en == EEXIST) {
2152 /*
2153 * We know something is in the way, but we don't know what;
2154 * we need to find out before we go any further.
2155 */
3deba4d2
TK
2156 int r = 0;
2157 /*
cafcd565 2158 * The SECURE_SYMLINKS logic has already removed a
3deba4d2
TK
2159 * symlink to a dir if the client wants that. So
2160 * follow the symlink if we're creating a dir.
2161 */
2162 if (S_ISDIR(a->mode))
bf234723 2163 r = la_stat(a->name, &a->st);
3deba4d2
TK
2164 /*
2165 * If it's not a dir (or it's a broken symlink),
2166 * then don't follow it.
2167 */
2168 if (r != 0 || !S_ISDIR(a->mode))
e6056040 2169#ifdef HAVE_LSTAT
3deba4d2 2170 r = lstat(a->name, &a->st);
e6056040 2171#else
2172 r = la_stat(a->name, &a->st);
2173#endif
3deba4d2 2174 if (r != 0) {
8f776fd9
TK
2175 archive_set_error(&a->archive, errno,
2176 "Can't stat existing object");
7d4496e9 2177 return (ARCHIVE_FAILED);
8f776fd9
TK
2178 }
2179
623fd7d3
TK
2180 /*
2181 * NO_OVERWRITE_NEWER doesn't apply to directories.
2182 */
2183 if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
2184 && !S_ISDIR(a->st.st_mode)) {
8f776fd9 2185 if (!older(&(a->st), a->entry)) {
c94df2a2 2186 archive_entry_unset_size(a->entry);
1584a716 2187 return (ARCHIVE_OK);
8f776fd9
TK
2188 }
2189 }
2190
2191 /* If it's our archive, we're done. */
7457cf54 2192 if (a->skip_file_set &&
7d2cbbc5
MN
2193 a->st.st_dev == (dev_t)a->skip_file_dev &&
2194 a->st.st_ino == (ino_t)a->skip_file_ino) {
2195 archive_set_error(&a->archive, 0,
2196 "Refusing to overwrite archive");
8f776fd9
TK
2197 return (ARCHIVE_FAILED);
2198 }
2199
2200 if (!S_ISDIR(a->st.st_mode)) {
6a595ef6
BD
2201 if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
2202 (void)clear_nochange_fflags(a);
b51d6b62 2203
2204 if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
2205 S_ISREG(a->st.st_mode)) {
2206 /* Use a temporary file to extract */
f001f3b0
MM
2207 if ((a->fd = la_mktemp(a)) == -1) {
2208 archive_set_error(&a->archive, errno,
2209 "Can't create temporary file");
b51d6b62 2210 return ARCHIVE_FAILED;
f001f3b0 2211 }
b51d6b62 2212 a->pst = NULL;
2213 en = 0;
2214 } else {
2215 /* A non-dir is in the way, unlink it. */
2216 if (unlink(a->name) != 0) {
2217 archive_set_error(&a->archive, errno,
2218 "Can't unlink already-existing "
2219 "object");
2220 return (ARCHIVE_FAILED);
2221 }
2222 a->pst = NULL;
2223 /* Try again. */
2224 en = create_filesystem_object(a);
8f776fd9 2225 }
8f776fd9
TK
2226 } else if (!S_ISDIR(a->mode)) {
2227 /* A dir is in the way of a non-dir, rmdir it. */
6a595ef6
BD
2228 if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
2229 (void)clear_nochange_fflags(a);
8f776fd9
TK
2230 if (rmdir(a->name) != 0) {
2231 archive_set_error(&a->archive, errno,
dc9a0fb4 2232 "Can't replace existing directory with non-directory");
7d4496e9 2233 return (ARCHIVE_FAILED);
8f776fd9
TK
2234 }
2235 /* Try again. */
2236 en = create_filesystem_object(a);
2237 } else {
2238 /*
2239 * There's a dir in the way of a dir. Don't
2240 * waste time with rmdir()/mkdir(), just fix
2241 * up the permissions on the existing dir.
2242 * Note that we don't change perms on existing
2243 * dirs unless _EXTRACT_PERM is specified.
2244 */
2245 if ((a->mode != a->st.st_mode)
2246 && (a->todo & TODO_MODE_FORCE))
2247 a->deferred |= (a->todo & TODO_MODE);
2248 /* Ownership doesn't need deferred fixup. */
2249 en = 0; /* Forget the EEXIST. */
2250 }
2251 }
2252
2253 if (en) {
2254 /* Everything failed; give up here. */
1bed2f31
MM
2255 if ((&a->archive)->error == NULL)
2256 archive_set_error(&a->archive, en, "Can't create '%s'",
2257 a->name);
7d4496e9 2258 return (ARCHIVE_FAILED);
8f776fd9
TK
2259 }
2260
2261 a->pst = NULL; /* Cached stat data no longer valid. */
2262 return (ret);
2263}
2264
2265/*
2266 * Returns 0 if creation succeeds, or else returns errno value from
2267 * the failed system call. Note: This function should only ever perform
2268 * a single system call.
2269 */
87599157 2270static int
8f776fd9
TK
2271create_filesystem_object(struct archive_write_disk *a)
2272{
2273 /* Create the entry. */
2274 const char *linkname;
2275 mode_t final_mode, mode;
2276 int r;
dfd6b54c
TK
2277 /* these for check_symlinks_fsobj */
2278 char *linkname_copy; /* non-const copy of linkname */
433e36b0 2279 struct stat st;
dfd6b54c
TK
2280 struct archive_string error_string;
2281 int error_number;
8f776fd9
TK
2282
2283 /* We identify hard/symlinks according to the link names. */
2284 /* Since link(2) and symlink(2) don't handle modes, we're done here. */
2285 linkname = archive_entry_hardlink(a->entry);
2286 if (linkname != NULL) {
4b57c013
TK
2287#if !HAVE_LINK
2288 return (EPERM);
2289#else
dfd6b54c
TK
2290 archive_string_init(&error_string);
2291 linkname_copy = strdup(linkname);
2292 if (linkname_copy == NULL) {
2293 return (EPERM);
2294 }
cc9cbbb1
MM
2295 /*
2296 * TODO: consider using the cleaned-up path as the link
2297 * target?
2298 */
2299 r = cleanup_pathname_fsobj(linkname_copy, &error_number,
2300 &error_string, a->flags);
dfd6b54c 2301 if (r != ARCHIVE_OK) {
cc9cbbb1
MM
2302 archive_set_error(&a->archive, error_number, "%s",
2303 error_string.s);
dfd6b54c 2304 free(linkname_copy);
532ff5fb 2305 archive_string_free(&error_string);
cc9cbbb1
MM
2306 /*
2307 * EPERM is more appropriate than error_number for our
2308 * callers
2309 */
dfd6b54c
TK
2310 return (EPERM);
2311 }
cc9cbbb1 2312 r = check_symlinks_fsobj(linkname_copy, &error_number,
5e646b89 2313 &error_string, a->flags, 1);
dfd6b54c 2314 if (r != ARCHIVE_OK) {
cc9cbbb1
MM
2315 archive_set_error(&a->archive, error_number, "%s",
2316 error_string.s);
dfd6b54c 2317 free(linkname_copy);
532ff5fb 2318 archive_string_free(&error_string);
cc9cbbb1
MM
2319 /*
2320 * EPERM is more appropriate than error_number for our
2321 * callers
2322 */
dfd6b54c
TK
2323 return (EPERM);
2324 }
2325 free(linkname_copy);
532ff5fb 2326 archive_string_free(&error_string);
b51d6b62 2327 /*
2328 * Unlinking and linking here is really not atomic,
2329 * but doing it right, would require us to construct
2330 * an mktemplink() function, and then use rename(2).
2331 */
2332 if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
2333 unlink(a->name);
5e646b89
MM
2334#ifdef HAVE_LINKAT
2335 r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name,
2336 0) ? errno : 0;
2337#else
8f776fd9 2338 r = link(linkname, a->name) ? errno : 0;
5e646b89 2339#endif
8f776fd9
TK
2340 /*
2341 * New cpio and pax formats allow hardlink entries
2342 * to carry data, so we may have to open the file
2343 * for hardlink entries.
76970580
JS
2344 *
2345 * If the hardlink was successfully created and
2346 * the archive doesn't have carry data for it,
86ada71e 2347 * consider it to be non-authoritative for meta data.
76970580
JS
2348 * This is consistent with GNU tar and BSD pax.
2349 * If the hardlink does carry data, let the last
2350 * archive entry decide ownership.
8f776fd9 2351 */
e9c0ba83 2352 if (r == 0 && a->filesize <= 0) {
76970580
JS
2353 a->todo = 0;
2354 a->deferred = 0;
e47c21de 2355 } else if (r == 0 && a->filesize > 0) {
433e36b0
MM
2356#ifdef HAVE_LSTAT
2357 r = lstat(a->name, &st);
2358#else
bf234723 2359 r = la_stat(a->name, &st);
433e36b0
MM
2360#endif
2361 if (r != 0)
8f776fd9 2362 r = errno;
433e36b0
MM
2363 else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
2364 a->fd = open(a->name, O_WRONLY | O_TRUNC |
2365 O_BINARY | O_CLOEXEC | O_NOFOLLOW);
2366 __archive_ensure_cloexec_flag(a->fd);
2367 if (a->fd < 0)
2368 r = errno;
2369 }
8f776fd9
TK
2370 }
2371 return (r);
4b57c013 2372#endif
8f776fd9
TK
2373 }
2374 linkname = archive_entry_symlink(a->entry);
4b57c013
TK
2375 if (linkname != NULL) {
2376#if HAVE_SYMLINK
99e20e46 2377 /*
2378 * Unlinking and linking here is really not atomic,
2379 * but doing it right, would require us to construct
2380 * an mktempsymlink() function, and then use rename(2).
2381 */
2382 if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
2383 unlink(a->name);
8f776fd9 2384 return symlink(linkname, a->name) ? errno : 0;
4b57c013
TK
2385#else
2386 return (EPERM);
2387#endif
2388 }
8f776fd9
TK
2389
2390 /*
2391 * The remaining system calls all set permissions, so let's
2392 * try to take advantage of that to avoid an extra chmod()
2393 * call. (Recall that umask is set to zero right now!)
2394 */
2395
2396 /* Mode we want for the final restored object (w/o file type bits). */
2397 final_mode = a->mode & 07777;
2398 /*
2399 * The mode that will actually be restored in this step. Note
2400 * that SUID, SGID, etc, require additional work to ensure
2401 * security, so we never restore them at this point.
2402 */
6027a837 2403 mode = final_mode & 0777 & ~a->user_umask;
8f776fd9 2404
d30a8faa
EB
2405 /*
2406 * Always create writable such that [f]setxattr() works if we're not
2407 * root.
2408 */
2409 if (a->user_uid != 0 &&
2410 a->todo & (TODO_HFS_COMPRESSION | TODO_XATTR)) {
38c806ec
EB
2411 mode |= 0200;
2412 }
2413
8f776fd9
TK
2414 switch (a->mode & AE_IFMT) {
2415 default:
2416 /* POSIX requires that we fall through here. */
2417 /* FALLTHROUGH */
2418 case AE_IFREG:
b51d6b62 2419 a->tmpname = NULL;
8f776fd9 2420 a->fd = open(a->name,
60141df1
MN
2421 O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode);
2422 __archive_ensure_cloexec_flag(a->fd);
8f776fd9
TK
2423 r = (a->fd < 0);
2424 break;
2425 case AE_IFCHR:
2426#ifdef HAVE_MKNOD
2427 /* Note: we use AE_IFCHR for the case label, and
2428 * S_IFCHR for the mknod() call. This is correct. */
2429 r = mknod(a->name, mode | S_IFCHR,
2430 archive_entry_rdev(a->entry));
3b25664d 2431 break;
8f776fd9
TK
2432#else
2433 /* TODO: Find a better way to warn about our inability
2434 * to restore a char device node. */
2435 return (EINVAL);
2436#endif /* HAVE_MKNOD */
8f776fd9
TK
2437 case AE_IFBLK:
2438#ifdef HAVE_MKNOD
2439 r = mknod(a->name, mode | S_IFBLK,
2440 archive_entry_rdev(a->entry));
3b25664d 2441 break;
8f776fd9
TK
2442#else
2443 /* TODO: Find a better way to warn about our inability
2444 * to restore a block device node. */
2445 return (EINVAL);
2446#endif /* HAVE_MKNOD */
8f776fd9
TK
2447 case AE_IFDIR:
2448 mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
2449 r = mkdir(a->name, mode);
2450 if (r == 0) {
2451 /* Defer setting dir times. */
2452 a->deferred |= (a->todo & TODO_TIMES);
2453 a->todo &= ~TODO_TIMES;
2454 /* Never use an immediate chmod(). */
71362fca
TK
2455 /* We can't avoid the chmod() entirely if EXTRACT_PERM
2456 * because of SysV SGID inheritance. */
2457 if ((mode != final_mode)
2458 || (a->flags & ARCHIVE_EXTRACT_PERM))
8f776fd9
TK
2459 a->deferred |= (a->todo & TODO_MODE);
2460 a->todo &= ~TODO_MODE;
2461 }
2462 break;
2463 case AE_IFIFO:
2464#ifdef HAVE_MKFIFO
2465 r = mkfifo(a->name, mode);
3b25664d 2466 break;
8f776fd9
TK
2467#else
2468 /* TODO: Find a better way to warn about our inability
2469 * to restore a fifo. */
2470 return (EINVAL);
2471#endif /* HAVE_MKFIFO */
8f776fd9
TK
2472 }
2473
2474 /* All the system calls above set errno on failure. */
2475 if (r)
2476 return (errno);
2477
2478 /* If we managed to set the final mode, we've avoided a chmod(). */
2479 if (mode == final_mode)
2480 a->todo &= ~TODO_MODE;
2481 return (0);
2482}
2483
2484/*
2485 * Cleanup function for archive_extract. Mostly, this involves processing
2486 * the fixup list, which is used to address a number of problems:
2487 * * Dir permissions might prevent us from restoring a file in that
2488 * dir, so we restore the dir with minimum 0700 permissions first,
2489 * then correct the mode at the end.
2490 * * Similarly, the act of restoring a file touches the directory
2491 * and changes the timestamp on the dir, so we have to touch-up dir
2492 * timestamps at the end as well.
2493 * * Some file flags can interfere with the restore by, for example,
2494 * preventing the creation of hardlinks to those files.
b8ad1655 2495 * * Mac OS extended metadata includes ACLs, so must be deferred on dirs.
8f776fd9
TK
2496 *
2497 * Note that tar/cpio do not require that archives be in a particular
2498 * order; there is no way to know when the last file has been restored
2499 * within a directory, so there's no way to optimize the memory usage
2500 * here by fixing up the directory any earlier than the
2501 * end-of-archive.
2502 *
2503 * XXX TODO: Directory ACLs should be restored here, for the same
2504 * reason we set directory perms here. XXX
2505 */
2506static int
911dc2bf 2507_archive_write_disk_close(struct archive *_a)
8f776fd9
TK
2508{
2509 struct archive_write_disk *a = (struct archive_write_disk *)_a;
2510 struct fixup_entry *next, *p;
b41daecb 2511 struct stat st;
8a1bd5c1 2512 char *c;
ede459d2 2513 int fd, ret, openflags;
8f776fd9 2514
42c1f3e1 2515 archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
8f776fd9
TK
2516 ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
2517 "archive_write_disk_close");
911dc2bf 2518 ret = _archive_write_disk_finish_entry(&a->archive);
8f776fd9
TK
2519
2520 /* Sort dir list so directories are fixed up in depth-first order. */
2521 p = sort_dir_list(a->fixup_list);
2522
2523 while (p != NULL) {
6d520405 2524 fd = -1;
8f776fd9 2525 a->pst = NULL; /* Mark stat cache as out-of-date. */
8a1bd5c1
MM
2526
2527 /* We must strip trailing slashes from the path to avoid
2528 dereferencing symbolic links to directories */
2529 c = p->name;
2530 while (*c != '\0')
2531 c++;
2532 while (c != p->name && *(c - 1) == '/') {
2533 c--;
2534 *c = '\0';
2535 }
2536
2537 if (p->fixup == 0)
2538 goto skip_fixup_entry;
2539 else {
ede459d2
MM
2540 /*
2541 * We need to verify if the type of the file
2542 * we are going to open matches the file type
2543 * of the fixup entry.
2544 */
2545 openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
2546 | O_CLOEXEC;
8a1bd5c1 2547#if defined(O_DIRECTORY)
ede459d2
MM
2548 if (p->filetype == AE_IFDIR)
2549 openflags |= O_DIRECTORY;
8a1bd5c1 2550#endif
ede459d2
MM
2551 fd = open(p->name, openflags);
2552
2553#if defined(O_DIRECTORY)
8a1bd5c1 2554 /*
ede459d2
MM
2555 * If we support O_DIRECTORY and open was
2556 * successful we can skip the file type check
2557 * for directories. For other file types
2558 * we need to verify via fstat() or lstat()
8a1bd5c1 2559 */
ede459d2
MM
2560 if (fd == -1 || p->filetype != AE_IFDIR) {
2561#if HAVE_FSTAT
2562 if (fd > 0 && (
2563 fstat(fd, &st) != 0 ||
2564 la_verify_filetype(st.st_mode,
2565 p->filetype) == 0)) {
2566 goto skip_fixup_entry;
2567 } else
2568#endif
e6056040 2569 if (
2570#ifdef HAVE_LSTAT
2571 lstat(p->name, &st) != 0 ||
2572#else
2573 la_stat(p->name, &st) != 0 ||
2574#endif
ede459d2
MM
2575 la_verify_filetype(st.st_mode,
2576 p->filetype) == 0) {
b41daecb 2577 goto skip_fixup_entry;
b41daecb
MM
2578 }
2579 }
8a1bd5c1
MM
2580#else
2581#if HAVE_FSTAT
2582 if (fd > 0 && (
ede459d2
MM
2583 fstat(fd, &st) != 0 ||
2584 la_verify_filetype(st.st_mode,
2585 p->filetype) == 0)) {
8a1bd5c1
MM
2586 goto skip_fixup_entry;
2587 } else
2588#endif
e6056040 2589 if (
2590#ifdef HAVE_LSTAT
2591 lstat(p->name, &st) != 0 ||
2592#else
2593 la_stat(p->name, &st) != 0 ||
2594#endif
ede459d2
MM
2595 la_verify_filetype(st.st_mode,
2596 p->filetype) == 0) {
8a1bd5c1
MM
2597 goto skip_fixup_entry;
2598 }
2599#endif
b837c72c 2600 }
8f776fd9 2601 if (p->fixup & TODO_TIMES) {
6d520405 2602 set_times(a, fd, p->mode, p->name,
5223514b
TK
2603 p->atime, p->atime_nanos,
2604 p->birthtime, p->birthtime_nanos,
b648c6c7
BJ
2605 p->mtime, p->mtime_nanos,
2606 p->ctime, p->ctime_nanos);
8f776fd9 2607 }
b837c72c
MM
2608 if (p->fixup & TODO_MODE_BASE) {
2609#ifdef HAVE_FCHMOD
6d520405 2610 if (fd >= 0)
8a1bd5c1 2611 fchmod(fd, p->mode & 07777);
b837c72c
MM
2612 else
2613#endif
b41daecb 2614#ifdef HAVE_LCHMOD
8a1bd5c1 2615 lchmod(p->name, p->mode & 07777);
b41daecb 2616#else
8a1bd5c1 2617 chmod(p->name, p->mode & 07777);
b41daecb 2618#endif
b837c72c 2619 }
b01b4bc1 2620 if (p->fixup & TODO_ACLS)
6d520405 2621 archive_write_disk_set_acls(&a->archive, fd,
b837c72c 2622 p->name, &p->acl, p->mode);
8f776fd9 2623 if (p->fixup & TODO_FFLAGS)
6d520405 2624 set_fflags_platform(a, fd, p->name,
8f776fd9 2625 p->mode, p->fflags_set, 0);
b8ad1655
TK
2626 if (p->fixup & TODO_MAC_METADATA)
2627 set_mac_metadata(a, p->name, p->mac_metadata,
2628 p->mac_metadata_size);
b41daecb 2629skip_fixup_entry:
8f776fd9 2630 next = p->next;
b01b4bc1 2631 archive_acl_clear(&p->acl);
b8ad1655 2632 free(p->mac_metadata);
8f776fd9 2633 free(p->name);
6d520405
MM
2634 if (fd >= 0)
2635 close(fd);
8f776fd9
TK
2636 free(p);
2637 p = next;
2638 }
2639 a->fixup_list = NULL;
2640 return (ret);
2641}
2642
2643static int
911dc2bf 2644_archive_write_disk_free(struct archive *_a)
8f776fd9 2645{
42c1f3e1 2646 struct archive_write_disk *a;
8f776fd9 2647 int ret;
42c1f3e1
TK
2648 if (_a == NULL)
2649 return (ARCHIVE_OK);
2650 archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC,
2651 ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
2652 a = (struct archive_write_disk *)_a;
911dc2bf 2653 ret = _archive_write_disk_close(&a->archive);
f4f791ea
TK
2654 archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
2655 archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
4736e4e7 2656 archive_entry_free(a->entry);
8f776fd9 2657 archive_string_free(&a->_name_data);
b51d6b62 2658 archive_string_free(&a->_tmpname_data);
8f776fd9
TK
2659 archive_string_free(&a->archive.error_string);
2660 archive_string_free(&a->path_safe);
42c1f3e1 2661 a->archive.magic = 0;
d1899374 2662 __archive_clean(&a->archive);
fb67a295 2663 free(a->decmpfs_header_p);
fb67a295
MN
2664 free(a->resource_fork);
2665 free(a->compressed_buffer);
2666 free(a->uncompressed_buffer);
a9a9683f
PB
2667#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
2668 && defined(HAVE_ZLIB_H)
fb67a295
MN
2669 if (a->stream_valid) {
2670 switch (deflateEnd(&a->stream)) {
2671 case Z_OK:
2672 break;
2673 default:
2674 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2675 "Failed to clean up compressor");
2676 ret = ARCHIVE_FATAL;
2677 break;
2678 }
2679 }
2680#endif
8f776fd9
TK
2681 free(a);
2682 return (ret);
2683}
2684
2685/*
2686 * Simple O(n log n) merge sort to order the fixup list. In
2687 * particular, we want to restore dir timestamps depth-first.
2688 */
2689static struct fixup_entry *
2690sort_dir_list(struct fixup_entry *p)
2691{
2692 struct fixup_entry *a, *b, *t;
2693
2694 if (p == NULL)
2695 return (NULL);
2696 /* A one-item list is already sorted. */
2697 if (p->next == NULL)
2698 return (p);
2699
2700 /* Step 1: split the list. */
2701 t = p;
2702 a = p->next->next;
2703 while (a != NULL) {
2704 /* Step a twice, t once. */
2705 a = a->next;
2706 if (a != NULL)
2707 a = a->next;
2708 t = t->next;
2709 }
2710 /* Now, t is at the mid-point, so break the list here. */
2711 b = t->next;
2712 t->next = NULL;
2713 a = p;
2714
2715 /* Step 2: Recursively sort the two sub-lists. */
2716 a = sort_dir_list(a);
2717 b = sort_dir_list(b);
2718
2719 /* Step 3: Merge the returned lists. */
2720 /* Pick the first element for the merged list. */
2721 if (strcmp(a->name, b->name) > 0) {
2722 t = p = a;
2723 a = a->next;
2724 } else {
2725 t = p = b;
2726 b = b->next;
2727 }
2728
2729 /* Always put the later element on the list first. */
2730 while (a != NULL && b != NULL) {
2731 if (strcmp(a->name, b->name) > 0) {
2732 t->next = a;
2733 a = a->next;
2734 } else {
2735 t->next = b;
2736 b = b->next;
2737 }
2738 t = t->next;
2739 }
2740
2741 /* Only one list is non-empty, so just splice it on. */
2742 if (a != NULL)
2743 t->next = a;
2744 if (b != NULL)
2745 t->next = b;
2746
2747 return (p);
2748}
2749
2750/*
2751 * Returns a new, initialized fixup entry.
2752 *
2753 * TODO: Reduce the memory requirements for this list by using a tree
2754 * structure rather than a simple list of names.
2755 */
2756static struct fixup_entry *
2757new_fixup(struct archive_write_disk *a, const char *pathname)
2758{
2759 struct fixup_entry *fe;
2760
dc467ac4 2761 fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
62756a10
MN
2762 if (fe == NULL) {
2763 archive_set_error(&a->archive, ENOMEM,
2764 "Can't allocate memory for a fixup");
8f776fd9 2765 return (NULL);
62756a10 2766 }
8f776fd9
TK
2767 fe->next = a->fixup_list;
2768 a->fixup_list = fe;
2769 fe->fixup = 0;
ede459d2 2770 fe->filetype = 0;
8f776fd9
TK
2771 fe->name = strdup(pathname);
2772 return (fe);
2773}
2774
2775/*
2776 * Returns a fixup structure for the current entry.
2777 */
2778static struct fixup_entry *
2779current_fixup(struct archive_write_disk *a, const char *pathname)
2780{
2781 if (a->current_fixup == NULL)
2782 a->current_fixup = new_fixup(a, pathname);
2783 return (a->current_fixup);
2784}
2785
1bed2f31
MM
2786/* Error helper for new *_fsobj functions */
2787static void
2788fsobj_error(int *a_eno, struct archive_string *a_estr,
2789 int err, const char *errstr, const char *path)
2790{
2791 if (a_eno)
2792 *a_eno = err;
2793 if (a_estr)
dce4ade5 2794 archive_string_sprintf(a_estr, "%s%s", errstr, path);
1bed2f31
MM
2795}
2796
8f776fd9
TK
2797/*
2798 * TODO: Someday, integrate this with the deep dir support; they both
2799 * scan the path and both can be optimized by comparing against other
2800 * recent paths.
2801 */
dfd6b54c
TK
2802/*
2803 * Checks the given path to see if any elements along it are symlinks. Returns
2804 * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
2805 */
8f776fd9 2806static int
1bed2f31 2807check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
13023595 2808 int flags, int checking_linkname)
8f776fd9 2809{
b6655592
MM
2810#if !defined(HAVE_LSTAT) && \
2811 !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
4b57c013 2812 /* Platform doesn't have lstat, so we can't look for symlinks. */
dfd6b54c 2813 (void)path; /* UNUSED */
c684b115 2814 (void)a_eno; /* UNUSED */
2815 (void)a_estr; /* UNUSED */
dfd6b54c 2816 (void)flags; /* UNUSED */
13023595 2817 (void)checking_linkname; /* UNUSED */
4b57c013
TK
2818 return (ARCHIVE_OK);
2819#else
dfd6b54c
TK
2820 int res = ARCHIVE_OK;
2821 char *tail;
2822 char *head;
2823 int last;
186116ce 2824 char c = '\0';
8f776fd9
TK
2825 int r;
2826 struct stat st;
b6655592
MM
2827 int chdir_fd;
2828#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2829 int fd;
2830#endif
dfd6b54c
TK
2831
2832 /* Nothing to do here if name is empty */
2833 if(path[0] == '\0')
2834 return (ARCHIVE_OK);
8f776fd9
TK
2835
2836 /*
2837 * Guard against symlink tricks. Reject any archive entry whose
2838 * destination would be altered by a symlink.
dfd6b54c
TK
2839 *
2840 * Walk the filename in chunks separated by '/'. For each segment:
2841 * - if it doesn't exist, continue
2842 * - if it's symlink, abort or remove it
2843 * - if it's a directory and it's not the last chunk, cd into it
2844 * As we go:
2845 * head points to the current (relative) path
cc9cbbb1
MM
2846 * tail points to the temporary \0 terminating the segment we're
2847 * currently examining
dfd6b54c
TK
2848 * c holds what used to be in *tail
2849 * last is 1 if this is the last tail
8f776fd9 2850 */
b6655592
MM
2851 chdir_fd = la_opendirat(AT_FDCWD, ".");
2852 __archive_ensure_cloexec_flag(chdir_fd);
2853 if (chdir_fd < 0) {
2c65d83f
PC
2854 fsobj_error(a_eno, a_estr, errno,
2855 "Could not open ", path);
dfd6b54c 2856 return (ARCHIVE_FATAL);
2c65d83f 2857 }
dfd6b54c
TK
2858 head = path;
2859 tail = path;
2860 last = 0;
2861 /* TODO: reintroduce a safe cache here? */
41ae0cf8 2862 /* Skip the root directory if the path is absolute. */
dfd6b54c
TK
2863 if(tail == path && tail[0] == '/')
2864 ++tail;
2865 /* Keep going until we've checked the entire name.
2866 * head, tail, path all alias the same string, which is
2867 * temporarily zeroed at tail, so be careful restoring the
2868 * stashed (c=tail[0]) for error messages.
2869 * Exiting the loop with break is okay; continue is not.
2870 */
2871 while (!last) {
cc9cbbb1
MM
2872 /*
2873 * Skip the separator we just consumed, plus any adjacent ones
2874 */
dfd6b54c
TK
2875 while (*tail == '/')
2876 ++tail;
8f776fd9 2877 /* Skip the next path element. */
dfd6b54c
TK
2878 while (*tail != '\0' && *tail != '/')
2879 ++tail;
2880 /* is this the last path component? */
2881 last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
2882 /* temporarily truncate the string here */
2883 c = tail[0];
2884 tail[0] = '\0';
8f776fd9 2885 /* Check that we haven't hit a symlink. */
b6655592
MM
2886#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2887 r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW);
e6056040 2888#elif defined(HAVE_LSTAT)
dfd6b54c 2889 r = lstat(head, &st);
e6056040 2890#else
2891 r = la_stat(head, &st);
b6655592 2892#endif
8f776fd9 2893 if (r != 0) {
dfd6b54c 2894 tail[0] = c;
8f776fd9 2895 /* We've hit a dir that doesn't exist; stop now. */
1fa9c7bf 2896 if (errno == ENOENT) {
8f776fd9 2897 break;
1fa9c7bf 2898 } else {
cc9cbbb1
MM
2899 /*
2900 * Treat any other error as fatal - best to be
2901 * paranoid here.
2902 * Note: This effectively disables deep
2903 * directory support when security checks are
2904 * enabled. Otherwise, very long pathnames that
2905 * trigger an error here could evade the
2906 * sandbox.
2907 * TODO: We could do better, but it would
2908 * probably require merging the symlink checks
2909 * with the deep-directory editing.
2910 */
1bed2f31 2911 fsobj_error(a_eno, a_estr, errno,
dce4ade5 2912 "Could not stat ", path);
dfd6b54c
TK
2913 res = ARCHIVE_FAILED;
2914 break;
2915 }
2916 } else if (S_ISDIR(st.st_mode)) {
2917 if (!last) {
b6655592
MM
2918#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2919 fd = la_opendirat(chdir_fd, head);
2920 if (fd < 0)
2921 r = -1;
2922 else {
2923 r = 0;
2924 close(chdir_fd);
2925 chdir_fd = fd;
2926 }
2927#else
2928 r = chdir(head);
2929#endif
2930 if (r != 0) {
dfd6b54c 2931 tail[0] = c;
1bed2f31 2932 fsobj_error(a_eno, a_estr, errno,
dce4ade5 2933 "Could not chdir ", path);
dfd6b54c
TK
2934 res = (ARCHIVE_FATAL);
2935 break;
2936 }
2937 /* Our view is now from inside this dir: */
2938 head = tail + 1;
1fa9c7bf 2939 }
8f776fd9 2940 } else if (S_ISLNK(st.st_mode)) {
13023595 2941 if (last && checking_linkname) {
5e646b89
MM
2942#ifdef HAVE_LINKAT
2943 /*
2944 * Hardlinks to symlinks are safe to write
2945 * if linkat() is supported as it does not
2946 * follow symlinks.
2947 */
2948 res = ARCHIVE_OK;
2949#else
2950 /*
2951 * We return ARCHIVE_FAILED here as we are
2952 * not able to safely write hardlinks
2953 * to symlinks.
2954 */
2955 tail[0] = c;
2956 fsobj_error(a_eno, a_estr, errno,
2957 "Cannot write hardlink to symlink ",
2958 path);
2959 res = ARCHIVE_FAILED;
2960#endif
2961 break;
2962 } else
dfd6b54c 2963 if (last) {
8f776fd9
TK
2964 /*
2965 * Last element is symlink; remove it
2966 * so we can overwrite it with the
2967 * item being extracted.
2968 */
b6655592
MM
2969#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
2970 r = unlinkat(chdir_fd, head, 0);
2971#else
2972 r = unlink(head);
2973#endif
2974 if (r != 0) {
dfd6b54c 2975 tail[0] = c;
1bed2f31 2976 fsobj_error(a_eno, a_estr, errno,
dce4ade5 2977 "Could not remove symlink ",
1bed2f31 2978 path);
dfd6b54c
TK
2979 res = ARCHIVE_FAILED;
2980 break;
8f776fd9
TK
2981 }
2982 /*
2983 * Even if we did remove it, a warning
2984 * is in order. The warning is silly,
2985 * though, if we're just replacing one
2986 * symlink with another symlink.
2987 */
dfd6b54c 2988 tail[0] = c;
cc9cbbb1
MM
2989 /*
2990 * FIXME: not sure how important this is to
2991 * restore
2992 */
2993 /*
dfd6b54c 2994 if (!S_ISLNK(path)) {
1bed2f31 2995 fsobj_error(a_eno, a_estr, 0,
dce4ade5 2996 "Removing symlink ", path);
8f776fd9 2997 }
dfd6b54c 2998 */
8f776fd9 2999 /* Symlink gone. No more problem! */
dfd6b54c
TK
3000 res = ARCHIVE_OK;
3001 break;
3002 } else if (flags & ARCHIVE_EXTRACT_UNLINK) {
8f776fd9 3003 /* User asked us to remove problems. */
b6655592
MM
3004#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3005 r = unlinkat(chdir_fd, head, 0);
3006#else
3007 r = unlink(head);
3008#endif
3009 if (r != 0) {
dfd6b54c 3010 tail[0] = c;
1bed2f31
MM
3011 fsobj_error(a_eno, a_estr, 0,
3012 "Cannot remove intervening "
dce4ade5 3013 "symlink ", path);
dfd6b54c
TK
3014 res = ARCHIVE_FAILED;
3015 break;
8f776fd9 3016 }
dfd6b54c 3017 tail[0] = c;
256e52f0
MM
3018 } else if ((flags &
3019 ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
3020 /*
3021 * We are not the last element and we want to
3022 * follow symlinks if they are a directory.
3023 *
3024 * This is needed to extract hardlinks over
3025 * symlinks.
3026 */
b6655592
MM
3027#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3028 r = fstatat(chdir_fd, head, &st, 0);
3029#else
bf234723 3030 r = la_stat(head, &st);
b6655592 3031#endif
256e52f0
MM
3032 if (r != 0) {
3033 tail[0] = c;
3034 if (errno == ENOENT) {
3035 break;
3036 } else {
3037 fsobj_error(a_eno, a_estr,
3038 errno,
dce4ade5 3039 "Could not stat ", path);
256e52f0
MM
3040 res = (ARCHIVE_FAILED);
3041 break;
3042 }
3043 } else if (S_ISDIR(st.st_mode)) {
b6655592
MM
3044#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3045 fd = la_opendirat(chdir_fd, head);
3046 if (fd < 0)
3047 r = -1;
3048 else {
3049 r = 0;
3050 close(chdir_fd);
3051 chdir_fd = fd;
3052 }
3053#else
3054 r = chdir(head);
3055#endif
3056 if (r != 0) {
256e52f0
MM
3057 tail[0] = c;
3058 fsobj_error(a_eno, a_estr,
3059 errno,
dce4ade5 3060 "Could not chdir ", path);
256e52f0
MM
3061 res = (ARCHIVE_FATAL);
3062 break;
3063 }
3064 /*
3065 * Our view is now from inside
3066 * this dir:
3067 */
3068 head = tail + 1;
3069 } else {
3070 tail[0] = c;
3071 fsobj_error(a_eno, a_estr, 0,
3072 "Cannot extract through "
dce4ade5 3073 "symlink ", path);
256e52f0
MM
3074 res = ARCHIVE_FAILED;
3075 break;
3076 }
8f776fd9 3077 } else {
dfd6b54c 3078 tail[0] = c;
1bed2f31 3079 fsobj_error(a_eno, a_estr, 0,
dce4ade5 3080 "Cannot extract through symlink ", path);
dfd6b54c
TK
3081 res = ARCHIVE_FAILED;
3082 break;
8f776fd9
TK
3083 }
3084 }
dfd6b54c
TK
3085 /* be sure to always maintain this */
3086 tail[0] = c;
3087 if (tail[0] != '\0')
3088 tail++; /* Advance to the next segment. */
3089 }
3090 /* Catches loop exits via break */
3091 tail[0] = c;
b6655592
MM
3092#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
3093 /* If we operate with openat(), fstatat() and unlinkat() there was
3094 * no chdir(), so just close the fd */
3095 if (chdir_fd >= 0)
3096 close(chdir_fd);
3097#elif HAVE_FCHDIR
dfd6b54c 3098 /* If we changed directory above, restore it here. */
b6655592
MM
3099 if (chdir_fd >= 0) {
3100 r = fchdir(chdir_fd);
dfd6b54c 3101 if (r != 0) {
1bed2f31
MM
3102 fsobj_error(a_eno, a_estr, errno,
3103 "chdir() failure", "");
dfd6b54c 3104 }
b6655592
MM
3105 close(chdir_fd);
3106 chdir_fd = -1;
dfd6b54c
TK
3107 if (r != 0) {
3108 res = (ARCHIVE_FATAL);
3109 }
8f776fd9 3110 }
dfd6b54c
TK
3111#endif
3112 /* TODO: reintroduce a safe cache here? */
3113 return res;
4b57c013 3114#endif
8f776fd9
TK
3115}
3116
dfd6b54c
TK
3117/*
3118 * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
3119 * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
3120 */
3121static int
3122check_symlinks(struct archive_write_disk *a)
3123{
3124 struct archive_string error_string;
3125 int error_number;
3126 int rc;
3127 archive_string_init(&error_string);
cc9cbbb1 3128 rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
5e646b89 3129 a->flags, 0);
dfd6b54c 3130 if (rc != ARCHIVE_OK) {
cc9cbbb1
MM
3131 archive_set_error(&a->archive, error_number, "%s",
3132 error_string.s);
dfd6b54c
TK
3133 }
3134 archive_string_free(&error_string);
3135 a->pst = NULL; /* to be safe */
3136 return rc;
3137}
3138
3139
a4b94153
MN
3140#if defined(__CYGWIN__)
3141/*
3142 * 1. Convert a path separator from '\' to '/' .
3143 * We shouldn't check multibyte character directly because some
3144 * character-set have been using the '\' character for a part of
3145 * its multibyte character code.
3146 * 2. Replace unusable characters in Windows with underscore('_').
3147 * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
3148 */
3149static void
764f7989 3150cleanup_pathname_win(char *path)
a4b94153
MN
3151{
3152 wchar_t wc;
3153 char *p;
3154 size_t alen, l;
3155 int mb, complete, utf8;
3156
3157 alen = 0;
3158 mb = 0;
3159 complete = 1;
3160 utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
764f7989 3161 for (p = path; *p != '\0'; p++) {
a4b94153
MN
3162 ++alen;
3163 if (*p == '\\') {
3164 /* If previous byte is smaller than 128,
3165 * this is not second byte of multibyte characters,
3166 * so we can replace '\' with '/'. */
3167 if (utf8 || !mb)
3168 *p = '/';
3169 else
3170 complete = 0;/* uncompleted. */
3171 } else if (*(unsigned char *)p > 127)
3172 mb = 1;
3173 else
3174 mb = 0;
cafcd565 3175 /* Rewrite the path name if its next character is unusable. */
a4b94153
MN
3176 if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
3177 *p == '<' || *p == '>' || *p == '|')
3178 *p = '_';
3179 }
3180 if (complete)
3181 return;
3182
3183 /*
3184 * Convert path separator in wide-character.
3185 */
764f7989 3186 p = path;
a4b94153
MN
3187 while (*p != '\0' && alen) {
3188 l = mbtowc(&wc, p, alen);
d2d75ef8 3189 if (l == (size_t)-1) {
a4b94153
MN
3190 while (*p != '\0') {
3191 if (*p == '\\')
3192 *p = '/';
3193 ++p;
3194 }
3195 break;
3196 }
3197 if (l == 1 && wc == L'\\')
3198 *p = '/';
3199 p += l;
3200 alen -= l;
3201 }
3202}
3203#endif
3204
8f776fd9
TK
3205/*
3206 * Canonicalize the pathname. In particular, this strips duplicate
3207 * '/' characters, '.' elements, and trailing '/'. It also raises an
59357157
AG
3208 * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is
3209 * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
3210 * is set) if the path is absolute.
8f776fd9
TK
3211 */
3212static int
1bed2f31
MM
3213cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
3214 int flags)
8f776fd9
TK
3215{
3216 char *dest, *src;
3217 char separator = '\0';
8f776fd9 3218
dfd6b54c 3219 dest = src = path;
8f776fd9 3220 if (*src == '\0') {
1bed2f31
MM
3221 fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
3222 "Invalid empty ", "pathname");
114420d4 3223 return (ARCHIVE_FAILED);
8f776fd9
TK
3224 }
3225
a4b94153 3226#if defined(__CYGWIN__)
764f7989 3227 cleanup_pathname_win(path);
a4b94153 3228#endif
8f776fd9 3229 /* Skip leading '/'. */
59357157 3230 if (*src == '/') {
dfd6b54c 3231 if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
1bed2f31
MM
3232 fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
3233 "Path is ", "absolute");
59357157
AG
3234 return (ARCHIVE_FAILED);
3235 }
3236
8f776fd9 3237 separator = *src++;
59357157 3238 }
8f776fd9
TK
3239
3240 /* Scan the pathname one element at a time. */
3241 for (;;) {
3242 /* src points to first char after '/' */
3243 if (src[0] == '\0') {
3244 break;
3245 } else if (src[0] == '/') {
3246 /* Found '//', ignore second one. */
3247 src++;
3248 continue;
3249 } else if (src[0] == '.') {
3250 if (src[1] == '\0') {
3251 /* Ignore trailing '.' */
3252 break;
3253 } else if (src[1] == '/') {
3254 /* Skip './'. */
3255 src += 2;
3256 continue;
3257 } else if (src[1] == '.') {
3258 if (src[2] == '/' || src[2] == '\0') {
3259 /* Conditionally warn about '..' */
cc9cbbb1
MM
3260 if (flags
3261 & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
1bed2f31
MM
3262 fsobj_error(a_eno, a_estr,
3263 ARCHIVE_ERRNO_MISC,
3264 "Path contains ", "'..'");
114420d4 3265 return (ARCHIVE_FAILED);
8f776fd9 3266 }
691997fd 3267 }
8f776fd9
TK
3268 /*
3269 * Note: Under no circumstances do we
3270 * remove '..' elements. In
3271 * particular, restoring
3272 * '/foo/../bar/' should create the
3273 * 'foo' dir as a side-effect.
3274 */
691997fd
TK
3275 }
3276 }
8f776fd9
TK
3277
3278 /* Copy current element, including leading '/'. */
3279 if (separator)
3280 *dest++ = '/';
3281 while (*src != '\0' && *src != '/') {
3282 *dest++ = *src++;
3283 }
3284
3285 if (*src == '\0')
3286 break;
3287
3288 /* Skip '/' separator. */
3289 separator = *src++;
3290 }
3291 /*
3292 * We've just copied zero or more path elements, not including the
3293 * final '/'.
3294 */
dfd6b54c 3295 if (dest == path) {
8f776fd9
TK
3296 /*
3297 * Nothing got copied. The path must have been something
3298 * like '.' or '/' or './' or '/././././/./'.
3299 */
3300 if (separator)
3301 *dest++ = '/';
3302 else
3303 *dest++ = '.';
3304 }
3305 /* Terminate the result. */
3306 *dest = '\0';
3307 return (ARCHIVE_OK);
3308}
3309
dfd6b54c
TK
3310static int
3311cleanup_pathname(struct archive_write_disk *a)
3312{
3313 struct archive_string error_string;
3314 int error_number;
3315 int rc;
3316 archive_string_init(&error_string);
cc9cbbb1
MM
3317 rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
3318 a->flags);
dfd6b54c 3319 if (rc != ARCHIVE_OK) {
cc9cbbb1
MM
3320 archive_set_error(&a->archive, error_number, "%s",
3321 error_string.s);
dfd6b54c
TK
3322 }
3323 archive_string_free(&error_string);
3324 return rc;
3325}
3326
8f776fd9
TK
3327/*
3328 * Create the parent directory of the specified path, assuming path
3329 * is already in mutable storage.
3330 */
3331static int
3332create_parent_dir(struct archive_write_disk *a, char *path)
3333{
3334 char *slash;
3335 int r;
3336
3337 /* Remove tail element to obtain parent name. */
3338 slash = strrchr(path, '/');
3339 if (slash == NULL)
3340 return (ARCHIVE_OK);
3341 *slash = '\0';
3342 r = create_dir(a, path);
3343 *slash = '/';
3344 return (r);
3345}
3346
3347/*
3348 * Create the specified dir, recursing to create parents as necessary.
3349 *
3350 * Returns ARCHIVE_OK if the path exists when we're done here.
7d4496e9 3351 * Otherwise, returns ARCHIVE_FAILED.
8f776fd9
TK
3352 * Assumes path is in mutable storage; path is unchanged on exit.
3353 */
3354static int
3355create_dir(struct archive_write_disk *a, char *path)
3356{
3357 struct stat st;
3358 struct fixup_entry *le;
3359 char *slash, *base;
3360 mode_t mode_final, mode;
3361 int r;
3362
8f776fd9
TK
3363 /* Check for special names and just skip them. */
3364 slash = strrchr(path, '/');
3365 if (slash == NULL)
3366 base = path;
3367 else
3368 base = slash + 1;
3369
3370 if (base[0] == '\0' ||
3371 (base[0] == '.' && base[1] == '\0') ||
3372 (base[0] == '.' && base[1] == '.' && base[2] == '\0')) {
3373 /* Don't bother trying to create null path, '.', or '..'. */
3374 if (slash != NULL) {
3375 *slash = '\0';
3376 r = create_dir(a, path);
3377 *slash = '/';
3378 return (r);
3379 }
3380 return (ARCHIVE_OK);
3381 }
3382
3383 /*
3384 * Yes, this should be stat() and not lstat(). Using lstat()
3385 * here loses the ability to extract through symlinks. Also note
3386 * that this should not use the a->st cache.
3387 */
bf234723 3388 if (la_stat(path, &st) == 0) {
8f776fd9
TK
3389 if (S_ISDIR(st.st_mode))
3390 return (ARCHIVE_OK);
3391 if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
3392 archive_set_error(&a->archive, EEXIST,
3393 "Can't create directory '%s'", path);
7d4496e9 3394 return (ARCHIVE_FAILED);
8f776fd9
TK
3395 }
3396 if (unlink(path) != 0) {
3397 archive_set_error(&a->archive, errno,
3398 "Can't create directory '%s': "
99c02b03
JS
3399 "Conflicting file cannot be removed",
3400 path);
7d4496e9 3401 return (ARCHIVE_FAILED);
8f776fd9
TK
3402 }
3403 } else if (errno != ENOENT && errno != ENOTDIR) {
3404 /* Stat failed? */
cc9cbbb1
MM
3405 archive_set_error(&a->archive, errno,
3406 "Can't test directory '%s'", path);
7d4496e9 3407 return (ARCHIVE_FAILED);
8f776fd9
TK
3408 } else if (slash != NULL) {
3409 *slash = '\0';
3410 r = create_dir(a, path);
3411 *slash = '/';
3412 if (r != ARCHIVE_OK)
3413 return (r);
3414 }
3415
3416 /*
3417 * Mode we want for the final restored directory. Per POSIX,
3418 * implicitly-created dirs must be created obeying the umask.
3419 * There's no mention whether this is different for privileged
3420 * restores (which the rest of this code handles by pretending
3421 * umask=0). I've chosen here to always obey the user's umask for
3422 * implicit dirs, even if _EXTRACT_PERM was specified.
3423 */
3424 mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
3425 /* Mode we want on disk during the restore process. */
3426 mode = mode_final;
3427 mode |= MINIMUM_DIR_MODE;
3428 mode &= MAXIMUM_DIR_MODE;
3429 if (mkdir(path, mode) == 0) {
3430 if (mode != mode_final) {
3431 le = new_fixup(a, path);
62756a10
MN
3432 if (le == NULL)
3433 return (ARCHIVE_FATAL);
8f776fd9
TK
3434 le->fixup |=TODO_MODE_BASE;
3435 le->mode = mode_final;
3436 }
3437 return (ARCHIVE_OK);
3438 }
3439
3440 /*
3441 * Without the following check, a/b/../b/c/d fails at the
3442 * second visit to 'b', so 'd' can't be created. Note that we
3443 * don't add it to the fixup list here, as it's already been
3444 * added.
3445 */
bf234723 3446 if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
8f776fd9
TK
3447 return (ARCHIVE_OK);
3448
b21f351a
TK
3449 archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
3450 path);
7d4496e9 3451 return (ARCHIVE_FAILED);
8f776fd9
TK
3452}
3453
3454/*
3455 * Note: Although we can skip setting the user id if the desired user
3456 * id matches the current user, we cannot skip setting the group, as
71362fca
TK
3457 * many systems set the gid based on the containing directory. So
3458 * we have to perform a chown syscall if we want to set the SGID
8f776fd9
TK
3459 * bit. (The alternative is to stat() and then possibly chown(); it's
3460 * more efficient to skip the stat() and just always chown().) Note
3461 * that a successful chown() here clears the TODO_SGID_CHECK bit, which
3462 * allows set_mode to skip the stat() check for the GID.
3463 */
3464static int
3465set_ownership(struct archive_write_disk *a)
3466{
7130b9d4
MM
3467#if !defined(__CYGWIN__) && !defined(__linux__)
3468/*
3469 * On Linux, a process may have the CAP_CHOWN capability.
3470 * On Windows there is no 'root' user with uid 0.
3471 * Elsewhere we can skip calling chown if we are not root and the desired
3472 * user id does not match the current user.
3473 */
3474 if (a->user_uid != 0 && a->user_uid != a->uid) {
8f776fd9 3475 archive_set_error(&a->archive, errno,
19363b4a 3476 "Can't set UID=%jd", (intmax_t)a->uid);
8f776fd9
TK
3477 return (ARCHIVE_WARN);
3478 }
a6ac842e 3479#endif
8f776fd9
TK
3480
3481#ifdef HAVE_FCHOWN
3482 /* If we have an fd, we can avoid a race. */
3483 if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) {
3484 /* We've set owner and know uid/gid are correct. */
3485 a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
3486 return (ARCHIVE_OK);
3487 }
3488#endif
3489
3490 /* We prefer lchown() but will use chown() if that's all we have. */
3491 /* Of course, if we have neither, this will always fail. */
3492#ifdef HAVE_LCHOWN
3493 if (lchown(a->name, a->uid, a->gid) == 0) {
3494 /* We've set owner and know uid/gid are correct. */
3495 a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
3496 return (ARCHIVE_OK);
3497 }
3498#elif HAVE_CHOWN
3499 if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) {
3500 /* We've set owner and know uid/gid are correct. */
3501 a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
3502 return (ARCHIVE_OK);
3503 }
3504#endif
3505
3506 archive_set_error(&a->archive, errno,
19363b4a
MN
3507 "Can't set user=%jd/group=%jd for %s",
3508 (intmax_t)a->uid, (intmax_t)a->gid, a->name);
8f776fd9
TK
3509 return (ARCHIVE_WARN);
3510}
3511
21ebff3b
TK
3512/*
3513 * Note: Returns 0 on success, non-zero on failure.
3514 */
3b73222c
BJ
3515static int
3516set_time(int fd, int mode, const char *name,
3517 time_t atime, long atime_nsec,
3518 time_t mtime, long mtime_nsec)
3519{
5223514b
TK
3520 /* Select the best implementation for this platform. */
3521#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS)
3522 /*
3523 * utimensat() and futimens() are defined in
3524 * POSIX.1-2008. They support ns resolution and setting times
3525 * on fds and symlinks.
3526 */
3b73222c 3527 struct timespec ts[2];
d2d75ef8 3528 (void)mode; /* UNUSED */
3b73222c
BJ
3529 ts[0].tv_sec = atime;
3530 ts[0].tv_nsec = atime_nsec;
3531 ts[1].tv_sec = mtime;
3532 ts[1].tv_nsec = mtime_nsec;
3533 if (fd >= 0)
3534 return futimens(fd, ts);
3535 return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW);
5223514b 3536
3b73222c 3537#elif HAVE_UTIMES
5223514b
TK
3538 /*
3539 * The utimes()-family functions support µs-resolution and
3540 * setting times fds and symlinks. utimes() is documented as
3541 * LEGACY by POSIX, futimes() and lutimes() are not described
3542 * in POSIX.
3543 */
8f776fd9
TK
3544 struct timeval times[2];
3545
82e3bb2a
TK
3546 times[0].tv_sec = atime;
3547 times[0].tv_usec = atime_nsec / 1000;
3548 times[1].tv_sec = mtime;
3549 times[1].tv_usec = mtime_nsec / 1000;
8f776fd9
TK
3550
3551#ifdef HAVE_FUTIMES
82e3bb2a
TK
3552 if (fd >= 0)
3553 return (futimes(fd, times));
3554#else
3555 (void)fd; /* UNUSED */
8f776fd9 3556#endif
8f776fd9 3557#ifdef HAVE_LUTIMES
82e3bb2a
TK
3558 (void)mode; /* UNUSED */
3559 return (lutimes(name, times));
8f776fd9 3560#else
82e3bb2a
TK
3561 if (S_ISLNK(mode))
3562 return (0);
3563 return (utimes(name, times));
8f776fd9 3564#endif
5223514b 3565
8f776fd9 3566#elif defined(HAVE_UTIME)
5223514b
TK
3567 /*
3568 * utime() is POSIX-standard but only supports 1s resolution and
3569 * does not support fds or symlinks.
3570 */
8f776fd9 3571 struct utimbuf times;
82e3bb2a
TK
3572 (void)fd; /* UNUSED */
3573 (void)name; /* UNUSED */
3574 (void)atime_nsec; /* UNUSED */
3575 (void)mtime_nsec; /* UNUSED */
3576 times.actime = atime;
3577 times.modtime = mtime;
5c6d3586 3578 if (S_ISLNK(mode))
82e3bb2a
TK
3579 return (ARCHIVE_OK);
3580 return (utime(name, &times));
5223514b 3581
82e3bb2a 3582#else
5223514b
TK
3583 /*
3584 * We don't know how to set the time on this platform.
3585 */
d2d75ef8
MN
3586 (void)fd; /* UNUSED */
3587 (void)mode; /* UNUSED */
3588 (void)name; /* UNUSED */
c684b115 3589 (void)atime; /* UNUSED */
d2d75ef8 3590 (void)atime_nsec; /* UNUSED */
c684b115 3591 (void)mtime; /* UNUSED */
d2d75ef8 3592 (void)mtime_nsec; /* UNUSED */
82e3bb2a 3593 return (ARCHIVE_WARN);
5223514b 3594#endif
82e3bb2a 3595}
5223514b 3596
8f2b0013 3597#ifdef F_SETTIMES
631247e1
BJ
3598static int
3599set_time_tru64(int fd, int mode, const char *name,
3600 time_t atime, long atime_nsec,
3601 time_t mtime, long mtime_nsec,
3602 time_t ctime, long ctime_nsec)
3603{
3604 struct attr_timbuf tstamp;
8f2b0013
REB
3605 tstamp.atime.tv_sec = atime;
3606 tstamp.mtime.tv_sec = mtime;
3607 tstamp.ctime.tv_sec = ctime;
3608#if defined (__hpux) && defined (__ia64)
3609 tstamp.atime.tv_nsec = atime_nsec;
3610 tstamp.mtime.tv_nsec = mtime_nsec;
3611 tstamp.ctime.tv_nsec = ctime_nsec;
3612#else
6893cc54 3613 tstamp.atime.tv_usec = atime_nsec / 1000;
8f2b0013
REB
3614 tstamp.mtime.tv_usec = mtime_nsec / 1000;
3615 tstamp.ctime.tv_usec = ctime_nsec / 1000;
3616#endif
631247e1
BJ
3617 return (fcntl(fd,F_SETTIMES,&tstamp));
3618}
8f2b0013 3619#endif /* F_SETTIMES */
631247e1 3620
5223514b 3621static int
21ebff3b
TK
3622set_times(struct archive_write_disk *a,
3623 int fd, int mode, const char *name,
5223514b
TK
3624 time_t atime, long atime_nanos,
3625 time_t birthtime, long birthtime_nanos,
b648c6c7 3626 time_t mtime, long mtime_nanos,
fc22f4a6 3627 time_t cctime, long ctime_nanos)
5223514b 3628{
21ebff3b
TK
3629 /* Note: set_time doesn't use libarchive return conventions!
3630 * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */
3631 int r1 = 0, r2 = 0;
5223514b 3632
631247e1
BJ
3633#ifdef F_SETTIMES
3634 /*
3635 * on Tru64 try own fcntl first which can restore even the
3636 * ctime, fall back to default code path below if it fails
3637 * or if we are not running as root
3638 */
3639 if (a->user_uid == 0 &&
3640 set_time_tru64(fd, mode, name,
3641 atime, atime_nanos, mtime,
fc22f4a6 3642 mtime_nanos, cctime, ctime_nanos) == 0) {
631247e1
BJ
3643 return (ARCHIVE_OK);
3644 }
433f74b0 3645#else /* Tru64 */
fc22f4a6 3646 (void)cctime; /* UNUSED */
433f74b0 3647 (void)ctime_nanos; /* UNUSED */
631247e1
BJ
3648#endif /* Tru64 */
3649
5223514b
TK
3650#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
3651 /*
3652 * If you have struct stat.st_birthtime, we assume BSD
3653 * birthtime semantics, in which {f,l,}utimes() updates
3654 * birthtime to earliest mtime. So we set the time twice,
3655 * first using the birthtime, then using the mtime. If
3656 * birthtime == mtime, this isn't necessary, so we skip it.
3657 * If birthtime > mtime, then this won't work, so we skip it.
3658 */
3659 if (birthtime < mtime
3660 || (birthtime == mtime && birthtime_nanos < mtime_nanos))
3661 r1 = set_time(fd, mode, name,
3662 atime, atime_nanos,
3663 birthtime, birthtime_nanos);
d2d75ef8
MN
3664#else
3665 (void)birthtime; /* UNUSED */
3666 (void)birthtime_nanos; /* UNUSED */
82e3bb2a 3667#endif
5223514b
TK
3668 r2 = set_time(fd, mode, name,
3669 atime, atime_nanos,
3670 mtime, mtime_nanos);
21ebff3b
TK
3671 if (r1 != 0 || r2 != 0) {
3672 archive_set_error(&a->archive, errno,
3673 "Can't restore time");
3674 return (ARCHIVE_WARN);
3675 }
3676 return (ARCHIVE_OK);
5223514b 3677}
82e3bb2a
TK
3678
3679static int
5223514b 3680set_times_from_entry(struct archive_write_disk *a)
82e3bb2a 3681{
fc22f4a6 3682 time_t atime, birthtime, mtime, cctime;
b648c6c7 3683 long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
5223514b
TK
3684
3685 /* Suitable defaults. */
fc22f4a6 3686 atime = birthtime = mtime = cctime = a->start_time;
b648c6c7 3687 atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
8f776fd9 3688
8e71fa72
TK
3689 /* If no time was provided, we're done. */
3690 if (!archive_entry_atime_is_set(a->entry)
82e3bb2a
TK
3691#if HAVE_STRUCT_STAT_ST_BIRTHTIME
3692 && !archive_entry_birthtime_is_set(a->entry)
3693#endif
8e71fa72
TK
3694 && !archive_entry_mtime_is_set(a->entry))
3695 return (ARCHIVE_OK);
3696
82e3bb2a
TK
3697 if (archive_entry_atime_is_set(a->entry)) {
3698 atime = archive_entry_atime(a->entry);
3699 atime_nsec = archive_entry_atime_nsec(a->entry);
3700 }
5223514b
TK
3701 if (archive_entry_birthtime_is_set(a->entry)) {
3702 birthtime = archive_entry_birthtime(a->entry);
3703 birthtime_nsec = archive_entry_birthtime_nsec(a->entry);
3704 }
82e3bb2a
TK
3705 if (archive_entry_mtime_is_set(a->entry)) {
3706 mtime = archive_entry_mtime(a->entry);
3707 mtime_nsec = archive_entry_mtime_nsec(a->entry);
3708 }
b648c6c7 3709 if (archive_entry_ctime_is_set(a->entry)) {
fc22f4a6 3710 cctime = archive_entry_ctime(a->entry);
b648c6c7
BJ
3711 ctime_nsec = archive_entry_ctime_nsec(a->entry);
3712 }
82e3bb2a 3713
21ebff3b 3714 return set_times(a, a->fd, a->mode, a->name,
5223514b
TK
3715 atime, atime_nsec,
3716 birthtime, birthtime_nsec,
b648c6c7 3717 mtime, mtime_nsec,
fc22f4a6 3718 cctime, ctime_nsec);
8f776fd9 3719}
8f776fd9
TK
3720
3721static int
3722set_mode(struct archive_write_disk *a, int mode)
3723{
3724 int r = ARCHIVE_OK;
6aea568d 3725 int r2;
8f776fd9
TK
3726 mode &= 07777; /* Strip off file type bits. */
3727
3728 if (a->todo & TODO_SGID_CHECK) {
3729 /*
3730 * If we don't know the GID is right, we must stat()
3731 * to verify it. We can't just check the GID of this
3732 * process, since systems sometimes set GID from
3733 * the enclosing dir or based on ACLs.
3734 */
911dc2bf 3735 if ((r = lazy_stat(a)) != ARCHIVE_OK)
2f8873c2 3736 return (r);
8f776fd9
TK
3737 if (a->pst->st_gid != a->gid) {
3738 mode &= ~ S_ISGID;
3739 if (a->flags & ARCHIVE_EXTRACT_OWNER) {
3740 /*
3741 * This is only an error if you
3742 * requested owner restore. If you
3743 * didn't, we'll try to restore
3744 * sgid/suid, but won't consider it a
3745 * problem if we can't.
3746 */
3747 archive_set_error(&a->archive, -1,
3748 "Can't restore SGID bit");
3749 r = ARCHIVE_WARN;
3750 }
3751 }
3752 /* While we're here, double-check the UID. */
3753 if (a->pst->st_uid != a->uid
3754 && (a->todo & TODO_SUID)) {
3755 mode &= ~ S_ISUID;
3756 if (a->flags & ARCHIVE_EXTRACT_OWNER) {
3757 archive_set_error(&a->archive, -1,
3758 "Can't restore SUID bit");
3759 r = ARCHIVE_WARN;
3760 }
3761 }
3762 a->todo &= ~TODO_SGID_CHECK;
3763 a->todo &= ~TODO_SUID_CHECK;
3764 } else if (a->todo & TODO_SUID_CHECK) {
3765 /*
3766 * If we don't know the UID is right, we can just check
3767 * the user, since all systems set the file UID from
3768 * the process UID.
3769 */
3770 if (a->user_uid != a->uid) {
3771 mode &= ~ S_ISUID;
3772 if (a->flags & ARCHIVE_EXTRACT_OWNER) {
3773 archive_set_error(&a->archive, -1,
3774 "Can't make file SUID");
3775 r = ARCHIVE_WARN;
3776 }
3777 }
3778 a->todo &= ~TODO_SUID_CHECK;
3779 }
3780
3781 if (S_ISLNK(a->mode)) {
91b5c59a 3782#ifdef HAVE_LCHMOD
8f776fd9 3783 /*
91b5c59a 3784 * If this is a symlink, use lchmod(). If the
8f776fd9
TK
3785 * platform doesn't support lchmod(), just skip it. A
3786 * platform that doesn't provide a way to set
3787 * permissions on symlinks probably ignores
3788 * permissions on symlinks, so a failure here has no
3789 * impact.
3790 */
91b5c59a 3791 if (lchmod(a->name, mode) != 0) {
65fe1034
RF
3792 switch (errno) {
3793 case ENOTSUP:
3794 case ENOSYS:
5ad9ecdd 3795#if ENOTSUP != EOPNOTSUPP
65fe1034 3796 case EOPNOTSUPP:
5ad9ecdd 3797#endif
65fe1034
RF
3798 /*
3799 * if lchmod is defined but the platform
3800 * doesn't support it, silently ignore
3801 * error
3802 */
3803 break;
3804 default:
3805 archive_set_error(&a->archive, errno,
3806 "Can't set permissions to 0%o", (int)mode);
3807 r = ARCHIVE_WARN;
3808 }
8f776fd9 3809 }
91b5c59a 3810#endif
8f776fd9
TK
3811 } else if (!S_ISDIR(a->mode)) {
3812 /*
3813 * If it's not a symlink and not a dir, then use
3814 * fchmod() or chmod(), depending on whether we have
3815 * an fd. Dirs get their perms set during the
3816 * post-extract fixup, which is handled elsewhere.
3817 */
3818#ifdef HAVE_FCHMOD
6aea568d
MM
3819 if (a->fd >= 0)
3820 r2 = fchmod(a->fd, mode);
3821 else
8f776fd9 3822#endif
6aea568d
MM
3823 /* If this platform lacks fchmod(), then
3824 * we'll just use chmod(). */
3825 r2 = chmod(a->name, mode);
3826
3827 if (r2 != 0) {
3828 archive_set_error(&a->archive, errno,
3829 "Can't set permissions to 0%o", (int)mode);
3830 r = ARCHIVE_WARN;
3831 }
8f776fd9
TK
3832 }
3833 return (r);
3834}
3835
3836static int
3837set_fflags(struct archive_write_disk *a)
3838{
3839 struct fixup_entry *le;
3840 unsigned long set, clear;
3841 int r;
8f776fd9 3842 mode_t mode = archive_entry_mode(a->entry);
8f776fd9
TK
3843 /*
3844 * Make 'critical_flags' hold all file flags that can't be
3845 * immediately restored. For example, on BSD systems,
3846 * SF_IMMUTABLE prevents hardlinks from being created, so
3847 * should not be set until after any hardlinks are created. To
3848 * preserve some semblance of portability, this uses #ifdef
3849 * extensively. Ugly, but it works.
3850 *
3851 * Yes, Virginia, this does create a security race. It's mitigated
3852 * somewhat by the practice of creating dirs 0700 until the extract
3853 * is done, but it would be nice if we could do more than that.
3854 * People restoring critical file systems should be wary of
3855 * other programs that might try to muck with files as they're
3856 * being restored.
3857 */
e2441c28 3858 const int critical_flags = 0
8f776fd9 3859#ifdef SF_IMMUTABLE
e2441c28 3860 | SF_IMMUTABLE
8f776fd9
TK
3861#endif
3862#ifdef UF_IMMUTABLE
e2441c28 3863 | UF_IMMUTABLE
8f776fd9
TK
3864#endif
3865#ifdef SF_APPEND
e2441c28 3866 | SF_APPEND
8f776fd9
TK
3867#endif
3868#ifdef UF_APPEND
e2441c28 3869 | UF_APPEND
8f776fd9 3870#endif
a9c5818b 3871#if defined(FS_APPEND_FL)
e2441c28 3872 | FS_APPEND_FL
a9c5818b 3873#elif defined(EXT2_APPEND_FL)
e2441c28 3874 | EXT2_APPEND_FL
8f776fd9 3875#endif
a9c5818b 3876#if defined(FS_IMMUTABLE_FL)
e2441c28 3877 | FS_IMMUTABLE_FL
a9c5818b 3878#elif defined(EXT2_IMMUTABLE_FL)
e2441c28 3879 | EXT2_IMMUTABLE_FL
8f776fd9 3880#endif
a9c5818b 3881#ifdef FS_JOURNAL_DATA_FL
e2441c28 3882 | FS_JOURNAL_DATA_FL
a9c5818b 3883#endif
e2441c28 3884 ;
8f776fd9
TK
3885
3886 if (a->todo & TODO_FFLAGS) {
3887 archive_entry_fflags(a->entry, &set, &clear);
3888
3889 /*
3890 * The first test encourages the compiler to eliminate
3891 * all of this if it's not necessary.
3892 */
3893 if ((critical_flags != 0) && (set & critical_flags)) {
3894 le = current_fixup(a, a->name);
62756a10
MN
3895 if (le == NULL)
3896 return (ARCHIVE_FATAL);
ede459d2 3897 le->filetype = archive_entry_filetype(a->entry);
8f776fd9
TK
3898 le->fixup |= TODO_FFLAGS;
3899 le->fflags_set = set;
3900 /* Store the mode if it's not already there. */
3901 if ((le->fixup & TODO_MODE) == 0)
3902 le->mode = mode;
3903 } else {
3904 r = set_fflags_platform(a, a->fd,
3905 a->name, mode, set, clear);
3906 if (r != ARCHIVE_OK)
3907 return (r);
3908 }
3909 }
3910 return (ARCHIVE_OK);
3911}
3912
6a595ef6
BD
3913static int
3914clear_nochange_fflags(struct archive_write_disk *a)
3915{
6a595ef6 3916 mode_t mode = archive_entry_mode(a->entry);
e2441c28 3917 const int nochange_flags = 0
6a595ef6 3918#ifdef SF_IMMUTABLE
e2441c28 3919 | SF_IMMUTABLE
6a595ef6
BD
3920#endif
3921#ifdef UF_IMMUTABLE
e2441c28 3922 | UF_IMMUTABLE
6a595ef6
BD
3923#endif
3924#ifdef SF_APPEND
e2441c28 3925 | SF_APPEND
6a595ef6
BD
3926#endif
3927#ifdef UF_APPEND
e2441c28 3928 | UF_APPEND
6a595ef6
BD
3929#endif
3930#ifdef EXT2_APPEND_FL
e2441c28 3931 | EXT2_APPEND_FL
6a595ef6
BD
3932#endif
3933#ifdef EXT2_IMMUTABLE_FL
e2441c28 3934 | EXT2_IMMUTABLE_FL
6a595ef6 3935#endif
e2441c28 3936 ;
6a595ef6 3937
cc9cbbb1
MM
3938 return (set_fflags_platform(a, a->fd, a->name, mode, 0,
3939 nochange_flags));
6a595ef6
BD
3940}
3941
8f776fd9 3942
c5e9786e
TK
3943#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS)
3944/*
3945 * BSD reads flags using stat() and sets them with one of {f,l,}chflags()
3946 */
8f776fd9
TK
3947static int
3948set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
3949 mode_t mode, unsigned long set, unsigned long clear)
3950{
2f8873c2 3951 int r;
e2441c28
MM
3952 const int sf_mask = 0
3953#ifdef SF_APPEND
3954 | SF_APPEND
3955#endif
3956#ifdef SF_ARCHIVED
3957 | SF_ARCHIVED
3958#endif
3959#ifdef SF_IMMUTABLE
3960 | SF_IMMUTABLE
3961#endif
3962#ifdef SF_NOUNLINK
3963 | SF_NOUNLINK
3964#endif
3965 ;
8f776fd9 3966 (void)mode; /* UNUSED */
1f759ffd 3967
8f776fd9
TK
3968 if (set == 0 && clear == 0)
3969 return (ARCHIVE_OK);
3970
3971 /*
3972 * XXX Is the stat here really necessary? Or can I just use
3973 * the 'set' flags directly? In particular, I'm not sure
3974 * about the correct approach if we're overwriting an existing
3975 * file that already has flags on it. XXX
3976 */
911dc2bf 3977 if ((r = lazy_stat(a)) != ARCHIVE_OK)
2f8873c2 3978 return (r);
8f776fd9
TK
3979
3980 a->st.st_flags &= ~clear;
3981 a->st.st_flags |= set;
1f759ffd
MM
3982
3983 /* Only super-user may change SF_* flags */
e2441c28 3984
1f759ffd
MM
3985 if (a->user_uid != 0)
3986 a->st.st_flags &= ~sf_mask;
3987
8f776fd9
TK
3988#ifdef HAVE_FCHFLAGS
3989 /* If platform has fchflags() and we were given an fd, use it. */
3990 if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0)
3991 return (ARCHIVE_OK);
3992#endif
3993 /*
3994 * If we can't use the fd to set the flags, we'll use the
3995 * pathname to set flags. We prefer lchflags() but will use
3996 * chflags() if we must.
3997 */
3998#ifdef HAVE_LCHFLAGS
3999 if (lchflags(name, a->st.st_flags) == 0)
4000 return (ARCHIVE_OK);
4001#elif defined(HAVE_CHFLAGS)
4002 if (S_ISLNK(a->st.st_mode)) {
4003 archive_set_error(&a->archive, errno,
4004 "Can't set file flags on symlink.");
4005 return (ARCHIVE_WARN);
4006 }
4007 if (chflags(name, a->st.st_flags) == 0)
4008 return (ARCHIVE_OK);
4009#endif
4010 archive_set_error(&a->archive, errno,
4011 "Failed to set file flags");
4012 return (ARCHIVE_WARN);
4013}
4014
a9c5818b
MM
4015#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
4016 defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
4017 (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
4018 defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
8f776fd9 4019/*
c5e9786e 4020 * Linux uses ioctl() to read and write file flags.
8f776fd9
TK
4021 */
4022static int
4023set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
4024 mode_t mode, unsigned long set, unsigned long clear)
4025{
4026 int ret;
4027 int myfd = fd;
0970d06a 4028 int newflags, oldflags;
8f776fd9
TK
4029 /*
4030 * Linux has no define for the flags that are only settable by
4031 * the root user. This code may seem a little complex, but
4032 * there seem to be some Linux systems that lack these
4033 * defines. (?) The code below degrades reasonably gracefully
4034 * if sf_mask is incomplete.
4035 */
e2441c28 4036 const int sf_mask = 0
a9c5818b 4037#if defined(FS_IMMUTABLE_FL)
e2441c28 4038 | FS_IMMUTABLE_FL
a9c5818b 4039#elif defined(EXT2_IMMUTABLE_FL)
e2441c28 4040 | EXT2_IMMUTABLE_FL
8f776fd9 4041#endif
a9c5818b 4042#if defined(FS_APPEND_FL)
e2441c28 4043 | FS_APPEND_FL
a9c5818b 4044#elif defined(EXT2_APPEND_FL)
e2441c28 4045 | EXT2_APPEND_FL
a9c5818b
MM
4046#endif
4047#if defined(FS_JOURNAL_DATA_FL)
e2441c28 4048 | FS_JOURNAL_DATA_FL
8f776fd9 4049#endif
e2441c28
MM
4050 ;
4051
4052 if (set == 0 && clear == 0)
4053 return (ARCHIVE_OK);
4054 /* Only regular files and dirs can have flags. */
4055 if (!S_ISREG(mode) && !S_ISDIR(mode))
4056 return (ARCHIVE_OK);
4057
4058 /* If we weren't given an fd, open it ourselves. */
4059 if (myfd < 0) {
e2ad1a2c
MM
4060 myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY |
4061 O_CLOEXEC | O_NOFOLLOW);
e2441c28
MM
4062 __archive_ensure_cloexec_flag(myfd);
4063 }
4064 if (myfd < 0)
4065 return (ARCHIVE_OK);
4066
8f776fd9
TK
4067 /*
4068 * XXX As above, this would be way simpler if we didn't have
4069 * to read the current flags from disk. XXX
4070 */
4071 ret = ARCHIVE_OK;
cafcd565
CP
4072
4073 /* Read the current file flags. */
a9c5818b
MM
4074 if (ioctl(myfd,
4075#ifdef FS_IOC_GETFLAGS
4076 FS_IOC_GETFLAGS,
4077#else
4078 EXT2_IOC_GETFLAGS,
4079#endif
4080 &oldflags) < 0)
cafcd565
CP
4081 goto fail;
4082
8f776fd9 4083 /* Try setting the flags as given. */
cafcd565 4084 newflags = (oldflags & ~clear) | set;
a9c5818b
MM
4085 if (ioctl(myfd,
4086#ifdef FS_IOC_SETFLAGS
4087 FS_IOC_SETFLAGS,
4088#else
4089 EXT2_IOC_SETFLAGS,
4090#endif
4091 &newflags) >= 0)
cafcd565
CP
4092 goto cleanup;
4093 if (errno != EPERM)
4094 goto fail;
4095
8f776fd9 4096 /* If we couldn't set all the flags, try again with a subset. */
cafcd565
CP
4097 newflags &= ~sf_mask;
4098 oldflags &= sf_mask;
4099 newflags |= oldflags;
a9c5818b
MM
4100 if (ioctl(myfd,
4101#ifdef FS_IOC_SETFLAGS
4102 FS_IOC_SETFLAGS,
4103#else
4104 EXT2_IOC_SETFLAGS,
4105#endif
4106 &newflags) >= 0)
cafcd565
CP
4107 goto cleanup;
4108
8f776fd9
TK
4109 /* We couldn't set the flags, so report the failure. */
4110fail:
4111 archive_set_error(&a->archive, errno,
4112 "Failed to set file flags");
4113 ret = ARCHIVE_WARN;
4114cleanup:
4115 if (fd < 0)
4116 close(myfd);
4117 return (ret);
4118}
4119
c5e9786e 4120#else
8f776fd9
TK
4121
4122/*
4123 * Of course, some systems have neither BSD chflags() nor Linux' flags
4124 * support through ioctl().
4125 */
4126static int
4127set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
4128 mode_t mode, unsigned long set, unsigned long clear)
4129{
4130 (void)a; /* UNUSED */
4131 (void)fd; /* UNUSED */
4132 (void)name; /* UNUSED */
4133 (void)mode; /* UNUSED */
4134 (void)set; /* UNUSED */
4135 (void)clear; /* UNUSED */
4136 return (ARCHIVE_OK);
4137}
4138
4139#endif /* __linux */
4140
b8ad1655
TK
4141#ifndef HAVE_COPYFILE_H
4142/* Default is to simply drop Mac extended metadata. */
4143static int
4144set_mac_metadata(struct archive_write_disk *a, const char *pathname,
4145 const void *metadata, size_t metadata_size)
4146{
4147 (void)a; /* UNUSED */
4148 (void)pathname; /* UNUSED */
4149 (void)metadata; /* UNUSED */
4150 (void)metadata_size; /* UNUSED */
4151 return (ARCHIVE_OK);
4152}
a70241b7
MN
4153
4154static int
4155fixup_appledouble(struct archive_write_disk *a, const char *pathname)
4156{
4157 (void)a; /* UNUSED */
4158 (void)pathname; /* UNUSED */
4159 return (ARCHIVE_OK);
4160}
b8ad1655
TK
4161#else
4162
4163/*
4164 * On Mac OS, we use copyfile() to unpack the metadata and
4165 * apply it to the target file.
4166 */
4d920441 4167
63f4eb7d 4168#if defined(HAVE_SYS_XATTR_H)
4d920441
MN
4169static int
4170copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd)
4171{
4172 ssize_t xattr_size;
4173 char *xattr_names = NULL, *xattr_val = NULL;
4174 int ret = ARCHIVE_OK, xattr_i;
4175
4176 xattr_size = flistxattr(tmpfd, NULL, 0, 0);
4177 if (xattr_size == -1) {
4178 archive_set_error(&a->archive, errno,
4179 "Failed to read metadata(xattr)");
4180 ret = ARCHIVE_WARN;
4181 goto exit_xattr;
4182 }
4183 xattr_names = malloc(xattr_size);
4184 if (xattr_names == NULL) {
4185 archive_set_error(&a->archive, ENOMEM,
4186 "Can't allocate memory for metadata(xattr)");
4187 ret = ARCHIVE_FATAL;
4188 goto exit_xattr;
4189 }
4190 xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0);
4191 if (xattr_size == -1) {
4192 archive_set_error(&a->archive, errno,
4193 "Failed to read metadata(xattr)");
4194 ret = ARCHIVE_WARN;
4195 goto exit_xattr;
4196 }
4197 for (xattr_i = 0; xattr_i < xattr_size;
4198 xattr_i += strlen(xattr_names + xattr_i) + 1) {
ae086fb2 4199 char *xattr_val_saved;
4d920441
MN
4200 ssize_t s;
4201 int f;
4202
4203 s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0);
4204 if (s == -1) {
4205 archive_set_error(&a->archive, errno,
4206 "Failed to get metadata(xattr)");
4207 ret = ARCHIVE_WARN;
4208 goto exit_xattr;
4209 }
ae086fb2 4210 xattr_val_saved = xattr_val;
4d920441
MN
4211 xattr_val = realloc(xattr_val, s);
4212 if (xattr_val == NULL) {
4213 archive_set_error(&a->archive, ENOMEM,
4214 "Failed to get metadata(xattr)");
4215 ret = ARCHIVE_WARN;
ae086fb2 4216 free(xattr_val_saved);
4d920441
MN
4217 goto exit_xattr;
4218 }
4219 s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0);
4220 if (s == -1) {
4221 archive_set_error(&a->archive, errno,
4222 "Failed to get metadata(xattr)");
4223 ret = ARCHIVE_WARN;
4224 goto exit_xattr;
4225 }
4226 f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0);
4227 if (f == -1) {
4228 archive_set_error(&a->archive, errno,
4229 "Failed to get metadata(xattr)");
4230 ret = ARCHIVE_WARN;
4231 goto exit_xattr;
4232 }
4233 }
4234exit_xattr:
4235 free(xattr_names);
4236 free(xattr_val);
4237 return (ret);
4238}
63f4eb7d 4239#endif
4d920441
MN
4240
4241static int
4242copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
4243{
3e668297
JS
4244#ifndef HAVE_SYS_ACL_H
4245 return 0;
4246#else
4d920441
MN
4247 acl_t acl, dfacl = NULL;
4248 int acl_r, ret = ARCHIVE_OK;
4249
4250 acl = acl_get_fd(tmpfd);
4251 if (acl == NULL) {
4252 if (errno == ENOENT)
4253 /* There are not any ACLs. */
4254 return (ret);
4255 archive_set_error(&a->archive, errno,
4256 "Failed to get metadata(acl)");
4257 ret = ARCHIVE_WARN;
4258 goto exit_acl;
4259 }
4260 dfacl = acl_dup(acl);
4261 acl_r = acl_set_fd(dffd, dfacl);
4262 if (acl_r == -1) {
4263 archive_set_error(&a->archive, errno,
4264 "Failed to get metadata(acl)");
4265 ret = ARCHIVE_WARN;
4266 goto exit_acl;
4267 }
4268exit_acl:
4269 if (acl)
4270 acl_free(acl);
4271 if (dfacl)
4272 acl_free(dfacl);
4273 return (ret);
3e668297 4274#endif
4d920441
MN
4275}
4276
4277static int
4278create_tempdatafork(struct archive_write_disk *a, const char *pathname)
4279{
4280 struct archive_string tmpdatafork;
4281 int tmpfd;
4282
4283 archive_string_init(&tmpdatafork);
4284 archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
4285 tmpfd = mkstemp(tmpdatafork.s);
4286 if (tmpfd < 0) {
4287 archive_set_error(&a->archive, errno,
4288 "Failed to mkstemp");
4289 archive_string_free(&tmpdatafork);
4290 return (-1);
4291 }
4292 if (copyfile(pathname, tmpdatafork.s, 0,
4293 COPYFILE_UNPACK | COPYFILE_NOFOLLOW
4294 | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
4295 archive_set_error(&a->archive, errno,
4296 "Failed to restore metadata");
4297 close(tmpfd);
4298 tmpfd = -1;
4299 }
4300 unlink(tmpdatafork.s);
4301 archive_string_free(&tmpdatafork);
4302 return (tmpfd);
4303}
4304
4305static int
4306copy_metadata(struct archive_write_disk *a, const char *metadata,
4307 const char *datafork, int datafork_compressed)
4308{
4309 int ret = ARCHIVE_OK;
4310
4311 if (datafork_compressed) {
4312 int dffd, tmpfd;
4313
4314 tmpfd = create_tempdatafork(a, metadata);
4315 if (tmpfd == -1)
4316 return (ARCHIVE_WARN);
4317
4318 /*
4319 * Do not open the data fork compressed by HFS+ compression
4320 * with at least a writing mode(O_RDWR or O_WRONLY). it
4321 * makes the data fork uncompressed.
4322 */
4323 dffd = open(datafork, 0);
4324 if (dffd == -1) {
4325 archive_set_error(&a->archive, errno,
4326 "Failed to open the data fork for metadata");
4327 close(tmpfd);
4328 return (ARCHIVE_WARN);
4329 }
4330
63f4eb7d 4331#if defined(HAVE_SYS_XATTR_H)
4d920441
MN
4332 ret = copy_xattrs(a, tmpfd, dffd);
4333 if (ret == ARCHIVE_OK)
63f4eb7d 4334#endif
4d920441
MN
4335 ret = copy_acls(a, tmpfd, dffd);
4336 close(tmpfd);
4337 close(dffd);
4338 } else {
4339 if (copyfile(metadata, datafork, 0,
4340 COPYFILE_UNPACK | COPYFILE_NOFOLLOW
4341 | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
4342 archive_set_error(&a->archive, errno,
4343 "Failed to restore metadata");
4344 ret = ARCHIVE_WARN;
4345 }
4346 }
4347 return (ret);
4348}
4349
b8ad1655
TK
4350static int
4351set_mac_metadata(struct archive_write_disk *a, const char *pathname,
4352 const void *metadata, size_t metadata_size)
4353{
4354 struct archive_string tmp;
4355 ssize_t written;
4356 int fd;
4357 int ret = ARCHIVE_OK;
4358
4359 /* This would be simpler if copyfile() could just accept the
4360 * metadata as a block of memory; then we could sidestep this
4361 * silly dance of writing the data to disk just so that
4362 * copyfile() can read it back in again. */
4363 archive_string_init(&tmp);
4364 archive_strcpy(&tmp, pathname);
4365 archive_strcat(&tmp, ".XXXXXX");
4366 fd = mkstemp(tmp.s);
4367
4368 if (fd < 0) {
4369 archive_set_error(&a->archive, errno,
4370 "Failed to restore metadata");
f356f0e0 4371 archive_string_free(&tmp);
b8ad1655
TK
4372 return (ARCHIVE_WARN);
4373 }
4374 written = write(fd, metadata, metadata_size);
4375 close(fd);
4d920441 4376 if ((size_t)written != metadata_size) {
b8ad1655
TK
4377 archive_set_error(&a->archive, errno,
4378 "Failed to restore metadata");
4379 ret = ARCHIVE_WARN;
4d920441
MN
4380 } else {
4381 int compressed;
4382
63f4eb7d 4383#if defined(UF_COMPRESSED)
4d920441
MN
4384 if ((a->todo & TODO_HFS_COMPRESSION) != 0 &&
4385 (ret = lazy_stat(a)) == ARCHIVE_OK)
4386 compressed = a->st.st_flags & UF_COMPRESSED;
4387 else
63f4eb7d 4388#endif
4d920441
MN
4389 compressed = 0;
4390 ret = copy_metadata(a, tmp.s, pathname, compressed);
b8ad1655
TK
4391 }
4392 unlink(tmp.s);
f356f0e0 4393 archive_string_free(&tmp);
b8ad1655
TK
4394 return (ret);
4395}
a70241b7
MN
4396
4397static int
4398fixup_appledouble(struct archive_write_disk *a, const char *pathname)
4399{
4400 char buff[8];
4401 struct stat st;
4402 const char *p;
4403 struct archive_string datafork;
4404 int fd = -1, ret = ARCHIVE_OK;
4405
4406 archive_string_init(&datafork);
4407 /* Check if the current file name is a type of the resource
4408 * fork file. */
4409 p = strrchr(pathname, '/');
4410 if (p == NULL)
4411 p = pathname;
4412 else
4413 p++;
4414 if (p[0] != '.' || p[1] != '_')
4415 goto skip_appledouble;
4416
4417 /*
4418 * Check if the data fork file exists.
4419 *
4420 * TODO: Check if this write disk object has handled it.
4421 */
4422 archive_strncpy(&datafork, pathname, p - pathname);
4423 archive_strcat(&datafork, p + 2);
e6056040 4424 if (
4425#ifdef HAVE_LSTAT
4426 lstat(datafork.s, &st) == -1 ||
4427#else
4428 la_stat(datafork.s, &st) == -1 ||
4429#endif
390d8301 4430 (((st.st_mode & AE_IFMT) != AE_IFREG) &&
4431 ((st.st_mode & AE_IFMT) != AE_IFDIR)))
a70241b7
MN
4432 goto skip_appledouble;
4433
4434 /*
4435 * Check if the file is in the AppleDouble form.
4436 */
4d920441 4437 fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC);
a70241b7
MN
4438 __archive_ensure_cloexec_flag(fd);
4439 if (fd == -1) {
4440 archive_set_error(&a->archive, errno,
4441 "Failed to open a restoring file");
4442 ret = ARCHIVE_WARN;
4443 goto skip_appledouble;
4444 }
4445 if (read(fd, buff, 8) == -1) {
4446 archive_set_error(&a->archive, errno,
4447 "Failed to read a restoring file");
4d920441 4448 close(fd);
a70241b7
MN
4449 ret = ARCHIVE_WARN;
4450 goto skip_appledouble;
4451 }
4d920441 4452 close(fd);
a70241b7
MN
4453 /* Check AppleDouble Magic Code. */
4454 if (archive_be32dec(buff) != 0x00051607)
4455 goto skip_appledouble;
4456 /* Check AppleDouble Version. */
4457 if (archive_be32dec(buff+4) != 0x00020000)
4458 goto skip_appledouble;
4459
4d920441 4460 ret = copy_metadata(a, pathname, datafork.s,
63f4eb7d 4461#if defined(UF_COMPRESSED)
4d920441 4462 st.st_flags & UF_COMPRESSED);
63f4eb7d
MN
4463#else
4464 0);
4465#endif
4d920441
MN
4466 if (ret == ARCHIVE_OK) {
4467 unlink(pathname);
4468 ret = ARCHIVE_EOF;
a70241b7 4469 }
a70241b7 4470skip_appledouble:
a70241b7
MN
4471 archive_string_free(&datafork);
4472 return (ret);
4473}
b8ad1655
TK
4474#endif
4475
365a91de 4476#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX
8f776fd9 4477/*
365a91de 4478 * Restore extended attributes - Linux, Darwin and AIX implementations:
0d621852 4479 * AIX' ea interface is syntaxwise identical to the Linux xattr interface.
8f776fd9
TK
4480 */
4481static int
4482set_xattrs(struct archive_write_disk *a)
4483{
4484 struct archive_entry *entry = a->entry;
c20d7a5c 4485 struct archive_string errlist;
8f776fd9
TK
4486 int ret = ARCHIVE_OK;
4487 int i = archive_entry_xattr_reset(entry);
c20d7a5c
MM
4488 short fail = 0;
4489
4490 archive_string_init(&errlist);
8f776fd9
TK
4491
4492 while (i--) {
4493 const char *name;
4494 const void *value;
4495 size_t size;
c20d7a5c
MM
4496 int e;
4497
8f776fd9 4498 archive_entry_xattr_next(entry, &name, &value, &size);
c20d7a5c
MM
4499
4500 if (name == NULL)
4501 continue;
365a91de 4502#if ARCHIVE_XATTR_LINUX
c20d7a5c
MM
4503 /* Linux: quietly skip POSIX.1e ACL extended attributes */
4504 if (strncmp(name, "system.", 7) == 0 &&
4505 (strcmp(name + 7, "posix_acl_access") == 0 ||
4506 strcmp(name + 7, "posix_acl_default") == 0))
4507 continue;
4508 if (strncmp(name, "trusted.SGI_", 12) == 0 &&
4509 (strcmp(name + 12, "ACL_DEFAULT") == 0 ||
4510 strcmp(name + 12, "ACL_FILE") == 0))
4511 continue;
4512
4513 /* Linux: xfsroot namespace is obsolete and unsupported */
4514 if (strncmp(name, "xfsroot.", 8) == 0) {
4515 fail = 1;
4516 archive_strcat(&errlist, name);
4517 archive_strappend_char(&errlist, ' ');
4518 continue;
4519 }
4520#endif
4521
4522 if (a->fd >= 0) {
4523#if ARCHIVE_XATTR_LINUX
4524 e = fsetxattr(a->fd, name, value, size, 0);
365a91de 4525#elif ARCHIVE_XATTR_DARWIN
c20d7a5c 4526 e = fsetxattr(a->fd, name, value, size, 0, 0);
365a91de 4527#elif ARCHIVE_XATTR_AIX
c20d7a5c 4528 e = fsetea(a->fd, name, value, size, 0);
8f776fd9 4529#endif
c20d7a5c 4530 } else {
365a91de 4531#if ARCHIVE_XATTR_LINUX
c20d7a5c
MM
4532 e = lsetxattr(archive_entry_pathname(entry),
4533 name, value, size, 0);
365a91de 4534#elif ARCHIVE_XATTR_DARWIN
c20d7a5c
MM
4535 e = setxattr(archive_entry_pathname(entry),
4536 name, value, size, 0, XATTR_NOFOLLOW);
365a91de 4537#elif ARCHIVE_XATTR_AIX
c20d7a5c
MM
4538 e = lsetea(archive_entry_pathname(entry),
4539 name, value, size, 0);
0d621852 4540#endif
c20d7a5c
MM
4541 }
4542 if (e == -1) {
8f776fd9 4543 ret = ARCHIVE_WARN;
c20d7a5c
MM
4544 archive_strcat(&errlist, name);
4545 archive_strappend_char(&errlist, ' ');
4546 if (errno != ENOTSUP && errno != ENOSYS)
4547 fail = 1;
8f776fd9
TK
4548 }
4549 }
c20d7a5c
MM
4550
4551 if (ret == ARCHIVE_WARN) {
4552 if (fail && errlist.length > 0) {
4553 errlist.length--;
4554 errlist.s[errlist.length] = '\0';
4555 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4556 "Cannot restore extended attributes: %s",
4557 errlist.s);
4558 } else
4559 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4560 "Cannot restore extended "
4561 "attributes on this file system.");
4562 }
4563
4564 archive_string_free(&errlist);
8f776fd9
TK
4565 return (ret);
4566}
365a91de 4567#elif ARCHIVE_XATTR_FREEBSD
b21f351a
TK
4568/*
4569 * Restore extended attributes - FreeBSD implementation
4570 */
4571static int
4572set_xattrs(struct archive_write_disk *a)
4573{
4574 struct archive_entry *entry = a->entry;
c20d7a5c 4575 struct archive_string errlist;
b21f351a
TK
4576 int ret = ARCHIVE_OK;
4577 int i = archive_entry_xattr_reset(entry);
c20d7a5c
MM
4578 short fail = 0;
4579
4580 archive_string_init(&errlist);
b21f351a
TK
4581
4582 while (i--) {
4583 const char *name;
4584 const void *value;
4585 size_t size;
4586 archive_entry_xattr_next(entry, &name, &value, &size);
4587 if (name != NULL) {
4588 int e;
4589 int namespace;
4590
4d1a6ebc
SW
4591 namespace = EXTATTR_NAMESPACE_USER;
4592
b21f351a
TK
4593 if (strncmp(name, "user.", 5) == 0) {
4594 /* "user." attributes go to user namespace */
4595 name += 5;
4596 namespace = EXTATTR_NAMESPACE_USER;
08f53f56
SW
4597 } else if (strncmp(name, "system.", 7) == 0) {
4598 name += 7;
4599 namespace = EXTATTR_NAMESPACE_SYSTEM;
5b4bc233
SW
4600 if (!strcmp(name, "nfs4.acl") ||
4601 !strcmp(name, "posix1e.acl_access") ||
4602 !strcmp(name, "posix1e.acl_default"))
4603 continue;
b21f351a 4604 } else {
c20d7a5c
MM
4605 /* Other namespaces are unsupported */
4606 archive_strcat(&errlist, name);
4607 archive_strappend_char(&errlist, ' ');
4608 fail = 1;
b21f351a
TK
4609 ret = ARCHIVE_WARN;
4610 continue;
4611 }
365a91de
MM
4612
4613 if (a->fd >= 0) {
4d1a6ebc
SW
4614 /*
4615 * On FreeBSD, extattr_set_fd does not
4616 * return the same as
4617 * extattr_set_file. It returns zero
4618 * on success, non-zero on failure.
4619 *
4620 * We can detect the failure by
4621 * manually setting errno prior to the
4622 * call and checking after.
4623 *
4624 * If errno remains zero, fake the
4625 * return value by setting e to size.
4626 *
4627 * This is a hack for now until I
4628 * (Shawn Webb) get FreeBSD to fix the
4629 * issue, if that's even possible.
4630 */
4631 errno = 0;
cc9cbbb1
MM
4632 e = extattr_set_fd(a->fd, namespace, name,
4633 value, size);
4d1a6ebc
SW
4634 if (e == 0 && errno == 0) {
4635 e = size;
4636 }
365a91de
MM
4637 } else {
4638 e = extattr_set_link(
cc9cbbb1
MM
4639 archive_entry_pathname(entry), namespace,
4640 name, value, size);
b21f351a
TK
4641 }
4642 if (e != (int)size) {
c20d7a5c
MM
4643 archive_strcat(&errlist, name);
4644 archive_strappend_char(&errlist, ' ');
b21f351a 4645 ret = ARCHIVE_WARN;
c20d7a5c
MM
4646 if (errno != ENOTSUP && errno != ENOSYS)
4647 fail = 1;
b21f351a
TK
4648 }
4649 }
4650 }
c20d7a5c
MM
4651
4652 if (ret == ARCHIVE_WARN) {
4653 if (fail && errlist.length > 0) {
4654 errlist.length--;
4655 errlist.s[errlist.length] = '\0';
4656
4657 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4658 "Cannot restore extended attributes: %s",
4659 errlist.s);
4660 } else
4661 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
4662 "Cannot restore extended "
4663 "attributes on this file system.");
4664 }
4665
4666 archive_string_free(&errlist);
b21f351a
TK
4667 return (ret);
4668}
8f776fd9
TK
4669#else
4670/*
4671 * Restore extended attributes - stub implementation for unsupported systems
4672 */
4673static int
4674set_xattrs(struct archive_write_disk *a)
4675{
4676 static int warning_done = 0;
4677
4678 /* If there aren't any extended attributes, then it's okay not
4679 * to extract them, otherwise, issue a single warning. */
4680 if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
4681 warning_done = 1;
4682 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
4683 "Cannot restore extended attributes on this system");
4684 return (ARCHIVE_WARN);
4685 }
4686 /* Warning was already emitted; suppress further warnings. */
4687 return (ARCHIVE_OK);
4688}
4689#endif
4690
8f776fd9
TK
4691/*
4692 * Test if file on disk is older than entry.
4693 */
4694static int
4695older(struct stat *st, struct archive_entry *entry)
4696{
4697 /* First, test the seconds and return if we have a definite answer. */
4698 /* Definitely older. */
c89d1a1e 4699 if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
8f776fd9
TK
4700 return (1);
4701 /* Definitely younger. */
c89d1a1e 4702 if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
8f776fd9
TK
4703 return (0);
4704 /* If this platform supports fractional seconds, try those. */
4705#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
4706 /* Definitely older. */
4707 if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry))
4708 return (1);
8f776fd9
TK
4709#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
4710 /* Definitely older. */
4711 if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry))
4712 return (1);
d831cc4b
BJ
4713#elif HAVE_STRUCT_STAT_ST_MTIME_N
4714 /* older. */
4715 if (st->st_mtime_n < archive_entry_mtime_nsec(entry))
4716 return (1);
4717#elif HAVE_STRUCT_STAT_ST_UMTIME
4718 /* older. */
4719 if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry))
4720 return (1);
a0b5f839
BJ
4721#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
4722 /* older. */
4723 if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry))
4724 return (1);
8f776fd9
TK
4725#else
4726 /* This system doesn't have high-res timestamps. */
4727#endif
d831cc4b 4728 /* Same age or newer, so not older. */
8f776fd9
TK
4729 return (0);
4730}
5b3644c3 4731
bea9f9cf
MM
4732#ifndef ARCHIVE_ACL_SUPPORT
4733int
4734archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
4735 struct archive_acl *abstract_acl, __LA_MODE_T mode)
4736{
4737 (void)a; /* UNUSED */
4738 (void)fd; /* UNUSED */
4739 (void)name; /* UNUSED */
4740 (void)abstract_acl; /* UNUSED */
4741 (void)mode; /* UNUSED */
4742 return (ARCHIVE_OK);
4743}
4744#endif
4745
0cb9df7f
SG
4746/*
4747 * Close the file descriptor if one is open.
4748 */
4749static void close_file_descriptor(struct archive_write_disk* a)
4750{
092631ce
SG
4751 if (a->fd >= 0) {
4752 close(a->fd);
4753 a->fd = -1;
4754 }
0cb9df7f
SG
4755}
4756
4757
5b3644c3
MN
4758#endif /* !_WIN32 || __CYGWIN__ */
4759