From 618b37c8752c3ad13c3fa5762ae59be51bc85a2c Mon Sep 17 00:00:00 2001
From: Apple <opensource@apple.com>
Date: Thu, 28 Aug 2014 21:33:35 +0000
Subject: [PATCH] copyfile-118.1.2.tar.gz

---
 copyfile.c                          |  78 +++++++++++---
 copyfile.h                          |  13 +--
 copyfile.xcodeproj/project.pbxproj  |  54 +++++-----
 copyfile_private.h                  |   5 +
 xattr_properties.c => xattr_flags.c | 154 +++++++++++++++++++---------
 xattr_flags.h                       | 149 +++++++++++++++++++++++++++
 xattr_name_with_flags.3             | 123 ++++++++++++++++++++++
 xattr_properties.h                  |  16 +--
 xcodescripts/copyfile.xcconfig      |  16 +++
 xcodescripts/install_files.sh       |  24 ++---
 10 files changed, 513 insertions(+), 119 deletions(-)
 rename xattr_properties.c => xattr_flags.c (65%)
 create mode 100644 xattr_flags.h
 create mode 100644 xattr_name_with_flags.3
 create mode 100644 xcodescripts/copyfile.xcconfig

diff --git a/copyfile.c b/copyfile.c
index 09d6305..99f26fc 100644
--- a/copyfile.c
+++ b/copyfile.c
@@ -72,7 +72,7 @@ static void *qtn_file_clone(void *x) { return NULL; }
 
 #include "copyfile.h"
 #include "copyfile_private.h"
-#include "xattr_properties.h"
+#include "xattr_flags.h"
 
 enum cfInternalFlags {
 	cfDelayAce = 1 << 0,
@@ -109,7 +109,7 @@ struct _copyfile_state
     off_t totalCopied;
     int err;
     char *xattr_name;
-    CopyOperationIntent_t copyIntent;
+    xattr_operation_intent_t copyIntent;
 };
 
 struct acl_entry {
@@ -2105,7 +2105,8 @@ goto exit;
 static int copyfile_stat(copyfile_state_t s)
 {
     struct timeval tval[2];
-    unsigned int added_flags = 0;
+    unsigned int added_flags = 0, dst_flags = 0;
+    struct stat dst_sb;
 
     /*
      * NFS doesn't support chflags; ignore errors as a result, since
@@ -2114,7 +2115,18 @@ static int copyfile_stat(copyfile_state_t s)
     if (s->internal_flags & cfMakeFileInvisible)
 	added_flags |= UF_HIDDEN;
 
-    (void)fchflags(s->dst_fd, (u_int)s->sb.st_flags | added_flags);
+    /*
+    * We need to check if SF_RESTRICTED was set on the destination
+    * by the kernel.  If it was, don't drop it.
+    */
+    if (fstat(s->dst_fd, &dst_sb))
+	return -1;
+    if (dst_sb.st_flags & SF_RESTRICTED)
+	added_flags |= SF_RESTRICTED;
+
+    /* Copy file flags, masking out any we don't want to preserve */
+    dst_flags = (s->sb.st_flags & ~COPYFILE_OMIT_FLAGS) | added_flags;
+    (void)fchflags(s->dst_fd, dst_flags);
 
     /* If this fails, we don't care */
     (void)fchown(s->dst_fd, s->sb.st_uid, s->sb.st_gid);
@@ -2288,9 +2300,49 @@ static int copyfile_xattr(copyfile_state_t s)
 	    if (OSSwapLittleToHostInt32(hdr->compression_magic) != DECMPFS_MAGIC) {
 		continue;
 	    }
-	    if (OSSwapLittleToHostInt32(hdr->compression_type) != 3 &&
-		OSSwapLittleToHostInt32(hdr->compression_type) != 4) {
-		continue;
+	    /*
+	     * From AppleFSCompression documentation:
+	     * "It is incumbent on the aware copy engine to identify
+	     *  the type of compression being used, and to perform an
+	     *  unaware copy of any file it does not recognize."
+	     *
+	     * Compression Types are defined in:
+	     * "AppleFSCompression/Common/compressorCommon.h"
+	     *
+	     * Unfortunately, they don't provide a way to dynamically
+	     * determine what possible compression_type values exist,
+	     * so we have to update this every time a new compression_type
+	     * is added (Types 7->10 were added in Yosemite)
+	     *
+	     * Ubiquity faulting file compression type 0x80000001 are
+	     * deprecated as of Yosemite, per rdar://17714998 don't copy the
+	     * decmpfs xattr on these files, zero byte files are safer
+	     * than a fault nobody knows how to handle.
+	     */
+	    switch (OSSwapLittleToHostInt32(hdr->compression_type)) {
+		case 3: /* zlib-compressed data in xattr */
+		case 4: /* 64k chunked zlib-compressed data in resource fork */
+
+		case 7: /* LZVN-compressed data in xattr */
+		case 8: /* 64k chunked LZVN-compressed data in resource fork */
+
+		case 9: /* uncompressed data in xattr (similar to but not identical to CMP_Type1) */
+		case 10: /* 64k chunked uncompressed data in resource fork */
+
+			/* valid compression type, we want to copy. */
+			break;
+                
+		case 5: /* specifies de-dup within the generation store. Don't copy decmpfs xattr. */
+			copyfile_debug(3, "compression_type <5> on attribute com.apple.decmpfs for src file %s is not copied.",
+				      s->src ? s->src : "(null string)");
+			continue;
+
+		case 6: /* unused */
+		case 0x80000001: /* faulting files are deprecated, don't copy decmpfs xattr */
+		default:
+			copyfile_warn("Invalid compression_type <%d> on attribute %s for src file %s",
+				      OSSwapLittleToHostInt32(hdr->compression_type), name, s->src ? s->src : "(null string)");
+			continue;
 	    }
 	    s->internal_flags |= cfSawDecmpEA;
 	}
@@ -2298,7 +2350,7 @@ static int copyfile_xattr(copyfile_state_t s)
 
 	// If we have a copy intention stated, and the EA is to be ignored, we ignore it
 	if (s->copyIntent
-	    && _PreserveEA(name, s->copyIntent) == 0)
+	    && xattr_preserve_for_intent(name, s->copyIntent) == 0)
 		continue;
 
 	s->xattr_name = strdup(name);
@@ -2412,7 +2464,7 @@ int copyfile_state_get(copyfile_state_t s, uint32_t flag, void *ret)
 #endif
 #ifdef COPYFILE_STATE_INTENT
        case COPYFILE_STATE_INTENT:
-           *(CopyOperationIntent_t*)ret = s->copyIntent;
+           *(xattr_operation_intent_t*)ret = s->copyIntent;
 	   break;
 #endif
 	default:
@@ -2488,7 +2540,7 @@ int copyfile_state_set(copyfile_state_t s, uint32_t flag, const void * thing)
 #endif
 #ifdef COPYFILE_STATE_INTENT
        case COPYFILE_STATE_INTENT:
-           s->copyIntent = *(CopyOperationIntent_t*)thing;
+           s->copyIntent = *(xattr_operation_intent_t*)thing;
 	   break;
 #endif
 	default:
@@ -3238,7 +3290,7 @@ acl_done:
 	    else
 	    {
 		if (s->copyIntent ||
-		    _PreserveEA((char*)entry->name, s->copyIntent) == 1) {
+		    xattr_preserve_for_intent((char*)entry->name, s->copyIntent) == 1) {
 			if (s->statuscb) {
 				int rv;
 				s->xattr_name = strdup((char*)entry->name);
@@ -3793,7 +3845,7 @@ static int copyfile_pack(copyfile_state_t s)
 		namelen = XATTR_MAXNAMELEN + 1;
 	    }
 	    if (s->copyIntent &&
-		_PreserveEA(nameptr, s->copyIntent) == 0) {
+		xattr_preserve_for_intent(nameptr, s->copyIntent) == 0) {
 		    // Skip it
 		    size_t amt = endnamebuf - (nameptr + namelen);
 		    memmove(nameptr, nameptr + namelen, amt);
@@ -3807,7 +3859,7 @@ static int copyfile_pack(copyfile_state_t s)
 		int rv;
 		char eaname[namelen];
 		bcopy(nameptr, eaname, namelen);
-		eaname[namelen] = 0; // Just to be sure!
+		eaname[namelen - 1] = 0; // Just to be sure!
 		s->xattr_name = eaname;
 		rv = (*s->statuscb)(COPYFILE_COPY_XATTR, COPYFILE_START, s, s->src, s->dst, s->ctx);
 		s->xattr_name = NULL;
diff --git a/copyfile.h b/copyfile.h
index 59c198a..91dfe87 100644
--- a/copyfile.h
+++ b/copyfile.h
@@ -24,14 +24,11 @@
 #define _COPYFILE_H_
 
 /*
- * this is an API to faciliatate copying of files and their
- * associated metadata.  There are several open source projects that
- * need modifications to support preserving extended attributes and
- * acls and this API collapses several hundred lines of modifications
- * into one or two calls.
- *
- * This implementation is incomplete and the interface may change in a 
- * future release.
+ * This API facilitates the copying of files and their associated
+ * metadata.  There are several open source projects that need
+ * modifications to support preserving extended attributes and ACLs
+ * and this API collapses several hundred lines of modifications into
+ * one or two calls.
  */
 
 /* private */
diff --git a/copyfile.xcodeproj/project.pbxproj b/copyfile.xcodeproj/project.pbxproj
index 04b9858..c125959 100644
--- a/copyfile.xcodeproj/project.pbxproj
+++ b/copyfile.xcodeproj/project.pbxproj
@@ -7,22 +7,25 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		72406E631676C3C80099568B /* xattr_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = 72406E621676C3C80099568B /* xattr_properties.c */; };
+		72406E631676C3C80099568B /* xattr_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 72406E621676C3C80099568B /* xattr_flags.c */; };
 		72B4C0F41676C47D00C13E05 /* copyfile_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B4C0F31676C47D00C13E05 /* copyfile_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		72EAA3B016A72F4500833E98 /* xattr_properties.h in Headers */ = {isa = PBXBuildFile; fileRef = 72EAA3AF16A72F4500833E98 /* xattr_properties.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		72EAA3B016A72F4500833E98 /* xattr_flags.h in Headers */ = {isa = PBXBuildFile; fileRef = 72EAA3AF16A72F4500833E98 /* xattr_flags.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		86EF9F0A1834018C00AAB3F3 /* xattr_properties.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EF9F091834018C00AAB3F3 /* xattr_properties.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FCCE17C3135A658F002CEE6D /* copyfile.c in Sources */ = {isa = PBXBuildFile; fileRef = FCCE17C1135A658F002CEE6D /* copyfile.c */; };
 		FCCE17C4135A658F002CEE6D /* copyfile.h in Headers */ = {isa = PBXBuildFile; fileRef = FCCE17C2135A658F002CEE6D /* copyfile.h */; settings = {ATTRIBUTES = (Public, ); }; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		72406E621676C3C80099568B /* xattr_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xattr_properties.c; sourceTree = "<group>"; };
+		3F1EFD4C185C4EB400D1C970 /* copyfile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = copyfile.xcconfig; path = xcodescripts/copyfile.xcconfig; sourceTree = "<group>"; };
+		72406E621676C3C80099568B /* xattr_flags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xattr_flags.c; sourceTree = "<group>"; };
 		72B4C0F31676C47D00C13E05 /* copyfile_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = copyfile_private.h; sourceTree = "<group>"; };
-		72EAA3AF16A72F4500833E98 /* xattr_properties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xattr_properties.h; sourceTree = "<group>"; };
+		72EAA3AF16A72F4500833E98 /* xattr_flags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xattr_flags.h; sourceTree = "<group>"; };
+		861E1C14180F0AF900E65B9A /* xattr_name_with_flags.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = xattr_name_with_flags.3; sourceTree = "<group>"; };
+		86EF9F091834018C00AAB3F3 /* xattr_properties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xattr_properties.h; sourceTree = "<group>"; };
 		FCCE17BB135A6444002CEE6D /* libcopyfile.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libcopyfile.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		FCCE17C0135A658F002CEE6D /* copyfile.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = copyfile.3; sourceTree = "<group>"; };
 		FCCE17C1135A658F002CEE6D /* copyfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = copyfile.c; sourceTree = "<group>"; };
 		FCCE17C2135A658F002CEE6D /* copyfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = copyfile.h; sourceTree = "<group>"; };
-		FCCE17C5135A659B002CEE6D /* BSD.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BSD.xcconfig; path = Makefiles/CoreOS/Xcode/BSD.xcconfig; sourceTree = DEVELOPER_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -39,13 +42,15 @@
 		FCCE17AB135A5FFB002CEE6D = {
 			isa = PBXGroup;
 			children = (
+				3F1EFD4C185C4EB400D1C970 /* copyfile.xcconfig */,
+				861E1C14180F0AF900E65B9A /* xattr_name_with_flags.3 */,
 				72B4C0F31676C47D00C13E05 /* copyfile_private.h */,
-				72EAA3AF16A72F4500833E98 /* xattr_properties.h */,
-				72406E621676C3C80099568B /* xattr_properties.c */,
+				72EAA3AF16A72F4500833E98 /* xattr_flags.h */,
+				72406E621676C3C80099568B /* xattr_flags.c */,
 				FCCE17C0135A658F002CEE6D /* copyfile.3 */,
 				FCCE17C1135A658F002CEE6D /* copyfile.c */,
+				86EF9F091834018C00AAB3F3 /* xattr_properties.h */,
 				FCCE17C2135A658F002CEE6D /* copyfile.h */,
-				FCCE17C5135A659B002CEE6D /* BSD.xcconfig */,
 				FCCE17BC135A6444002CEE6D /* Products */,
 			);
 			sourceTree = "<group>";
@@ -66,8 +71,9 @@
 			buildActionMask = 2147483647;
 			files = (
 				FCCE17C4135A658F002CEE6D /* copyfile.h in Headers */,
+				72EAA3B016A72F4500833E98 /* xattr_flags.h in Headers */,
 				72B4C0F41676C47D00C13E05 /* copyfile_private.h in Headers */,
-				72EAA3B016A72F4500833E98 /* xattr_properties.h in Headers */,
+				86EF9F0A1834018C00AAB3F3 /* xattr_properties.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -140,7 +146,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				FCCE17C3135A658F002CEE6D /* copyfile.c in Sources */,
-				72406E631676C3C80099568B /* xattr_properties.c in Sources */,
+				72406E631676C3C80099568B /* xattr_flags.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -149,7 +155,7 @@
 /* Begin XCBuildConfiguration section */
 		FCCE17B3135A5FFB002CEE6D /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = FCCE17C5135A659B002CEE6D /* BSD.xcconfig */;
+			baseConfigurationReference = 3F1EFD4C185C4EB400D1C970 /* copyfile.xcconfig */;
 			buildSettings = {
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
@@ -176,16 +182,9 @@
 		FCCE17BD135A6444002CEE6D /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				BUILD_VARIANTS = (
-					normal,
-					debug,
-				);
-				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
 				EXECUTABLE_PREFIX = lib;
 				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_PREPROCESSOR_DEFINITIONS = "__DARWIN_NOW_CANCELABLE=1";
-				INSTALL_PATH = /usr/lib/system;
-				"INSTALL_PATH[sdk=iphonesimulator*]" = "$(SDKROOT)/usr/lib/system";
 				LINK_WITH_STANDARD_LIBRARIES = NO;
 				OTHER_LDFLAGS = (
 					"-Wl,-umbrella,System",
@@ -199,6 +198,8 @@
 					"-lquarantine",
 					"-lsystem_asl",
 					"-lsystem_info",
+					"-lxpc",
+					"-ldispatch",
 				);
 				"OTHER_LDFLAGS[sdk=iphoneos*]" = (
 					"-Wl,-umbrella,System",
@@ -211,22 +212,23 @@
 					"-lsystem_blocks",
 					"-lsystem_asl",
 					"-lsystem_info",
+					"-ldispatch",
+					"-lxpc",
 				);
 				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
 					"-Wl,-umbrella,System",
 					"-L/usr/lib/system",
-					"-ldyld_sim",
-					"-lcompiler_rt_sim",
+					"-ldyld",
+					"-lcompiler_rt",
+					"-lsystem_sim_kernel",
+					"-lsystem_malloc",
 					"-lsystem_sim_c",
 					"-lsystem_sim_blocks",
+					"-lsystem_sim_asl",
 					"-lsystem_sim_info",
-					"-Wl,-upward-lSystem",
+					"-ldispatch",
+					"-lxpc",
 				);
-				"PRIVATE_HEADERS_FOLDER_PATH[sdk=iphonesimulator*]" = "$(SDKROOT)/usr/local/include";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				"PRODUCT_NAME[sdk=iphonesimulator*]" = copyfile_sim;
-				PUBLIC_HEADERS_FOLDER_PATH = /usr/include;
-				"PUBLIC_HEADERS_FOLDER_PATH[sdk=iphonesimulator*]" = "$(SDKROOT)/usr/include";
 				WARNING_CFLAGS = (
 					"-Wall",
 					"-Wextra",
diff --git a/copyfile_private.h b/copyfile_private.h
index 8f805d9..0111e0d 100644
--- a/copyfile_private.h
+++ b/copyfile_private.h
@@ -30,4 +30,9 @@
  */
 # define COPYFILE_STATE_INTENT	256
 
+/*
+ * File flags that are not preserved when copying stat information.
+ */
+#define COPYFILE_OMIT_FLAGS 	(UF_TRACKED | SF_RESTRICTED)
+
 #endif /* _COPYFILE_PRIVATE_H */
diff --git a/xattr_properties.c b/xattr_flags.c
similarity index 65%
rename from xattr_properties.c
rename to xattr_flags.c
index 78eccd0..8e8fd05 100644
--- a/xattr_properties.c
+++ b/xattr_flags.c
@@ -29,8 +29,13 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/xattr.h>
+#include <dispatch/dispatch.h>
+#include <xpc/private.h>
 
-#include <xattr_properties.h>
+#include <xattr_flags.h>
+
+#define FLAG_DELIM_CHAR	'#'
+#define FLAG_DELIM_STR "#"
 
 /*
  * Some default propeteries for EAs we know about internally.
@@ -43,17 +48,30 @@ struct defaultList {
 
 #define propFlagsPrefix	0x0001	// The name is a prefix, so only look at that part
 
+static const struct defaultList *defaultPropertyTable = NULL;
+
 static const struct defaultList
-defaultPropertyTable[] = {
-	{ "com.apple.quarantine", "PC", 0 },	// not public
-	{ "com.apple.TextEncoding", "PC", 0 },	// Content-dependent, public
-	{ "com.apple.metadata:", "P", propFlagsPrefix },	// Don't export, keep for copy & safe save
-	{ "com.apple.security.", "N", propFlagsPrefix },
-	{ XATTR_RESOURCEFORK_NAME, "PC", 0 },	// Don't keep for safe save
-	{ XATTR_FINDERINFO_NAME, "PC", 0 },	// Same as ResourceFork
+defaultUnboxedPropertyTable[] = {
+	{ "com.apple.quarantine", "PCS", 0 },	// not public
+	{ "com.apple.TextEncoding", "CS", 0 },	// Content-dependent, public
+	{ "com.apple.metadata:", "PS", propFlagsPrefix },	// Don't export, keep for copy & safe save
+	{ "com.apple.security.", "S", propFlagsPrefix },
+	{ XATTR_RESOURCEFORK_NAME, "PCS", 0 },	// Don't keep for safe save
+	{ XATTR_FINDERINFO_NAME, "PCS", 0 },	// Same as ResourceFork
 	{ 0, 0, 0 },
 };
 
+static const struct defaultList
+defaultSandboxedPropertyTable[] = {
+    { "com.apple.quarantine", "PCS", 0 },	// not public
+    { "com.apple.TextEncoding", "CS", 0 },	// Content-dependent, public
+    { "com.apple.metadata:", "PS", propFlagsPrefix },	// Don't export, keep for copy & safe save
+    { "com.apple.security.", "N", propFlagsPrefix },
+    { XATTR_RESOURCEFORK_NAME, "PCS", 0 },	// Don't keep for safe save
+    { XATTR_FINDERINFO_NAME, "PCS", 0 },	// Same as ResourceFork
+    { 0, 0, 0 },
+};
+
 /*
  * The property lists on an EA are set by having a suffix character,
  * and then a list of characters.  In general, we're choosing upper-case
@@ -63,19 +81,20 @@ defaultPropertyTable[] = {
 struct propertyListMapping {
 	char enable;	// Character to enable
 	char disable;	// Character to disable -- usually lower-case of enable
-	CopyOperationProperties_t	value;
+	xattr_operation_intent_t	value;
 };
 static const struct propertyListMapping
 PropertyListMapTable[] = {
-	{ 'C', 'c', kCopyOperationPropertyContentDependent },
-	{ 'P', 'p', kCopyOperationPropertyNoExport },
-	{ 'N', 'n', kCopyOperationPropertyNeverPreserve },
+	{ 'C', 'c', XATTR_FLAG_CONTENT_DEPENDENT },
+	{ 'P', 'p', XATTR_FLAG_NO_EXPORT },
+	{ 'N', 'n', XATTR_FLAG_NEVER_PRESERVE },
+	{ 'S', 's', XATTR_FLAG_SYNCABLE },
 	{ 0, 0, 0 },
 };
 	
 /*
  * Given a converted property list (that is, converted to the
- * CopyOperationProperties_t type), and an intent, determine if
+ * xattr_operation_intent_t type), and an intent, determine if
  * it should be preserved or not.
  *
  * I've chosen to use a block instead of a simple mask on the belief
@@ -84,24 +103,27 @@ PropertyListMapTable[] = {
  * as being exclusionary.
  */
 static const struct divineIntent {
-	CopyOperationIntent_t intent;
-	int (^checker)(CopyOperationProperties_t);
+	xattr_operation_intent_t intent;
+	int (^checker)(xattr_flags_t);
 } intentTable[] = {
-	{ CopyOperationIntentCopy, ^(CopyOperationProperties_t props) {
-			if (props & kCopyOperationPropertyNeverPreserve)
+	{ XATTR_OPERATION_INTENT_COPY, ^(xattr_flags_t flags) {
+			if (flags & XATTR_FLAG_NEVER_PRESERVE)
 				return 0;
 			return 1;
 		} },
-	{ CopyOperationIntentSave, ^(CopyOperationProperties_t props) {
-			if (props & (kCopyOperationPropertyContentDependent | kCopyOperationPropertyNeverPreserve))
+	{ XATTR_OPERATION_INTENT_SAVE, ^(xattr_flags_t flags) {
+			if (flags & (XATTR_FLAG_CONTENT_DEPENDENT | XATTR_FLAG_NEVER_PRESERVE))
 				return 0;
 			return 1;
 		} },
-	{ CopyOperationIntentShare, ^(CopyOperationProperties_t props) {
-			if ((props & (kCopyOperationPropertyNoExport | kCopyOperationPropertyNeverPreserve)) != 0)
+	{ XATTR_OPERATION_INTENT_SHARE, ^(xattr_flags_t flags) {
+			if ((flags & (XATTR_FLAG_NO_EXPORT | XATTR_FLAG_NEVER_PRESERVE)) != 0)
 				return 0;
 			return 1;
 		} },
+	{ XATTR_OPERATION_INTENT_SYNC, ^(xattr_flags_t flags) {
+			return (flags & (XATTR_FLAG_SYNCABLE | XATTR_FLAG_NEVER_PRESERVE)) == XATTR_FLAG_SYNCABLE;
+		} },
 	{ 0, 0 },
 };
 
@@ -114,6 +136,15 @@ static const char *
 nameInDefaultList(const char *eaname)
 {
 	const struct defaultList *retval;
+	static dispatch_once_t onceToken;
+    
+	dispatch_once(&onceToken, ^{
+		if (_xpc_runtime_is_app_sandboxed()) {
+			defaultPropertyTable = defaultSandboxedPropertyTable;
+		} else {
+			defaultPropertyTable = defaultUnboxedPropertyTable;
+		}
+	});
 
 	for (retval = defaultPropertyTable; retval->eaName; retval++) {
 		if ((retval->flags & propFlagsPrefix) != 0 &&
@@ -143,12 +174,12 @@ findPropertyList(const char *eaname)
 
 /*
  * Convert a property list string (e.g., "pCd") into a
- * CopyOperationProperties_t type.
+ * xattr_operation_intent_t type.
  */
-static CopyOperationProperties_t
+static xattr_operation_intent_t
 stringToProperties(const char *proplist)
 {
-	CopyOperationProperties_t retval = 0;
+	xattr_operation_intent_t retval = 0;
 	const char *ptr;
 
 	// A switch would be more efficient, but less generic.
@@ -167,7 +198,7 @@ stringToProperties(const char *proplist)
 
 /*
  * Given an EA name (e.g., "com.apple.lfs.hfs.test"), and a
- * CopyOperationProperties_t value (it's currently an integral value, so
+ * xattr_operation_intent_t value (it's currently an integral value, so
  * just a bitmask), cycle through the list of known properties, and return
  * a string with the EA name, and the property list appended.  E.g., we
  * might return "com.apple.lfs.hfs.test#pD".
@@ -186,7 +217,7 @@ stringToProperties(const char *proplist)
  * for sanity checking.  That would require having more than 64 bits to use.)
  */
 char *
-_xattrNameWithProperties(const char *orig, CopyOperationProperties_t propList)
+xattr_name_with_flags(const char *orig, xattr_flags_t propList)
 {
 	char *retval = NULL;
 	char suffix[66] = { 0 }; // 66:  uint64_t for property types, plus '#', plus NUL
@@ -233,15 +264,51 @@ _xattrNameWithProperties(const char *orig, CopyOperationProperties_t propList)
 	return retval;
 }
 
-CopyOperationProperties_t
-_xattrPropertiesFromName(const char *eaname)
+char *
+xattr_name_without_flags(const char *eaname)
+{
+	char *retval = NULL;
+	char *tmp;
+
+	if ((tmp = strrchr(eaname, FLAG_DELIM_CHAR)) == NULL) {
+		retval = strdup(eaname);
+	} else {
+		retval = calloc(tmp - eaname + 1, 1);
+		if (retval) {
+			strlcpy(retval, eaname, tmp - eaname + 1);
+		}
+	}
+	if (retval == NULL) {
+		errno = ENOMEM;
+	}
+	return retval;
+}
+
+int
+xattr_intent_with_flags(xattr_operation_intent_t intent, xattr_flags_t flags)
+{
+	const struct divineIntent *ip;
+
+	for (ip = intentTable; ip->intent; ip++) {
+		if (ip->intent == intent) {
+			return ip->checker(flags);
+		}
+	}
+	if ((flags & XATTR_FLAG_NEVER_PRESERVE) != 0)
+		return 0;	// Special case, don't try to copy this one
+
+	return 1;	// Default
+}
+
+xattr_flags_t
+xattr_flags_from_name(const char *eaname)
 {
-	CopyOperationProperties_t retval = 0;
+	xattr_flags_t retval = 0;
 	const char *propList;
 
 	propList = findPropertyList(eaname);
 	if (propList == NULL) {
-		propList = findPropertyList(eaname);
+		propList = nameInDefaultList(eaname);
 	}
 	if (propList != NULL) {
 		retval = stringToProperties(propList);
@@ -257,32 +324,17 @@ _xattrPropertiesFromName(const char *eaname)
  * This returns 0 if it should not be preserved, and 1 if it should.
  * 
  * It simply looks through the tables we have above, and compares the
- * CopyOperationProperties_t for the EA with the intent.  If the
+ * xattr_operation_intent_t for the EA with the intent.  If the
  * EA doesn't have any properties, and it's not on the default list, the
  * default is to preserve it.
  */
 
 int
-_PreserveEA(const char *eaname, CopyOperationIntent_t intent)
+xattr_preserve_for_intent(const char *eaname, xattr_operation_intent_t intent)
 {
-	const struct divineIntent *ip;
-	CopyOperationProperties_t props;
-	const char *propList;
-
-	if ((propList = findPropertyList(eaname)) == NULL &&
-	    (propList = nameInDefaultList(eaname)) == NULL)
-		props = 0;
-	else
-		props = stringToProperties(propList);
-
-	for (ip = intentTable; ip->intent; ip++) {
-		if (ip->intent == intent) {
-			return ip->checker(props);
-		}
-	}
-	
-	if ((props & kCopyOperationPropertyNeverPreserve) != 0)
-		return 0;	// Special case, don't try to preserve this one
+	xattr_flags_t flags = xattr_flags_from_name(eaname);
 
-	return 1;	// Default to preserving everything
+	return xattr_intent_with_flags(intent, flags);
 }
+
+#include "xattr_properties.h"
diff --git a/xattr_flags.h b/xattr_flags.h
new file mode 100644
index 0000000..032b6ad
--- /dev/null
+++ b/xattr_flags.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2013 Apple, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _XATTR_FLAGS_H
+#define _XATTR_FLAGS_H
+
+#include <stdint.h>
+
+#include <sys/cdefs.h>
+#include <Availability.h>
+
+__BEGIN_DECLS
+
+/*
+ * xattr_operation_intent_t is used to declare what the intent of the copy is.
+ * Not a bit-field (for now, at least).
+ *
+ * XATTR_OPERATION_INTENT_COPY indicates that the EA is attached to an object
+ * that is simply being copied.  E.g., cp src dst
+ *
+ * XATTR_OPERATION_INTENT_SAVE indicates that the EA is attached to an object
+ * being saved; as in a "safe save," the destination is being replaced by
+ * the source, so the question is whether the EA should be applied to the
+ * destination, or generated anew.
+ *
+ * XATTR_OPERATION_INTENT_SHARE  indicates that the EA is attached to an object that
+ * is being given out to other people.  For example, saving to a public folder,
+ * or attaching to an email message.
+ *
+ * XATTR_OPERATION_INTENT_SYNC  indicates that the EA is attached to an object that
+ * is being synced to other storages for the same user.  For example synced to
+ * iCloud.
+ */
+
+#define XATTR_OPERATION_INTENT_COPY	1
+#define XATTR_OPERATION_INTENT_SAVE	2
+#define XATTR_OPERATION_INTENT_SHARE	3
+#define XATTR_OPERATION_INTENT_SYNC	4
+
+typedef unsigned int xattr_operation_intent_t;
+
+typedef uint64_t xattr_flags_t;
+
+/*
+ * Various properties used to determine how to handle the xattr during
+ * copying.  The intent is that the default is reasonable for most xattrs.
+ */
+
+/*
+ * XATTR_FLAG_NO_EXPORT
+ * Declare that the extended property should not be exported; this is
+ * deliberately a bit vague, but this is used by XATTR_OPERATION_INTENT_SHARE
+ * to indicate not to preserve the xattr.
+ */
+#define XATTR_FLAG_NO_EXPORT	((xattr_flags_t)0x0001)
+
+/*
+ * XATTR_FLAG_CONTENT_DEPENDENT
+ * Declares the extended attribute to be tied to the contents of the file (or
+ * vice versa), such that it should be re-created when the contents of the
+ * file change.  Examples might include cryptographic keys, checksums, saved
+ * position or search information, and text encoding.
+ *
+ * This property causes the EA to be preserved for copy and share, but not for
+ * safe save.  (In a safe save, the EA exists on the original, and will not
+ * be copied to the new version.)
+ */
+#define	XATTR_FLAG_CONTENT_DEPENDENT	((xattr_flags_t)0x0002)
+
+/*
+ * XATTR_FLAG_NEVER_PRESERVE
+ * Declares that the extended attribute is never to be copied, for any
+ * intention type.
+ */
+#define XATTR_FLAG_NEVER_PRESERVE	((xattr_flags_t)0x0004)
+
+/*
+ * XATTR_FLAG_SYNCABLE
+ * Declares that the extended attribute is to be synced, used by the
+ * XATTR_OPERATION_ITENT_SYNC intention.  Syncing tends to want to minimize the
+ * amount of metadata synced around, hence the default behavior is for the EA
+ * NOT to be synced, even if it would else be preserved for the
+ * XATTR_OPERATION_ITENT_COPY intention.
+ */
+#define XATTR_FLAG_SYNCABLE	((xattr_flags_t)0x0008)
+
+/* Given a named extended attribute, and a copy intent, should the EA be preserved? */
+extern int xattr_preserve_for_intent(const char *, xattr_operation_intent_t) __OSX_AVAILABLE_STARTING( __MAC_10_10, __IPHONE_8_0);
+
+/*
+ * Given an extended attribute name, and a set of properties, return an
+ *  allocated C string with the name.  This will return NULL on error;
+ * errno may be set to ENOMEM if the new name cannot be allocated, or
+ * ENAMETOOLONG if the new name is longer than the maximum for EAs (127 UTF8
+ * characters).  The caller must deallocate the return value otherwise.
+ *
+ * If no properties are set, it returns a copy of the EA name.
+ *
+ * If the EA name is in the internal list, and the properties are the same as
+ * defined there, then it will also return an unmodified copy of the EA name.
+ */
+extern char *xattr_name_with_flags(const char *, xattr_flags_t) __OSX_AVAILABLE_STARTING( __MAC_10_10, __IPHONE_8_0);
+
+/*
+ * Given an extended attribute name, which may or may not have properties encoded
+ * as a suffix, return just the name of the attribute.  E.g., com.example.mine#P
+ * would return "com.example.mine".  The return value will be NULL on error;
+ * errno will be set to ENOMEM if it cannot be allocated.  The caller must deallocate
+ * the return value.
+ */
+extern char *xattr_name_without_flags(const char *) __OSX_AVAILABLE_STARTING( __MAC_10_10, __IPHONE_8_0);
+
+/*
+ * Given an EA name, return the properties.  If the name is in the internal list,
+ * those properties will be returned.  Unknown property encodings are ignored.
+ */
+extern xattr_flags_t xattr_flags_from_name(const char *) __OSX_AVAILABLE_STARTING( __MAC_10_10, __IPHONE_8_0);
+
+/*
+ * Given an xattr_operation_intent_t and an xattr_flags_t, return whether it should
+ * be preserved.  The default (in case either flags or intent is 0, or unknown
+ * values) is to return 1; it only returns 0 if the flags and intent indicate it
+ * should not be preserved.
+ */
+extern int xattr_intent_with_flags(xattr_operation_intent_t, xattr_flags_t) __OSX_AVAILABLE_STARTING( __MAC_10_10, __IPHONE_8_0);
+
+__END_DECLS
+
+#endif /* _XATTR_FLAGS_H */
diff --git a/xattr_name_with_flags.3 b/xattr_name_with_flags.3
new file mode 100644
index 0000000..509f8b1
--- /dev/null
+++ b/xattr_name_with_flags.3
@@ -0,0 +1,123 @@
+.\"
+.\" Copyright (c) 2013 Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd October 7, 2013
+.Dt XATTR_NAME_WITH_FLAGS 3
+.Os
+.Sh NAME
+.Nm xattr_preserve_for_intent , xattr_name_with_flags , xattr_name_without_flags ,
+.Nm xattr_flags_from_name , xattr_intent_with_flags
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xattr_properties.h
+.Ft int
+.Fn xattr_preserve_for_intent "const char *" "xattr_operation_intent_t"
+.Ft char *
+.Fn xattr_name_with_flags "const char *" "xattr_flags_t"
+.Ft char *
+.Fn xattr_name_without_flags "const char *"
+.Ft xattr_flags_t
+.Fn xattr_flags_from_name "const char *"
+.Ft int
+.Fn xattr_intent_with_flags "xattr_operation_intent_t" "xattr_flags_t"
+.Sh DESCRIPTION
+These functions are used in conjunction with copying extended attributes from
+one file to another.  Various types of copying (an "intent") check flags to
+determine which is allowed or not.
+.Pp
+The
+.Fn xattr_name_with_flags
+function returns an extended attribute name with the appropriate flags encoded
+as a string; the
+.Fn xattr_name_without_flags
+undoes this, giving the name of the extended attribute without the flags
+encoding.  The slight inverse of that is
+.Fn xattr_flags_from_name ,
+which will return the flags encoded in a name.
+.Pp
+The values returned by
+.Fn xattr_name_with_flags
+and
+.Fn xattr_name_without_flags
+are allocated using
+.Xr malloc 3 ,
+and should be released by the caller, using
+.Xr free 3 .
+.Pp
+These functions also have an internal table of pre-defined names, maintained
+by the operating system.
+.Pp
+The function
+.Fn xattr_intent_with_flags
+will return 0 if the
+.Ar flags
+argument indicates it should not be preserved for the given
+intent, or 1 if it should.
+.Pp
+The function
+.Fn xattr_presere_for_intent
+combines the functions above, and will return zero if the
+named extended attribute should be preserved during a copy for
+the given intent.
+.Sh INTENT
+The type
+.Dt xattr_operation_intent_t
+is an integral type, which is used to indicate what the intent for the operation
+is.  The following intent values are defined:
+.Bl -tag -width XATTR_OPERATION_INTENT_SHARE
+.It Dv XATTR_OPERATION_INTENT_COPY
+Indicates that the intent is to simply copy from the source to the destination.
+E.g., with cp.  Most extended attributes should generally be preserved in this
+case.
+.It Dv XATTR_OPERATION_INTENT_SAVE
+Indicates that intent is to perform a save (perhaps as in a "safe save").
+This differs from a copy in that the content may be changing; the destination
+may be over-writing or replacing the source, and som extended attributes should
+not be preserved during this process.
+.It Dv XATTR_OPERATION_INTENT_SHARE
+Indicates that the intent is to share, or export, the object.  For example,
+saving as an attachment in an email message, or placing in a public folder.
+Sensitive information should probably not be preserved in this case.
+.It Dv XATTR_OPERATION_INTENT_SYNC
+Indicates that the intent is to sync the object to a service like iCloud.
+.El
+.Sh FLAGS
+Various flags are defined by the type
+.Dt xattr_flags_t ;
+the currently-defined values for this are
+.Bl -tag -width XATTR_FLAG_CONTENT_DEPENDENT
+.It Dv XATTR_FLAG_NO_EXPORT
+This indicates that the extended attribute should not be exported, or shared.
+This is used with
+.Dv XATTR_OPERATION_INTENT_SHARE .
+.It Dv XATTR_FLAG_CONTENT_DEPENDENT
+This indicates that the extended attribute is tied to the contents of the
+file (or vice versa), such that it should be re-created when the contents
+are changed.  A checksum, for example, should not be copied, and would thus
+be marked with this flag.
+.It Dv XATTR_FLAG_NEVER_PRESERVE
+This indicates that the extended attribute should never be copied from a
+source object to a destination, no matter what the given intent is.
+.It Dv XATTR_FLAG_SYNCABLE
+This indicates that the extended attribute should be copied when the file
+is synced on services like iCloud. Sync services tends to want the metadata
+synced to be kept to a bare minimum, and may enforce additional restrictions
+on the acceptable size and number of extended attributes.
+.El
+.Sh EXAMPLE
+The following example is a simple function that, given an extended attribute
+name and an operation intent, will return whether or not the extended attribute
+should be copied.  (This essentially does what
+.Fn xattr_preserve_for_intent
+does.)
+.Bd -literal -offset indent
+int
+ShouldCopyEA(const char *eaName, xattr_operation_intent_t intent)
+{
+	xattr_flags_t flags = xattr_flags_from_name(eaName);
+	return xattr_intent_with_flags(intent, flags);
+}
+.Ed
+.Sh HISTORY
+These functions first appeared in Mac OS in 2013.
diff --git a/xattr_properties.h b/xattr_properties.h
index e6eb457..21d9a29 100644
--- a/xattr_properties.h
+++ b/xattr_properties.h
@@ -27,7 +27,7 @@
 #include <stdint.h>
 
 #include <sys/cdefs.h>
-
+#include <Availability.h>
 
 __BEGIN_DECLS
 
@@ -89,9 +89,10 @@ typedef uint64_t CopyOperationProperties_t;
  */
 #define kCopyOperationPropertyNeverPreserve	((CopyOperationProperties_t)0x0004)
 
-// Given a named extended attribute, and a copy intent, should the EA be preserved?
-extern int _PreserveEA(const char *, CopyOperationIntent_t);
-
+#if 0
+/*
+ * These are all going to be removed, and I don't believe anyone used them.
+ */
 /*
  * Given an extended attribute name, and a set of properties, return an
  *  allocated C string with the name.  This will return NULL on error;
@@ -104,7 +105,7 @@ extern int _PreserveEA(const char *, CopyOperationIntent_t);
  * If the EA name is in the internal list, and the properties are the same as
  * defined there, then it will also return an unmodified copy of the EA name.
  */
-extern char *_xattrNameWithProperties(const char *, CopyOperationProperties_t);
+extern char *_xattrNameWithProperties(const char *, CopyOperationProperties_t) DEPRECATED_IN_MAC_OS_X_VERSION_10_10_AND_LATER;
 
 /*
  * Given an extended attribute name, which may or may not have properties encoded
@@ -113,13 +114,14 @@ extern char *_xattrNameWithProperties(const char *, CopyOperationProperties_t);
  * errno will be set to ENOMEM if it cannot be allocated.  The caller must deallocate
  * the return value.
  */
-extern char *_xattrNameWithoutProperties(const char *);
+extern char *_xattrNameWithoutProperties(const char *) DEPRECATED_IN_MAC_OS_X_VERSION_10_10_AND_LATER;
 
 /*
  * Given an EA name, return the properties.  If the name is in the internal list,
  * those properties will be returned.  Unknown property encodings are ignored.
  */
-extern CopyOperationProperties_t _xattrPropertiesFromName(const char *);
+extern CopyOperationProperties_t _xattrPropertiesFromName(const char *) DEPRECATED_IN_MAC_OS_X_VERSION_10_10_AND_LATER;
+#endif /* 0 */
 
 __END_DECLS
 
diff --git a/xcodescripts/copyfile.xcconfig b/xcodescripts/copyfile.xcconfig
new file mode 100644
index 0000000..d451a2a
--- /dev/null
+++ b/xcodescripts/copyfile.xcconfig
@@ -0,0 +1,16 @@
+#include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"
+#include "<DEVELOPER_DIR>/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig"
+
+// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be
+INSTALL_PATH_ACTUAL = /usr/lib/system
+
+// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable
+INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL)
+
+// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as an unconditional prefix
+PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/include
+PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include
+
+BUILD_VARIANTS = normal debug
+
+PRODUCT_NAME = copyfile
diff --git a/xcodescripts/install_files.sh b/xcodescripts/install_files.sh
index 50174fb..8aacf91 100644
--- a/xcodescripts/install_files.sh
+++ b/xcodescripts/install_files.sh
@@ -1,20 +1,9 @@
 #!/bin/sh
 set -e -x
 
-# check if we're building for the simulator
-if [ "${RC_ProjectName%_Sim}" != "${RC_ProjectName}" ] ; then
-        if [ -d ${DSTROOT}${SDKROOT}/usr/lib/system ] ; then
-                for lib in ${DSTROOT}${SDKROOT}/usr/lib/system/*.dylib ; do
-                        install_name_tool -id "${lib#${DSTROOT}${SDKROOT}}" "${lib}"
-                done
-        fi
-	exit 0
-fi
-
-# don't install files for installhdrs or simulator builds
-if [ "$ACTION" == "installhdrs" -o ] ; then
-	exit 0
-fi
+# don't install man pages for installhdrs or iOS builds
+if [ "$ACTION" = installhdrs ]; then exit 0; fi
+if [ "${PLATFORM_NAME/iphone/}" != "${PLATFORM_NAME}" ]; then exit 0; fi
 
 function InstallManPages() {
 	for MANPAGE in "$@"; do
@@ -42,3 +31,10 @@ LinkManPages copyfile.3 \
 	copyfile_state_free.3 \
 	copyfile_state_get.3 \
 	copyfile_state_set.3
+
+InstallManPages xattr_name_with_flags.3
+LinkManPages    xattr_name_with_flags.3 \
+	xattr_name_without_flags.3 \
+	xattr_flags_from_name.3 \
+	xattr_intent_with_flags.3
+
-- 
2.47.2