]> git.saurik.com Git - apple/copyfile.git/commitdiff
copyfile-166.40.1.tar.gz macos-10151 macos-10152 macos-10153 macos-10154 macos-10155 macos-10156 v166.40.1
authorApple <opensource@apple.com>
Tue, 23 Jul 2019 02:20:45 +0000 (02:20 +0000)
committerApple <opensource@apple.com>
Tue, 23 Jul 2019 02:20:45 +0000 (02:20 +0000)
copyfile.3
copyfile.c
copyfile.h
copyfile_test/main.c
copyfile_test/stat_test.c
copyfile_test/stat_test.h

index be1aa318e5749d28f7f5e2a53fd83797c890c31a..55d445446f58b58d70b7fbf22726192e07848cb8 100644 (file)
@@ -1,7 +1,7 @@
 .\"
 .\" Copyright (c) 2002 Apple Computer, Inc.  All rights reserved.
 .\"
-.Dd November 2, 2017
+.Dd July 22, 2019
 .Dt COPYFILE 3
 .Os
 .Sh NAME
@@ -217,6 +217,12 @@ This is a convenience macro, equivalent to
 .Dv (COPYFILE_NOFOLLOW_DST | COPYFILE_NOFOLLOW_SRC) .
 .It Dv COPYFILE_RUN_IN_PLACE
 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.
+.It Dv COPYFILE_PRESERVE_DST_TRACKED
+Preserve the UF_TRACKED flag at
+.Va to
+when copying metadata, regardless of whether
+.Va from
+has it set.  This flag is used in conjunction with COPYFILE_STAT, or COPYFILE_CLONE (for its fallback case).
 .El
 .Pp
 Copying files into a directory is supported. If
index 286d0ff8584649e037380c798225d5b937766bb5..443dbc5cf878a5ee0d4d044d79aba8c203a81ac1 100644 (file)
@@ -2744,6 +2744,16 @@ static int copyfile_stat(copyfile_state_t s)
                return -1;
        added_flags |= (dst_sb.st_flags & COPYFILE_PRESERVE_FLAGS);
 
+       /*
+        * The caller requested that copyfile attempts to preserve UF_TRACKED
+        * on the destination. This can be used to avoid dangling docIDs when
+        * the copy races against a process that sets the flag on newly created
+        * documents for instance.
+        */
+       if (s->flags & COPYFILE_PRESERVE_DST_TRACKED) {
+               added_flags |= (dst_sb.st_flags & UF_TRACKED);
+       }
+
        /* 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);
index 1e98a995190e2b207dc64f04fb50c4e3f084bf79..dfe4d0824deab7d97acd309d5f20369c57f80344 100644 (file)
@@ -108,6 +108,8 @@ typedef int (*copyfile_callback_t)(int, int, copyfile_state_t, const char *, con
 
 #define COPYFILE_DATA_SPARSE   (1<<27)
 
+#define COPYFILE_PRESERVE_DST_TRACKED  (1<<28)
+
 #define COPYFILE_VERBOSE       (1<<30)
 
 #define        COPYFILE_RECURSE_ERROR  0
index 338b17cdced51f38e5dd471f5c55742df849a4cc..a5384e9431c9349d0f6e4bd07094211554d50262 100644 (file)
@@ -55,6 +55,7 @@ int main(__unused int argc, __unused const char * argv[]) {
        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);
+       failed |= do_preserve_dst_tracked_test(TEST_DIR, stb.f_bsize);
 
        // Cleanup the disk image we ran our tests on.
        if (USING_DISK_IMAGE) {
index 08905446f9b382a64ff851182dde5691151ef8fc..0ab294499b04e645e5fccf3fdd0dfd5e5b1c1817 100644 (file)
@@ -147,3 +147,43 @@ bool do_preserve_dst_flags_test(const char *test_directory, __unused size_t bloc
 
        return success ? EXIT_SUCCESS : EXIT_FAILURE;
 }
+
+bool do_preserve_dst_tracked_test(const char *test_directory, __unused size_t block_size) {
+       char file_src[BSIZE_B] = {0}, file_dst[BSIZE_B] = {0};
+       off_t src_fsize = 0x1000;
+       int test_file_id;
+       struct stat dst_stb;
+       bool success = true;
+
+       printf("START [preserve_dst_tracked]\n");
+
+       // Create source file
+       assert_with_errno(snprintf(file_src, BSIZE_B, "%s/" TEST_FILE_NAME, test_directory) > 0);
+       assert_no_err(close(open(file_src, O_CREAT|O_EXCL, 0644)));
+       assert_no_err(truncate(file_src, src_fsize));
+
+       // Create destination file
+       test_file_id = rand() % DEFAULT_NAME_MOD;
+       assert_with_errno(snprintf(file_dst, BSIZE_B, "%s/%s.%d", test_directory, TEST_FILE_NAME, test_file_id) > 0);
+       assert_no_err(close(open(file_dst, O_CREAT|O_EXCL, 0644)));
+
+       // Track destination file
+       assert_no_err(chflags(file_dst, UF_TRACKED));
+
+       // Try to copy src onto destination
+       assert_no_err(copyfile(file_src, file_dst, NULL, COPYFILE_DATA|COPYFILE_STAT|COPYFILE_PRESERVE_DST_TRACKED));
+
+       assert_no_err(stat(file_dst, &dst_stb));
+       success &= (dst_stb.st_size == src_fsize);
+       success &= (dst_stb.st_flags & UF_TRACKED);
+       if (success) {
+               printf("PASS  [preserve_dst_tracked]\n");
+       } else {
+               printf("FAIL  [preserve_dst_tracked]\n");
+       }
+
+       (void)unlink(file_src);
+       (void)unlink(file_dst);
+
+       return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
index ab5c3c5f79cada14b3fd0b4bf3d3256922baffd4..719c95c33ca0da049d07621c8775dc36a6920c93 100644 (file)
@@ -10,5 +10,6 @@
 #include <stdlib.h>
 
 bool do_preserve_dst_flags_test(const char *test_directory, size_t block_size);
+bool do_preserve_dst_tracked_test(const char *test_directory, size_t block_size);
 
 #endif /* stat_test_h */