]> git.saurik.com Git - apple/copyfile.git/commitdiff
copyfile-127.tar.gz os-x-1011 os-x-10111 os-x-10112 os-x-10113 os-x-10114 os-x-10115 os-x-10116 v127
authorApple <opensource@apple.com>
Tue, 28 Jul 2015 19:07:57 +0000 (19:07 +0000)
committerApple <opensource@apple.com>
Tue, 28 Jul 2015 19:07:57 +0000 (19:07 +0000)
copyfile.c
copyfile.xcodeproj/project.pbxproj
xattr_name_with_flags.3
xcodescripts/copyfile.xcconfig

index 99f26fcdb7b545ee77cb72182842d586c7c358c3..b60739ee0c15ed40754f987fe24f75ad702c8dce 100644 (file)
@@ -46,6 +46,8 @@
 #include <fts.h>
 #include <libgen.h>
 
+#include <System/sys/content_protection.h>
+
 #ifdef VOL_CAP_FMT_DECMPFS_COMPRESSION
 # include <Kernel/sys/decmpfs.h>
 #endif
@@ -75,11 +77,17 @@ static void *qtn_file_clone(void *x) { return NULL; }
 #include "xattr_flags.h"
 
 enum cfInternalFlags {
-       cfDelayAce = 1 << 0,
-       cfMakeFileInvisible = 1 << 1,
-       cfSawDecmpEA = 1 << 2,
+       cfDelayAce                = 1 << 0, /* set if ACE shouldn't be set until post-order traversal */
+       cfMakeFileInvisible       = 1 << 1, /* set if kFinderInvisibleMask is on src */
+       cfSawDecmpEA              = 1 << 2, /* set if we've seen a com.apple.decmpfs xattr */
+       cfSrcProtSupportValid     = 1 << 3, /* set if cfSrcSupportsCProtect is valid */
+       cfSrcSupportsCProtect     = 1 << 4, /* set if src supports MNT_CPROTECT */
+       cfDstProtSupportValid     = 1 << 5, /* set if cfDstSupportsCProtect is valid */
+       cfDstSupportsCProtect     = 1 << 6, /* set if dst supports MNT_CPROTECT */
 };
 
+#define COPYFILE_MNT_CPROTECT_MASK (cfSrcProtSupportValid | cfSrcSupportsCProtect | cfDstProtSupportValid | cfDstSupportsCProtect)
+
 /*
  * The state structure keeps track of
  * the source filename, the destination filename, their
@@ -112,6 +120,9 @@ struct _copyfile_state
     xattr_operation_intent_t copyIntent;
 };
 
+#define GET_PROT_CLASS(fd) fcntl((fd), F_GETPROTECTIONCLASS)
+#define SET_PROT_CLASS(fd, prot_class) fcntl((fd), F_SETPROTECTIONCLASS, (prot_class))
+
 struct acl_entry {
         u_int32_t       ae_magic;
 #define _ACL_ENTRY_MAGIC        0xac1ac101
@@ -173,6 +184,16 @@ doesdecmpfs(int fd) {
        return 0;
 }
 
+static int
+does_copy_protection(int fd)
+{
+    struct statfs sfs;
+
+    if (fstatfs(fd, &sfs) == -1)
+        return -1;
+
+    return ((sfs.f_flags & MNT_CPROTECT) == MNT_CPROTECT);
+}
 
 static void
 sort_xattrname_list(void *start, size_t length)
@@ -592,6 +613,7 @@ copytree(copyfile_state_t s)
        const char *paths[2] =  { 0 };
        unsigned int flags = 0;
        int fts_flags = FTS_NOCHDIR;
+       dev_t last_dev = s->sb.st_dev;
 
        if (s == NULL) {
                errno = EINVAL;
@@ -604,7 +626,7 @@ copytree(copyfile_state_t s)
                goto done;
        }
 
-       flags = s->flags & (COPYFILE_ALL | COPYFILE_NOFOLLOW | COPYFILE_VERBOSE);
+       flags = s->flags & (COPYFILE_ALL | COPYFILE_NOFOLLOW | COPYFILE_VERBOSE | COPYFILE_EXCL);
 
        paths[0] = src = s->src;
        dst = s->dst;
@@ -674,7 +696,7 @@ copytree(copyfile_state_t s)
         * 6)  src is a directory, dst does not exist
         *
         * (1) copies src to dst/basename(src).
-        * (2) fails if COPYFILE_EXCLUSIVE is set, otherwise copies src to dst.
+        * (2) fails if COPYFILE_EXCL is set, otherwise copies src to dst.
         * (3) and (6) copy src to the name dst.
         * (4) copies the contents of src to the contents of dst.
         * (5) is an error.
@@ -716,6 +738,11 @@ copytree(copyfile_state_t s)
                }
                tstate->statuscb = s->statuscb;
                tstate->ctx = s->ctx;
+               if (last_dev == ftsent->fts_dev) {
+                       tstate->internal_flags |= (s->internal_flags & COPYFILE_MNT_CPROTECT_MASK);
+               } else {
+                       last_dev = ftsent->fts_dev;
+               }
                asprintf(&dstfile, "%s%s%s", dst, dstpathsep, ftsent->fts_path + offset);
                if (dstfile == NULL) {
                        copyfile_state_free(tstate);
@@ -846,6 +873,9 @@ copytree(copyfile_state_t s)
                }
 skipit:
 stopit:
+               s->internal_flags &= ~COPYFILE_MNT_CPROTECT_MASK;
+               s->internal_flags |= (tstate->internal_flags & COPYFILE_MNT_CPROTECT_MASK);
+
                copyfile_state_free(tstate);
                free(dstfile);
                if (retval == -1)
@@ -1492,8 +1522,11 @@ static int copyfile_unset_acl(copyfile_state_t s)
 static int copyfile_open(copyfile_state_t s)
 {
     int oflags = O_EXCL | O_CREAT | O_WRONLY;
-    int islnk = 0, isdir = 0;
+    int islnk = 0, isdir = 0, isreg = 0;
     int osrc = 0, dsrc = 0;
+    int prot_class = PROTECTION_CLASS_DEFAULT;
+    int set_cprot_explicit = 0;
+    int error = 0;
 
     if (s->src && s->src_fd == -2)
     {
@@ -1519,6 +1552,7 @@ static int copyfile_open(copyfile_state_t s)
                isdir = 1;
                break;
            case S_IFREG:
+               isreg = 1;
                break;
            default:
                if (!(strcmp(s->src, "/dev/null") == 0 && (s->flags & COPYFILE_METADATA))) {
@@ -1550,8 +1584,8 @@ static int copyfile_open(copyfile_state_t s)
        {
                copyfile_warn("open on %s", s->src);
                return -1;
-       } else
-           copyfile_debug(2, "open successful on source (%s)", s->src);
+       }
+       copyfile_debug(2, "open successful on source (%s)", s->src);
 
        (void)copyfile_quarantine(s);
     }
@@ -1582,6 +1616,31 @@ static int copyfile_open(copyfile_state_t s)
                }
        }
 
+       if (!(s->internal_flags & cfSrcProtSupportValid))
+       {
+               if ((error = does_copy_protection(s->src_fd)) > 0)
+               {
+                       s->internal_flags |= cfSrcSupportsCProtect;
+               }
+               else if (error < 0)
+               {
+                       copyfile_warn("does_copy_protection failed on (%s) with error <%d>", s->src, errno);
+                       return -1;
+               }
+               s->internal_flags |= cfSrcProtSupportValid;
+       }
+
+       /* copy protection is only valid for regular files and directories. */
+       if ((isreg || isdir) && (s->internal_flags & cfSrcSupportsCProtect))
+       {
+               prot_class = GET_PROT_CLASS(s->src_fd);
+               if (prot_class < 0)
+               {
+                       copyfile_warn("GET_PROT_CLASS failed on (%s) with error <%d>", s->src, errno);
+                       return -1;
+               }
+       }
+
        if (islnk) {
                size_t sz = (size_t)s->sb.st_size + 1;
                char *bp;
@@ -1624,7 +1683,8 @@ static int copyfile_open(copyfile_state_t s)
                        copyfile_warn("Cannot open directory %s for reading", s->dst);
                        return -1;
                }
-       } else while((s->dst_fd = open(s->dst, oflags | dsrc, s->sb.st_mode | S_IWUSR)) < 0)
+               set_cprot_explicit = 1;
+       } else while((s->dst_fd = open_dprotected_np(s->dst, oflags | dsrc, prot_class, 0, s->sb.st_mode | S_IWUSR)) < 0)
        {
            /*
             * We set S_IWUSR because fsetxattr does not -- at the time this comment
@@ -1639,10 +1699,14 @@ static int copyfile_open(copyfile_state_t s)
                    if (s->flags & COPYFILE_EXCL)
                        break;
                    oflags = oflags & ~O_CREAT;
+                   /* if O_CREAT isn't set in open_dprotected_np, it won't set protection class.
+                    * Set the flag here so we know to do it later.
+                    */
+                   set_cprot_explicit = 1;
                    if (s->flags & (COPYFILE_PACK | COPYFILE_DATA))
                    {
-                       copyfile_debug(4, "truncating existing file (%s)", s->dst);
-                       oflags |= O_TRUNC;
+                       copyfile_debug(4, "truncating existing file (%s)", s->dst);
+                       oflags |= O_TRUNC;
                    }
                    continue;
                case EACCES:
@@ -1674,6 +1738,37 @@ static int copyfile_open(copyfile_state_t s)
            return -1;
        }
        copyfile_debug(2, "open successful on destination (%s)", s->dst);
+
+       if (s->internal_flags & cfSrcSupportsCProtect)
+       {
+               if (!(s->internal_flags & cfDstProtSupportValid))
+               {
+                       if ((error = does_copy_protection(s->dst_fd)) > 0)
+                       {
+                               s->internal_flags |= cfDstSupportsCProtect;
+                       }
+                       else if (error < 0)
+                       {
+                               copyfile_warn("does_copy_protection failed on (%s) with error <%d>", s->dst, errno);
+                               return -1;
+                       }
+                       s->internal_flags |= cfDstProtSupportValid;
+               }
+
+               if ((isreg || isdir)
+                   && set_cprot_explicit
+                   && (s->internal_flags & cfDstSupportsCProtect))
+               {
+                       /* Protection class is set in open_dprotected_np for regular files that aren't truncated.
+                        * We set the protection class here for truncated files and directories.
+                        */
+                       if (SET_PROT_CLASS(s->dst_fd, prot_class) != 0)
+                       {
+                               copyfile_warn("SET_PROT_CLASS failed on (%s) with error <%d>", s->dst, errno);
+                               return -1;
+                       }
+               }
+       }
     }
 
     if (s->dst_fd < 0 || s->src_fd < 0)
@@ -2312,7 +2407,8 @@ static int copyfile_xattr(copyfile_state_t s)
             * 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)
+            * is added. Types 7->10 were added in 10.10, Types 11 & 12
+            * were added in 10.11.
             *
             * Ubiquity faulting file compression type 0x80000001 are
             * deprecated as of Yosemite, per rdar://17714998 don't copy the
@@ -2320,15 +2416,18 @@ static int copyfile_xattr(copyfile_state_t s)
             * 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 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 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 9:  /* uncompressed data in xattr (similar to but not identical to CMP_Type1) */
                case 10: /* 64k chunked uncompressed data in resource fork */
 
+               case 11: /* LZFSE-compressed data in xattr */
+               case 12: /* 64k chunked LZFSE-compressed data in resource fork */
+
                        /* valid compression type, we want to copy. */
                        break;
                 
index c125959761378e5ff7488d11f658b27eff713c94..87bc6380aa002fb4b592a73aea64e23bce3ee260 100644 (file)
@@ -54,6 +54,7 @@
                                FCCE17BC135A6444002CEE6D /* Products */,
                        );
                        sourceTree = "<group>";
+                       usesTabs = 1;
                };
                FCCE17BC135A6444002CEE6D /* Products */ = {
                        isa = PBXGroup;
                                GCC_WARN_UNUSED_LABEL = YES;
                                GCC_WARN_UNUSED_PARAMETER = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
+                               SDKROOT = macosx.internal;
                                WARNING_CFLAGS = (
                                        "-Wall",
                                        "-Wextra",
                                        "-lxpc",
                                        "-ldispatch",
                                );
-                               "OTHER_LDFLAGS[sdk=iphoneos*]" = (
+                               "OTHER_LDFLAGS[sdk=iphone*]" = (
                                        "-Wl,-umbrella,System",
                                        "-L/usr/lib/system",
                                        "-ldyld",
                                        "-lcompiler_rt",
-                                       "-lsystem_kernel",
+                                       "-lsystem$(SIM_SUFFIX)_kernel",
                                        "-lsystem_malloc",
                                        "-lsystem_c",
                                        "-lsystem_blocks",
                                        "-ldispatch",
                                        "-lxpc",
                                );
-                               "OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
-                                       "-Wl,-umbrella,System",
-                                       "-L/usr/lib/system",
-                                       "-ldyld",
-                                       "-lcompiler_rt",
-                                       "-lsystem_sim_kernel",
-                                       "-lsystem_malloc",
-                                       "-lsystem_sim_c",
-                                       "-lsystem_sim_blocks",
-                                       "-lsystem_sim_asl",
-                                       "-lsystem_sim_info",
-                                       "-ldispatch",
-                                       "-lxpc",
-                               );
+                               SDKROOT = macosx.internal;
+                               "SIM_SUFFIX[sdk=iphonesimulator*]" = _sim;
                                WARNING_CFLAGS = (
                                        "-Wall",
                                        "-Wextra",
index 509f8b133ea625890f0445a9f6eec352c986439b..e8b6b7626584e08ae99bebbf1296dd10a6c2ffd8 100644 (file)
@@ -10,7 +10,7 @@
 .Sh LIBRARY
 .Lb libc
 .Sh SYNOPSIS
-.In xattr_properties.h
+.In xattr_flags.h
 .Ft int
 .Fn xattr_preserve_for_intent "const char *" "xattr_operation_intent_t"
 .Ft char *
index d451a2a304532c78ea8f2403c80da9bff0a73e07..d365fb5fb198adff56f8b132a6ac1cd46ad92084 100644 (file)
@@ -1,15 +1,9 @@
 #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
+INSTALL_PATH = /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
+PUBLIC_HEADERS_FOLDER_PATH = /usr/include
+PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include
 
 BUILD_VARIANTS = normal debug