--- src/buffer.c.orig 2004-12-21 07:09:24.000000000 -0800
+++ src/buffer.c 2008-03-03 19:49:46.000000000 -0800
@@ -438,6 +438,41 @@
record_end = record_start + blocking_factor;
}
+#if HAVE_QUARANTINE
+void
+init_qtn(const char *file_name)
+{
+ int fd;
+
+ if (strcmp(file_name, "-") == 0)
+ return;
+
+ if ((fd = open(file_name, O_RDONLY)) < 0)
+ return;
+
+ if ((archive_qtn_file = qtn_file_alloc()) != NULL) {
+ if (qtn_file_init_with_fd(archive_qtn_file, fd) != 0) {
+ qtn_file_free(archive_qtn_file);
+ archive_qtn_file = NULL;
+ }
+ }
+
+ close(fd);
+}
+
+void
+finish_qtn(void)
+{
+ if (archive_qtn_file != NULL) {
+ qtn_file_free(archive_qtn_file);
+ archive_qtn_file = NULL;
+ }
+}
+#else
+void init_qtn(const char *file_name) {}
+void finish_qtn(void) {}
+#endif
+
/* Open an archive file. The argument specifies whether we are
reading or writing, or both. */
static void
@@ -571,6 +606,7 @@
sys_detect_dev_null_output ();
sys_save_archive_dev_ino ();
SET_BINARY_MODE (archive);
+ init_qtn(archive_name_array[0]);
switch (wanted_access)
{
@@ -864,6 +900,8 @@
free (real_s_name);
free (record_buffer[0]);
free (record_buffer[1]);
+
+ finish_qtn();
}
/* Called to initialize the global volume number. */
--- src/common.h.orig 2004-12-21 06:31:58.000000000 -0800
+++ src/common.h 2008-03-03 18:42:03.000000000 -0800
@@ -20,6 +20,13 @@
/* Declare the GNU tar archive format. */
#include "tar.h"
+#include <TargetConditionals.h>
+#define HAVE_QUARANTINE (!TARGET_OS_EMBEDDED)
+
+#if HAVE_QUARANTINE
+#include <quarantine.h>
+#endif
+
/* The checksum field is filled with this while the checksum is computed. */
#define CHKBLANKS " " /* 8 blanks, no null */
@@ -302,6 +309,9 @@
/* File descriptor for archive file. */
GLOBAL int archive;
+#if HAVE_QUARANTINE
+GLOBAL qtn_file_t archive_qtn_file;
+#endif
/* Nonzero when outputting to /dev/null. */
GLOBAL bool dev_null_output;
--- src/extract.c.orig 2004-12-21 01:55:12.000000000 -0800
+++ src/extract.c 2008-03-03 19:51:38.000000000 -0800
@@ -413,6 +413,51 @@
quotearg_colon (dir)));
}
+#if HAVE_QUARANTINE
+void
+apply_qtn(int fd)
+{
+ int stat_ok;
+ struct stat sb;
+ int qstatus;
+
+ if (archive_qtn_file != NULL) {
+ stat_ok = (fstat(fd, &sb) == 0);
+
+ if (stat_ok) fchmod(fd, sb.st_mode | S_IWUSR);
+ qstatus = qtn_file_apply_to_fd(archive_qtn_file, fd);
+ if (stat_ok) fchmod(fd, sb.st_mode);
+
+ if (qstatus) {
+ warnx("qtn_file_apply_to_fd: %s", qtn_error(qstatus));
+ }
+ }
+}
+
+void
+apply_qtn_to_path(char *path)
+{
+ int stat_ok;
+ struct stat sb;
+ int qstatus;
+
+ if (archive_qtn_file != NULL) {
+ stat_ok = (stat(path, &sb) == 0);
+
+ if (stat_ok) chmod(path, sb.st_mode | S_IWUSR);
+ qstatus = qtn_file_apply_to_path(archive_qtn_file, path);
+ if (stat_ok) chmod(path, sb.st_mode);
+
+ if (qstatus) {
+ warnx("qtn_file_apply_to_path: %s", qtn_error(qstatus));
+ }
+ }
+}
+#else
+void apply_qtn(int fd) {}
+void apply_qtn_to_path(char *path) {}
+#endif
+
/* After a file/link/directory creation has failed, see if
it's because some required directory was not present, and if so,
create all required directories. Return non-zero if a directory
@@ -452,6 +497,8 @@
if (status == 0)
{
+ apply_qtn_to_path(file_name);
+
/* Create a struct delayed_set_stat even if
invert_permissions is zero, because
repair_delayed_set_stat may need to update the struct. */
@@ -698,6 +745,7 @@
|| old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES)
{
+ apply_qtn_to_path(file_name);
if (status == 0)
delay_set_stat (file_name, ¤t_stat_info,
((mode ^ current_stat_info.stat.st_mode)
@@ -807,6 +854,7 @@
}
#endif /* __APPLE__ */
+ apply_qtn(fd);
mv_begin (¤t_stat_info);
if (current_stat_info.is_sparse)
sparse_extract_file (fd, ¤t_stat_info, &size);
--- src/list.c.orig 2008-07-11 19:37:25.000000000 -0700
+++ src/list.c 2008-07-11 19:39:27.000000000 -0700
@@ -230,6 +230,9 @@
rename(cle->tmp, cle->src);
}
+ /* 5781559: Make sure EAs don't destroy overriding quarantine information. */
+ apply_qtn_to_path(cle->dst);
+
free(cle->tmp);
free(cle->dst);
free(cle->src);