COPYFILE(3) | Library Functions Manual | COPYFILE(3) |
copyfile
,
fcopyfile
,
copyfile_state_alloc
,
copyfile_state_free
,
copyfile_state_get
,
copyfile_state_set
— copy a
file
Standard C Library (libc, -lc)
#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);
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
COPYFILE_STAT
COPYFILE_XATTR
COPYFILE_DATA
These values may be or'd together; several convenience macros are provided:
COPYFILE_SECURITY
(COPYFILE_STAT|COPYFILE_ACL)
.COPYFILE_METADATA
(COPYFILE_SECURITY|COPYFILE_XATTR)
.COPYFILE_ALL
(COPYFILE_METADATA|COPYFILE_DATA)
.The
copyfile
()
and fcopyfile
() functions can also have their
behavior modified by the following flags:
COPYFILE_RECURSIVE
copyfile
() to recursively copy a hierarchy.
This flag is not used by fcopyfile
(); see below
for more information.COPYFILE_CHECK
COPYFILE_CHECK|COPYFILE_METADATA
, and the
from file had extended attributes but no ACLs, the
return value would be COPYFILE_XATTR .)
COPYFILE_PACK
COPYFILE_UNPACK
COPYFILE_EXCL
copyfile
() function.)COPYFILE_NOFOLLOW_SRC
copyfile
()
function.)COPYFILE_NOFOLLOW_DST
copyfile
()
function.)COPYFILE_MOVE
copyfile
() function.) No error is returned if
remove(3) fails. Note that
remove(3) removes a symbolic link
itself, not the target of the link.COPYFILE_UNLINK
copyfile
() function.)COPYFILE_CLONE_FORCE
copyfile
() function.)COPYFILE_CLONE
copyfile
() function.)COPYFILE_DATA_SPARSE
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
(COPYFILE_NOFOLLOW_DST
|
COPYFILE_NOFOLLOW_SRC)
.COPYFILE_RUN_IN_PLACE
COPYFILE_PRESERVE_DST_TRACKED
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
copyfile_state_get
()) and
src (for
copyfile_state_set
()) parameters are pointers to
int.COPYFILE_STATE_SRC_FILENAME
COPYFILE_STATE_DST_FILENAME
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
COPYFILE_STATE_STATUS_CTX
COPYFILE_STATE_QUARANTINE
COPYFILE_STATE_COPIED
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
COPYFILE_COPY_XATTR
(see below for details). This
field cannot be set, and may be NULL
.COPYFILE_STATE_WAS_CLONED
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
COPYFILE_STATE_FORBID_CROSS_MOUNT
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 is a pointer to
bool (type bool *
).COPYFILE_STATE_RECURSIVE_SRC_FTSENT
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
When given the COPYFILE_RECURSIVE
flag,
copyfile
() (but not
fcopyfile
()) will use the
fts(3) 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
COPYFILE_RECURSE_DIR
COPYFILE_STATE_FORBID_CROSS_MOUNT
is set, the
call-back function will be skipped for any encountered mount points.COPYFILE_RECURSE_DIR_CLEANUP
COPYFILE_STAT
operation -
note that this occurs even if the COPYFILE_STAT
flag was not passed to the recursive copy).COPYFILE_RECURSE_ERROR
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
COPYFILE_FINISH
COPYFILE_ERR
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
COPYFILE_SKIP
COPYFILE_SKIP
from the call-back function will
prevent the contents of the directory from being copied.)COPYFILE_QUIT
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)). 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.
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) 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
COPYFILE_SKIP
COPYFILE_QUIT
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.
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.
Both
copyfile
()
and fcopyfile
() can copy symbolic links; there is a
gap between when the source link is examined and the actual copy is started,
and this can be a potential security risk, especially if the process has
elevated privileges.
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.
/* 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);
copyfile
() and
fcopyfile
() will fail if:
EINVAL
]COPYFILE_RECURSIVE
.EINVAL
]copyfile
() was a NULL
pointer.EINVAL
]fcopyfile
() was a negative number.ENOMEM
]ENOTSUP
]ENOTSUP
]ENOTSUP
]ECANCELED
]EEXIST
]copyfile
() already existed and was passed in with
COPYFILE_EXCL
.ENOENT
]copyfile
() did not exist.EACCES
]EACCES
]EBADF
]In addition, both functions may set errno
via an underlying library or system call.
The copyfile
() API was introduced in Mac
OS X 10.5.
Recursive copies do not honor hard links.
March 26, 2024 | macOS 14.6 |