2018-08-28 13:48:16 +00:00
|
|
|
#include <Common/createHardLink.h>
|
|
|
|
#include <Common/Exception.h>
|
2022-05-08 17:01:47 +00:00
|
|
|
#include <cerrno>
|
2018-08-28 13:48:16 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2018-11-21 20:56:37 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int CANNOT_STAT;
|
|
|
|
extern const int CANNOT_LINK;
|
|
|
|
}
|
|
|
|
|
2018-08-28 13:48:16 +00:00
|
|
|
void createHardLink(const String & source_path, const String & destination_path)
|
|
|
|
{
|
|
|
|
if (0 != link(source_path.c_str(), destination_path.c_str()))
|
|
|
|
{
|
|
|
|
if (errno == EEXIST)
|
|
|
|
{
|
|
|
|
auto link_errno = errno;
|
|
|
|
|
|
|
|
struct stat source_descr;
|
|
|
|
struct stat destination_descr;
|
|
|
|
|
|
|
|
if (0 != lstat(source_path.c_str(), &source_descr))
|
2019-08-07 12:52:47 +00:00
|
|
|
throwFromErrnoWithPath("Cannot stat " + source_path, source_path, ErrorCodes::CANNOT_STAT);
|
2018-08-28 13:48:16 +00:00
|
|
|
|
|
|
|
if (0 != lstat(destination_path.c_str(), &destination_descr))
|
2019-08-07 12:52:47 +00:00
|
|
|
throwFromErrnoWithPath("Cannot stat " + destination_path, destination_path, ErrorCodes::CANNOT_STAT);
|
2018-08-28 13:48:16 +00:00
|
|
|
|
|
|
|
if (source_descr.st_ino != destination_descr.st_ino)
|
2019-08-07 12:52:47 +00:00
|
|
|
throwFromErrnoWithPath(
|
|
|
|
"Destination file " + destination_path + " is already exist and have different inode.",
|
|
|
|
destination_path, ErrorCodes::CANNOT_LINK, link_errno);
|
2018-08-28 13:48:16 +00:00
|
|
|
}
|
|
|
|
else
|
2019-08-07 12:52:47 +00:00
|
|
|
throwFromErrnoWithPath("Cannot link " + source_path + " to " + destination_path, destination_path,
|
|
|
|
ErrorCodes::CANNOT_LINK);
|
2018-08-28 13:48:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|