]> git.saurik.com Git - apple/copyfile.git/commitdiff
copyfile-166.tar.gz macos-1015 v166
authorApple <opensource@apple.com>
Thu, 25 Apr 2019 18:09:42 +0000 (18:09 +0000)
committerApple <opensource@apple.com>
Thu, 25 Apr 2019 18:09:42 +0000 (18:09 +0000)
17 files changed:
.gitignore [new file with mode: 0644]
copyfile.3
copyfile.c
copyfile.h
copyfile.xcodeproj/project.pbxproj
copyfile_private.h
copyfile_test/copyfile_test.entitlements [new file with mode: 0644]
copyfile_test/main.c
copyfile_test/sparse_test.c
copyfile_test/sparse_test.h
copyfile_test/stat_test.c [new file with mode: 0644]
copyfile_test/stat_test.h [new file with mode: 0644]
copyfile_test/test_utils.c
copyfile_test/test_utils.h
xattr_flags.h
xattr_name_with_flags.3
xattr_properties.h

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..909d75d
--- /dev/null
@@ -0,0 +1,4 @@
+copyfile.xcodeproj/project.xcworkspace
+copyfile.xcodeproj/xcuserdata/
+.DS_Store
+build/
index ceb898b037909a03d071563293ef4c2a92d5e05d..be1aa318e5749d28f7f5e2a53fd83797c890c31a 100644 (file)
@@ -1,7 +1,7 @@
 .\"
 .\" Copyright (c) 2002 Apple Computer, Inc.  All rights reserved.
 .\"
 .\"
 .\" Copyright (c) 2002 Apple Computer, Inc.  All rights reserved.
 .\"
-.Dd August 30, 2017
+.Dd November 2, 2017
 .Dt COPYFILE 3
 .Os
 .Sh NAME
 .Dt COPYFILE 3
 .Os
 .Sh NAME
@@ -185,7 +185,8 @@ This flag is equivalent to (COPYFILE_EXCL | COPYFILE_ACL | COPYFILE_STAT | COPYF
 | COPYFILE_NOFOLLOW_SRC).
 Note that if cloning is successful, progress callbacks will not be invoked.
 Note also that there is no support for cloning directories: if a directory is provided as the source,
 | COPYFILE_NOFOLLOW_SRC).
 Note that if cloning is successful, progress callbacks will not be invoked.
 Note also that there is no support for cloning directories: if a directory is provided as the source,
-an error will be returned.
+an error will be returned. Since this flag implies COPYFILE_NOFOLLOW_SRC, symbolic links themselves will
+be cloned instead of their targets.
 (This is only applicable for the
 .Fn copyfile
 function.)
 (This is only applicable for the
 .Fn copyfile
 function.)
@@ -196,7 +197,8 @@ This flag is equivalent to (COPYFILE_EXCL | COPYFILE_ACL | COPYFILE_STAT | COPYF
 | COPYFILE_NOFOLLOW_SRC).
 Note that if cloning is successful, progress callbacks will not be invoked.
 Note also that there is no support for cloning directories: if a directory is provided as the source and
 | COPYFILE_NOFOLLOW_SRC).
 Note that if cloning is successful, progress callbacks will not be invoked.
 Note also that there is no support for cloning directories: if a directory is provided as the source and
-COPYFILE_CLONE_FORCE is not passed, this will instead copy the directory. Recursive copying however is
+COPYFILE_CLONE_FORCE is not passed, this will instead copy the directory. Since this flag implies COPYFILE_NOFOLLOW_SRC,
+symbolic links themselves will be cloned instead of their targets. Recursive copying however is
 supported, see below for more information.
 (This is only applicable for the
 .Fn copyfile
 supported, see below for more information.
 (This is only applicable for the
 .Fn copyfile
@@ -217,6 +219,18 @@ This is a convenience macro, equivalent to
 If the src file has quarantine information, add the QTN_FLAG_DO_NOT_TRANSLOCATE flag to the quarantine information of the dst file. This allows a bundle to run in place instead of being translocated.
 .El
 .Pp
 If the src file has quarantine information, add the QTN_FLAG_DO_NOT_TRANSLOCATE flag to the quarantine information of the dst file. This allows a bundle to run in place instead of being translocated.
 .El
 .Pp
+Copying files into a directory is supported. If
+.Va to
+is a directory,
+.Va from
+will be copied into
+.Va to
+(if
+.Va from
+is a directory,
+copying its contents requires use of the COPYFILE_RECURSIVE parameter,
+which is documented below).
+.Pp
 The
 .Fn copyfile_state_get
 and
 The
 .Fn copyfile_state_get
 and
@@ -478,6 +492,19 @@ and
 .Dv COPYFILE_UNLINK
 flags are not used during a recursive copy, and will result
 in an error being returned.
 .Dv COPYFILE_UNLINK
 flags are not used during a recursive copy, and will result
 in an error being returned.
+.Pp
+Note that if the source path ends in a
+.Va /
+its contents are copied rather than the directory itself (like cp(1)).
+The behavior of a recursive copy on a directory hierarchy also depends
+on the contents of the destination. If the destination is a directory,
+the source directory (or its contents, if the source path ends in a
+.Va /
+) will be copied into it. If the destination exists but is not a
+directory, and the source is a non-empty directory, the copy will fail;
+the exact error set depends on the flags provided to
+.Fn copyfile
+initially.
 .Sh Progress Callback
 In addition to the recursive callbacks described above,
 .Fn copyfile
 .Sh Progress Callback
 In addition to the recursive callbacks described above,
 .Fn copyfile
index 99e6d42b10ad2ea43d14c20d3d677c7d9c085f10..286d0ff8584649e037380c798225d5b937766bb5 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2004-2010 Apple, Inc. All rights reserved.
+ * Copyright (c) 2004-2019 Apple, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  *
  * @APPLE_LICENSE_HEADER_START@
  *
 #define qtn_file_t void *
 #define QTN_SERIALIZED_DATA_MAX 0
 static void * qtn_file_alloc(void) { return NULL; }
 #define qtn_file_t void *
 #define QTN_SERIALIZED_DATA_MAX 0
 static void * qtn_file_alloc(void) { return NULL; }
-static int qtn_file_init_with_fd(void *x, int y) { return -1; }
-static int qtn_file_init_with_path(void *x, const char *path) { return -1; }
-static int qtn_file_init_with_data(void *x, const void *data, size_t len) { return -1; }
-static void qtn_file_free(void *x) { return; }
-static int qtn_file_apply_to_fd(void *x, int y) { return 0; }
-static char *qtn_error(int x) { return NULL; }
-static int qtn_file_to_data(void *x, char *y, size_t z) { return -1; }
-static void *qtn_file_clone(void *x) { return NULL; }
-static uint32_t qtn_file_get_flags(void *x) { return 0; }
-static int qtn_file_set_flags(void *x, uint32_t flags) { return 0; }
+static int qtn_file_init_with_fd(__unused void *x, __unused int y) { return -1; }
+static int qtn_file_init_with_path(__unused void *x, __unused const char *path) { return -1; }
+static int qtn_file_init_with_data(__unused void *x, __unused const void *data, __unused size_t len) { return -1; }
+static void qtn_file_free(__unused void *x) { return; }
+static int qtn_file_apply_to_fd(__unused void *x, __unused int y) { return 0; }
+static char *qtn_error(__unused int x) { return NULL; }
+static int qtn_file_to_data(__unused void *x, __unused char *y, __unused size_t *z) { return -1; }
+static void *qtn_file_clone(__unused void *x) { return NULL; }
+static uint32_t qtn_file_get_flags(__unused void *x) { return 0; }
+static int qtn_file_set_flags(__unused void *x, __unused uint32_t flags) { return 0; }
 #define        XATTR_QUARANTINE_NAME "figgledidiggledy"
 #define QTN_FLAG_DO_NOT_TRANSLOCATE 0
 #endif /* TARGET_OS_IPHONE */
 #define        XATTR_QUARANTINE_NAME "figgledidiggledy"
 #define QTN_FLAG_DO_NOT_TRANSLOCATE 0
 #endif /* TARGET_OS_IPHONE */
@@ -237,7 +237,7 @@ sort_xattrname_list(void *start, size_t length)
 
        tmp = ptrs[indx++] = (char*)start;
 
 
        tmp = ptrs[indx++] = (char*)start;
 
-       while (tmp = memchr(tmp, 0, ((char*)start + length) - tmp)) {
+       while ((tmp = memchr(tmp, 0, ((char*)start + length) - tmp))) {
                if (indx == nel) {
                        nel += 10;
                        ptrs = realloc(ptrs, sizeof(char**) * nel);
                if (indx == nel) {
                        nel += 10;
                        ptrs = realloc(ptrs, sizeof(char**) * nel);
@@ -645,7 +645,7 @@ copytree(copyfile_state_t s)
                retval = -1;
                goto done;
        }
                retval = -1;
                goto done;
        }
-       if (s->flags & (COPYFILE_MOVE | COPYFILE_UNLINK | COPYFILE_CHECK | COPYFILE_PACK | COPYFILE_UNPACK)) {
+       if (s->flags & (COPYFILE_MOVE | COPYFILE_UNLINK | COPYFILE_CHECK | COPYFILE_PACK | COPYFILE_UNPACK | COPYFILE_CLONE_FORCE)) {
                errno = EINVAL;
                retval = -1;
                goto done;
                errno = EINVAL;
                retval = -1;
                goto done;
@@ -2701,6 +2701,8 @@ error_exit:
 /*
  * Attempt to set the destination file's stat information -- including
  * flags and time-related fields -- to the source's.
 /*
  * Attempt to set the destination file's stat information -- including
  * flags and time-related fields -- to the source's.
+ * Note that we must set file flags *last*, as setting a flag like
+ * UF_IMMUTABLE can prevent us from setting other attributes.
  */
 static int copyfile_stat(copyfile_state_t s)
 {
  */
 static int copyfile_stat(copyfile_state_t s)
 {
@@ -2713,6 +2715,20 @@ static int copyfile_stat(copyfile_state_t s)
                struct timespec acc_time;
        } ma_times;
 
                struct timespec acc_time;
        } ma_times;
 
+       /* Try to set m/atimes using setattrlist(), for nanosecond precision. */
+       memset(&attrlist, 0, sizeof(attrlist));
+       attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
+       attrlist.commonattr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME;
+       ma_times.mod_time = s->sb.st_mtimespec;
+       ma_times.acc_time = s->sb.st_atimespec;
+       (void)fsetattrlist(s->dst_fd, &attrlist, &ma_times, sizeof(ma_times), 0);
+
+       /* If this fails, we don't care */
+       (void)fchown(s->dst_fd, s->sb.st_uid, s->sb.st_gid);
+
+       /* This may have already been done in copyfile_security() */
+       (void)fchmod(s->dst_fd, s->sb.st_mode & ~S_IFMT);
+
        /*
         * NFS doesn't support chflags; ignore errors as a result, since
         * we don't return failure for this.
        /*
         * NFS doesn't support chflags; ignore errors as a result, since
         * we don't return failure for this.
@@ -2721,32 +2737,17 @@ static int copyfile_stat(copyfile_state_t s)
                added_flags |= UF_HIDDEN;
 
        /*
                added_flags |= UF_HIDDEN;
 
        /*
-        * We need to check if SF_RESTRICTED was set on the destination
-        * by the kernel.  If it was, don't drop it.
+        * We need to check if certain flags were set on the destination
+        * by the kernel.  If they were, don't drop them.
         */
        if (fstat(s->dst_fd, &dst_sb))
                return -1;
         */
        if (fstat(s->dst_fd, &dst_sb))
                return -1;
-       if (dst_sb.st_flags & SF_RESTRICTED)
-               added_flags |= SF_RESTRICTED;
+       added_flags |= (dst_sb.st_flags & COPYFILE_PRESERVE_FLAGS);
 
        /* 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);
 
 
        /* 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);
-
-       /* This may have already been done in copyfile_security() */
-       (void)fchmod(s->dst_fd, s->sb.st_mode & ~S_IFMT);
-
-       /* Try to set m/atimes using setattrlist(), for nanosecond precision. */
-       memset(&attrlist, 0, sizeof(attrlist));
-       attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
-       attrlist.commonattr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME;
-       ma_times.mod_time = s->sb.st_mtimespec;
-       ma_times.acc_time = s->sb.st_atimespec;
-       (void)fsetattrlist(s->dst_fd, &attrlist, &ma_times, sizeof(ma_times), 0);
-
        return 0;
 }
 
        return 0;
 }
 
@@ -3003,7 +3004,7 @@ static int copyfile_xattr(copyfile_state_t s)
                        {
                                errno = error;
                                ret = -1;
                        {
                                errno = error;
                                ret = -1;
-                               copyfile_warn("could not set attributes %s on destination file descriptor: %s", name, strerror(error));
+                               copyfile_warn("could not set attributes %s on destination file descriptor", name);
                                continue;
                        }
                }
                                continue;
                        }
                }
@@ -3252,9 +3253,6 @@ int main(int c, char *v[])
  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
  */
 
  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
  */
 
-
-#define offsetof(type, member) __builtin_offsetof(type, member)
-
 #define        XATTR_MAXATTRLEN   (16*1024*1024)
 
 
 #define        XATTR_MAXATTRLEN   (16*1024*1024)
 
 
@@ -4425,10 +4423,10 @@ static int copyfile_pack(copyfile_state_t s)
        filehdr->appledouble.version            = ADH_VERSION;
        filehdr->appledouble.numEntries         = 2;
        filehdr->appledouble.entries[0].type    = AD_FINDERINFO;
        filehdr->appledouble.version            = ADH_VERSION;
        filehdr->appledouble.numEntries         = 2;
        filehdr->appledouble.entries[0].type    = AD_FINDERINFO;
-       filehdr->appledouble.entries[0].offset  = (u_int32_t)offsetof(apple_double_header_t, finfo);
+       filehdr->appledouble.entries[0].offset  = (u_int32_t)__builtin_offsetof(apple_double_header_t, finfo);
        filehdr->appledouble.entries[0].length  = FINDERINFOSIZE;
        filehdr->appledouble.entries[1].type    = AD_RESOURCE;
        filehdr->appledouble.entries[0].length  = FINDERINFOSIZE;
        filehdr->appledouble.entries[1].type    = AD_RESOURCE;
-       filehdr->appledouble.entries[1].offset  = (u_int32_t)offsetof(apple_double_header_t, pad);
+       filehdr->appledouble.entries[1].offset  = (u_int32_t)__builtin_offsetof(apple_double_header_t, pad);
        filehdr->appledouble.entries[1].length  = 0;
        bcopy(ADH_MACOSX, filehdr->appledouble.filler, sizeof(filehdr->appledouble.filler));
 
        filehdr->appledouble.entries[1].length  = 0;
        bcopy(ADH_MACOSX, filehdr->appledouble.filler, sizeof(filehdr->appledouble.filler));
 
index efea9dd5445ea19f607ac038067d2b7cc1815627..1e98a995190e2b207dc64f04fb50c4e3f084bf79 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2004-2010 Apple, Inc. All rights reserved.
+ * Copyright (c) 2004-2019 Apple, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
index b8ec504038649744601a719e723addfc8d5523bd..f2827504a8a2ab6b7d9a1eca6d07a86bf3ca5866 100644 (file)
@@ -7,6 +7,7 @@
        objects = {
 
 /* Begin PBXBuildFile section */
        objects = {
 
 /* Begin PBXBuildFile section */
+               098AF3B622692BF300F9BA42 /* stat_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 098AF3B522692BF300F9BA42 /* stat_test.c */; };
                721D4F071EA95283000F0555 /* copyfile.c in Sources */ = {isa = PBXBuildFile; fileRef = FCCE17C1135A658F002CEE6D /* copyfile.c */; };
                721D4F081EA95290000F0555 /* xattr_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 72406E621676C3C80099568B /* xattr_flags.c */; };
                72406E631676C3C80099568B /* xattr_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 72406E621676C3C80099568B /* xattr_flags.c */; };
                721D4F071EA95283000F0555 /* copyfile.c in Sources */ = {isa = PBXBuildFile; fileRef = FCCE17C1135A658F002CEE6D /* copyfile.c */; };
                721D4F081EA95290000F0555 /* xattr_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 72406E621676C3C80099568B /* xattr_flags.c */; };
                72406E631676C3C80099568B /* xattr_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 72406E621676C3C80099568B /* xattr_flags.c */; };
@@ -34,6 +35,9 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               098AF3B422692BF300F9BA42 /* stat_test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stat_test.h; sourceTree = "<group>"; };
+               098AF3B522692BF300F9BA42 /* stat_test.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = stat_test.c; sourceTree = "<group>"; };
+               098AF3B7226A510E00F9BA42 /* copyfile_test.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = copyfile_test.entitlements; sourceTree = "<group>"; };
                3F1EFD4C185C4EB400D1C970 /* copyfile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = copyfile.xcconfig; path = xcodescripts/copyfile.xcconfig; sourceTree = "<group>"; };
                721D4F051EA95008000F0555 /* libcopyfile.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcopyfile.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/lib/system/libcopyfile.tbd; sourceTree = DEVELOPER_DIR; };
                72406E621676C3C80099568B /* xattr_flags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xattr_flags.c; sourceTree = "<group>"; };
                3F1EFD4C185C4EB400D1C970 /* copyfile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = copyfile.xcconfig; path = xcodescripts/copyfile.xcconfig; sourceTree = "<group>"; };
                721D4F051EA95008000F0555 /* libcopyfile.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcopyfile.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/lib/system/libcopyfile.tbd; sourceTree = DEVELOPER_DIR; };
                72406E621676C3C80099568B /* xattr_flags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xattr_flags.c; sourceTree = "<group>"; };
                                726EE9DA1E9423E50017A5B9 /* main.c */,
                                726EE9DE1E9425160017A5B9 /* sparse_test.c */,
                                726EE9DF1E9425160017A5B9 /* sparse_test.h */,
                                726EE9DA1E9423E50017A5B9 /* main.c */,
                                726EE9DE1E9425160017A5B9 /* sparse_test.c */,
                                726EE9DF1E9425160017A5B9 /* sparse_test.h */,
+                               098AF3B522692BF300F9BA42 /* stat_test.c */,
+                               098AF3B422692BF300F9BA42 /* stat_test.h */,
                                726EE9E51E946D590017A5B9 /* test_utils.c */,
                                726EE9E11E9427B40017A5B9 /* test_utils.h */,
                                726EE9E21E946B320017A5B9 /* systemx.c */,
                                726EE9E31E946B320017A5B9 /* systemx.h */,
                                726EE9E51E946D590017A5B9 /* test_utils.c */,
                                726EE9E11E9427B40017A5B9 /* test_utils.h */,
                                726EE9E21E946B320017A5B9 /* systemx.c */,
                                726EE9E31E946B320017A5B9 /* systemx.h */,
+                               098AF3B7226A510E00F9BA42 /* copyfile_test.entitlements */,
                        );
                        path = copyfile_test;
                        sourceTree = "<group>";
                        );
                        path = copyfile_test;
                        sourceTree = "<group>";
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               098AF3B622692BF300F9BA42 /* stat_test.c in Sources */,
                                721D4F081EA95290000F0555 /* xattr_flags.c in Sources */,
                                721D4F071EA95283000F0555 /* copyfile.c in Sources */,
                                726EE9DB1E9423E50017A5B9 /* main.c in Sources */,
                                721D4F081EA95290000F0555 /* xattr_flags.c in Sources */,
                                721D4F071EA95283000F0555 /* copyfile.c in Sources */,
                                726EE9DB1E9423E50017A5B9 /* main.c in Sources */,
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = copyfile_test/copyfile_test.entitlements;
                                CODE_SIGN_IDENTITY = "-";
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                CODE_SIGN_IDENTITY = "-";
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
index 0111e0d750bc82cafb3cbc60ab9dc1ef5e2e2ca5..2d5417fa3df2fbe927e18df8c6bdafaa90692ed4 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2013 Apple, Inc. All rights reserved.
+ * Copyright (c) 2013-19 Apple, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 /*
  * File flags that are not preserved when copying stat information.
  */
 /*
  * File flags that are not preserved when copying stat information.
  */
-#define COPYFILE_OMIT_FLAGS    (UF_TRACKED | SF_RESTRICTED)
+#define COPYFILE_OMIT_FLAGS    (UF_TRACKED | SF_RESTRICTED | SF_NOUNLINK | UF_DATAVAULT)
+
+/*
+ * File flags that are not removed when replacing an existing file.
+ */
+#define COPYFILE_PRESERVE_FLAGS        (SF_RESTRICTED | SF_NOUNLINK | UF_DATAVAULT)
 
 #endif /* _COPYFILE_PRIVATE_H */
 
 #endif /* _COPYFILE_PRIVATE_H */
diff --git a/copyfile_test/copyfile_test.entitlements b/copyfile_test/copyfile_test.entitlements
new file mode 100644 (file)
index 0000000..f5b1b18
Binary files /dev/null and b/copyfile_test/copyfile_test.entitlements differ
index 616dbe3f7b514c9f6a77b34b47876594806af1e8..338b17cdced51f38e5dd471f5c55742df849a4cc 100644 (file)
@@ -12,6 +12,7 @@
 #include <removefile.h>
 
 #include "sparse_test.h"
 #include <removefile.h>
 
 #include "sparse_test.h"
+#include "stat_test.h"
 #include "test_utils.h"
 
 #define DISK_IMAGE_SIZE_MB     512
 #include "test_utils.h"
 
 #define DISK_IMAGE_SIZE_MB     512
@@ -53,6 +54,7 @@ int main(__unused int argc, __unused const char * argv[]) {
        failed |= do_sparse_test(TEST_DIR, stb.f_bsize);
        failed |= do_sparse_recursive_test(TEST_DIR, stb.f_bsize);
        failed |= do_fcopyfile_offset_test(TEST_DIR, stb.f_bsize);
        failed |= do_sparse_test(TEST_DIR, stb.f_bsize);
        failed |= do_sparse_recursive_test(TEST_DIR, stb.f_bsize);
        failed |= do_fcopyfile_offset_test(TEST_DIR, stb.f_bsize);
+       failed |= do_preserve_dst_flags_test(TEST_DIR, stb.f_bsize);
 
        // Cleanup the disk image we ran our tests on.
        if (USING_DISK_IMAGE) {
 
        // Cleanup the disk image we ran our tests on.
        if (USING_DISK_IMAGE) {
index ccced99fc02033c577eb956f5fa3595219e1b0dd..fc126d76710fbb9065c80c285e6e19fbed0a222e 100644 (file)
 #include "test_utils.h"
 #include "systemx.h"
 
 #include "test_utils.h"
 #include "systemx.h"
 
-#define OPEN_FLAGS     O_CREAT|O_TRUNC|O_RDWR
-#define OPEN_PERM      0666
-#define MKDIR_PERM     0777
-#define NAME_MOD       999
-
 /*
  * Copy the file pointed to by src_fd (and orig_name) to copy_name,
  * using copyfile()/fcopyfile() and COPYFILE_DATA. If do_sparse, also pass COPYFILE_DATA_SPARSE.
 /*
  * Copy the file pointed to by src_fd (and orig_name) to copy_name,
  * using copyfile()/fcopyfile() and COPYFILE_DATA. If do_sparse, also pass COPYFILE_DATA_SPARSE.
@@ -69,18 +64,18 @@ static bool test_copy(int src_fd, char* orig_name, char* copy_name, bool do_spar
 
        // Next, verify fcopyfile().
        // Make an fd for the destination.
 
        // Next, verify fcopyfile().
        // Make an fd for the destination.
-       assert_with_errno((copy_fd = open(copy_name, OPEN_FLAGS, OPEN_PERM)) > 0);
+       assert_with_errno((copy_fd = open(copy_name, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM)) > 0);
 
        // Call fcopyfile().
        assert_with_errno((cpf_state = copyfile_state_alloc()) != NULL);
        assert_no_err(fcopyfile(src_fd, copy_fd, cpf_state, flags));
 
 
        // Call fcopyfile().
        assert_with_errno((cpf_state = copyfile_state_alloc()) != NULL);
        assert_no_err(fcopyfile(src_fd, copy_fd, cpf_state, flags));
 
-       // 1. The copy is a sparse file (if start_off is a multiple of the block size).
+       // 1. The copy is a sparse file (if start_off is 0).
        // 2. The copyfile_state_t for the copy returns that all bytes were copied.
        assert_no_err(fstat(src_fd, &orig_sb));
        assert_no_err(fstat(copy_fd, &copy_sb));
        result &= verify_copy_sizes(&orig_sb, &copy_sb, cpf_state,
        // 2. The copyfile_state_t for the copy returns that all bytes were copied.
        assert_no_err(fstat(src_fd, &orig_sb));
        assert_no_err(fstat(copy_fd, &copy_sb));
        result &= verify_copy_sizes(&orig_sb, &copy_sb, cpf_state,
-                                                               start_off % copy_sb.st_blksize ? false : do_sparse, start_off);
+               start_off > 0 ? false : do_sparse, start_off);
 
        // 3. The copy and the source have identical contents.
        if (start_off == 0) {
 
        // 3. The copy and the source have identical contents.
        if (start_off == 0) {
@@ -217,13 +212,13 @@ bool do_sparse_test(const char* apfs_test_directory, size_t block_size) {
                sub_test_success = false;
 
                // Make new names for this file and its copies.
                sub_test_success = false;
 
                // Make new names for this file and its copies.
-               test_file_id = rand() % NAME_MOD;
+               test_file_id = rand() % DEFAULT_NAME_MOD;
                create_test_file_name(apfs_test_directory, "sparse", test_file_id, out_name);
                create_test_file_name(apfs_test_directory, "copy_sparse", test_file_id, sparse_copy_name);
                create_test_file_name(apfs_test_directory, "copy_full", test_file_id, full_copy_name);
 
                // Create the test file.
                create_test_file_name(apfs_test_directory, "sparse", test_file_id, out_name);
                create_test_file_name(apfs_test_directory, "copy_sparse", test_file_id, sparse_copy_name);
                create_test_file_name(apfs_test_directory, "copy_full", test_file_id, full_copy_name);
 
                // Create the test file.
-               fd = open(out_name, OPEN_FLAGS, OPEN_PERM);
+               fd = open(out_name, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
                assert_with_errno(fd >= 0);
 
                // Write to the test file, making it sparse.
                assert_with_errno(fd >= 0);
 
                // Write to the test file, making it sparse.
@@ -277,19 +272,19 @@ bool do_sparse_recursive_test(const char *apfs_test_directory, size_t block_size
        assert_with_errno(snprintf(exterior_dir_src, BSIZE_B, "%s/recursive_src", apfs_test_directory) > 0);
        assert_with_errno(snprintf(interior_dir_src, BSIZE_B, "%s/interior", exterior_dir_src) > 0);
 
        assert_with_errno(snprintf(exterior_dir_src, BSIZE_B, "%s/recursive_src", apfs_test_directory) > 0);
        assert_with_errno(snprintf(interior_dir_src, BSIZE_B, "%s/interior", exterior_dir_src) > 0);
 
-       assert_no_err(mkdir(exterior_dir_src, MKDIR_PERM));
-       assert_no_err(mkdir(interior_dir_src, MKDIR_PERM));
+       assert_no_err(mkdir(exterior_dir_src, DEFAULT_MKDIR_PERM));
+       assert_no_err(mkdir(interior_dir_src, DEFAULT_MKDIR_PERM));
 
 
-       test_file_id = rand() % NAME_MOD;
+       test_file_id = rand() % DEFAULT_NAME_MOD;
        create_test_file_name(exterior_dir_src, "exterior_sparse_file", test_file_id, exterior_file_src);
        create_test_file_name(interior_dir_src, "interior_sparse_file", test_file_id, interior_file_src);
 
        // Create the actual test files.
        create_test_file_name(exterior_dir_src, "exterior_sparse_file", test_file_id, exterior_file_src);
        create_test_file_name(interior_dir_src, "interior_sparse_file", test_file_id, interior_file_src);
 
        // Create the actual test files.
-       exterior_file_src_fd = open(exterior_file_src, OPEN_FLAGS, OPEN_PERM);
+       exterior_file_src_fd = open(exterior_file_src, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
        assert_with_errno(exterior_file_src_fd >= 0);
        write_start_and_end_holes(exterior_file_src_fd, block_size);
 
        assert_with_errno(exterior_file_src_fd >= 0);
        write_start_and_end_holes(exterior_file_src_fd, block_size);
 
-       interior_file_src_fd = open(interior_file_src, OPEN_FLAGS, OPEN_PERM);
+       interior_file_src_fd = open(interior_file_src, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
        assert_with_errno(interior_file_src_fd >= 0);
        write_middle_hole(interior_file_src_fd, block_size);
 
        assert_with_errno(interior_file_src_fd >= 0);
        write_middle_hole(interior_file_src_fd, block_size);
 
@@ -344,20 +339,20 @@ bool do_fcopyfile_offset_test(const char *apfs_test_directory, size_t block_size
        printf("START [fcopyfile_offset]\n");
 
        // Make new names for this file and its copies.
        printf("START [fcopyfile_offset]\n");
 
        // Make new names for this file and its copies.
-       test_file_id = rand() % NAME_MOD;
+       test_file_id = rand() % DEFAULT_NAME_MOD;
 
        create_test_file_name(apfs_test_directory, "foff_sparse", test_file_id, out_name);
        create_test_file_name(apfs_test_directory, "foff_copy_sparse", test_file_id, sparse_copy_name);
        create_test_file_name(apfs_test_directory, "foff_copy_full", test_file_id, full_copy_name);
 
        // Create the test file.
 
        create_test_file_name(apfs_test_directory, "foff_sparse", test_file_id, out_name);
        create_test_file_name(apfs_test_directory, "foff_copy_sparse", test_file_id, sparse_copy_name);
        create_test_file_name(apfs_test_directory, "foff_copy_full", test_file_id, full_copy_name);
 
        // Create the test file.
-       src_fd = open(out_name, OPEN_FLAGS, OPEN_PERM);
+       src_fd = open(out_name, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
        assert_with_errno(src_fd >= 0);
        // This writes 5 * block_size bytes.
        assert_with_errno(lseek(src_fd, write_middle_hole(src_fd, block_size), SEEK_SET) == 0);
 
        // Create a sparse copy using fcopyfile().
        assert_with_errno(src_fd >= 0);
        // This writes 5 * block_size bytes.
        assert_with_errno(lseek(src_fd, write_middle_hole(src_fd, block_size), SEEK_SET) == 0);
 
        // Create a sparse copy using fcopyfile().
-       sparse_copy_fd = open(sparse_copy_name, OPEN_FLAGS, OPEN_PERM);
+       sparse_copy_fd = open(sparse_copy_name, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
        assert_with_errno(sparse_copy_fd >= 0);
 
        // Seek the sparse copy to a non-zero offset.
        assert_with_errno(sparse_copy_fd >= 0);
 
        // Seek the sparse copy to a non-zero offset.
@@ -373,7 +368,7 @@ bool do_fcopyfile_offset_test(const char *apfs_test_directory, size_t block_size
 
        // Now, repeat the same procedure with a full copy.
        assert_with_errno(lseek(src_fd, 0, SEEK_SET) == 0);
 
        // Now, repeat the same procedure with a full copy.
        assert_with_errno(lseek(src_fd, 0, SEEK_SET) == 0);
-       full_copy_fd = open(full_copy_name, OPEN_FLAGS, OPEN_PERM);
+       full_copy_fd = open(full_copy_name, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
        assert_with_errno(full_copy_name >= 0);
 
        assert_with_errno(lseek(full_copy_fd, block_size, SEEK_SET) == (off_t) block_size);
        assert_with_errno(full_copy_name >= 0);
 
        assert_with_errno(lseek(full_copy_fd, block_size, SEEK_SET) == (off_t) block_size);
index 414007eba91990baa054d2f896647bacbd90d439..089b28069691a9b1efb8b61b1571c405b2c4eee2 100644 (file)
@@ -6,6 +6,9 @@
 #ifndef sparse_test_h
 #define sparse_test_h
 
 #ifndef sparse_test_h
 #define sparse_test_h
 
+#include <stdbool.h>
+#include <stdlib.h>
+
 bool do_sparse_test(const char *apfs_test_directory, size_t block_size);
 bool do_sparse_recursive_test(const char *apfs_test_directory, size_t block_size);
 bool do_fcopyfile_offset_test(const char *apfs_test_directory, size_t block_size);
 bool do_sparse_test(const char *apfs_test_directory, size_t block_size);
 bool do_sparse_recursive_test(const char *apfs_test_directory, size_t block_size);
 bool do_fcopyfile_offset_test(const char *apfs_test_directory, size_t block_size);
diff --git a/copyfile_test/stat_test.c b/copyfile_test/stat_test.c
new file mode 100644 (file)
index 0000000..0890544
--- /dev/null
@@ -0,0 +1,149 @@
+//
+//  stat_test.c
+//  copyfile_test
+//
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <removefile.h>
+#include <sandbox/rootless.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "../copyfile.h"
+#include "stat_test.h"
+#include "test_utils.h"
+
+#define STORAGE_CLASS          "copyfile_test"
+#define SPECIAL_DIR_NAME       "special_dir/"
+#define REGULAR_DIR_NAME       "regular_dir"
+#define TEST_FILE_NAME         "almighty_tallest"
+
+typedef int (*special_mkdir_func)(const char *, mode_t, const char *);
+
+static bool test_special_dir_with_flag(const char *source_directory, const char *test_directory,
+       special_mkdir_func create_func, uint32_t flag_to_test) {
+       char special_dir[BSIZE_B] = {0}, regular_dir[BSIZE_B] = {0}, test_file[BSIZE_B] = {0};
+       struct stat sb = {0};
+       bool success = true;
+
+       // The plan here is as follows:
+       //
+       // (1) Create a special directory using 'create_func', and verify that its bsdflags
+       // have `flag_to_test` set.
+       //
+       // (2) Copy the contents of `source_directory` into that special directory,
+       // and verify that the directory and, optionally, a well-known file inside it
+       // have `flag_to_test` set.
+       //
+       // (3) Copy the contents of the special directory into a directory that is not a child
+       // of our special directory (a 'regular' directory), and verify that the directory and
+       // a well-known file inside it do *NOT* have `flag_to_test` set.
+
+       // Create path names.
+       assert_with_errno(snprintf(special_dir, BSIZE_B, "%s/" SPECIAL_DIR_NAME, test_directory) > 0);
+       assert_with_errno(snprintf(regular_dir, BSIZE_B, "%s/" REGULAR_DIR_NAME, test_directory) > 0);
+       assert_with_errno(snprintf(test_file, BSIZE_B, "%s/" TEST_FILE_NAME, special_dir) > 0);
+
+       // Create our regular directory.
+       assert_no_err(mkdir(regular_dir, DEFAULT_MKDIR_PERM));
+
+       // Create our special directory.
+       assert_no_err(create_func(special_dir, DEFAULT_MKDIR_PERM, STORAGE_CLASS));
+
+       // (1) Make sure the special directory has the specified bit set.
+       assert_no_err(stat(special_dir, &sb));
+       assert(sb.st_flags & flag_to_test);
+
+       // Now, copy the source directory's into the special directory.
+       assert_no_err(copyfile(source_directory, special_dir, NULL, COPYFILE_ALL|COPYFILE_RECURSIVE));
+
+       // (2) Make sure that the resulting folder (and optionally, its well-known subfile)
+       // have the specified bit set.
+       assert_no_err(stat(special_dir, &sb));
+       success &= verify_st_flags(&sb, flag_to_test);
+
+       if (flag_to_test != SF_NOUNLINK) {
+               assert_no_err(stat(test_file, &sb));
+               success &= verify_st_flags(&sb, flag_to_test);
+       }
+
+       // Finally, copy the contents of the special directory into our regular directory.
+       // Since at least one of the files in this directory will have a rootless xattr,
+       // which cannot be copied here, we do not attempt to copy extended attributes here.
+       assert_no_err(copyfile(special_dir, regular_dir, NULL,
+               COPYFILE_DATA|COPYFILE_SECURITY|COPYFILE_RECURSIVE));
+
+       // (3) Make sure that the regular directory (and optionally, its well-known subfile)
+       // do *NOT* have the specified bit set.
+       assert_no_err(stat(regular_dir, &sb));
+       success &= ((sb.st_flags & flag_to_test) == 0);
+
+       if (flag_to_test != SF_NOUNLINK) {
+               // Rebuild the path to the subfile, as our original path is relative
+               // to the special directory.
+               memset(test_file, 0, BSIZE_B);
+               assert_with_errno(snprintf(test_file, BSIZE_B, "%s/" TEST_FILE_NAME, regular_dir) > 0);
+
+               assert_no_err(stat(test_file, &sb));
+               success &= verify_st_flags(&sb, 0);
+       }
+
+       // Clean up after the test.
+       assert_no_err(removefile(special_dir, NULL, REMOVEFILE_RECURSIVE));
+       assert_no_err(removefile(regular_dir, NULL, REMOVEFILE_RECURSIVE));
+
+       return success;
+}
+
+bool do_preserve_dst_flags_test(const char *test_directory, __unused size_t block_size) {
+       int interior_file_src_fd, test_file_id;
+       char exterior_dir_src[BSIZE_B] = {0}, interior_file_src[BSIZE_B] = {0};
+       uid_t euid = geteuid();
+       bool success = true;
+
+       printf("START [preserve_dst_flags]\n");
+
+       // Construct our source layout.
+       assert_with_errno(snprintf(exterior_dir_src, BSIZE_B, "%s/" TEST_FILE_NAME, test_directory) > 0);
+
+       assert_no_err(mkdir(exterior_dir_src, DEFAULT_MKDIR_PERM));
+
+       test_file_id = rand() % DEFAULT_NAME_MOD;
+       create_test_file_name(exterior_dir_src, TEST_FILE_NAME, test_file_id, interior_file_src);
+
+       // Create our interior test file.
+       interior_file_src_fd = open(interior_file_src, DEFAULT_OPEN_FLAGS, DEFAULT_OPEN_PERM);
+       assert_with_errno(interior_file_src_fd >= 0);
+       assert_no_err(close(interior_file_src_fd)); // file only needs to exist
+
+       if (euid == 0) {
+               // Try to copy our directory into a restricted environment.
+               success &= test_special_dir_with_flag(exterior_dir_src, test_directory,
+                       rootless_mkdir_restricted, SF_RESTRICTED);
+
+               // Make sure SF_NOUNLINK works as well.
+               success &= test_special_dir_with_flag(exterior_dir_src, test_directory,
+                       rootless_mkdir_nounlink, SF_NOUNLINK);
+       } else {
+               printf("Skipping SF_RESTRICTED and SF_NOUNLINK tests, because we are not root.\n");
+       }
+
+       // Try to copy our directory into a datavault.
+       success &= test_special_dir_with_flag(exterior_dir_src, test_directory,
+               rootless_mkdir_datavault, UF_DATAVAULT);
+
+       if (success) {
+               printf("PASS  [preserve_dst_flags]\n");
+       } else {
+               printf("FAIL  [preserve_dst_flags]\n");
+       }
+
+       (void)removefile(exterior_dir_src, NULL, REMOVEFILE_RECURSIVE);
+
+       return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/copyfile_test/stat_test.h b/copyfile_test/stat_test.h
new file mode 100644 (file)
index 0000000..ab5c3c5
--- /dev/null
@@ -0,0 +1,14 @@
+//
+//  stat_test.h
+//  copyfile_test
+//
+
+#ifndef stat_test_h
+#define stat_test_h
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool do_preserve_dst_flags_test(const char *test_directory, size_t block_size);
+
+#endif /* stat_test_h */
index 97c9efe21d1cd776506133f121685140fa7dc4af..95741b131f11123cfef90d16aa3f1e5783276954 100644 (file)
 #include "test_utils.h"
 #include "systemx.h"
 
 #include "test_utils.h"
 #include "systemx.h"
 
+bool verify_st_flags(struct stat *sb, uint32_t flags_to_expect) {
+       // Verify that sb's flags include flags_to_expect.
+       if (((sb->st_flags & flags_to_expect)) != flags_to_expect) {
+               printf("st_flags (%u) do not include expected flags (%u)\n",
+                       sb->st_flags, flags_to_expect);
+               return false;
+       }
+
+       return true;
+}
+
 bool verify_fd_contents(int orig_fd, off_t orig_pos, int copy_fd, off_t copy_pos, size_t length) {
        // Read *length* contents of the two fds and make sure they compare as equal.
        // Don't alter the position of either fd.
 bool verify_fd_contents(int orig_fd, off_t orig_pos, int copy_fd, off_t copy_pos, size_t length) {
        // Read *length* contents of the two fds and make sure they compare as equal.
        // Don't alter the position of either fd.
@@ -39,7 +50,8 @@ bool verify_fd_contents(int orig_fd, off_t orig_pos, int copy_fd, off_t copy_pos
                for (size_t bad_off = 0; bad_off < length; bad_off++) {
                        if (orig_contents[bad_off] != copy_contents[bad_off]) {
                                printf("first mismatch is at offset %zu, original 0x%llx COPY 0x%llx\n",
                for (size_t bad_off = 0; bad_off < length; bad_off++) {
                        if (orig_contents[bad_off] != copy_contents[bad_off]) {
                                printf("first mismatch is at offset %zu, original 0x%llx COPY 0x%llx\n",
-                                          bad_off, orig_contents[bad_off], copy_contents[bad_off]);
+                                          bad_off, (unsigned long long)orig_contents[bad_off],
+                                          (unsigned long long)copy_contents[bad_off]);
                                break;
                        }
                }
                                break;
                        }
                }
@@ -68,14 +80,14 @@ bool verify_copy_sizes(struct stat *orig_sb, struct stat *copy_sb, copyfile_stat
        // If requested, verify that the copy is a sparse file.
        if (do_sparse) {
                if (orig_sb->st_size - src_start != copy_sb->st_size) {
        // If requested, verify that the copy is a sparse file.
        if (do_sparse) {
                if (orig_sb->st_size - src_start != copy_sb->st_size) {
-                       printf("original size - offset (%zd) != copy size (%zd)\n",
+                       printf("original size - offset (%lld) != copy size (%lld)\n",
                                   orig_sb->st_size - src_start, copy_sb->st_size);
                        result = false;
                }
 
                                   orig_sb->st_size - src_start, copy_sb->st_size);
                        result = false;
                }
 
-               blocks_offset = src_start / orig_sb->st_blksize;
+               blocks_offset = src_start / S_BLKSIZE;
                if (orig_sb->st_blocks - blocks_offset < copy_sb->st_blocks) {
                if (orig_sb->st_blocks - blocks_offset < copy_sb->st_blocks) {
-                       printf("original blocks - offset (%zd) < copy blocks (%zd)\n",
+                       printf("original blocks - offset (%lld) < copy blocks (%lld)\n",
                                   orig_sb->st_blocks - blocks_offset, copy_sb->st_blocks);
                        result = false;
                }
                                   orig_sb->st_blocks - blocks_offset, copy_sb->st_blocks);
                        result = false;
                }
@@ -85,7 +97,7 @@ bool verify_copy_sizes(struct stat *orig_sb, struct stat *copy_sb, copyfile_stat
        if (cpf_state) {
                assert_no_err(copyfile_state_get(cpf_state, COPYFILE_STATE_COPIED, &cpf_bytes_copied));
                if (orig_sb->st_size - src_start != cpf_bytes_copied) {
        if (cpf_state) {
                assert_no_err(copyfile_state_get(cpf_state, COPYFILE_STATE_COPIED, &cpf_bytes_copied));
                if (orig_sb->st_size - src_start != cpf_bytes_copied) {
-                       printf("original size - start (%zd) != copied bytes (%zd)\n",
+                       printf("original size - start (%lld) != copied bytes (%lld)\n",
                                   orig_sb->st_size - src_start, cpf_bytes_copied);
                        result = false;
                }
                                   orig_sb->st_size - src_start, cpf_bytes_copied);
                        result = false;
                }
index a8fabf858e728ca4ee6ebc3d98d6c2b0ab25bd2f..4cd7faa7dd46cbc1c5465483da416bb999f8d915 100644 (file)
 #define BSIZE_B                                        128
 #define MAX_DISK_IMAGE_SIZE_MB 1024
 
 #define BSIZE_B                                        128
 #define MAX_DISK_IMAGE_SIZE_MB 1024
 
+#define DEFAULT_NAME_MOD               999
+#define DEFAULT_OPEN_FLAGS             O_CREAT|O_TRUNC|O_RDWR
+#define DEFAULT_OPEN_PERM              0666
+#define DEFAULT_MKDIR_PERM             0777
+
 #define DISK_IMAGE_PATH                        "/tmp/copyfile_sparse.sparseimage"
 #define VOLUME_NAME                            "apfs_sparse"
 #define DEFAULT_FSTYPE                 "JHFS+"
 #define DISK_IMAGE_PATH                        "/tmp/copyfile_sparse.sparseimage"
 #define VOLUME_NAME                            "apfs_sparse"
 #define DEFAULT_FSTYPE                 "JHFS+"
@@ -30,6 +35,7 @@
 #define DIFF_PATH                              "/usr/bin/diff"
 
 // Test routine helpers.
 #define DIFF_PATH                              "/usr/bin/diff"
 
 // Test routine helpers.
+bool verify_st_flags(struct stat *sb, uint32_t flags_to_expect);
 bool verify_fd_contents(int orig_fd, off_t orig_pos, int copy_fd, off_t copy_pos, size_t length);
 bool verify_copy_contents(const char *orig_name, const char *copy_name);
 bool verify_copy_sizes(struct stat *orig_sb, struct stat *copy_sb, copyfile_state_t cpf_state,
 bool verify_fd_contents(int orig_fd, off_t orig_pos, int copy_fd, off_t copy_pos, size_t length);
 bool verify_copy_contents(const char *orig_name, const char *copy_name);
 bool verify_copy_sizes(struct stat *orig_sb, struct stat *copy_sb, copyfile_state_t cpf_state,
index 032b6ad011c2af01755f8585cd6d8c54d52dab6a..dc7290a1035e224686255f8ed605b22fc05c24e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2013 Apple, Inc. All rights reserved.
+ * Copyright (c) 2013-19 Apple, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
index 0840430613bee208c9f54495831237afd2a87287..35afc2a866abe01f4d7c8d6443183785ccfd5485 100644 (file)
@@ -1,7 +1,7 @@
 .\"
 .\" Copyright (c) 2013 Apple Computer, Inc.  All rights reserved.
 .\"
 .\"
 .\" Copyright (c) 2013 Apple Computer, Inc.  All rights reserved.
 .\"
-.Dd December 21, 2016
+.Dd October 9, 2018
 .Dt XATTR_NAME_WITH_FLAGS 3
 .Os
 .Sh NAME
 .Dt XATTR_NAME_WITH_FLAGS 3
 .Os
 .Sh NAME
@@ -80,7 +80,7 @@ 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
 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.
+Indicates that the intent is to sync the object to a service like iCloud Drive.
 .El
 .Sh FLAGS
 Various flags are defined by the type
 .El
 .Sh FLAGS
 Various flags are defined by the type
@@ -101,9 +101,8 @@ 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
 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.
+is synced on services like iCloud Drive. Sync services 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
 .El
 .Sh EXAMPLE
 The following example is a simple function that, given an extended attribute
index 21d9a29eb73215f6836818ca02d9a9a06034d372..942720301d8848477fa8de8e2f2ca2de158cde75 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2013 Apple, Inc. All rights reserved.
+ * Copyright (c) 2013-19 Apple, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -89,40 +89,6 @@ typedef uint64_t CopyOperationProperties_t;
  */
 #define kCopyOperationPropertyNeverPreserve    ((CopyOperationProperties_t)0x0004)
 
  */
 #define kCopyOperationPropertyNeverPreserve    ((CopyOperationProperties_t)0x0004)
 
-#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;
- * 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 *_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
- * 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 *_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 *) DEPRECATED_IN_MAC_OS_X_VERSION_10_10_AND_LATER;
-#endif /* 0 */
-
 __END_DECLS
 
 #endif /* _XATTR_PROPERTIES_H */
 __END_DECLS
 
 #endif /* _XATTR_PROPERTIES_H */