---
name: "copyfile"
section: "3"
platform: "macos"
package: "copyfile"
version: "240"
release: "macOS 26.5"
platforms: ["macos"]
url: "https://new.carta.tech/copyfile"
---

# copyfile(3)

copy a file

## NAME

**copyfile**, **fcopyfile**, **copyfile\_state\_alloc**, **copyfile\_state\_free**, **copyfile\_state\_get**, **copyfile\_state\_set** – copy a file

## LIBRARY

Standard C Library (libc, -lc)

## SYNOPSIS

**#include \<copyfile.h\>**

*int*\

**copyfile**(*const char \*from*, *const char \*to*, *copyfile\_state\_t state*, *copyfile\_flags\_t flags*);

*int*\

**fcopyfile**(*int from*, *int to*, *copyfile\_state\_t state*, *copyfile\_flags\_t flags*);

*copyfile\_state\_t*\

**copyfile\_state\_alloc**(*void*);

*int*\

**copyfile\_state\_free**(*copyfile\_state\_t state*);

*int*\

**copyfile\_state\_get**(*copyfile\_state\_t state*, *uint32\_t flag*, *void \* dst*);

*int*\

**copyfile\_state\_set**(*copyfile\_state\_t state*, *uint32\_t flag*, *const void \* src*);

*typedef* *int*\

**(\*copyfile\_callback\_t)**(*int what*, *int stage*, *copyfile\_state\_t state*, *const char \* src*, *const char \* dst*, *void \* ctx*);

## DESCRIPTION

These functions are used to copy a file's data and/or metadata.  (Metadata consists of permissions, extended attributes, access control lists, and so forth.)

The **copyfile\_state\_alloc**() function initializes a *copyfile\_state\_t* object (which is an opaque data type). This object can be passed to **copyfile**() and **fcopyfile**(); **copyfile\_state\_get**() and **copyfile\_state\_set**() can be used to manipulate the state (see below). The **copyfile\_state\_free**() function is used to deallocate the object and its contents.

The **copyfile**() function can copy the named *from* file to the named *to* file; the **fcopyfile**() function does the same, but using the file descriptors of already-opened files. If the *state* parameter is the return value from **copyfile\_state\_alloc**(), then **copyfile**() and **fcopyfile**() will use the information from the state object; if it is NULL, then both functions will work normally, but less control will be available to the caller. The *flags* parameter controls which contents are copied:

- COPYFILE\_ACL

  Copy the source file's access control lists.

- COPYFILE\_STAT

  Copy the source file's POSIX information (mode, modification time, etc.). Note that setuid and setgid bits are by default not copied from source files or to destination files that reside on volumes that are mounted with the MNT\_NOSUID [mount(2)](/mount/2.md) flag, but this can be overridden through the use of COPYFILE\_STATE\_PRESERVE\_SUID in the *copyfile\_state\_t* object.

- COPYFILE\_XATTR

  Copy the source file's extended attributes.

- COPYFILE\_DATA

  Copy the source file's data.

These values may be or'd together; several convenience macros are provided:

- COPYFILE\_SECURITY

  Copy the source file's POSIX and ACL information; equivalent to (COPYFILE\_STAT\|COPYFILE\_ACL).

- COPYFILE\_METADATA

  Copy the metadata; equivalent to (COPYFILE\_SECURITY\|COPYFILE\_XATTR).

- COPYFILE\_ALL

  Copy the entire file; equivalent to (COPYFILE\_METADATA\|COPYFILE\_DATA).

The **copyfile**() and **fcopyfile**() functions can also have their behavior modified by the following flags:

- COPYFILE\_RECURSIVE

  Causes **copyfile**() to recursively copy a hierarchy. This flag is not used by **fcopyfile**(); see below for more information.

- COPYFILE\_CHECK

  Return a bitmask (corresponding to the *flags* argument) indicating which contents would be copied; no data are actually copied.  (E.g., if *flags* was set to COPYFILE\_CHECK\|COPYFILE\_METADATA, and the *from* file had extended attributes but no ACLs, the return value would be COPYFILE\_XATTR .)

- COPYFILE\_PACK

  Serialize the *from* file. The *to* file is an AppleDouble-format file.

- COPYFILE\_UNPACK

  Unserialize the *from* file. The *from* file is an AppleDouble-format file; the *to* file will have the extended attributes, ACLs, resource fork, and FinderInfo data from the *to* file, regardless of the *flags* argument passed in.

- COPYFILE\_EXCL

  Fail if the *to* file already exists.  (This is only applicable for the **copyfile**() function.)

- COPYFILE\_NOFOLLOW\_SRC

  Do not follow the *from* file, if it is a symbolic link.  (This is only applicable for the **copyfile**() function.)

- COPYFILE\_NOFOLLOW\_DST

  Do not follow the *to* file, if it is a symbolic link.  (This is only applicable for the **copyfile**() function.)

- COPYFILE\_MOVE

  Unlink (using [remove(3)](/remove/3.md)) the *from* file.  (This is only applicable for the **copyfile**() function.)  No error is returned if [remove(3)](/remove/3.md) fails. Note that [remove(3)](/remove/3.md) removes a symbolic link itself, not the target of the link.

- COPYFILE\_UNLINK

  Unlink the *to* file before starting.  (This is only applicable for the **copyfile**() function.)

- COPYFILE\_CLONE\_FORCE

  Clone the file instead. This is a force flag i.e. if cloning fails, an error is returned. This flag is equivalent to (COPYFILE\_EXCL \| COPYFILE\_STAT \| COPYFILE\_XATTR \| COPYFILE\_DATA \| COPYFILE\_NOFOLLOW\_SRC). Note that if cloning is successful, progress callbacks will not be invoked, nor will any setuid or setgid bits be copied to the destination. Note also that there is no support for cloning directories: if a directory is provided as the source, 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 **copyfile**() function.) Finally, note that ACLs will not be cloned unless COPYFILE\_ACL is also passed.

- COPYFILE\_CLONE

  Try to clone the file instead. This is a best try flag i.e. if cloning fails, fallback to copying the file. This flag is equivalent to (COPYFILE\_EXCL \| COPYFILE\_STAT \| COPYFILE\_XATTR \| COPYFILE\_DATA \| COPYFILE\_NOFOLLOW\_SRC). Note that if cloning is successful, progress callbacks will not be invoked, nor will any setuid or setgid bits be copied to the destination. 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. 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 **copyfile**() function.) Finally, note that ACLs will not be cloned unless COPYFILE\_ACL is also passed.

- COPYFILE\_DATA\_SPARSE

  Copy a file sparsely. This requires that the source and destination file systems support sparse files with hole sizes at least as large as their block sizes. This also requires that the source file is sparse, and for **fcopyfile**() the source file descriptor's offset be a multiple of the minimum hole size. If COPYFILE\_DATA is also specified, this will fall back to a full copy if sparse copying cannot be performed for any reason; otherwise, an error is returned.

- COPYFILE\_NOFOLLOW

  This is a convenience macro, equivalent to (COPYFILE\_NOFOLLOW\_DST \| COPYFILE\_NOFOLLOW\_SRC).

- 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.

- COPYFILE\_PRESERVE\_DST\_TRACKED

  Preserve the UF\_TRACKED flag at *to* when copying metadata, regardless of whether *from* has it set. This flag is used in conjunction with COPYFILE\_STAT, or COPYFILE\_CLONE (for its fallback case).

**fcopyfile**() function can also have its behavior modified by the following flags:

- COPYFILE\_NOCACHE

  turn caching off for both *from* and *to* arguments. This is a best effort attempt, and if succeeded the file descriptors would keep the no-caching policy when returning from **fcopyfile**()

Copying files into a directory is supported. If *to* is a directory, *from* will be copied into *to* (if *from* is a directory, copying its contents requires use of the COPYFILE\_RECURSIVE parameter, which is documented below).

The **copyfile\_state\_get**() and **copyfile\_state\_set**() functions can be used to manipulate the *copyfile\_state\_t* object returned by **copyfile\_state\_alloc**(). In both functions, the *dst* parameter's type depends on the *flag* parameter that is passed in.

- COPYFILE\_STATE\_SRC\_FD

  - COPYFILE\_STATE\_DST\_FD

  Get or set the file descriptor associated with the source (or destination) file. If this has not been initialized yet, the value will be -2. The *dst* (for **copyfile\_state\_get**()) and *src* (for **copyfile\_state\_set**()) parameters are pointers to *int*.

- COPYFILE\_STATE\_SRC\_FILENAME

  - COPYFILE\_STATE\_DST\_FILENAME

  Get or set the filename associated with the source (or destination) file. If it has not been initialized yet, the value will be NULL. For **copyfile\_state\_set**(), the *src* parameter is a pointer to a C string (i.e., *char\** *);* **copyfile\_state\_set**() makes a private copy of this string. For **copyfile\_state\_get**() function, the *dst* parameter is a pointer to a pointer to a C string (i.e., *char\*\** *);* the returned value is a pointer to the *state* *'s* copy, and must not be modified or released.

- COPYFILE\_STATE\_STATUS\_CB

  Get or set the callback status function (currently only used for recursive copies; see below for details). The *src* parameter and the *dst* parameter are pointers to a function of type *copyfile\_callback\_t* (see above).

- COPYFILE\_STATE\_STATUS\_CTX

  Get or set the context parameter for the status call-back function (see below for details). The *src* parameter and the *dst* parameter are opaque pointers (type *void \** ).

- COPYFILE\_STATE\_QUARANTINE

  Get or set the quarantine information with the source file. The *src* parameter is a pointer to an opaque object (type *void \** ).

- COPYFILE\_STATE\_COPIED

  Get the number of data bytes copied so far. (Only valid for **copyfile\_state\_get**(); see below for more details about callbacks.) If a COPYFILE\_CLONE or COPYFILE\_CLONE\_FORCE operation successfully cloned the requested objects, then this value will be 0. The *dst* parameter is a pointer to *off\_t* (type *off\_t \** *).*

- COPYFILE\_STATE\_XATTRNAME

  Get the name of the extended attribute during a callback for COPYFILE\_COPY\_XATTR (see below for details).  This field cannot be set, and may be NULL.

- COPYFILE\_STATE\_WAS\_CLONED

  True if a COPYFILE\_CLONE or COPYFILE\_CLONE\_FORCE operation successfully cloned the requested objects. The *dst* parameter is a pointer to *bool* (type *bool \** *).*

- COPYFILE\_STATE\_SRC\_BSIZE

  - COPYFILE\_STATE\_DST\_BSIZE

  - COPYFILE\_STATE\_BSIZE

  Get or set the copy blocksize associated with the source or destination file (or both). The caller must ensure that its environment does not restrict a memory allocation of this size. If the copy blocksize for the destination file is specified to be larger than the copy blocksize for the source file, it will be ignored. If this has not been initialized by the caller, the value will be 0. The *dst* parameter and the *src* parameter are pointers to *uint32\_t* (type *uint32\_t \** *).*

- COPYFILE\_STATE\_FORBID\_CROSS\_MOUNT

  Get or set the current setting for crossing mount points during a COPYFILE\_RECURSIVE operation. By default, recursive copying descends into directories that have a different device number than the directory from which the descent began. The *dst* parameter and the *src* parameter are pointers to *bool* (type *bool \** *).*

- COPYFILE\_STATE\_NOCPROTECT

  Get or set the current setting for copying content-protection classes from the source to the destination file. The *dst* parameter and the *src* parameter are pointers to *uint32\_t* (type *uint32\_t \** *).*

- COPYFILE\_STATE\_PRESERVE\_SUID

  Get or set the current setting for preserving the setuid and setgid bits on the destination file during a copy. (See the descriptions above for COPYFILE\_STAT and COPYFILE\_CLONE for details.) The *dst* parameter and the *src* parameter are pointers to *uint32\_t* (type *uint32\_t \** *).*

- COPYFILE\_STATE\_RECURSIVE\_SRC\_FTSENT

  Get any available file entry information during a recursive copy. If none is available, the value will be NULL. (Only valid for **copyfile\_state\_get**(*).*) The *dst* parameter is a pointer to a pointer to a const *FTSENT* (type *const* *FTSENT \*\** *);* the returned value is the *state* *'s* copy, and must not be modified or released.

- COPYFILE\_STATE\_FORBID\_DST\_EXISTING\_SYMLINKS

  Get or set the current setting for forbidding copying over existing symlinks. By default, copying over an existing destination is allowed regardless of the type of file that already exists at the destination path. The *dst* parameter and the *src* parameter are pointers to *uint32\_t* (type *uint32\_t \** *).*

## Recursive Copies

When given the COPYFILE\_RECURSIVE flag, **copyfile**() (but not **fcopyfile**()) will use the [fts(3)](/fts/3.md) functions to recursively descend into the source file-system object. It then calls **copyfile**() on each of the entries it finds that way. If a call-back function is given (using **copyfile\_state\_set**() and COPYFILE\_STATE\_STATUS\_CB ), the call-back function will be called four times for each directory object, and twice for all other objects.  (Each directory will be examined twice, once on entry -- before copying each of the objects contained in the directory -- and once on exit -- after copying each object contained in the directory, in order to perform some final cleanup.)

The call-back function will have one of the following values as the first argument, indicating what is being copied:

- COPYFILE\_RECURSE\_FILE

  The object being copied is a file (or, rather, something other than a directory).

- COPYFILE\_RECURSE\_DIR

  The object being copied is a directory, and is being entered.  (That is, none of the filesystem objects contained within the directory have been copied yet.) When COPYFILE\_STATE\_FORBID\_CROSS\_MOUNT is set, the call-back function will be skipped for any encountered mount points.

- COPYFILE\_RECURSE\_DIR\_CLEANUP

  The object being copied is a directory, and all of the objects contained have been copied. At this stage, the destination directory being copied will have any extra permissions that were added to allow the copying will be removed (by a final COPYFILE\_STAT operation - note that this occurs even if the COPYFILE\_STAT flag was not passed to the recursive copy).

- COPYFILE\_RECURSE\_ERROR

  There was an error in processing an element of the source hierarchy; this happens when [fts(3)](/fts/3.md) returns an error or unknown file type. (Currently, the second argument to the call-back function will always be COPYFILE\_ERR in this case.)

The second argument to the call-back function will indicate the stage of the copy, and will be one of the following values:

- COPYFILE\_START

  Before copying has begun. The third parameter will be a newly-created *copyfile\_state\_t* object with the call-back function and context pre-loaded.

- COPYFILE\_FINISH

  After copying has successfully finished.

- COPYFILE\_ERR

  Indicates an error has happened at some stage. If the first argument to the call-back function is COPYFILE\_RECURSE\_ERROR, then an error occurred while processing the source hierarchy; otherwise, it will indicate what type of object was being copied, and errno will be set to indicate the error.

The fourth and fifth parameters are the source and destination paths that are to be copied (or have been copied, or failed to copy, depending on the second argument).

The last argument to the call-back function will be the value set by COPYFILE\_STATE\_STATUS\_CTX, if any.

The call-back function is required to return one of the following values:

- COPYFILE\_CONTINUE

  The copy will continue as expected.

- COPYFILE\_SKIP

  This object will be skipped, and the next object will be processed. (Note that, when entering a directory, returning COPYFILE\_SKIP from the call-back function will prevent the contents of the directory from being copied.)

- COPYFILE\_QUIT

  The entire copy is aborted at this stage. Any filesystem objects created up to this point will remain. **copyfile**() will return -1, but errno will be unmodified.

The call-back function must always return one of the values listed above; if not, the results are undefined.

The call-back function will be called twice for each object (and an additional two times for directory cleanup); the first call will have a *stage* parameter of COPYFILE\_START; the second time, that value will be either COPYFILE\_FINISH or COPYFILE\_ERR to indicate a successful completion, or an error during processing. In the event of an error, the errno value will be set appropriately.

Note that recursive cloning is also supported with the COPYFILE\_CLONE flag (but not the COPYFILE\_CLONE\_FORCE flag). A recursive clone operation invokes **copyfile**() with COPYFILE\_CLONE on every entry found in the source file-system object. Because **copyfile**() does not allow the cloning of directories, a recursive clone will instead copy any directory it finds (while cloning its contents). As symbolic links may point to directories, they are not followed during recursive clones even if the source is a symbolic link. Additionally, because the COPYFILE\_CLONE flag implies the COPYFILE\_EXCL flag, recursive clones require a nonexistent destination.

The COPYFILE\_PACK, COPYFILE\_UNPACK, COPYFILE\_MOVE, and COPYFILE\_UNLINK flags are not used during a recursive copy, and will result in an error being returned.

Note that if the source path ends in a */* its contents are copied rather than the directory itself (like [cp(1)](/cp/1.md)). 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 */* ) 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 **copyfile**() initially.

## Progress Callback

In addition to the recursive callbacks described above, **copyfile**() and **fcopyfile**() will also use a callback to report data (e.g., COPYFILE\_DATA) progress. If given, the callback will be invoked on each [write(2)](/write/2.md) call. The first argument to the callback function will be COPYFILE\_COPY\_DATA. The second argument will either be COPYFILE\_PROGRESS (indicating that the write was successful), or COPYFILE\_ERR (indicating that there was an error of some sort).

The amount of data bytes copied so far can be retrieved using **copyfile\_state\_get**(), with the COPYFILE\_STATE\_COPIED requestor (the argument type is a pointer to *off\_t* *).*

When copying extended attributes, the first argument to the callback function will be COPYFILE\_COPY\_XATTR. The other arguments will be as described for COPYFILE\_COPY\_DATA; the name of the extended attribute being copied may be retrieved using **copyfile\_state\_get**() and the parameter COPYFILE\_STATE\_XATTRNAME. When using COPYFILE\_PACK, the callback may be called with COPYFILE\_START for each of the extended attributes first, followed by COPYFILE\_PROGRESS before getting and packing the data for each individual attribute, and then COPYFILE\_FINISH when finished with each individual attribute. (That is, COPYFILE\_START may be called for all of the extended attributes, before the first callback with COPYFILE\_PROGRESS is invoked.) Any attribute skipped by returning COPYFILE\_SKIP from the COPYFILE\_START callback will not be placed into the packed output file.

The return value for the data callback must be one of

- COPYFILE\_CONTINUE

  The copy will continue as expected. (In the case of error, it will attempt to write the data again.)

- COPYFILE\_SKIP

  The data copy will be aborted, but without error.

- COPYFILE\_QUIT

  The data copy will be aborted; in the case of COPYFILE\_PROGRESS, errno will be set to ECANCELED.

While the *src* and *dst* parameters will be passed in, they may be NULL in the case of **fcopyfile**().

Note that progress callbacks are not invoked when a clone is requested (e.g. COPYFILE\_CLONE) unless the clone cannot be performed and a copy is performed instead.

## RETURN VALUES

Except when given the COPYFILE\_CHECK flag, **copyfile**() and **fcopyfile**() return less than 0 on error, and 0 on success. All of the other functions return 0 on success, and less than 0 on error.

## WARNING

When performing a recursive copy, if the source hierarchy changes while the copy is occurring, the results are undefined; however, an effort is made to detect this and return an error to the caller instead of proceeding.

**fcopyfile**() does not reset the seek position for either source or destination. This can result in the destination file being a different size than the source file.

Both **copyfile**() and **fcopyfile**() will temporarily mark an unwritable destination writable for the duration of the copy. After the copy is performed (except when the COPYFILE\_STAT flag is passed in), an attempt is made to revert the destination's permissions to their starting state.

## EXAMPLES

```
/* Initialize a state variable */
copyfile_state_t s;
s = copyfile_state_alloc();
/* Copy the data and extended attributes of one file to another */
copyfile("/tmp/f1", "/tmp/f2", s, COPYFILE_DATA | COPYFILE_XATTR);
/* Convert a file to an AppleDouble file for serialization */
copyfile("/tmp/f2", "/tmp/tmpfile", NULL, COPYFILE_ALL | COPYFILE_PACK);
/* Release the state variable */
copyfile_state_free(s);
/* A more complex way to call copyfile() */
s = copyfile_state_alloc();
copyfile_state_set(s, COPYFILE_STATE_SRC_FILENAME, "/tmp/foo");
/* One of src or dst must be set... rest can come from the state */
copyfile(NULL, "/tmp/bar", s, COPYFILE_ALL);
/* Now copy the same source file to another destination file */
copyfile(NULL, "/tmp/car", s, COPYFILE_ALL);
copyfile_state_free(s);
/* Remove extended attributes from a file */
copyfile("/dev/null", "/tmp/bar", NULL, COPYFILE_XATTR);
```

## ERRORS

**copyfile**() and **fcopyfile**() will fail if:

- \[EINVAL\]

  An invalid flag was passed in with COPYFILE\_RECURSIVE.

- \[EINVAL\]

  The *from* or *to* parameter to **copyfile**() was a NULL pointer.

- \[EINVAL\]

  The *from* or *to* parameter to **fcopyfile**() was a negative number.

- \[ENOMEM\]

  A memory allocation failed.

- \[ENOTSUP\]

  The source file was not a directory, symbolic link, or regular file.

- \[ENOTSUP\]

  COPYFILE\_CLONE\_FORCE was specified and file cloning is not supported.

- \[ENOTSUP\]

  COPYFILE\_DATA\_SPARSE was specified, sparse copying is not supported, and COPYFILE\_DATA was not specified.

- \[ECANCELED\]

  The copy was cancelled by callback.

- \[EEXIST\]

  The *to* parameter to **copyfile**() already existed and was passed in with COPYFILE\_EXCL.

- \[ENOENT\]

  The *from* parameter to **copyfile**() did not exist.

- \[EACCES\]

  Search permission is denied for a component of the path prefix for the *from* or *to* parameters.

- \[EACCES\]

  Write permission is denied for a component of the path prefix for the *to* parameter.

- \[EBADF\]

  COPYFILE\_RECURSIVE was specified and a change in the source hierarchy was detected.

In addition, both functions may set errno via an underlying library or system call.

## SEE ALSO

[getxattr(2)](/getxattr/2.md), [listxattr(2)](/listxattr/2.md), [setxattr(2)](/setxattr/2.md), [acl(3)](/acl/3.md)

## HISTORY

The **copyfile**() API was introduced in Mac OS X 10.5.

## BUGS

Recursive copies do not honor hard links.
