В API нет встроенной эквивалентной функции CopyFile. Но sendfile можно использовать для копирования файла в режиме ядра, который является более быстрым и лучшим решением (по многим причинам), чем открытие файла, циклическое переключение по нему для чтения в буфер и запись вывода в другой файл.
Обновление:
Начиная с версии ядра ядра 2.6.33, ограничение, требующее, чтобы вывод sendfile
был сокетом, было отменено, и исходный код работал бы как в Linux, так и - однако, для OS X 10.9 Mavericks, sendfile
в OS X теперь требуется, чтобы вывод был сокетом, а код не работал!
Следующий фрагмент кода должен работать на большинстве OS X (по состоянию на 10.5), (Free) BSD и Linux (по состоянию на 2.6.33). Реализация является «нулевым копированием» для всех платформ, то есть все это выполняется в пространстве ядра и нет копирования буферов или данных в пространство пользователя и из него. Практически лучшая производительность, которую вы можете получить.
#include <fcntl.h>
#include <unistd.h>
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <copyfile.h>
#else
#include <sys/sendfile.h>
#endif
int OSCopyFile(const char* source, const char* destination)
{
int input, output;
if ((input = open(source, O_RDONLY)) == -1)
{
return -1;
}
if ((output = creat(destination, 0660)) == -1)
{
close(input);
return -1;
}
//Here we use kernel-space copying for performance reasons
#if defined(__APPLE__) || defined(__FreeBSD__)
//fcopyfile works on FreeBSD and OS X 10.5+
int result = fcopyfile(input, output, 0, COPYFILE_ALL);
#else
//sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
off_t bytesCopied = 0;
struct stat fileinfo = {0};
fstat(input, &fileinfo);
int result = sendfile(output, input, &bytesCopied, fileinfo.st_size);
#endif
close(input);
close(output);
return result;
}
РЕДАКТИРОВАТЬ : Заменить открытие пункта назначения вызовом на creat()
, так как мы хотим, чтобы был указан флаг O_TRUNC
. См. Комментарий ниже.